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 <nranns@cisco.com>
This commit is contained in:
Neale Ranns
2018-07-11 10:31:26 -07:00
committed by Damjan Marion
parent 631de0dffe
commit 1855b8e48d
18 changed files with 366 additions and 34 deletions

View File

@ -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_ARP:
case IP_LOOKUP_NEXT_GLEAN: case IP_LOOKUP_NEXT_GLEAN:
case IP_LOOKUP_NEXT_BCAST:
adj_nbr_midchain_update_rewrite (ai, pppoe_fixup, t, adj_nbr_midchain_update_rewrite (ai, pppoe_fixup, t,
ADJ_FLAG_NONE, ADJ_FLAG_NONE,
pppoe_build_rewrite (vnm, pppoe_build_rewrite (vnm,

View File

@ -35,6 +35,13 @@ ip_adjacency_t *adj_pool;
*/ */
int adj_per_adj_counters; int adj_per_adj_counters;
const ip46_address_t ADJ_BCAST_ADDR = {
.ip6 = {
.as_u64[0] = 0xffffffffffffffff,
.as_u64[1] = 0xffffffffffffffff,
},
};
always_inline void always_inline void
adj_poison (ip_adjacency_t * adj) adj_poison (ip_adjacency_t * adj)
{ {
@ -172,6 +179,7 @@ adj_last_lock_gone (ip_adjacency_t *adj)
/* FALL THROUGH */ /* FALL THROUGH */
case IP_LOOKUP_NEXT_ARP: case IP_LOOKUP_NEXT_ARP:
case IP_LOOKUP_NEXT_REWRITE: case IP_LOOKUP_NEXT_REWRITE:
case IP_LOOKUP_NEXT_BCAST:
/* /*
* complete and incomplete nbr adjs * complete and incomplete nbr adjs
*/ */

View File

@ -81,6 +81,9 @@ typedef enum
/** Multicast Adjacency. */ /** Multicast Adjacency. */
IP_LOOKUP_NEXT_MCAST, IP_LOOKUP_NEXT_MCAST,
/** Broadcasr Adjacency. */
IP_LOOKUP_NEXT_BCAST,
/** Multicast Midchain Adjacency. An Adjacency for sending macst packets /** Multicast Midchain Adjacency. An Adjacency for sending macst packets
* on a tunnel/virtual interface */ * on a tunnel/virtual interface */
IP_LOOKUP_NEXT_MCAST_MIDCHAIN, IP_LOOKUP_NEXT_MCAST_MIDCHAIN,
@ -110,6 +113,7 @@ typedef enum
[IP_LOOKUP_NEXT_GLEAN] = "ip4-glean", \ [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean", \
[IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite", \ [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite", \
[IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast", \ [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast", \
[IP_LOOKUP_NEXT_BCAST] = "ip4-rewrite-bcast", \
[IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain", \ [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain", \
[IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain", \ [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain", \
[IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \ [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \
@ -122,6 +126,7 @@ typedef enum
[IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor", \ [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor", \
[IP_LOOKUP_NEXT_GLEAN] = "ip6-glean", \ [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean", \
[IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite", \ [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite", \
[IP_LOOKUP_NEXT_BCAST] = "ip6-rewrite-bcast", \
[IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast", \ [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast", \
[IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain", \ [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain", \
[IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip6-mcast-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", \ [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 * Forward delcartion
*/ */

View File

@ -230,6 +230,11 @@ adj_nbr_add_or_lock (fib_protocol_t nh_proto,
adj_index = adj_get_index(adj); adj_index = adj_get_index(adj);
adj_lock(adj_index); 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, vnet_rewrite_init(vnm, sw_if_index, link_type,
adj_get_nd_node(nh_proto), adj_get_nd_node(nh_proto),
vnet_tx_node_index_for_sw_interface(vnm, sw_if_index), vnet_tx_node_index_for_sw_interface(vnm, sw_if_index),

View File

@ -492,6 +492,15 @@ arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
arp_nbr_probe (adj); arp_nbr_probe (adj);
} }
break; 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: case IP_LOOKUP_NEXT_MCAST:
{ {
/* /*

View File

@ -45,6 +45,20 @@ autoreply define sw_interface_set_mtu
u32 mtu[4]; /* 0 - L3, 1 - IP4, 2 - IP6, 3 - MPLS */ 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 /** \brief Interface Event generated by want_interface_events
@param client_index - opaque cookie to identify the sender @param client_index - opaque cookie to identify the sender

View File

@ -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); 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 * 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); adj_glean_update_rewrite (ai);
break; break;
case IP_LOOKUP_NEXT_ARP: case IP_LOOKUP_NEXT_ARP:
case IP_LOOKUP_NEXT_BCAST:
/* /*
* default rewirte in neighbour adj * default rewirte in neighbour adj
*/ */

View File

@ -648,6 +648,32 @@ typedef enum
extern vnet_mtu_t vnet_link_to_mtu (vnet_link_t link); extern vnet_mtu_t vnet_link_to_mtu (vnet_link_t link);
typedef enum vnet_sw_interface_flags_t_
{
/* Interface is "up" meaning adminstratively up.
Up in the sense of link state being up is maintained by hardware interface. */
VNET_SW_INTERFACE_FLAG_ADMIN_UP = (1 << 0),
/* Interface is disabled for forwarding: punt all traffic to slow-path. */
VNET_SW_INTERFACE_FLAG_PUNT = (1 << 1),
VNET_SW_INTERFACE_FLAG_PROXY_ARP = (1 << 2),
VNET_SW_INTERFACE_FLAG_UNNUMBERED = (1 << 3),
VNET_SW_INTERFACE_FLAG_BOND_SLAVE = (1 << 4),
/* Interface does not appear in CLI/API */
VNET_SW_INTERFACE_FLAG_HIDDEN = (1 << 5),
/* Interface in ERROR state */
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 /* Software-interface. This corresponds to a Ethernet VLAN, ATM vc, a
tunnel, etc. Configuration (e.g. IP address) gets attached to tunnel, etc. Configuration (e.g. IP address) gets attached to
software interface. */ software interface. */
@ -655,25 +681,7 @@ typedef struct
{ {
vnet_sw_interface_type_t type:16; vnet_sw_interface_type_t type:16;
u16 flags; vnet_sw_interface_flags_t 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)
/* Interface is disabled for forwarding: punt all traffic to slow-path. */
#define VNET_SW_INTERFACE_FLAG_PUNT (1 << 1)
#define VNET_SW_INTERFACE_FLAG_PROXY_ARP (1 << 2)
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED (1 << 3)
#define VNET_SW_INTERFACE_FLAG_BOND_SLAVE (1 << 4)
/* Interface does not appear in CLI/API */
#define VNET_SW_INTERFACE_FLAG_HIDDEN (1 << 5)
/* Interface in ERROR state */
#define VNET_SW_INTERFACE_FLAG_ERROR (1 << 6)
/* Index for this interface. */ /* Index for this interface. */
u32 sw_if_index; u32 sw_if_index;

View File

@ -70,7 +70,9 @@ _(CREATE_LOOPBACK, create_loopback) \
_(CREATE_LOOPBACK_INSTANCE, create_loopback_instance) \ _(CREATE_LOOPBACK_INSTANCE, create_loopback_instance) \
_(DELETE_LOOPBACK, delete_loopback) \ _(DELETE_LOOPBACK, delete_loopback) \
_(INTERFACE_NAME_RENUMBER, interface_name_renumber) \ _(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 static void
vl_api_sw_interface_set_flags_t_handler (vl_api_sw_interface_set_flags_t * mp) 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); 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 static void
send_sw_interface_details (vpe_api_main_t * am, send_sw_interface_details (vpe_api_main_t * am,
vl_api_registration_t * rp, vl_api_registration_t * rp,

View File

@ -1273,6 +1273,46 @@ VLIB_CLI_COMMAND (clear_tag_command, static) = {
}; };
/* *INDENT-ON* */ /* *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 * static clib_error_t *
set_hw_interface_rx_mode (vnet_main_t * vnm, u32 hw_if_index, set_hw_interface_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
u32 queue_id, vnet_hw_interface_rx_mode mode) u32 queue_id, vnet_hw_interface_rx_mode mode)

View File

@ -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); 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); 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_get_flags (vnet_main_t * vnm, u32 sw_if_index)
{ {
vnet_sw_interface_t *sw = vnet_get_sw_interface (vnm, 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, int vnet_sw_interface_stats_collect_enable_disable (u32 sw_if_index,
u8 enable); u8 enable);
void vnet_sw_interface_ip_directed_broadcast (vnet_main_t * vnm,
u32 sw_if_index, u8 enable);
/* Formats sw/hw interface. */ /* Formats sw/hw interface. */
format_function_t format_vnet_hw_interface; format_function_t format_vnet_hw_interface;

View File

@ -245,6 +245,8 @@ clib_error_t *ip4_add_del_interface_address (vlib_main_t * vm,
ip4_address_t * address, ip4_address_t * address,
u32 address_length, u32 is_del); 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); 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); int ip4_address_compare (ip4_address_t * a1, ip4_address_t * a2);

View File

@ -340,6 +340,45 @@ ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index,
return result; 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 static void
ip4_add_interface_routes (u32 sw_if_index, ip4_add_interface_routes (u32 sw_if_index,
ip4_main_t * im, u32 fib_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)); FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT));
net_pfx.fp_addr.ip4.as_u32 |= ~im->fib_masks[pfx.fp_len]; 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) if (net_pfx.fp_addr.ip4.as_u32 != pfx.fp_addr.ip4.as_u32)
fib_table_entry_special_add(fib_index, ip4_add_subnet_bcast_route(fib_index, &net_pfx, sw_if_index);
&net_pfx,
FIB_SOURCE_INTERFACE,
(FIB_ENTRY_FLAG_DROP |
FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT));
} }
else if (pfx.fp_len == 31) 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); (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 */ /* Built-in ip4 unicast rx feature path definition */
/* *INDENT-OFF* */ /* *INDENT-OFF* */
VNET_FEATURE_ARC_INIT (ip4_unicast, static) = 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); 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 static uword
ip4_midchain (vlib_main_t * vm, ip4_midchain (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame) 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", [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) = { VLIB_REGISTER_NODE (ip4_rewrite_mcast_node) = {
.function = ip4_rewrite_mcast, .function = ip4_rewrite_mcast,

View File

@ -1943,6 +1943,16 @@ ip6_rewrite (vlib_main_t * vm,
return ip6_rewrite_inline (vm, node, frame, 0, 0, 0); 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 static uword
ip6_rewrite_mcast (vlib_main_t * vm, ip6_rewrite_mcast (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame) 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, .format_trace = format_ip6_forward_next_trace,
.sibling_of = "ip6-rewrite", .sibling_of = "ip6-rewrite",
}; };
/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_midchain_node, ip6_midchain); VLIB_NODE_FUNCTION_MULTIARCH (ip6_midchain_node, ip6_midchain);
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_rewrite_node) = VLIB_REGISTER_NODE (ip6_rewrite_node) =
{ {
.function = ip6_rewrite, .function = ip6_rewrite,
@ -2001,11 +2009,19 @@ VLIB_REGISTER_NODE (ip6_rewrite_node) =
[IP6_REWRITE_NEXT_FRAGMENT] = "ip6-frag", [IP6_REWRITE_NEXT_FRAGMENT] = "ip6-frag",
}, },
}; };
/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_node, ip6_rewrite); 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) = VLIB_REGISTER_NODE (ip6_rewrite_mcast_node) =
{ {
.function = ip6_rewrite_mcast, .function = ip6_rewrite_mcast,
@ -2014,11 +2030,9 @@ VLIB_REGISTER_NODE (ip6_rewrite_mcast_node) =
.format_trace = format_ip6_rewrite_trace, .format_trace = format_ip6_rewrite_trace,
.sibling_of = "ip6-rewrite", .sibling_of = "ip6-rewrite",
}; };
/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_mcast_node, ip6_rewrite_mcast); VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_mcast_node, ip6_rewrite_mcast);
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (ip6_mcast_midchain_node, static) = VLIB_REGISTER_NODE (ip6_mcast_midchain_node, static) =
{ {
.function = ip6_mcast_midchain, .function = ip6_mcast_midchain,
@ -2027,9 +2041,9 @@ VLIB_REGISTER_NODE (ip6_mcast_midchain_node, static) =
.format_trace = format_ip6_rewrite_trace, .format_trace = format_ip6_rewrite_trace,
.sibling_of = "ip6-rewrite", .sibling_of = "ip6-rewrite",
}; };
/* *INDENT-ON* */
VLIB_NODE_FUNCTION_MULTIARCH (ip6_mcast_midchain_node, ip6_mcast_midchain); VLIB_NODE_FUNCTION_MULTIARCH (ip6_mcast_midchain_node, ip6_mcast_midchain);
/* *INDENT-ON* */
/* /*
* Hop-by-Hop handling * Hop-by-Hop handling

View File

@ -662,6 +662,14 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
ip6_nbr_probe (adj); ip6_nbr_probe (adj);
} }
break; 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: case IP_LOOKUP_NEXT_MCAST:
{ {
/* /*

View File

@ -399,6 +399,7 @@ mpls_tunnel_update_adj (vnet_main_t * vnm,
{ {
case IP_LOOKUP_NEXT_ARP: case IP_LOOKUP_NEXT_ARP:
case IP_LOOKUP_NEXT_GLEAN: case IP_LOOKUP_NEXT_GLEAN:
case IP_LOOKUP_NEXT_BCAST:
adj_nbr_midchain_update_rewrite(ai, mpls_tunnel_fixup, adj_nbr_midchain_update_rewrite(ai, mpls_tunnel_fixup,
NULL, NULL,
ADJ_FLAG_NONE, ADJ_FLAG_NONE,

View File

@ -1392,5 +1392,74 @@ class TestIPInput(VppTestCase):
# Reset MTU for subsequent tests # Reset MTU for subsequent tests
self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0]) 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__': if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner) unittest.main(testRunner=VppTestRunner)

View File

@ -720,6 +720,18 @@ class VppPapiProvider(object):
{'sw_if_index': sw_if_index, {'sw_if_index': sw_if_index,
'enable': enable}) '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): def sw_interface_set_flags(self, sw_if_index, admin_up_down):
""" """