aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/pppoe/pppoe.c1
-rw-r--r--src/vnet/adj/adj.c8
-rw-r--r--src/vnet/adj/adj.h10
-rw-r--r--src/vnet/adj/adj_nbr.c5
-rw-r--r--src/vnet/ethernet/arp.c9
-rw-r--r--src/vnet/interface.api14
-rw-r--r--src/vnet/interface.c17
-rw-r--r--src/vnet/interface.h36
-rw-r--r--src/vnet/interface_api.c21
-rw-r--r--src/vnet/interface_cli.c40
-rw-r--r--src/vnet/interface_funcs.h4
-rw-r--r--src/vnet/ip/ip4.h2
-rw-r--r--src/vnet/ip/ip4_forward.c105
-rw-r--r--src/vnet/ip/ip6_forward.c28
-rw-r--r--src/vnet/ip/ip6_neighbor.c8
-rw-r--r--src/vnet/mpls/mpls_tunnel.c1
-rw-r--r--test/test_ip4.py69
-rw-r--r--test/vpp_papi_provider.py12
18 files changed, 361 insertions, 29 deletions
diff --git a/src/plugins/pppoe/pppoe.c b/src/plugins/pppoe/pppoe.c
index dfbe2e487c9..e5ab5d0c013 100644
--- a/src/plugins/pppoe/pppoe.c
+++ b/src/plugins/pppoe/pppoe.c
@@ -184,6 +184,7 @@ pppoe_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
{
case IP_LOOKUP_NEXT_ARP:
case IP_LOOKUP_NEXT_GLEAN:
+ case IP_LOOKUP_NEXT_BCAST:
adj_nbr_midchain_update_rewrite (ai, pppoe_fixup, t,
ADJ_FLAG_NONE,
pppoe_build_rewrite (vnm,
diff --git a/src/vnet/adj/adj.c b/src/vnet/adj/adj.c
index 0de3fc8b775..80a5d05aaf4 100644
--- a/src/vnet/adj/adj.c
+++ b/src/vnet/adj/adj.c
@@ -35,6 +35,13 @@ ip_adjacency_t *adj_pool;
*/
int adj_per_adj_counters;
+const ip46_address_t ADJ_BCAST_ADDR = {
+ .ip6 = {
+ .as_u64[0] = 0xffffffffffffffff,
+ .as_u64[1] = 0xffffffffffffffff,
+ },
+};
+
always_inline void
adj_poison (ip_adjacency_t * adj)
{
@@ -172,6 +179,7 @@ adj_last_lock_gone (ip_adjacency_t *adj)
/* FALL THROUGH */
case IP_LOOKUP_NEXT_ARP:
case IP_LOOKUP_NEXT_REWRITE:
+ case IP_LOOKUP_NEXT_BCAST:
/*
* complete and incomplete nbr adjs
*/
diff --git a/src/vnet/adj/adj.h b/src/vnet/adj/adj.h
index fe77d1634e0..18a2e1ddbbb 100644
--- a/src/vnet/adj/adj.h
+++ b/src/vnet/adj/adj.h
@@ -81,6 +81,9 @@ typedef enum
/** Multicast Adjacency. */
IP_LOOKUP_NEXT_MCAST,
+ /** Broadcasr Adjacency. */
+ IP_LOOKUP_NEXT_BCAST,
+
/** Multicast Midchain Adjacency. An Adjacency for sending macst packets
* on a tunnel/virtual interface */
IP_LOOKUP_NEXT_MCAST_MIDCHAIN,
@@ -110,6 +113,7 @@ typedef enum
[IP_LOOKUP_NEXT_GLEAN] = "ip4-glean", \
[IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite", \
[IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast", \
+ [IP_LOOKUP_NEXT_BCAST] = "ip4-rewrite-bcast", \
[IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain", \
[IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain", \
[IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \
@@ -122,6 +126,7 @@ typedef enum
[IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor", \
[IP_LOOKUP_NEXT_GLEAN] = "ip6-glean", \
[IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite", \
+ [IP_LOOKUP_NEXT_BCAST] = "ip6-rewrite-bcast", \
[IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast", \
[IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain", \
[IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip6-mcast-midchain", \
@@ -132,6 +137,11 @@ typedef enum
}
/**
+ * The special broadcast address (to construct a broadcast adjacency
+ */
+extern const ip46_address_t ADJ_BCAST_ADDR;
+
+/**
* Forward delcartion
*/
struct ip_adjacency_t_;
diff --git a/src/vnet/adj/adj_nbr.c b/src/vnet/adj/adj_nbr.c
index 3f66acbb5c5..3a474a8e199 100644
--- a/src/vnet/adj/adj_nbr.c
+++ b/src/vnet/adj/adj_nbr.c
@@ -230,6 +230,11 @@ adj_nbr_add_or_lock (fib_protocol_t nh_proto,
adj_index = adj_get_index(adj);
adj_lock(adj_index);
+ if (ip46_address_is_equal(&ADJ_BCAST_ADDR, nh_addr))
+ {
+ adj->lookup_next_index = IP_LOOKUP_NEXT_BCAST;
+ }
+
vnet_rewrite_init(vnm, sw_if_index, link_type,
adj_get_nd_node(nh_proto),
vnet_tx_node_index_for_sw_interface(vnm, sw_if_index),
diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c
index 09f5661f435..f7d8ff867f8 100644
--- a/src/vnet/ethernet/arp.c
+++ b/src/vnet/ethernet/arp.c
@@ -492,6 +492,15 @@ arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
arp_nbr_probe (adj);
}
break;
+ case IP_LOOKUP_NEXT_BCAST:
+ adj_nbr_update_rewrite (ai,
+ ADJ_NBR_REWRITE_FLAG_COMPLETE,
+ ethernet_build_rewrite
+ (vnm,
+ sw_if_index,
+ VNET_LINK_IP4,
+ VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
+ break;
case IP_LOOKUP_NEXT_MCAST:
{
/*
diff --git a/src/vnet/interface.api b/src/vnet/interface.api
index 2cbf4f68dbc..b839e898bf2 100644
--- a/src/vnet/interface.api
+++ b/src/vnet/interface.api
@@ -45,6 +45,20 @@ autoreply define sw_interface_set_mtu
u32 mtu[4]; /* 0 - L3, 1 - IP4, 2 - IP6, 3 - MPLS */
};
+/** \brief Set IP4 directed broadcast
+ The directed broadcast enabled a packet sent to the interface's
+ subnet address will be broadcast on the interface
+ @param sw_if_index
+ @param enable
+*/
+autoreply define sw_interface_set_ip_directed_broadcast
+{
+ u32 client_index;
+ u32 context;
+ u32 sw_if_index;
+ u8 enable;
+};
+
/** \brief Interface Event generated by want_interface_events
@param client_index - opaque cookie to identify the sender
diff --git a/src/vnet/interface.c b/src/vnet/interface.c
index a9346a2b072..ca4dc493aac 100644
--- a/src/vnet/interface.c
+++ b/src/vnet/interface.c
@@ -705,6 +705,22 @@ vnet_sw_interface_set_protocol_mtu (vnet_main_t * vnm, u32 sw_if_index,
call_sw_interface_mtu_change_callbacks (vnm, sw_if_index);
}
+void
+vnet_sw_interface_ip_directed_broadcast (vnet_main_t * vnm,
+ u32 sw_if_index, u8 enable)
+{
+ vnet_sw_interface_t *si;
+
+ si = vnet_get_sw_interface (vnm, sw_if_index);
+
+ if (enable)
+ si->flags |= VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST;
+ else
+ si->flags &= ~VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST;
+
+ ip4_directed_broadcast (sw_if_index, enable);
+}
+
/*
* Reflect a change in hardware MTU on protocol MTUs
*/
@@ -1609,6 +1625,7 @@ default_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
adj_glean_update_rewrite (ai);
break;
case IP_LOOKUP_NEXT_ARP:
+ case IP_LOOKUP_NEXT_BCAST:
/*
* default rewirte in neighbour adj
*/
diff --git a/src/vnet/interface.h b/src/vnet/interface.h
index f82cf9d2485..d869b0c70a2 100644
--- a/src/vnet/interface.h
+++ b/src/vnet/interface.h
@@ -648,32 +648,40 @@ typedef enum
extern vnet_mtu_t vnet_link_to_mtu (vnet_link_t link);
-/* Software-interface. This corresponds to a Ethernet VLAN, ATM vc, a
- tunnel, etc. Configuration (e.g. IP address) gets attached to
- software interface. */
-typedef struct
+typedef enum vnet_sw_interface_flags_t_
{
- vnet_sw_interface_type_t type:16;
-
- u16 flags;
/* Interface is "up" meaning adminstratively up.
Up in the sense of link state being up is maintained by hardware interface. */
-#define VNET_SW_INTERFACE_FLAG_ADMIN_UP (1 << 0)
+ VNET_SW_INTERFACE_FLAG_ADMIN_UP = (1 << 0),
/* Interface is disabled for forwarding: punt all traffic to slow-path. */
-#define VNET_SW_INTERFACE_FLAG_PUNT (1 << 1)
+ VNET_SW_INTERFACE_FLAG_PUNT = (1 << 1),
-#define VNET_SW_INTERFACE_FLAG_PROXY_ARP (1 << 2)
+ VNET_SW_INTERFACE_FLAG_PROXY_ARP = (1 << 2),
-#define VNET_SW_INTERFACE_FLAG_UNNUMBERED (1 << 3)
+ VNET_SW_INTERFACE_FLAG_UNNUMBERED = (1 << 3),
-#define VNET_SW_INTERFACE_FLAG_BOND_SLAVE (1 << 4)
+ VNET_SW_INTERFACE_FLAG_BOND_SLAVE = (1 << 4),
/* Interface does not appear in CLI/API */
-#define VNET_SW_INTERFACE_FLAG_HIDDEN (1 << 5)
+ VNET_SW_INTERFACE_FLAG_HIDDEN = (1 << 5),
/* Interface in ERROR state */
-#define VNET_SW_INTERFACE_FLAG_ERROR (1 << 6)
+ VNET_SW_INTERFACE_FLAG_ERROR = (1 << 6),
+
+ /* Interface has IP configured directed broadcast */
+ VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST = (1 << 7),
+
+} __attribute__ ((packed)) vnet_sw_interface_flags_t;
+
+/* Software-interface. This corresponds to a Ethernet VLAN, ATM vc, a
+ tunnel, etc. Configuration (e.g. IP address) gets attached to
+ software interface. */
+typedef struct
+{
+ vnet_sw_interface_type_t type:16;
+
+ vnet_sw_interface_flags_t flags;
/* Index for this interface. */
u32 sw_if_index;
diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c
index e2f4d8fd130..1d167c680fe 100644
--- a/src/vnet/interface_api.c
+++ b/src/vnet/interface_api.c
@@ -70,7 +70,9 @@ _(CREATE_LOOPBACK, create_loopback) \
_(CREATE_LOOPBACK_INSTANCE, create_loopback_instance) \
_(DELETE_LOOPBACK, delete_loopback) \
_(INTERFACE_NAME_RENUMBER, interface_name_renumber) \
-_(COLLECT_DETAILED_INTERFACE_STATS, collect_detailed_interface_stats)
+_(COLLECT_DETAILED_INTERFACE_STATS, collect_detailed_interface_stats) \
+_(SW_INTERFACE_SET_IP_DIRECTED_BROADCAST, \
+ sw_interface_set_ip_directed_broadcast)
static void
vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp)
@@ -164,6 +166,23 @@ vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp)
}
static void
+ vl_api_sw_interface_set_ip_directed_broadcast_t_handler
+ (vl_api_sw_interface_set_ip_directed_broadcast_t * mp)
+{
+ vl_api_sw_interface_set_ip_directed_broadcast_reply_t *rmp;
+ u32 sw_if_index = ntohl (mp->sw_if_index);
+ int rv = 0;
+
+ VALIDATE_SW_IF_INDEX (mp);
+
+ vnet_sw_interface_ip_directed_broadcast (vnet_get_main (),
+ sw_if_index, mp->enable);
+
+ BAD_SW_IF_INDEX_LABEL;
+ REPLY_MACRO (VL_API_SW_INTERFACE_SET_IP_DIRECTED_BROADCAST_REPLY);
+}
+
+static void
send_sw_interface_details (vpe_api_main_t * am,
vl_api_registration_t * rp,
vnet_sw_interface_t * swif,
diff --git a/src/vnet/interface_cli.c b/src/vnet/interface_cli.c
index 264c1f34e18..91725b6a688 100644
--- a/src/vnet/interface_cli.c
+++ b/src/vnet/interface_cli.c
@@ -1274,6 +1274,46 @@ VLIB_CLI_COMMAND (clear_tag_command, static) = {
/* *INDENT-ON* */
static clib_error_t *
+set_ip_directed_broadcast (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ u32 sw_if_index = ~0;
+ u8 enable = 0;
+
+ if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index));
+ else if (unformat (input, "enable"))
+ enable = 1;
+ else if (unformat (input, "disable"))
+ enable = 0;
+ else
+ return clib_error_return (0, "unknown input: `%U'",
+ format_unformat_error, input);
+
+ if (~0 == sw_if_index)
+ return clib_error_return (0, "specify an interface: `%U'",
+ format_unformat_error, input);
+
+ vnet_sw_interface_ip_directed_broadcast (vnm, sw_if_index, enable);
+
+ return 0;
+}
+
+/*?
+ * This command is used to enable/disable IP directed broadcast
+ * If directed broadcast is enabled a packet sent to the interface's
+ * subnet broadcast address will be sent L2 broadcast on the interface,
+ * otherwise it is dropped.
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (set_ip_directed_broadcast_command, static) = {
+ .path = "set interface ip directed-broadcast",
+ .short_help = "set interface enable <interface> <enable|disable>",
+ .function = set_ip_directed_broadcast,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
set_hw_interface_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
u32 queue_id, vnet_hw_interface_rx_mode mode)
{
diff --git a/src/vnet/interface_funcs.h b/src/vnet/interface_funcs.h
index 206bfbe0e96..a8a41e364f4 100644
--- a/src/vnet/interface_funcs.h
+++ b/src/vnet/interface_funcs.h
@@ -224,7 +224,7 @@ void vnet_delete_hw_interface (vnet_main_t * vnm, u32 hw_if_index);
void vnet_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index);
int vnet_sw_interface_is_p2p (vnet_main_t * vnm, u32 sw_if_index);
-always_inline uword
+always_inline vnet_sw_interface_flags_t
vnet_sw_interface_get_flags (vnet_main_t * vnm, u32 sw_if_index)
{
vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, sw_if_index);
@@ -368,6 +368,8 @@ void vnet_sw_interface_update_unnumbered (u32 sw_if_index,
int vnet_sw_interface_stats_collect_enable_disable (u32 sw_if_index,
u8 enable);
+void vnet_sw_interface_ip_directed_broadcast (vnet_main_t * vnm,
+ u32 sw_if_index, u8 enable);
/* Formats sw/hw interface. */
format_function_t format_vnet_hw_interface;
diff --git a/src/vnet/ip/ip4.h b/src/vnet/ip/ip4.h
index 8187a9dd0e2..fcef559010c 100644
--- a/src/vnet/ip/ip4.h
+++ b/src/vnet/ip/ip4.h
@@ -245,6 +245,8 @@ clib_error_t *ip4_add_del_interface_address (vlib_main_t * vm,
ip4_address_t * address,
u32 address_length, u32 is_del);
+void ip4_directed_broadcast (u32 sw_if_index, u8 enable);
+
void ip4_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable);
int ip4_address_compare (ip4_address_t * a1, ip4_address_t * a2);
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index fd8559d9986..000710ed817 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -341,6 +341,45 @@ ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index,
}
static void
+ip4_add_subnet_bcast_route (u32 fib_index,
+ fib_prefix_t *pfx,
+ u32 sw_if_index)
+{
+ vnet_sw_interface_flags_t iflags;
+
+ iflags = vnet_sw_interface_get_flags(vnet_get_main(), sw_if_index);
+
+ fib_table_entry_special_remove(fib_index,
+ pfx,
+ FIB_SOURCE_INTERFACE);
+
+ if (iflags & VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST)
+ {
+ fib_table_entry_update_one_path (fib_index, pfx,
+ FIB_SOURCE_INTERFACE,
+ FIB_ENTRY_FLAG_NONE,
+ DPO_PROTO_IP4,
+ /* No next-hop address */
+ &ADJ_BCAST_ADDR,
+ sw_if_index,
+ // invalid FIB index
+ ~0,
+ 1,
+ // no out-label stack
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ }
+ else
+ {
+ fib_table_entry_special_add(fib_index,
+ pfx,
+ FIB_SOURCE_INTERFACE,
+ (FIB_ENTRY_FLAG_DROP |
+ FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT));
+ }
+}
+
+static void
ip4_add_interface_routes (u32 sw_if_index,
ip4_main_t * im, u32 fib_index,
ip_interface_address_t * a)
@@ -385,11 +424,7 @@ ip4_add_interface_routes (u32 sw_if_index,
FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT));
net_pfx.fp_addr.ip4.as_u32 |= ~im->fib_masks[pfx.fp_len];
if (net_pfx.fp_addr.ip4.as_u32 != pfx.fp_addr.ip4.as_u32)
- fib_table_entry_special_add(fib_index,
- &net_pfx,
- FIB_SOURCE_INTERFACE,
- (FIB_ENTRY_FLAG_DROP |
- FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT));
+ ip4_add_subnet_bcast_route(fib_index, &net_pfx, sw_if_index);
}
else if (pfx.fp_len == 31)
{
@@ -637,6 +672,45 @@ ip4_add_del_interface_address (vlib_main_t * vm,
(vm, sw_if_index, address, address_length, is_del);
}
+void
+ip4_directed_broadcast (u32 sw_if_index, u8 enable)
+{
+ ip_interface_address_t *ia;
+ ip4_main_t *im;
+
+ im = &ip4_main;
+
+ /*
+ * when directed broadcast is enabled, the subnet braodcast route will forward
+ * packets using an adjacency with a broadcast MAC. otherwise it drops
+ */
+ /* *INDENT-OFF* */
+ foreach_ip_interface_address(&im->lookup_main, ia,
+ sw_if_index, 0,
+ ({
+ if (ia->address_length <= 30)
+ {
+ ip4_address_t *ipa;
+
+ ipa = ip_interface_address_get_address (&im->lookup_main, ia);
+
+ fib_prefix_t pfx = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr = {
+ .ip4.as_u32 = (ipa->as_u32 | ~im->fib_masks[ia->address_length]),
+ },
+ };
+
+ ip4_add_subnet_bcast_route
+ (fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4,
+ sw_if_index),
+ &pfx, sw_if_index);
+ }
+ }));
+ /* *INDENT-ON* */
+}
+
/* Built-in ip4 unicast rx feature path definition */
/* *INDENT-OFF* */
VNET_FEATURE_ARC_INIT (ip4_unicast, static) =
@@ -2522,6 +2596,16 @@ ip4_rewrite (vlib_main_t * vm,
}
static uword
+ip4_rewrite_bcast (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * frame)
+{
+ if (adj_are_counters_enabled ())
+ return ip4_rewrite_inline (vm, node, frame, 1, 0, 0);
+ else
+ return ip4_rewrite_inline (vm, node, frame, 0, 0, 0);
+}
+
+static uword
ip4_midchain (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
@@ -2566,7 +2650,16 @@ VLIB_REGISTER_NODE (ip4_rewrite_node) = {
[IP4_REWRITE_NEXT_FRAGMENT] = "ip4-frag",
},
};
-VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_node, ip4_rewrite)
+
+VLIB_REGISTER_NODE (ip4_rewrite_bcast_node) = {
+ .function = ip4_rewrite,
+ .name = "ip4-rewrite-bcast",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_ip4_rewrite_trace,
+ .sibling_of = "ip4-rewrite",
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_bcast_node, ip4_rewrite_bcast)
VLIB_REGISTER_NODE (ip4_rewrite_mcast_node) = {
.function = ip4_rewrite_mcast,
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 41f5b151a09..888b52643c1 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -1944,6 +1944,16 @@ ip6_rewrite (vlib_main_t * vm,
}
static uword
+ip6_rewrite_bcast (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * frame)
+{
+ if (adj_are_counters_enabled ())
+ return ip6_rewrite_inline (vm, node, frame, 1, 0, 0);
+ else
+ return ip6_rewrite_inline (vm, node, frame, 0, 0, 0);
+}
+
+static uword
ip6_rewrite_mcast (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
{
@@ -1982,11 +1992,9 @@ VLIB_REGISTER_NODE (ip6_midchain_node) =
.format_trace = format_ip6_forward_next_trace,
.sibling_of = "ip6-rewrite",
};
-/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_midchain_node, ip6_midchain);
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_rewrite_node) =
{
.function = ip6_rewrite,
@@ -2001,11 +2009,19 @@ VLIB_REGISTER_NODE (ip6_rewrite_node) =
[IP6_REWRITE_NEXT_FRAGMENT] = "ip6-frag",
},
};
-/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_node, ip6_rewrite);
-/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (ip6_rewrite_bcast_node) = {
+ .function = ip6_rewrite,
+ .name = "ip6-rewrite-bcast",
+ .vector_size = sizeof (u32),
+
+ .format_trace = format_ip6_rewrite_trace,
+ .sibling_of = "ip6-rewrite",
+};
+VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_bcast_node, ip6_rewrite_bcast)
+
VLIB_REGISTER_NODE (ip6_rewrite_mcast_node) =
{
.function = ip6_rewrite_mcast,
@@ -2014,11 +2030,9 @@ VLIB_REGISTER_NODE (ip6_rewrite_mcast_node) =
.format_trace = format_ip6_rewrite_trace,
.sibling_of = "ip6-rewrite",
};
-/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_mcast_node, ip6_rewrite_mcast);
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_mcast_midchain_node, static) =
{
.function = ip6_mcast_midchain,
@@ -2027,9 +2041,9 @@ VLIB_REGISTER_NODE (ip6_mcast_midchain_node, static) =
.format_trace = format_ip6_rewrite_trace,
.sibling_of = "ip6-rewrite",
};
-/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_mcast_midchain_node, ip6_mcast_midchain);
+/* *INDENT-ON* */
/*
* Hop-by-Hop handling
diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c
index a6227fc413a..7c7a7069e89 100644
--- a/src/vnet/ip/ip6_neighbor.c
+++ b/src/vnet/ip/ip6_neighbor.c
@@ -662,6 +662,14 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
ip6_nbr_probe (adj);
}
break;
+ case IP_LOOKUP_NEXT_BCAST:
+ adj_nbr_update_rewrite (ai,
+ ADJ_NBR_REWRITE_FLAG_COMPLETE,
+ ethernet_build_rewrite (vnm,
+ sw_if_index,
+ VNET_LINK_IP6,
+ VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
+ break;
case IP_LOOKUP_NEXT_MCAST:
{
/*
diff --git a/src/vnet/mpls/mpls_tunnel.c b/src/vnet/mpls/mpls_tunnel.c
index a142edf3f0a..d3faeac6a0d 100644
--- a/src/vnet/mpls/mpls_tunnel.c
+++ b/src/vnet/mpls/mpls_tunnel.c
@@ -399,6 +399,7 @@ mpls_tunnel_update_adj (vnet_main_t * vnm,
{
case IP_LOOKUP_NEXT_ARP:
case IP_LOOKUP_NEXT_GLEAN:
+ case IP_LOOKUP_NEXT_BCAST:
adj_nbr_midchain_update_rewrite(ai, mpls_tunnel_fixup,
NULL,
ADJ_FLAG_NONE,
diff --git a/test/test_ip4.py b/test/test_ip4.py
index 2d98ed5297b..e501bff3fec 100644
--- a/test/test_ip4.py
+++ b/test/test_ip4.py
@@ -1392,5 +1392,74 @@ class TestIPInput(VppTestCase):
# Reset MTU for subsequent tests
self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0])
+
+class TestIPDirectedBroadcast(VppTestCase):
+ """ IPv4 Directed Broadcast """
+
+ def setUp(self):
+ super(TestIPDirectedBroadcast, self).setUp()
+
+ self.create_pg_interfaces(range(2))
+
+ for i in self.pg_interfaces:
+ i.admin_up()
+
+ def tearDown(self):
+ super(TestIPDirectedBroadcast, self).tearDown()
+ for i in self.pg_interfaces:
+ i.admin_down()
+
+ def test_ip_input(self):
+ """ IP Directed Broadcast """
+
+ #
+ # set the directed broadcast on pg0 first, then config IP4 addresses
+ # for pg1 directed broadcast is always disabled
+ self.vapi.sw_interface_set_ip_directed_broadcast(
+ self.pg0.sw_if_index, 1)
+
+ p0 = (Ether(src=self.pg1.remote_mac,
+ dst=self.pg1.local_mac) /
+ IP(src="1.1.1.1",
+ dst=self.pg0._local_ip4_bcast) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 2000))
+ p1 = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg0.local_mac) /
+ IP(src="1.1.1.1",
+ dst=self.pg1._local_ip4_bcast) /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 2000))
+
+ self.pg0.config_ip4()
+ self.pg0.resolve_arp()
+ self.pg1.config_ip4()
+ self.pg1.resolve_arp()
+
+ #
+ # test packet is L2 broadcast
+ #
+ rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
+ self.assertTrue(rx[0][Ether].dst, "ff:ff:ff:ff:ff:ff")
+
+ self.send_and_assert_no_replies(self.pg0, p1 * 65,
+ "directed broadcast disabled")
+
+ #
+ # toggle directed broadcast on pg0
+ #
+ self.vapi.sw_interface_set_ip_directed_broadcast(
+ self.pg0.sw_if_index, 0)
+ self.send_and_assert_no_replies(self.pg1, p0 * 65,
+ "directed broadcast disabled")
+
+ self.vapi.sw_interface_set_ip_directed_broadcast(
+ self.pg0.sw_if_index, 1)
+ rx = self.send_and_expect(self.pg1, p0 * 65, self.pg0)
+
+ self.pg0.unconfig_ip4()
+ self.pg1.unconfig_ip4()
+
+
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 5383b07fc4c..6ea1d2f3b3a 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -720,6 +720,18 @@ class VppPapiProvider(object):
{'sw_if_index': sw_if_index,
'enable': enable})
+ def sw_interface_set_ip_directed_broadcast(
+ self,
+ sw_if_index,
+ enable=1):
+ """IP Directed broadcast
+ :param sw_if_index - interface the operation is applied to
+
+ """
+ return self.api(self.papi.sw_interface_set_ip_directed_broadcast,
+ {'sw_if_index': sw_if_index,
+ 'enable': enable})
+
def sw_interface_set_flags(self, sw_if_index, admin_up_down):
"""