diff options
Diffstat (limited to 'src/vnet/ip')
-rw-r--r-- | src/vnet/ip/ip4.h | 2 | ||||
-rw-r--r-- | src/vnet/ip/ip4_forward.c | 105 | ||||
-rw-r--r-- | src/vnet/ip/ip6_forward.c | 28 | ||||
-rw-r--r-- | src/vnet/ip/ip6_neighbor.c | 8 |
4 files changed, 130 insertions, 13 deletions
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: { /* |