For DHCP client configuration control the setting of the broadcast flag in the
DISCOVER message sent.
According to RFC2131:
In the case of a client using DHCP for initial configuration (before
the client's TCP/IP software has been completely configured), DHCP
requires creative use of the client's TCP/IP software and liberal
interpretation of RFC 1122. The TCP/IP software SHOULD accept and
forward to the IP layer any IP packets delivered to the client's
hardware address before the IP address is configured; DHCP servers
and BOOTP relay agents may not be able to deliver DHCP messages to
clients that cannot accept hardware unicast datagrams before the
TCP/IP software is configured.
To work around some clients that cannot accept IP unicast datagrams
before the TCP/IP software is configured as discussed in the previous
paragraph, DHCP uses the 'flags' field [21]. The leftmost bit is
defined as the BROADCAST (B) flag. The semantics of this flag are
discussed in section 4.1 of this document. The remaining bits of the
flags field are reserved for future use. They MUST be set to zero by
clients and ignored by servers and relay agents. Figure 2 gives the
format of the 'flags' field.
this changes means VPP conforms to the:
"SHOULD accept and forward to the IP layer any IP packets delivered
to the client's hardware address before the IP address is configured"
with the caveat that VPP allows DHCP packets destined to the stanard client
DHCP port to be delivered. With this enhancement the control-plane is now
able to choose the setting of the broadcast flag.
Change-Id: Ia4eb2c9bb1e30c29f9192facc645e9533641955a
Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:
+1
-1
@@ -724,7 +724,7 @@ API_FILES += vnet/lisp-gpe/lisp_gpe.api
|
||||
########################################
|
||||
libvnet_la_SOURCES += \
|
||||
vnet/dhcp/client.c \
|
||||
vnet/dhcp/client.h \
|
||||
vnet/dhcp/dhcp_client_detect.c \
|
||||
vnet/dhcp/dhcp_api.c
|
||||
|
||||
nobase_include_HEADERS += \
|
||||
|
||||
+53
-98
@@ -21,56 +21,6 @@ dhcp_client_main_t dhcp_client_main;
|
||||
static u8 *format_dhcp_client_state (u8 * s, va_list * va);
|
||||
static vlib_node_registration_t dhcp_client_process_node;
|
||||
|
||||
static void
|
||||
dhcp_client_add_rx_address (dhcp_client_main_t * dcm, dhcp_client_t * c)
|
||||
{
|
||||
/* Install a local entry for the offered address */
|
||||
fib_prefix_t rx = {
|
||||
.fp_len = 32,
|
||||
.fp_addr.ip4 = c->leased_address,
|
||||
.fp_proto = FIB_PROTOCOL_IP4,
|
||||
};
|
||||
|
||||
fib_table_entry_special_add (fib_table_get_index_for_sw_if_index
|
||||
(FIB_PROTOCOL_IP4, c->sw_if_index), &rx,
|
||||
FIB_SOURCE_DHCP, (FIB_ENTRY_FLAG_LOCAL));
|
||||
|
||||
/* And add the server's address as uRPF exempt so we can accept
|
||||
* local packets from it */
|
||||
fib_prefix_t server = {
|
||||
.fp_len = 32,
|
||||
.fp_addr.ip4 = c->dhcp_server,
|
||||
.fp_proto = FIB_PROTOCOL_IP4,
|
||||
};
|
||||
|
||||
fib_table_entry_special_add (fib_table_get_index_for_sw_if_index
|
||||
(FIB_PROTOCOL_IP4, c->sw_if_index), &server,
|
||||
FIB_SOURCE_URPF_EXEMPT, (FIB_ENTRY_FLAG_DROP));
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp_client_remove_rx_address (dhcp_client_main_t * dcm, dhcp_client_t * c)
|
||||
{
|
||||
fib_prefix_t rx = {
|
||||
.fp_len = 32,
|
||||
.fp_addr.ip4 = c->leased_address,
|
||||
.fp_proto = FIB_PROTOCOL_IP4,
|
||||
};
|
||||
|
||||
fib_table_entry_special_remove (fib_table_get_index_for_sw_if_index
|
||||
(FIB_PROTOCOL_IP4, c->sw_if_index), &rx,
|
||||
FIB_SOURCE_DHCP);
|
||||
fib_prefix_t server = {
|
||||
.fp_len = 32,
|
||||
.fp_addr.ip4 = c->dhcp_server,
|
||||
.fp_proto = FIB_PROTOCOL_IP4,
|
||||
};
|
||||
|
||||
fib_table_entry_special_remove (fib_table_get_index_for_sw_if_index
|
||||
(FIB_PROTOCOL_IP4, c->sw_if_index), &server,
|
||||
FIB_SOURCE_URPF_EXEMPT);
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp_client_acquire_address (dhcp_client_main_t * dcm, dhcp_client_t * c)
|
||||
{
|
||||
@@ -233,13 +183,6 @@ dhcp_client_for_us (u32 bi, vlib_buffer_t * b,
|
||||
c->next_transmit = now + 5.0;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* in order to accept unicasted ACKs we need to configure the offered
|
||||
* address on the interface. However, at this point we may not know the
|
||||
* subnet-mask (an OFFER may not contain it). So add a temporary receice
|
||||
* and uRPF excempt entry
|
||||
*/
|
||||
dhcp_client_add_rx_address (dcm, c);
|
||||
|
||||
/* Received an offer, go send a request */
|
||||
c->state = DHCP_REQUEST;
|
||||
@@ -267,9 +210,11 @@ dhcp_client_for_us (u32 bi, vlib_buffer_t * b,
|
||||
void (*fp) (u32, u32, u8 *, u8, u8, u8 *, u8 *, u8 *) =
|
||||
c->event_callback;
|
||||
|
||||
/* replace the temporary RX address with the correct subnet */
|
||||
dhcp_client_remove_rx_address (dcm, c);
|
||||
/* add the advertised subnet and disable the feature */
|
||||
dhcp_client_acquire_address (dcm, c);
|
||||
vnet_feature_enable_disable ("ip4-unicast",
|
||||
"ip4-dhcp-client-detect",
|
||||
c->sw_if_index, 0, 0, 0);
|
||||
|
||||
/*
|
||||
* Configure default IP route:
|
||||
@@ -285,8 +230,19 @@ dhcp_client_for_us (u32 bi, vlib_buffer_t * b,
|
||||
.ip4 = c->router_address,
|
||||
};
|
||||
|
||||
fib_table_entry_path_add (fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, c->sw_if_index), &all_0s, FIB_SOURCE_DHCP, FIB_ENTRY_FLAG_NONE, DPO_PROTO_IP4, &nh, c->sw_if_index, ~0, 1, NULL, // no label stack
|
||||
FIB_ROUTE_PATH_FLAG_NONE);
|
||||
/* *INDENT-OFF* */
|
||||
fib_table_entry_path_add (
|
||||
fib_table_get_index_for_sw_if_index (
|
||||
FIB_PROTOCOL_IP4,
|
||||
c->sw_if_index),
|
||||
&all_0s,
|
||||
FIB_SOURCE_DHCP,
|
||||
FIB_ENTRY_FLAG_NONE,
|
||||
DPO_PROTO_IP4,
|
||||
&nh, c->sw_if_index,
|
||||
~0, 1, NULL, // no label stack
|
||||
FIB_ROUTE_PATH_FLAG_NONE);
|
||||
/* *INDENT-ON* */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -418,7 +374,9 @@ send_dhcp_pkt (dhcp_client_main_t * dcm, dhcp_client_t * c,
|
||||
dhcp->hardware_type = 1; /* ethernet */
|
||||
dhcp->hardware_address_length = 6;
|
||||
dhcp->transaction_identifier = c->transaction_id;
|
||||
dhcp->flags = clib_host_to_net_u16 (is_broadcast ? DHCP_FLAG_BROADCAST : 0);
|
||||
dhcp->flags =
|
||||
clib_host_to_net_u16 (is_broadcast && c->set_broadcast_flag ?
|
||||
DHCP_FLAG_BROADCAST : 0);
|
||||
dhcp->magic_cookie.as_u32 = DHCP_MAGIC;
|
||||
|
||||
o = (dhcp_option_t *) dhcp->options;
|
||||
@@ -676,14 +634,13 @@ dhcp_client_process (vlib_main_t * vm,
|
||||
break;
|
||||
|
||||
case ~0:
|
||||
pool_foreach (c, dcm->clients, (
|
||||
{
|
||||
timeout =
|
||||
dhcp_client_sm (now, timeout,
|
||||
(uword) (c -
|
||||
dcm->clients));
|
||||
}
|
||||
));
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (c, dcm->clients,
|
||||
({
|
||||
timeout = dhcp_client_sm (now, timeout,
|
||||
(uword) (c - dcm->clients));
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
if (pool_elts (dcm->clients) == 0)
|
||||
timeout = 100.0;
|
||||
break;
|
||||
@@ -785,13 +742,14 @@ show_dhcp_client_command_fn (vlib_main_t * vm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
pool_foreach (c, dcm->clients, (
|
||||
{
|
||||
vlib_cli_output (vm, "%U",
|
||||
format_dhcp_client, dcm,
|
||||
c, verbose);
|
||||
}
|
||||
));
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (c, dcm->clients,
|
||||
({
|
||||
vlib_cli_output (vm, "%U",
|
||||
format_dhcp_client, dcm,
|
||||
c, verbose);
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -812,11 +770,6 @@ dhcp_client_add_del (dhcp_client_add_del_args_t * a)
|
||||
vlib_main_t *vm = dcm->vlib_main;
|
||||
dhcp_client_t *c;
|
||||
uword *p;
|
||||
fib_prefix_t all_1s = {
|
||||
.fp_len = 32,
|
||||
.fp_addr.ip4.as_u32 = 0xffffffff,
|
||||
.fp_proto = FIB_PROTOCOL_IP4,
|
||||
};
|
||||
fib_prefix_t all_0s = {
|
||||
.fp_len = 0,
|
||||
.fp_addr.ip4.as_u32 = 0x0,
|
||||
@@ -840,6 +793,7 @@ dhcp_client_add_del (dhcp_client_add_del_args_t * a)
|
||||
c->option_55_data = a->option_55_data;
|
||||
c->hostname = a->hostname;
|
||||
c->client_identifier = a->client_identifier;
|
||||
c->set_broadcast_flag = a->set_broadcast_flag;
|
||||
do
|
||||
{
|
||||
c->transaction_id = random_u32 (&dcm->seed);
|
||||
@@ -848,17 +802,18 @@ dhcp_client_add_del (dhcp_client_add_del_args_t * a)
|
||||
set_l2_rewrite (dcm, c);
|
||||
hash_set (dcm->client_by_sw_if_index, a->sw_if_index, c - dcm->clients);
|
||||
|
||||
/* this add is ref counted by FIB so we can add for each itf */
|
||||
fib_table_entry_special_add (fib_table_get_index_for_sw_if_index
|
||||
(FIB_PROTOCOL_IP4, c->sw_if_index),
|
||||
&all_1s, FIB_SOURCE_DHCP,
|
||||
FIB_ENTRY_FLAG_LOCAL);
|
||||
|
||||
/*
|
||||
* enable the interface to RX IPv4 packets
|
||||
* this is also ref counted
|
||||
* In order to accept any OFFER, whether broadcasted or unicasted, we
|
||||
* need to configure the dhcp-client-detect feature as an input feature
|
||||
* so the DHCP OFFER is sent to the ip4-local node. Without this a
|
||||
* broadcasted OFFER hits the 255.255.255.255/32 address and a unicast
|
||||
* hits 0.0.0.0/0 both of which default to drop and the latter may forward
|
||||
* of box - not what we want. Nor to we want to change these route for
|
||||
* all interfaces in this table
|
||||
*/
|
||||
ip4_sw_interface_enable_disable (c->sw_if_index, 1);
|
||||
vnet_feature_enable_disable ("ip4-unicast",
|
||||
"ip4-dhcp-client-detect",
|
||||
c->sw_if_index, 1, 0, 0);
|
||||
|
||||
vlib_process_signal_event (vm, dhcp_client_process_node.index,
|
||||
EVENT_DHCP_CLIENT_WAKEUP, c - dcm->clients);
|
||||
@@ -867,10 +822,6 @@ dhcp_client_add_del (dhcp_client_add_del_args_t * a)
|
||||
{
|
||||
c = pool_elt_at_index (dcm->clients, p[0]);
|
||||
|
||||
fib_table_entry_special_remove (fib_table_get_index_for_sw_if_index
|
||||
(FIB_PROTOCOL_IP4, c->sw_if_index),
|
||||
&all_1s, FIB_SOURCE_DHCP);
|
||||
|
||||
if (c->router_address.as_u32)
|
||||
{
|
||||
ip46_address_t nh = {
|
||||
@@ -883,9 +834,7 @@ dhcp_client_add_del (dhcp_client_add_del_args_t * a)
|
||||
DPO_PROTO_IP4, &nh, c->sw_if_index, ~0,
|
||||
1, FIB_ROUTE_PATH_FLAG_NONE);
|
||||
}
|
||||
dhcp_client_remove_rx_address (dcm, c);
|
||||
dhcp_client_release_address (dcm, c);
|
||||
ip4_sw_interface_enable_disable (c->sw_if_index, 0);
|
||||
|
||||
vec_free (c->option_55_data);
|
||||
vec_free (c->hostname);
|
||||
@@ -903,7 +852,8 @@ dhcp_client_config (vlib_main_t * vm,
|
||||
u8 * hostname,
|
||||
u8 * client_id,
|
||||
u32 is_add,
|
||||
u32 client_index, void *event_callback, u32 pid)
|
||||
u32 client_index,
|
||||
void *event_callback, u8 set_broadcast_flag, u32 pid)
|
||||
{
|
||||
dhcp_client_add_del_args_t _a, *a = &_a;
|
||||
int rv;
|
||||
@@ -914,6 +864,7 @@ dhcp_client_config (vlib_main_t * vm,
|
||||
a->client_index = client_index;
|
||||
a->pid = pid;
|
||||
a->event_callback = event_callback;
|
||||
a->set_broadcast_flag = set_broadcast_flag;
|
||||
vec_validate (a->hostname, strlen ((char *) hostname) - 1);
|
||||
strncpy ((char *) a->hostname, (char *) hostname, vec_len (a->hostname));
|
||||
vec_validate (a->client_identifier, strlen ((char *) client_id) - 1);
|
||||
@@ -990,6 +941,7 @@ dhcp_client_set_command_fn (vlib_main_t * vm,
|
||||
u32 sw_if_index;
|
||||
u8 *hostname = 0;
|
||||
u8 sw_if_index_set = 0;
|
||||
u8 set_broadcast_flag = 1;
|
||||
int is_add = 1;
|
||||
dhcp_client_add_del_args_t _a, *a = &_a;
|
||||
int rv;
|
||||
@@ -1003,6 +955,8 @@ dhcp_client_set_command_fn (vlib_main_t * vm,
|
||||
;
|
||||
else if (unformat (input, "del"))
|
||||
is_add = 0;
|
||||
else if (unformat (input, "broadcast", &set_broadcast_flag))
|
||||
is_add = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
@@ -1015,6 +969,7 @@ dhcp_client_set_command_fn (vlib_main_t * vm,
|
||||
a->sw_if_index = sw_if_index;
|
||||
a->hostname = hostname;
|
||||
a->client_identifier = format (0, "vpe 1.0%c", 0);
|
||||
a->set_broadcast_flag = set_broadcast_flag;
|
||||
|
||||
/*
|
||||
* Option 55 request list. These data precisely match
|
||||
|
||||
@@ -71,6 +71,10 @@ typedef struct
|
||||
/* Information used for event callback */
|
||||
u32 client_index;
|
||||
u32 pid;
|
||||
|
||||
/* Set the broadcast Flag in the Discover/Request messages */
|
||||
u8 set_broadcast_flag;
|
||||
|
||||
void *event_callback;
|
||||
} dhcp_client_t;
|
||||
|
||||
@@ -90,6 +94,7 @@ typedef struct
|
||||
{
|
||||
int is_add;
|
||||
u32 sw_if_index;
|
||||
u8 set_broadcast_flag;
|
||||
|
||||
/* vectors, consumed by dhcp client code */
|
||||
u8 *hostname;
|
||||
@@ -118,7 +123,8 @@ int dhcp_client_config (vlib_main_t * vm,
|
||||
u8 * hostname,
|
||||
u8 * client_id,
|
||||
u32 is_add,
|
||||
u32 client_index, void *event_callback, u32 pid);
|
||||
u32 client_index,
|
||||
void *event_callback, u8 set_broadcast_flag, u32 pid);
|
||||
|
||||
#endif /* included_dhcp_client_h */
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@ autoreply define dhcp_proxy_set_vss
|
||||
@param is_add - add the config if non-zero, else delete
|
||||
@param want_dhcp_event - DHCP event sent to the sender
|
||||
via dhcp_compl_event API message if non-zero
|
||||
@param set_broadcast_flag - in the DHCP Discover to control
|
||||
how the resulting OFFER is addressed.
|
||||
@param pid - sender's pid
|
||||
*/
|
||||
autoreply define dhcp_client_config
|
||||
@@ -82,6 +84,7 @@ autoreply define dhcp_client_config
|
||||
u8 client_id[64];
|
||||
u8 is_add;
|
||||
u8 want_dhcp_event;
|
||||
u8 set_broadcast_flag;
|
||||
u32 pid;
|
||||
};
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ static void vl_api_dhcp_client_config_t_handler
|
||||
mp->hostname, mp->client_id,
|
||||
mp->is_add, mp->client_index,
|
||||
mp->want_dhcp_event ? dhcp_compl_event_callback :
|
||||
NULL, mp->pid);
|
||||
NULL, mp->set_broadcast_flag, mp->pid);
|
||||
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,20 +24,25 @@ singular_db<interface::key_t, dhcp_config> dhcp_config::m_db;
|
||||
|
||||
dhcp_config::event_handler dhcp_config::m_evh;
|
||||
|
||||
dhcp_config::dhcp_config(const interface& itf, const std::string& hostname)
|
||||
dhcp_config::dhcp_config(const interface& itf,
|
||||
const std::string& hostname,
|
||||
bool set_broadcast_flag)
|
||||
: m_itf(itf.singular())
|
||||
, m_hostname(hostname)
|
||||
, m_client_id(l2_address_t::ZERO)
|
||||
, m_set_broadcast_flag(set_broadcast_flag)
|
||||
, m_binding(0)
|
||||
{
|
||||
}
|
||||
|
||||
dhcp_config::dhcp_config(const interface& itf,
|
||||
const std::string& hostname,
|
||||
const l2_address_t& client_id)
|
||||
const l2_address_t& client_id,
|
||||
bool set_broadcast_flag)
|
||||
: m_itf(itf.singular())
|
||||
, m_hostname(hostname)
|
||||
, m_client_id(client_id)
|
||||
, m_set_broadcast_flag(set_broadcast_flag)
|
||||
, m_binding(0)
|
||||
{
|
||||
}
|
||||
@@ -46,6 +51,7 @@ dhcp_config::dhcp_config(const dhcp_config& o)
|
||||
: m_itf(o.m_itf)
|
||||
, m_hostname(o.m_hostname)
|
||||
, m_client_id(o.m_client_id)
|
||||
, m_set_broadcast_flag(o.m_set_broadcast_flag)
|
||||
, m_binding(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -41,14 +41,17 @@ public:
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
dhcp_config(const interface& itf, const std::string& hostname);
|
||||
dhcp_config(const interface& itf,
|
||||
const std::string& hostname,
|
||||
bool set_broadcast_flag = true);
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
dhcp_config(const interface& itf,
|
||||
const std::string& hostname,
|
||||
const l2_address_t& client_id);
|
||||
const l2_address_t& client_id,
|
||||
bool set_broadcast_flag = true);
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
@@ -202,6 +205,11 @@ private:
|
||||
*/
|
||||
const l2_address_t m_client_id;
|
||||
|
||||
/**
|
||||
* Flag to control the setting the of DHCP discover's broadcast flag
|
||||
*/
|
||||
const bool m_set_broadcast_flag;
|
||||
|
||||
/**
|
||||
* HW configuration for the binding. The bool representing the
|
||||
* do/don't bind.
|
||||
|
||||
@@ -23,11 +23,13 @@ namespace dhcp_config_cmds {
|
||||
bind_cmd::bind_cmd(HW::item<bool>& item,
|
||||
const handle_t& itf,
|
||||
const std::string& hostname,
|
||||
const l2_address_t& client_id)
|
||||
const l2_address_t& client_id,
|
||||
bool set_broadcast_flag)
|
||||
: rpc_cmd(item)
|
||||
, m_itf(itf)
|
||||
, m_hostname(hostname)
|
||||
, m_client_id(client_id)
|
||||
, m_set_broadcast_flag(set_broadcast_flag)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@ public:
|
||||
bind_cmd(HW::item<bool>& item,
|
||||
const handle_t& itf,
|
||||
const std::string& hostname,
|
||||
const l2_address_t& client_id);
|
||||
const l2_address_t& client_id,
|
||||
bool set_braodcast_flag = false);
|
||||
|
||||
/**
|
||||
* Issue the command to VPP/HW
|
||||
@@ -68,6 +69,11 @@ private:
|
||||
* The DHCP client's ID
|
||||
*/
|
||||
const l2_address_t m_client_id;
|
||||
|
||||
/**
|
||||
* Flag to control the setting the of DHCP discover's broadcast flag
|
||||
*/
|
||||
const bool m_set_broadcast_flag;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+105
-4
@@ -214,7 +214,8 @@ class TestDHCP(VppTestCase):
|
||||
self.assertEqual(udp.dport, DHCP4_SERVER_PORT)
|
||||
self.assertEqual(udp.sport, DHCP4_CLIENT_PORT)
|
||||
|
||||
def verify_orig_dhcp_discover(self, pkt, intf, hostname, client_id=None):
|
||||
def verify_orig_dhcp_discover(self, pkt, intf, hostname, client_id=None,
|
||||
broadcast=1):
|
||||
self.verify_orig_dhcp_pkt(pkt, intf)
|
||||
|
||||
self.verify_dhcp_msg_type(pkt, "discover")
|
||||
@@ -224,9 +225,13 @@ class TestDHCP(VppTestCase):
|
||||
bootp = pkt[BOOTP]
|
||||
self.assertEqual(bootp.ciaddr, "0.0.0.0")
|
||||
self.assertEqual(bootp.giaddr, "0.0.0.0")
|
||||
self.assertEqual(bootp.flags, 0x8000)
|
||||
if broadcast:
|
||||
self.assertEqual(bootp.flags, 0x8000)
|
||||
else:
|
||||
self.assertEqual(bootp.flags, 0x0000)
|
||||
|
||||
def verify_orig_dhcp_request(self, pkt, intf, hostname, ip):
|
||||
def verify_orig_dhcp_request(self, pkt, intf, hostname, ip,
|
||||
broadcast=1):
|
||||
self.verify_orig_dhcp_pkt(pkt, intf)
|
||||
|
||||
self.verify_dhcp_msg_type(pkt, "request")
|
||||
@@ -235,7 +240,10 @@ class TestDHCP(VppTestCase):
|
||||
bootp = pkt[BOOTP]
|
||||
self.assertEqual(bootp.ciaddr, "0.0.0.0")
|
||||
self.assertEqual(bootp.giaddr, "0.0.0.0")
|
||||
self.assertEqual(bootp.flags, 0x8000)
|
||||
if broadcast:
|
||||
self.assertEqual(bootp.flags, 0x8000)
|
||||
else:
|
||||
self.assertEqual(bootp.flags, 0x0000)
|
||||
|
||||
def verify_relayed_dhcp_discover(self, pkt, intf, src_intf=None,
|
||||
fib_id=0, oui=0,
|
||||
@@ -1310,6 +1318,14 @@ class TestDHCP(VppTestCase):
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
|
||||
#
|
||||
# We'll get an ARP request for the router address
|
||||
#
|
||||
rx = self.pg3.get_capture(1)
|
||||
|
||||
self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
|
||||
#
|
||||
# At the end of this procedure there should be a connected route
|
||||
# in the FIB
|
||||
@@ -1325,6 +1341,91 @@ class TestDHCP(VppTestCase):
|
||||
self.assertFalse(find_route(self, self.pg3.local_ip4, 32))
|
||||
self.assertFalse(find_route(self, self.pg3.local_ip4, 24))
|
||||
|
||||
#
|
||||
# Rince and repeat, this time with VPP configured not to set
|
||||
# the braodcast flag in the discover and request messages,
|
||||
# and for the server to unicast the responses.
|
||||
#
|
||||
# Configure DHCP client on PG3 and capture the discover sent
|
||||
#
|
||||
self.vapi.dhcp_client(self.pg3.sw_if_index, hostname,
|
||||
set_broadcast_flag=0)
|
||||
|
||||
rx = self.pg3.get_capture(1)
|
||||
|
||||
self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname,
|
||||
broadcast=0)
|
||||
|
||||
#
|
||||
# Send back on offer, unicasted to the offered address.
|
||||
# Expect the request.
|
||||
#
|
||||
p_offer = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
|
||||
IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
|
||||
UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
|
||||
BOOTP(op=1, yiaddr=self.pg3.local_ip4) /
|
||||
DHCP(options=[('message-type', 'offer'),
|
||||
('server_id', self.pg3.remote_ip4),
|
||||
('end')]))
|
||||
|
||||
self.pg3.add_stream(p_offer)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
|
||||
rx = self.pg3.get_capture(1)
|
||||
self.verify_orig_dhcp_request(rx[0], self.pg3, hostname,
|
||||
self.pg3.local_ip4,
|
||||
broadcast=0)
|
||||
|
||||
#
|
||||
# Send an acknowloedgement
|
||||
#
|
||||
p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
|
||||
IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
|
||||
UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
|
||||
BOOTP(op=1, yiaddr=self.pg3.local_ip4) /
|
||||
DHCP(options=[('message-type', 'ack'),
|
||||
('subnet_mask', "255.255.255.0"),
|
||||
('router', self.pg3.remote_ip4),
|
||||
('server_id', self.pg3.remote_ip4),
|
||||
('lease_time', 43200),
|
||||
('end')]))
|
||||
|
||||
self.pg3.add_stream(p_ack)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
self.pg_start()
|
||||
|
||||
#
|
||||
# We'll get an ARP request for the router address
|
||||
#
|
||||
rx = self.pg3.get_capture(1)
|
||||
|
||||
self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4)
|
||||
self.pg_enable_capture(self.pg_interfaces)
|
||||
|
||||
#
|
||||
# At the end of this procedure there should be a connected route
|
||||
# in the FIB
|
||||
#
|
||||
self.assertTrue(find_route(self, self.pg3.local_ip4, 24))
|
||||
self.assertTrue(find_route(self, self.pg3.local_ip4, 32))
|
||||
|
||||
# remove the left over ARP entry
|
||||
self.vapi.ip_neighbor_add_del(self.pg3.sw_if_index,
|
||||
mactobinary(self.pg3.remote_mac),
|
||||
self.pg3.remote_ip4,
|
||||
is_add=0)
|
||||
#
|
||||
# remove the DHCP config
|
||||
#
|
||||
self.vapi.dhcp_client(self.pg3.sw_if_index, hostname, is_add=0)
|
||||
|
||||
#
|
||||
# and now the route should be gone
|
||||
#
|
||||
self.assertFalse(find_route(self, self.pg3.local_ip4, 32))
|
||||
self.assertFalse(find_route(self, self.pg3.local_ip4, 24))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(testRunner=VppTestRunner)
|
||||
|
||||
@@ -2132,6 +2132,7 @@ class VppPapiProvider(object):
|
||||
hostname,
|
||||
client_id='',
|
||||
is_add=1,
|
||||
set_broadcast_flag=1,
|
||||
want_dhcp_events=0):
|
||||
return self.api(
|
||||
self.papi.dhcp_client_config,
|
||||
@@ -2141,6 +2142,7 @@ class VppPapiProvider(object):
|
||||
'client_id': client_id,
|
||||
'is_add': is_add,
|
||||
'want_dhcp_event': want_dhcp_events,
|
||||
'set_broadcast_flag': set_broadcast_flag,
|
||||
'pid': os.getpid(),
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user