summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vnet.am2
-rw-r--r--src/vnet/dhcp/client.c151
-rw-r--r--src/vnet/dhcp/client.h8
-rw-r--r--src/vnet/dhcp/dhcp.api3
-rw-r--r--src/vnet/dhcp/dhcp_api.c2
-rw-r--r--src/vnet/dhcp/dhcp_client_detect.c333
-rw-r--r--src/vpp-api/vom/dhcp_config.cpp10
-rw-r--r--src/vpp-api/vom/dhcp_config.hpp12
-rw-r--r--src/vpp-api/vom/dhcp_config_cmds.cpp4
-rw-r--r--src/vpp-api/vom/dhcp_config_cmds.hpp8
10 files changed, 426 insertions, 107 deletions
diff --git a/src/vnet.am b/src/vnet.am
index 84407bc1861..32d3167b16e 100644
--- a/src/vnet.am
+++ b/src/vnet.am
@@ -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 += \
diff --git a/src/vnet/dhcp/client.c b/src/vnet/dhcp/client.c
index 8043bf22d43..03fc2689abf 100644
--- a/src/vnet/dhcp/client.c
+++ b/src/vnet/dhcp/client.c
@@ -22,56 +22,6 @@ 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
diff --git a/src/vnet/dhcp/client.h b/src/vnet/dhcp/client.h
index d9c7e25d0b2..1c2becb3058 100644
--- a/src/vnet/dhcp/client.h
+++ b/src/vnet/dhcp/client.h
@@ -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 */
diff --git a/src/vnet/dhcp/dhcp.api b/src/vnet/dhcp/dhcp.api
index 528915a46e9..721a1be3547 100644
--- a/src/vnet/dhcp/dhcp.api
+++ b/src/vnet/dhcp/dhcp.api
@@ -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;
};
diff --git a/src/vnet/dhcp/dhcp_api.c b/src/vnet/dhcp/dhcp_api.c
index 8e210cdd5b0..401f6b75edc 100644
--- a/src/vnet/dhcp/dhcp_api.c
+++ b/src/vnet/dhcp/dhcp_api.c
@@ -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;
diff --git a/src/vnet/dhcp/dhcp_client_detect.c b/src/vnet/dhcp/dhcp_client_detect.c
new file mode 100644
index 00000000000..1b916cdd356
--- /dev/null
+++ b/src/vnet/dhcp/dhcp_client_detect.c
@@ -0,0 +1,333 @@
+/*
+ * DHCP feature; applied as an input feature to select DHCP packets
+ *
+ * Copyright (c) 2013 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vnet/dhcp/client.h>
+#include <vnet/udp/udp.h>
+
+#define foreach_dhcp_client_detect \
+ _(EXTRACT, "Extract")
+
+typedef enum
+{
+#define _(sym,str) DHCP_CLIENT_DETECT_ERROR_##sym,
+ foreach_dhcp_client_detect
+#undef _
+ DHCP_CLIENT_DETECT_N_ERROR,
+} dhcp_client_detect_error_t;
+
+static char *dhcp_client_detect_error_strings[] = {
+#define _(sym,string) string,
+ foreach_dhcp_client_detect
+#undef _
+};
+
+typedef enum
+{
+#define _(sym,str) DHCP_CLIENT_DETECT_NEXT_##sym,
+ foreach_dhcp_client_detect
+#undef _
+ DHCP_CLIENT_DETECT_N_NEXT,
+} dhcp_client_detect_next_t;
+
+/**
+ * per-packet trace data
+ */
+typedef struct dhcp_client_detect_trace_t_
+{
+ /* per-pkt trace data */
+ u8 extracted;
+} dhcp_client_detect_trace_t;
+
+static uword
+dhcp_client_detect_node_fn (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * frame)
+{
+ dhcp_client_detect_next_t next_index;
+ u16 dhcp_client_port_network_order;
+ u32 n_left_from, *from, *to_next;
+ u32 extractions;
+
+ dhcp_client_port_network_order =
+ clib_net_to_host_u16 (UDP_DST_PORT_dhcp_to_client);
+ next_index = 0;
+ extractions = 0;
+ n_left_from = frame->n_vectors;
+ from = vlib_frame_vector_args (frame);
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ /*
+ * This loop is optimised not so we can really quickly process DHCp
+ * offers... but so we can quickly sift them out when the interface
+ * is also receving 'normal' packets
+ */
+ while (n_left_from >= 8 && n_left_to_next >= 4)
+ {
+ udp_header_t *udp0, *udp1, *udp2, *udp3;
+ ip4_header_t *ip0, *ip1, *ip2, *ip3;
+ vlib_buffer_t *b0, *b1, *b2, *b3;
+ u32 next0, next1, next2, next3;
+ u32 bi0, bi1, bi2, bi3;
+
+ next0 = next1 = next2 = next3 = ~0;
+ bi0 = to_next[0] = from[0];
+ bi1 = to_next[1] = from[1];
+ bi2 = to_next[2] = from[2];
+ bi3 = to_next[3] = from[3];
+
+ /* Prefetch next iteration. */
+ {
+ vlib_buffer_t *p2, *p3, *p4, *p5;
+
+ p2 = vlib_get_buffer (vm, from[2]);
+ p3 = vlib_get_buffer (vm, from[3]);
+ p4 = vlib_get_buffer (vm, from[4]);
+ p5 = vlib_get_buffer (vm, from[5]);
+
+ vlib_prefetch_buffer_header (p2, STORE);
+ vlib_prefetch_buffer_header (p3, STORE);
+ vlib_prefetch_buffer_header (p4, STORE);
+ vlib_prefetch_buffer_header (p5, STORE);
+
+ CLIB_PREFETCH (p2->data, sizeof (ip0[0]) + sizeof (udp0[0]),
+ STORE);
+ CLIB_PREFETCH (p3->data, sizeof (ip0[0]) + sizeof (udp0[0]),
+ STORE);
+ CLIB_PREFETCH (p4->data, sizeof (ip0[0]) + sizeof (udp0[0]),
+ STORE);
+ CLIB_PREFETCH (p5->data, sizeof (ip0[0]) + sizeof (udp0[0]),
+ STORE);
+ }
+
+ from += 4;
+ to_next += 4;
+ n_left_from -= 4;
+ n_left_to_next -= 4;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ b1 = vlib_get_buffer (vm, bi1);
+ b2 = vlib_get_buffer (vm, bi2);
+ b3 = vlib_get_buffer (vm, bi3);
+ ip0 = vlib_buffer_get_current (b0);
+ ip1 = vlib_buffer_get_current (b1);
+ ip2 = vlib_buffer_get_current (b2);
+ ip3 = vlib_buffer_get_current (b2);
+
+ vnet_feature_next (vnet_buffer (b0)->sw_if_index[VLIB_TX],
+ &next0, b0);
+ vnet_feature_next (vnet_buffer (b1)->sw_if_index[VLIB_TX],
+ &next1, b1);
+ vnet_feature_next (vnet_buffer (b2)->sw_if_index[VLIB_TX],
+ &next2, b2);
+ vnet_feature_next (vnet_buffer (b3)->sw_if_index[VLIB_TX],
+ &next3, b3);
+
+ if (ip0->protocol == IP_PROTOCOL_UDP)
+ {
+ udp0 = (udp_header_t *) (ip0 + 1);
+
+ if (dhcp_client_port_network_order == udp0->dst_port)
+ {
+ next0 = DHCP_CLIENT_DETECT_NEXT_EXTRACT;
+ extractions++;
+ }
+ }
+ if (ip1->protocol == IP_PROTOCOL_UDP)
+ {
+ udp1 = (udp_header_t *) (ip1 + 1);
+
+ if (dhcp_client_port_network_order == udp1->dst_port)
+ {
+ next1 = DHCP_CLIENT_DETECT_NEXT_EXTRACT;
+ extractions++;
+ }
+ }
+ if (ip2->protocol == IP_PROTOCOL_UDP)
+ {
+ udp2 = (udp_header_t *) (ip2 + 1);
+
+ if (dhcp_client_port_network_order == udp2->dst_port)
+ {
+ next2 = DHCP_CLIENT_DETECT_NEXT_EXTRACT;
+ extractions++;
+ }
+ }
+ if (ip3->protocol == IP_PROTOCOL_UDP)
+ {
+ udp3 = (udp_header_t *) (ip3 + 1);
+
+ if (dhcp_client_port_network_order == udp3->dst_port)
+ {
+ next3 = DHCP_CLIENT_DETECT_NEXT_EXTRACT;
+ extractions++;
+ }
+ }
+
+ if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ dhcp_client_detect_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->extracted = (next0 == DHCP_CLIENT_DETECT_NEXT_EXTRACT);
+ }
+ if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ dhcp_client_detect_trace_t *t =
+ vlib_add_trace (vm, node, b1, sizeof (*t));
+ t->extracted = (next1 == DHCP_CLIENT_DETECT_NEXT_EXTRACT);
+ }
+ if (PREDICT_FALSE (b2->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ dhcp_client_detect_trace_t *t =
+ vlib_add_trace (vm, node, b2, sizeof (*t));
+ t->extracted = (next2 == DHCP_CLIENT_DETECT_NEXT_EXTRACT);
+ }
+ if (PREDICT_FALSE (b3->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ dhcp_client_detect_trace_t *t =
+ vlib_add_trace (vm, node, b3, sizeof (*t));
+ t->extracted = (next3 == DHCP_CLIENT_DETECT_NEXT_EXTRACT);
+ }
+
+ /* verify speculative enqueue, maybe switch current next frame */
+ vlib_validate_buffer_enqueue_x4 (vm, node, next_index,
+ to_next, n_left_to_next,
+ bi0, bi1, bi2, bi3,
+ next0, next1, next2, next3);
+ }
+
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ udp_header_t *udp0;
+ vlib_buffer_t *b0;
+ ip4_header_t *ip0;
+ u32 next0 = ~0;
+ u32 bi0;
+
+ bi0 = from[0];
+ to_next[0] = bi0;
+ from += 1;
+ to_next += 1;
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ ip0 = vlib_buffer_get_current (b0);
+
+ /*
+ * when this feature is applied on an interface that is already
+ * accepting packets (because e.g. the interface has other addresses
+ * assigned) we are looking for the preverbial needle in the haystack
+ * so assume the packet is not the one we are looking for.
+ */
+ vnet_feature_next (vnet_buffer (b0)->sw_if_index[VLIB_TX],
+ &next0, b0);
+
+ /*
+ * all we are looking for here is DHCP/BOOTP packet-to-client
+ * UDO port.
+ */
+ if (ip0->protocol == IP_PROTOCOL_UDP)
+ {
+ udp0 = (udp_header_t *) (ip0 + 1);
+
+ if (dhcp_client_port_network_order == udp0->dst_port)
+ {
+ next0 = DHCP_CLIENT_DETECT_NEXT_EXTRACT;
+ extractions++;
+ }
+ }
+
+ if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ dhcp_client_detect_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->extracted = (next0 == DHCP_CLIENT_DETECT_NEXT_EXTRACT);
+ }
+
+ /* verify speculative enqueue, maybe switch current next frame */
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+ to_next, n_left_to_next,
+ bi0, next0);
+ }
+
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ vlib_node_increment_counter (vm, node->node_index,
+ DHCP_CLIENT_DETECT_ERROR_EXTRACT, extractions);
+
+ return frame->n_vectors;
+}
+
+/* packet trace format function */
+static u8 *
+format_dhcp_client_detect_trace (u8 * s, va_list * args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ dhcp_client_detect_trace_t *t =
+ va_arg (*args, dhcp_client_detect_trace_t *);
+
+ s = format (s, "dhcp-client-detect: %s", (t->extracted ? "yes" : "no"));
+
+ return s;
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (dhcp_client_detect_node) = {
+ .function = dhcp_client_detect_node_fn,
+ .name = "ip4-dhcp-client-detect",
+ .vector_size = sizeof (u32),
+ .format_trace = format_dhcp_client_detect_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+
+ .n_errors = ARRAY_LEN(dhcp_client_detect_error_strings),
+ .error_strings = dhcp_client_detect_error_strings,
+
+ .n_next_nodes = DHCP_CLIENT_DETECT_N_NEXT,
+ .next_nodes = {
+ /*
+ * Jump straight to the UDP dispatch node thus avoiding
+ * the RPF checks in ip4-local that will fail
+ */
+ [DHCP_CLIENT_DETECT_NEXT_EXTRACT] = "ip4-udp-lookup",
+ },
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (dhcp_client_detect_node,
+ dhcp_client_detect_node_fn);
+
+VNET_FEATURE_INIT (ip4_dvr_reinject_feat_node, static) =
+{
+ .arc_name = "ip4-unicast",
+ .node_name = "ip4-dhcp-client-detect",
+ .runs_before = VNET_FEATURES ("ip4-drop"),
+};
+
+/* *INDENT-ON* */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vpp-api/vom/dhcp_config.cpp b/src/vpp-api/vom/dhcp_config.cpp
index 0b6e2eff0de..8071fb15c57 100644
--- a/src/vpp-api/vom/dhcp_config.cpp
+++ b/src/vpp-api/vom/dhcp_config.cpp
@@ -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)
{
}
diff --git a/src/vpp-api/vom/dhcp_config.hpp b/src/vpp-api/vom/dhcp_config.hpp
index db97af98c19..8ea608d809d 100644
--- a/src/vpp-api/vom/dhcp_config.hpp
+++ b/src/vpp-api/vom/dhcp_config.hpp
@@ -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
@@ -203,6 +206,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.
*/
diff --git a/src/vpp-api/vom/dhcp_config_cmds.cpp b/src/vpp-api/vom/dhcp_config_cmds.cpp
index ff24fe2f463..9e803be7b8d 100644
--- a/src/vpp-api/vom/dhcp_config_cmds.cpp
+++ b/src/vpp-api/vom/dhcp_config_cmds.cpp
@@ -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)
{
}
diff --git a/src/vpp-api/vom/dhcp_config_cmds.hpp b/src/vpp-api/vom/dhcp_config_cmds.hpp
index 863cf599b74..726ff992577 100644
--- a/src/vpp-api/vom/dhcp_config_cmds.hpp
+++ b/src/vpp-api/vom/dhcp_config_cmds.hpp
@@ -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;
};
/**
'>1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686