summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/l2/l2.api7
-rw-r--r--src/vnet/l2/l2_api.c4
-rw-r--r--src/vnet/l2/l2_bd.c94
-rw-r--r--src/vnet/l2/l2_bd.h2
-rw-r--r--src/vnet/l2/l2_input.c5
-rw-r--r--src/vnet/l2/l2_input.h8
-rw-r--r--test/vpp_l2.py8
7 files changed, 118 insertions, 10 deletions
diff --git a/src/vnet/l2/l2.api b/src/vnet/l2/l2.api
index dc743763f70..1c2873fdf3c 100644
--- a/src/vnet/l2/l2.api
+++ b/src/vnet/l2/l2.api
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-option version = "2.1.2";
+option version = "2.2.2";
import "vnet/ip/ip_types.api";
import "vnet/ethernet/ethernet_types.api";
@@ -247,6 +247,7 @@ autoreply define bridge_domain_set_mac_age
@param forward - enable/disable forwarding on all interfaces in the bd
@param learn - enable/disable learning on all interfaces in the bd
@param arp_term - enable/disable arp termination in the bd
+ @param arp_ufwd - enable/disable arp unicast forwarding in the bd
@param mac_age - mac aging time in min, 0 for disabled
@param is_add - add or delete flag
*/
@@ -260,6 +261,7 @@ autoreply define bridge_domain_add_del
u8 forward;
u8 learn;
u8 arp_term;
+ u8 arp_ufwd;
u8 mac_age;
u8 bd_tag[64];
u8 is_add;
@@ -296,6 +298,7 @@ typeonly manual_print manual_endian define bridge_domain_sw_if
@param forward - forwarding state on all interfaces in the bd
@param learn - learning state on all interfaces in the bd
@param arp_term - arp termination state on all interfaces in the bd
+ @param arp_ufwd - arp unicast forwarding state on all interfaces in the bd
@param mac_age - mac aging time in min, 0 for disabled
@param bd_tag - optional textual tag for the bridge domain
@param n_sw_ifs - number of sw_if_index's in the domain
@@ -309,6 +312,7 @@ manual_print manual_endian define bridge_domain_details
u8 forward;
u8 learn;
u8 arp_term;
+ u8 arp_ufwd;
u8 mac_age;
u8 bd_tag[64];
u32 bvi_sw_if_index;
@@ -326,6 +330,7 @@ enum bd_flags
BRIDGE_API_FLAG_FLOOD = 0x4,
BRIDGE_API_FLAG_UU_FLOOD = 0x8,
BRIDGE_API_FLAG_ARP_TERM = 0x10,
+ BRIDGE_API_FLAG_ARP_UFWD = 0x20,
};
/** \brief Set bridge flags request
diff --git a/src/vnet/l2/l2_api.c b/src/vnet/l2/l2_api.c
index f60cd41bb39..b55c5d3744a 100644
--- a/src/vnet/l2/l2_api.c
+++ b/src/vnet/l2/l2_api.c
@@ -438,6 +438,7 @@ vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
.forward = mp->forward,
.learn = mp->learn,
.arp_term = mp->arp_term,
+ .arp_ufwd = mp->arp_ufwd,
.mac_age = mp->mac_age,
.bd_id = ntohl (mp->bd_id),
.bd_tag = mp->bd_tag
@@ -470,6 +471,7 @@ send_bridge_domain_details (l2input_main_t * l2im,
mp->forward = bd_feature_forward (bd_config);
mp->learn = bd_feature_learn (bd_config);
mp->arp_term = bd_feature_arp_term (bd_config);
+ mp->arp_ufwd = bd_feature_arp_ufwd (bd_config);
mp->bvi_sw_if_index = ntohl (bd_config->bvi_sw_if_index);
mp->uu_fwd_sw_if_index = ntohl (bd_config->uu_fwd_sw_if_index);
mp->mac_age = bd_config->mac_age;
@@ -552,6 +554,8 @@ bd_flags_decode (vl_api_bd_flags_t v)
f |= L2_UU_FLOOD;
if (v & BRIDGE_API_FLAG_ARP_TERM)
f |= L2_ARP_TERM;
+ if (v & BRIDGE_API_FLAG_ARP_UFWD)
+ f |= L2_ARP_UFWD;
return (f);
}
diff --git a/src/vnet/l2/l2_bd.c b/src/vnet/l2/l2_bd.c
index 4dd359ed0b7..207ef4d6601 100644
--- a/src/vnet/l2/l2_bd.c
+++ b/src/vnet/l2/l2_bd.c
@@ -52,7 +52,8 @@ bd_validate (l2_bridge_domain_t * bd_config)
{
if (bd_is_valid (bd_config))
return;
- bd_config->feature_bitmap = ~(L2INPUT_FEAT_ARP_TERM | L2INPUT_FEAT_UU_FWD);
+ bd_config->feature_bitmap =
+ ~(L2INPUT_FEAT_ARP_TERM | L2INPUT_FEAT_UU_FWD | L2INPUT_FEAT_ARP_UFWD);
bd_config->bvi_sw_if_index = ~0;
bd_config->uu_fwd_sw_if_index = ~0;
bd_config->members = 0;
@@ -275,6 +276,10 @@ bd_set_flags (vlib_main_t * vm, u32 bd_index, bd_flags_t flags, u32 enable)
{
feature_bitmap |= L2INPUT_FEAT_ARP_TERM;
}
+ if (flags & L2_ARP_UFWD)
+ {
+ feature_bitmap |= L2INPUT_FEAT_ARP_UFWD;
+ }
if (enable)
{
@@ -597,6 +602,71 @@ VLIB_CLI_COMMAND (bd_uu_flood_cli, static) = {
/* *INDENT-ON* */
/**
+ Set bridge-domain arp-unicast forward enable/disable.
+ The CLI format is:
+ set bridge-domain arp-ufwd <bd_index> [disable]
+*/
+static clib_error_t *
+bd_arp_ufwd (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ bd_main_t *bdm = &bd_main;
+ clib_error_t *error = 0;
+ u32 bd_index, bd_id;
+ u32 enable;
+ uword *p;
+
+ if (!unformat (input, "%d", &bd_id))
+ {
+ error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+
+ if (bd_id == 0)
+ return clib_error_return (0,
+ "No operations on the default bridge domain are supported");
+
+ p = hash_get (bdm->bd_index_by_bd_id, bd_id);
+
+ if (p == 0)
+ return clib_error_return (0, "No such bridge domain %d", bd_id);
+
+ bd_index = p[0];
+
+ enable = 1;
+ if (unformat (input, "disable"))
+ {
+ enable = 0;
+ }
+
+ /* set the bridge domain flag */
+ bd_set_flags (vm, bd_index, L2_ARP_UFWD, enable);
+
+done:
+ return error;
+}
+
+/*?
+ * Layer 2 arp-unicast forwarding can be enabled and disabled on each
+ * bridge-domain. It is disabled by default.
+ *
+ * @cliexpar
+ * Example of how to enable arp-unicast forwarding (where 200 is the
+ * bridge-domain-id):
+ * @cliexcmd{set bridge-domain arp-ufwd 200}
+ * Example of how to disable arp-unicast forwarding (where 200 is the bridge-domain-id):
+ * @cliexcmd{set bridge-domain arp-ufwd 200 disable}
+?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (bd_arp_ufwd_cli, static) = {
+ .path = "set bridge-domain arp-ufwd",
+ .short_help = "set bridge-domain arp-ufwd <bridge-domain-id> [disable]",
+ .function = bd_arp_ufwd,
+};
+/* *INDENT-ON* */
+
+/**
Set bridge-domain arp term enable/disable.
The CLI format is:
set bridge-domain arp term <bridge-domain-id> [disable]
@@ -1046,10 +1116,11 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
{
printed = 1;
vlib_cli_output (vm,
- "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s %=11s",
+ "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s %=9s %=11s",
"BD-ID", "Index", "BSN", "Age(min)",
"Learning", "U-Forwrd", "UU-Flood",
- "Flooding", "ARP-Term", "BVI-Intf");
+ "Flooding", "ARP-Term", "arp-ufwd",
+ "BVI-Intf");
}
if (bd_config->mac_age)
@@ -1057,7 +1128,7 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
else
as = format (as, "off");
vlib_cli_output (vm,
- "%=8d %=7d %=4d %=9v %=9s %=9s %=11U %=9s %=9s %=11U",
+ "%=8d %=7d %=4d %=9v %=9s %=9s %=11U %=9s %=9s %=9s %=11U",
bd_config->bd_id, bd_index, bd_config->seq_num, as,
bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ?
"on" : "off",
@@ -1068,6 +1139,8 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
"on" : "off",
bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ?
"on" : "off",
+ bd_config->feature_bitmap & L2INPUT_FEAT_ARP_UFWD ?
+ "on" : "off",
format_vnet_sw_if_index_name_with_NA,
vnm, bd_config->bvi_sw_if_index);
vec_reset_length (as);
@@ -1226,6 +1299,11 @@ bd_add_del (l2_bridge_domain_add_del_args_t * a)
else
disable_flags |= L2_ARP_TERM;
+ if (a->arp_ufwd)
+ enable_flags |= L2_ARP_UFWD;
+ else
+ disable_flags |= L2_ARP_UFWD;
+
if (enable_flags)
bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
@@ -1267,7 +1345,8 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
clib_error_t *error = 0;
u8 is_add = 1;
u32 bd_id = ~0;
- u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
+ u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term =
+ 0, arp_ufwd = 0;
u32 mac_age = 0;
u8 *bd_tag = NULL;
l2_bridge_domain_add_del_args_t _a, *a = &_a;
@@ -1291,6 +1370,8 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
;
else if (unformat (line_input, "arp-term %d", &arp_term))
;
+ else if (unformat (line_input, "arp-ufwd %d", &arp_ufwd))
+ ;
else if (unformat (line_input, "mac-age %d", &mac_age))
;
else if (unformat (line_input, "bd-tag %s", &bd_tag))
@@ -1335,6 +1416,7 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
a->forward = (u8) forward;
a->learn = (u8) learn;
a->arp_term = (u8) arp_term;
+ a->arp_ufwd = (u8) arp_ufwd;
a->mac_age = (u8) mac_age;
a->bd_tag = bd_tag;
@@ -1404,7 +1486,7 @@ VLIB_CLI_COMMAND (bd_create_cli, static) = {
.path = "create bridge-domain",
.short_help = "create bridge-domain <bridge-domain-id>"
" [learn <0|1>] [forward <0|1>] [uu-flood <0|1>] [flood <0|1>] [arp-term <0|1>]"
- " [mac-age <nn>] [bd-tag <tag>] [del]",
+ " [arp-ufwd <0|1>] [mac-age <nn>] [bd-tag <tag>] [del]",
.function = bd_add_del_command_fn,
};
/* *INDENT-ON* */
diff --git a/src/vnet/l2/l2_bd.h b/src/vnet/l2/l2_bd.h
index 65d3dadab28..360880839ec 100644
--- a/src/vnet/l2/l2_bd.h
+++ b/src/vnet/l2/l2_bd.h
@@ -123,6 +123,7 @@ typedef struct
u8 forward;
u8 learn;
u8 arp_term;
+ u8 arp_ufwd;
u8 mac_age;
u8 *bd_tag;
u8 is_add;
@@ -152,6 +153,7 @@ typedef enum bd_flags_t_
L2_FLOOD = (1 << 2),
L2_UU_FLOOD = (1 << 3),
L2_ARP_TERM = (1 << 4),
+ L2_ARP_UFWD = (1 << 5),
} bd_flags_t;
u32 bd_set_flags (vlib_main_t * vm, u32 bd_index, bd_flags_t flags,
diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c
index 704223a3d75..4efb5562806 100644
--- a/src/vnet/l2/l2_input.c
+++ b/src/vnet/l2/l2_input.c
@@ -196,11 +196,13 @@ classify_and_dispatch (l2input_main_t * msm, vlib_buffer_t * b0, u32 * next0)
L2INPUT_FEAT_UU_FLOOD |
L2INPUT_FEAT_UU_FWD | L2INPUT_FEAT_GBP_FWD);
+ if (ethertype != ETHERNET_TYPE_ARP)
+ feat_mask &= ~(L2INPUT_FEAT_ARP_UFWD);
+
/* Disable ARP-term for non-ARP and non-ICMP6 packet */
if (ethertype != ETHERNET_TYPE_ARP &&
(ethertype != ETHERNET_TYPE_IP6 || protocol != IP_PROTOCOL_ICMP6))
feat_mask &= ~(L2INPUT_FEAT_ARP_TERM);
-
/*
* For packet from BVI - set SHG of ARP request or ICMPv6 neighbor
* solicitation packet from BVI to 0 so it can also flood to VXLAN
@@ -705,6 +707,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */
L2INPUT_FEAT_UU_FWD |
L2INPUT_FEAT_FLOOD |
L2INPUT_FEAT_LEARN |
+ L2INPUT_FEAT_ARP_UFWD |
L2INPUT_FEAT_ARP_TERM);
/* Make sure last-chance drop is configured */
diff --git a/src/vnet/l2/l2_input.h b/src/vnet/l2/l2_input.h
index 93da1277e67..ce9a7d5f0cd 100644
--- a/src/vnet/l2/l2_input.h
+++ b/src/vnet/l2/l2_input.h
@@ -102,6 +102,7 @@ l2input_bd_config (u32 bd_index)
_(DROP, "feature-bitmap-drop") \
_(XCONNECT, "l2-output") \
_(FLOOD, "l2-flood") \
+ _(ARP_UFWD, "l2-uu-fwd") \
_(ARP_TERM, "arp-term-l2bd") \
_(UU_FLOOD, "l2-flood") \
_(GBP_FWD, "gbp-fwd") \
@@ -190,6 +191,13 @@ bd_feature_arp_term (l2_bridge_domain_t * bd_config)
L2INPUT_FEAT_ARP_TERM);
}
+static_always_inline u8
+bd_feature_arp_ufwd (l2_bridge_domain_t * bd_config)
+{
+ return ((bd_config->feature_bitmap & L2INPUT_FEAT_ARP_UFWD) ==
+ L2INPUT_FEAT_ARP_UFWD);
+}
+
/** Masks for eliminating features that do not apply to a packet */
/** Get a pointer to the config for the given interface */
diff --git a/test/vpp_l2.py b/test/vpp_l2.py
index 79c72e69051..90de91695f2 100644
--- a/test/vpp_l2.py
+++ b/test/vpp_l2.py
@@ -23,6 +23,7 @@ class BRIDGE_FLAGS:
FLOOD = 4
UU_FLOOD = 8
ARP_TERM = 16
+ ARP_UFWD = 32
def find_bridge_domain(test, bd_id):
@@ -70,7 +71,7 @@ class VppBridgeDomain(VppObject):
def __init__(self, test, bd_id,
flood=1, uu_flood=1, forward=1,
- learn=1, arp_term=1):
+ learn=1, arp_term=1, arp_ufwd=0):
self._test = test
self.bd_id = bd_id
self.flood = flood
@@ -78,6 +79,7 @@ class VppBridgeDomain(VppObject):
self.forward = forward
self.learn = learn
self.arp_term = arp_term
+ self.arp_ufwd = arp_ufwd
def add_vpp_config(self):
self._test.vapi.bridge_domain_add_del(bd_id=self.bd_id,
@@ -85,7 +87,9 @@ class VppBridgeDomain(VppObject):
uu_flood=self.uu_flood,
forward=self.forward,
learn=self.learn,
- arp_term=self.arp_term, is_add=1)
+ arp_term=self.arp_term,
+ arp_ufwd=self.arp_ufwd,
+ is_add=1)
self._test.registry.register(self, self._test.logger)
def remove_vpp_config(self):