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:

committed by
Damjan Marion

parent
631de0dffe
commit
1855b8e48d
@ -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,
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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),
|
||||||
|
@ -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:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user