From 1855b8e48d95289cc9f0a6e339f2148d64ac705c Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Wed, 11 Jul 2018 10:31:26 -0700 Subject: [PATCH] IP directed broadcast with ip direct broadcast enable a packet to the interface's subnet broadcast address with be sent L2 broadcast on the interface. dissabled, it will be dropped. it is disabled by default, which preserves current behaviour Change-Id: If154cb92e64834e97a541b32624354348a0eafb3 Signed-off-by: Neale Ranns --- src/plugins/pppoe/pppoe.c | 1 + src/vnet/adj/adj.c | 8 ++++ src/vnet/adj/adj.h | 10 +++++ src/vnet/adj/adj_nbr.c | 5 +++ src/vnet/ethernet/arp.c | 9 ++++ src/vnet/interface.api | 14 ++++++ src/vnet/interface.c | 17 +++++++ src/vnet/interface.h | 36 +++++++++------ src/vnet/interface_api.c | 21 ++++++++- src/vnet/interface_cli.c | 40 +++++++++++++++++ src/vnet/interface_funcs.h | 4 +- src/vnet/ip/ip4.h | 2 + src/vnet/ip/ip4_forward.c | 105 +++++++++++++++++++++++++++++++++++++++++--- src/vnet/ip/ip6_forward.c | 28 +++++++++--- src/vnet/ip/ip6_neighbor.c | 8 ++++ src/vnet/mpls/mpls_tunnel.c | 1 + test/test_ip4.py | 69 +++++++++++++++++++++++++++++ test/vpp_papi_provider.py | 12 +++++ 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", \ @@ -131,6 +136,11 @@ typedef enum [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop", \ } +/** + * The special broadcast address (to construct a broadcast adjacency + */ +extern const ip46_address_t ADJ_BCAST_ADDR; + /** * Forward delcartion */ 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) @@ -163,6 +165,23 @@ vl_api_sw_interface_set_mtu_t_handler (vl_api_sw_interface_set_mtu_t * mp) REPLY_MACRO (VL_API_SW_INTERFACE_SET_MTU_REPLY); } +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, 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 @@ -1273,6 +1273,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 ", + .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 @@ -340,6 +340,45 @@ ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index, return result; } +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, @@ -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) = @@ -2521,6 +2595,16 @@ ip4_rewrite (vlib_main_t * vm, return ip4_rewrite_inline (vm, node, frame, 0, 0, 0); } +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 @@ -1943,6 +1943,16 @@ ip6_rewrite (vlib_main_t * vm, return ip6_rewrite_inline (vm, node, frame, 0, 0, 0); } +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): """ -- 2.16.6