summaryrefslogtreecommitdiffstats
path: root/src/vnet/ip
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet/ip')
-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
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:
{
/*