Add support for API client to receive L2 MAC events

Added APIs want_l2_macs_events and l2_macs_event to allow an API
client to receive notification events from VPP for MAC learned
or aged in L2FIB. Only one API client is allowed for L2 MAC events.

The want_l2_macs_events API allow caller to specify MAC learn
limit, event scan delay and max number of MACs that can be included
in a event message. These parameters should be choosen properly as
to not have too many MAC events sent by VPP and overwhelm the API
share memory. They can all be left as 0's so VPP will setup reasonable
defaults which are: 1000 learn limit, 100 msec scan delay and 100
MACs per event message.

If want_l2_macs_events is never called, VPP learning and aging
should behave as before except that MAC entries provisioned by API
or CLI will not be aged, even if it is not set as static_mac. These
non static MACs, however, can be overwritten by MAC learning on a
MAC move as a leared MAC. Only learned MACs are subject to aging.

Change-Id: Ia3757a80cf8adb2811a089d2eafbd6439461285c
Signed-off-by: John Lo <loj@cisco.com>
This commit is contained in:
John Lo
2017-08-03 00:35:36 -04:00
committed by Neale Ranns
parent a825c8bf5c
commit 8d00fff8df
11 changed files with 605 additions and 173 deletions
+79 -7
View File
@@ -1283,6 +1283,30 @@ vl_api_ip6_nd_event_t_handler_json (vl_api_ip6_nd_event_t * mp)
/* JSON output not supported */
}
static void
vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp)
{
u32 n_macs = ntohl (mp->n_macs);
errmsg ("L2MAC event recived with pid %d cl-idx %d for %d macs: \n",
ntohl (mp->pid), mp->client_index, n_macs);
int i;
for (i = 0; i < n_macs; i++)
{
vl_api_mac_entry_t *mac = &mp->mac[i];
errmsg (" [%d] sw_if_index %d mac_addr %U is_del %d \n",
i + 1, ntohl (mac->sw_if_index),
format_ethernet_address, mac->mac_addr, mac->is_del);
if (i == 1000)
break;
}
}
static void
vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp)
{
/* JSON output not supported */
}
#define vl_api_bridge_domain_details_t_endian vl_noop_handler
#define vl_api_bridge_domain_details_t_print vl_noop_handler
@@ -4597,6 +4621,7 @@ _(modify_vhost_user_if_reply) \
_(delete_vhost_user_if_reply) \
_(want_ip4_arp_events_reply) \
_(want_ip6_nd_events_reply) \
_(want_l2_macs_events_reply) \
_(input_acl_set_interface_reply) \
_(ipsec_spd_add_del_reply) \
_(ipsec_interface_add_del_spd_reply) \
@@ -4813,6 +4838,8 @@ _(WANT_IP4_ARP_EVENTS_REPLY, want_ip4_arp_events_reply) \
_(IP4_ARP_EVENT, ip4_arp_event) \
_(WANT_IP6_ND_EVENTS_REPLY, want_ip6_nd_events_reply) \
_(IP6_ND_EVENT, ip6_nd_event) \
_(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply) \
_(L2_MACS_EVENT, l2_macs_event) \
_(INPUT_ACL_SET_INTERFACE_REPLY, input_acl_set_interface_reply) \
_(IP_ADDRESS_DETAILS, ip_address_details) \
_(IP_DETAILS, ip_details) \
@@ -6607,8 +6634,9 @@ api_l2_flags (vat_main_t * vam)
unformat_input_t *i = vam->input;
vl_api_l2_flags_t *mp;
u32 sw_if_index;
u32 feature_bitmap = 0;
u32 flags = 0;
u8 sw_if_index_set = 0;
u8 is_set = 0;
int ret;
/* Parse args required to build the message */
@@ -6628,13 +6656,19 @@ api_l2_flags (vat_main_t * vam)
break;
}
else if (unformat (i, "learn"))
feature_bitmap |= L2INPUT_FEAT_LEARN;
flags |= L2_LEARN;
else if (unformat (i, "forward"))
feature_bitmap |= L2INPUT_FEAT_FWD;
flags |= L2_FWD;
else if (unformat (i, "flood"))
feature_bitmap |= L2INPUT_FEAT_FLOOD;
flags |= L2_FLOOD;
else if (unformat (i, "uu-flood"))
feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
flags |= L2_UU_FLOOD;
else if (unformat (i, "arp-term"))
flags |= L2_ARP_TERM;
else if (unformat (i, "off"))
is_set = 0;
else if (unformat (i, "disable"))
is_set = 0;
else
break;
}
@@ -6648,7 +6682,8 @@ api_l2_flags (vat_main_t * vam)
M (L2_FLAGS, mp);
mp->sw_if_index = ntohl (sw_if_index);
mp->feature_bitmap = ntohl (feature_bitmap);
mp->feature_bitmap = ntohl (flags);
mp->is_set = is_set;
S (mp);
W (ret);
@@ -12534,6 +12569,42 @@ api_want_ip6_nd_events (vat_main_t * vam)
return ret;
}
static int
api_want_l2_macs_events (vat_main_t * vam)
{
unformat_input_t *line_input = vam->input;
vl_api_want_l2_macs_events_t *mp;
u8 enable_disable = 1;
u32 scan_delay = 0;
u32 max_macs_in_event = 0;
u32 learn_limit = 0;
int ret;
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
if (unformat (line_input, "learn-limit %d", &learn_limit))
;
else if (unformat (line_input, "scan-delay %d", &scan_delay))
;
else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
;
else if (unformat (line_input, "disable"))
enable_disable = 0;
else
break;
}
M (WANT_L2_MACS_EVENTS, mp);
mp->enable_disable = enable_disable;
mp->pid = htonl (getpid ());
mp->learn_limit = htonl (learn_limit);
mp->scan_delay = (u8) scan_delay;
mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
S (mp);
W (ret);
return ret;
}
static int
api_input_acl_set_interface (vat_main_t * vam)
{
@@ -19831,7 +19902,7 @@ _(l2fib_add_del, \
_(l2fib_flush_bd, "bd_id <bridge-domain-id>") \
_(l2fib_flush_int, "<intfc> | sw_if_index <id>") \
_(l2_flags, \
"sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood]\n") \
"sw_if <intfc> | sw_if_index <id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
_(bridge_flags, \
"bd_id <bridge-domain-id> [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \
_(tap_connect, \
@@ -19974,6 +20045,7 @@ _(input_acl_set_interface, \
" [l2-table <nn>] [del]") \
_(want_ip4_arp_events, "address <ip4-address> [del]") \
_(want_ip6_nd_events, "address <ip6-address> [del]") \
_(want_l2_macs_events, "[disable] [learn-limit <n>] [scan-delay <n>] [max-entries <n>]") \
_(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)") \
_(ip_dump, "ipv4 | ipv6") \
_(ipsec_spd_add_del, "spd_id <n> [del]") \
+3 -2
View File
@@ -112,8 +112,9 @@ _(BD_ALREADY_EXISTS, -119, "Bridge domain already exists") \
_(BD_IN_USE, -120, "Bridge domain has member interfaces") \
_(BD_NOT_MODIFIABLE, -121, "Bridge domain 0 can't be deleted/modified") \
_(BD_ID_EXCEED_MAX, -122, "Bridge domain ID exceed 16M limit") \
_(UNSUPPORTED, -123, "Unsupported") \
_(SUBIF_DOESNT_EXIST, -124, "Subinterface doesn't exist")
_(SUBIF_DOESNT_EXIST, -123, "Subinterface doesn't exist") \
_(L2_MACS_EVENT_CLINET_PRESENT, -124, "Client already exist for L2 MACs events") \
_(UNSUPPORTED, -125, "Unsupported")
typedef enum
{
+59 -6
View File
@@ -133,12 +133,64 @@ autoreply define l2fib_add_del
u8 bvi_mac;
};
/** \brief Set L2 flags request !!! TODO - need more info, feature bits in l2_input.h
/** \brief Register to recive L2 MAC events for leanred and aged MAC
Will also change MAC learn limit to L2LEARN_INFORM_LIMIT
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param learn_limit - MAC learn limit, 0 => default to 1000
@param scan_delay - event scan delay in 10 msec unit, 0 => default to 100 msec
@param max_macs_in_event - in units of 10 mac entries, 0 => default to 100 entries
@param enable_disable - 1 => register for MAC events, 0 => cancel registration
@param pid - sender's pid
*/
autoreply define want_l2_macs_events
{
u32 client_index;
u32 context;
u32 learn_limit;
u8 scan_delay;
u8 max_macs_in_event;
u8 enable_disable;
u32 pid;
};
/** \brief Entry for learned or aged MAC in L2 MAC Events
@param sw_if_index - sw_if_index in the domain
@param mac_addr - mac_address
@is_del - 0 => newly learned MAC, 1 => aged out MAC
*/
typeonly define mac_entry
{
u32 sw_if_index;
u8 mac_addr[6];
u8 is_del;
u8 spare;
};
/** \brief L2 MAC event for a list of learned or aged MACs
@param client_index - opaque cookie to identify the sender
@param pid - client pid registered to receive notification
@param n_macs - number of learned/aged MAC enntries
@param mac - array of learned/aged MAC entries
*/
define l2_macs_event
{
u32 client_index;
u32 pid;
u32 n_macs;
vl_api_mac_entry_t mac[n_macs];
};
/** \brief Set interface L2 flags (such as L2_LEARN, L2_FWD,
L2_FLOOD, L2_UU_FLOOD, or L2_ARP_TERM bits). This can be used
to disable one or more of the features represented by the
flag bits on an interface to override what is set as default
for all interfaces in the bridge domain
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param sw_if_index - interface
@param is_set - if non-zero, set the bits, else clear them
@param feature_bitmap - non-zero bits to set or clear
@param feature_bitmap - non-zero bits (as above) to set or clear
*/
define l2_flags
{
@@ -149,9 +201,10 @@ define l2_flags
u32 feature_bitmap;
};
/** \brief Set L2 bits response
/** \brief Set interface L2 flags response
@param context - sender context, to match reply w/ request
@param retval - return code for the set l2 bits request
@param resulting_feature_bitmap - the internal l2 feature bitmap after the request is implemented
*/
define l2_flags_reply
{
@@ -250,12 +303,12 @@ manual_print manual_endian define bridge_domain_details
};
/** \brief Set bridge flags (such as L2_LEARN, L2_FWD, L2_FLOOD,
L2_UU_FLOOD, or L2_ARP_TERM) request
L2_UU_FLOOD, or L2_ARP_TERM bits) request
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param bd_id - the bridge domain to set the flags for
@param is_set - if non-zero, set the flags, else clear them
@param feature_bitmap - bits that are non-zero to set or clear
@param feature_bitmap - bits (as above) that are non-zero to set or clear
*/
define bridge_flags
{
@@ -269,7 +322,7 @@ define bridge_flags
/** \brief Set bridge flags response
@param context - sender context, to match reply w/ request
@param retval - return code for the set bridge flags request
@param resulting_feature_bitmap - the feature bitmap value after the request is implemented
@param resulting_feature_bitmap - the internal L2 feature bitmap after the request is implemented
*/
define bridge_flags_reply
{
+77 -6
View File
@@ -25,6 +25,7 @@
#include <vnet/l2/l2_input.h>
#include <vnet/l2/l2_fib.h>
#include <vnet/l2/l2_vtr.h>
#include <vnet/l2/l2_learn.h>
#include <vnet/vnet_msg_enum.h>
@@ -55,6 +56,7 @@ _(L2FIB_FLUSH_ALL, l2fib_flush_all) \
_(L2FIB_FLUSH_INT, l2fib_flush_int) \
_(L2FIB_FLUSH_BD, l2fib_flush_bd) \
_(L2FIB_ADD_DEL, l2fib_add_del) \
_(WANT_L2_MACS_EVENTS, want_l2_macs_events) \
_(L2_FLAGS, l2_flags) \
_(BRIDGE_DOMAIN_ADD_DEL, bridge_domain_add_del) \
_(BRIDGE_DOMAIN_DUMP, bridge_domain_dump) \
@@ -221,8 +223,8 @@ vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
goto bad_sw_if_index;
}
}
u32 static_mac = mp->static_mac ? 1 : 0;
u32 bvi_mac = mp->bvi_mac ? 1 : 0;
u8 static_mac = mp->static_mac ? 1 : 0;
u8 bvi_mac = mp->bvi_mac ? 1 : 0;
l2fib_add_fwd_entry (mac, bd_index, sw_if_index, static_mac,
bvi_mac);
}
@@ -237,6 +239,58 @@ vl_api_l2fib_add_del_t_handler (vl_api_l2fib_add_del_t * mp)
REPLY_MACRO (VL_API_L2FIB_ADD_DEL_REPLY);
}
static void
vl_api_want_l2_macs_events_t_handler (vl_api_want_l2_macs_events_t * mp)
{
int rv = 0;
vl_api_want_l2_macs_events_reply_t *rmp;
l2learn_main_t *lm = &l2learn_main;
l2fib_main_t *fm = &l2fib_main;
u32 pid = ntohl (mp->pid);
u32 learn_limit = ntohl (mp->learn_limit);
if (mp->enable_disable)
{
if (lm->client_pid == 0)
{
lm->client_pid = pid;
lm->client_index = mp->client_index;
if (mp->max_macs_in_event)
fm->max_macs_in_event = mp->max_macs_in_event * 10;
else
fm->max_macs_in_event = L2FIB_EVENT_MAX_MACS_DEFAULT;
if (mp->scan_delay)
fm->event_scan_delay = (f64) (mp->scan_delay) * 10e-3;
else
fm->event_scan_delay = L2FIB_EVENT_SCAN_DELAY_DEFAULT;
/* change learn limit and flush all learned MACs */
if (learn_limit && (learn_limit < L2LEARN_DEFAULT_LIMIT))
lm->global_learn_limit = learn_limit;
else
lm->global_learn_limit = L2FIB_EVENT_LEARN_LIMIT_DEFAULT;
l2fib_flush_all_mac (vlib_get_main ());
}
else if (lm->client_pid != pid)
{
rv = VNET_API_ERROR_L2_MACS_EVENT_CLINET_PRESENT;
goto exit;
}
}
else if (lm->client_pid)
{
lm->client_pid = 0;
lm->client_index = 0;
lm->global_learn_limit = L2LEARN_DEFAULT_LIMIT;
}
exit:
REPLY_MACRO (VL_API_WANT_L2_MACS_EVENTS_REPLY);
}
static void
vl_api_l2fib_flush_int_t_handler (vl_api_l2fib_flush_int_t * mp)
{
@@ -293,8 +347,25 @@ vl_api_l2_flags_t_handler (vl_api_l2_flags_t * mp)
VALIDATE_SW_IF_INDEX (mp);
u32 sw_if_index = ntohl (mp->sw_if_index);
u32 flags = ntohl (mp->feature_bitmap) & L2INPUT_VALID_MASK;
rbm = l2input_intf_bitmap_enable (sw_if_index, flags, mp->is_set);
u32 flags = ntohl (mp->feature_bitmap);
u32 bitmap = 0;
if (flags & L2_LEARN)
bitmap |= L2INPUT_FEAT_LEARN;
if (flags & L2_FWD)
bitmap |= L2INPUT_FEAT_FWD;
if (flags & L2_FLOOD)
bitmap |= L2INPUT_FEAT_FLOOD;
if (flags & L2_UU_FLOOD)
bitmap |= L2INPUT_FEAT_UU_FLOOD;
if (flags & L2_ARP_TERM)
bitmap |= L2INPUT_FEAT_ARP_TERM;
rbm = l2input_intf_bitmap_enable (sw_if_index, bitmap, mp->is_set);
BAD_SW_IF_INDEX_LABEL;
@@ -455,13 +526,13 @@ vl_api_bridge_flags_t_handler (vl_api_bridge_flags_t * mp)
goto out;
}
bd_set_flags (vm, bd_index, flags, mp->is_set);
u32 bitmap = bd_set_flags (vm, bd_index, flags, mp->is_set);
out:
/* *INDENT-OFF* */
REPLY_MACRO2(VL_API_BRIDGE_FLAGS_REPLY,
({
rmp->resulting_feature_bitmap = ntohl(flags);
rmp->resulting_feature_bitmap = ntohl(bitmap);
}));
/* *INDENT-ON* */
}
+6 -31
View File
@@ -263,7 +263,7 @@ bd_set_flags (vlib_main_t * vm, u32 bd_index, u32 flags, u32 enable)
bd_config->feature_bitmap &= ~feature_bitmap;
}
return 0;
return bd_config->feature_bitmap;
}
/**
@@ -328,12 +328,7 @@ bd_learn (vlib_main_t * vm,
}
/* set the bridge domain flag */
if (bd_set_flags (vm, bd_index, L2_LEARN, enable))
{
error =
clib_error_return (0, "bridge-domain id %d out of range", bd_index);
goto done;
}
bd_set_flags (vm, bd_index, L2_LEARN, enable);
done:
return error;
@@ -397,12 +392,7 @@ bd_fwd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
}
/* set the bridge domain flag */
if (bd_set_flags (vm, bd_index, L2_FWD, enable))
{
error =
clib_error_return (0, "bridge-domain id %d out of range", bd_index);
goto done;
}
bd_set_flags (vm, bd_index, L2_FWD, enable);
done:
return error;
@@ -468,12 +458,7 @@ bd_flood (vlib_main_t * vm,
}
/* set the bridge domain flag */
if (bd_set_flags (vm, bd_index, L2_FLOOD, enable))
{
error =
clib_error_return (0, "bridge-domain id %d out of range", bd_index);
goto done;
}
bd_set_flags (vm, bd_index, L2_FLOOD, enable);
done:
return error;
@@ -538,12 +523,7 @@ bd_uu_flood (vlib_main_t * vm,
}
/* set the bridge domain flag */
if (bd_set_flags (vm, bd_index, L2_UU_FLOOD, enable))
{
error =
clib_error_return (0, "bridge-domain id %d out of range", bd_index);
goto done;
}
bd_set_flags (vm, bd_index, L2_UU_FLOOD, enable);
done:
return error;
@@ -605,12 +585,7 @@ bd_arp_term (vlib_main_t * vm,
enable = 0;
/* set the bridge domain flag */
if (bd_set_flags (vm, bd_index, L2_ARP_TERM, enable))
{
error =
clib_error_return (0, "bridge-domain id %d out of range", bd_index);
goto done;
}
bd_set_flags (vm, bd_index, L2_ARP_TERM, enable);
done:
return error;
+294 -100
View File
File diff suppressed because it is too large Load Diff
+31 -6
View File
@@ -27,6 +27,18 @@
#define L2FIB_NUM_BUCKETS (64 * 1024)
#define L2FIB_MEMORY_SIZE (256<<20)
/* Ager scan interval is 1 minute for aging */
#define L2FIB_AGE_SCAN_INTERVAL (60.0)
/* MAC event scan delay is 100 msec unless specified by MAC event client */
#define L2FIB_EVENT_SCAN_DELAY_DEFAULT (0.1)
/* Max MACs in a event message is 100 unless specified by MAC event client */
#define L2FIB_EVENT_MAX_MACS_DEFAULT (100)
/* MAC event learn limit is 1000 unless specified by MAC event client */
#define L2FIB_EVENT_LEARN_LIMIT_DEFAULT (1000)
typedef struct
{
@@ -36,6 +48,16 @@ typedef struct
/* per swif vector of sequence number for interface based flush of MACs */
u8 *swif_seq_num;
/* last event or ager scan duration */
f64 evt_scan_duration;
f64 age_scan_duration;
/* delay between event scans, default to 100 msec */
f64 event_scan_delay;
/* max macs in evet message, default to 100 entries */
u32 max_macs_in_event;
/* convenience variables */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
@@ -89,12 +111,15 @@ typedef struct
{
struct
{
u32 sw_if_index; /* output sw_if_index (L3 interface if bvi==1) */
u32 sw_if_index; /* output sw_if_index (L3 intf if bvi==1) */
u8 static_mac:1; /* static mac, no dataplane learning */
u8 static_mac:1; /* static mac, no MAC move */
u8 age_not:1; /* not subject to age */
u8 bvi:1; /* mac is for a bridged virtual interface */
u8 filter:1; /* drop packets to/from this mac */
u8 unused1:5;
u8 lrn_evt:1; /* MAC learned to be sent in L2 MAC event */
u8 unused:3;
u8 timestamp; /* timestamp for aging */
l2fib_seq_num_t sn; /* bd/int seq num */
} fields;
@@ -348,11 +373,11 @@ void l2fib_clear_table (void);
void
l2fib_add_entry (u64 mac,
u32 bd_index,
u32 sw_if_index, u32 static_mac, u32 drop_mac, u32 bvi_mac);
u32 sw_if_index, u8 static_mac, u8 drop_mac, u8 bvi_mac);
static inline void
l2fib_add_fwd_entry (u64 mac, u32 bd_index, u32 sw_if_index, u32 static_mac,
u32 bvi_mac)
l2fib_add_fwd_entry (u64 mac, u32 bd_index, u32 sw_if_index, u8 static_mac,
u8 bvi_mac)
{
l2fib_add_entry (mac, bd_index, sw_if_index, static_mac, 0, bvi_mac);
}
+2 -1
View File
@@ -141,8 +141,9 @@ l2fwd_process (vlib_main_t * vm,
vnet_buffer (b0)->sw_if_index[VLIB_TX] = result0->fields.sw_if_index;
*next0 = L2FWD_NEXT_L2_OUTPUT;
int l2fib_seq_num_valid = 1;
/* check l2fib seq num for stale entries */
if (!result0->fields.static_mac)
if (!result0->fields.age_not)
{
l2fib_seq_num_t in_sn = {.as_u16 = vnet_buffer (b0)->l2.l2fib_sn };
l2fib_seq_num_t expected_sn = {
+20 -10
View File
@@ -123,11 +123,9 @@ l2learn_process (vlib_node_runtime_t * node,
/* Check mac table lookup result */
if (PREDICT_TRUE (result0->fields.sw_if_index == sw_if_index0))
{
/*
* The entry was in the table, and the sw_if_index matched, the normal case
*/
/* Entry in L2FIB with matching sw_if_index matched - normal fast path */
counter_base[L2LEARN_ERROR_HIT] += 1;
int update = !result0->fields.static_mac &&
int update = !result0->fields.age_not && /* static_mac always age_not */
(result0->fields.timestamp != timestamp ||
result0->fields.sn.as_u16 != vnet_buffer (b0)->l2.l2fib_sn);
@@ -136,10 +134,10 @@ l2learn_process (vlib_node_runtime_t * node,
}
else if (result0->raw == ~0)
{
/* The entry was not in table, so add it */
/* Entry not in L2FIB - add it */
counter_base[L2LEARN_ERROR_MISS] += 1;
if (msm->global_learn_count == msm->global_learn_limit)
if (msm->global_learn_count >= msm->global_learn_limit)
{
/*
* Global limit reached. Do not learn the mac but forward the packet.
@@ -149,15 +147,22 @@ l2learn_process (vlib_node_runtime_t * node,
return;
}
/* Do not learn if mac is 0 */
l2fib_entry_key_t key = *key0;
key.fields.bd_index = 0;
if (key.raw == 0)
return;
/* It is ok to learn */
msm->global_learn_count++;
result0->raw = 0; /* clear all fields */
result0->fields.sw_if_index = sw_if_index0;
result0->fields.lrn_evt = (msm->client_pid != 0);
cached_key->raw = ~0; /* invalidate the cache */
}
else
{
/* The entry was in the table, but with the wrong sw_if_index mapping (mac move) */
/* Entry in L2FIB with different sw_if_index - mac move or filter */
if (result0->fields.filter)
{
ASSERT (result0->fields.sw_if_index == ~0);
@@ -167,8 +172,6 @@ l2learn_process (vlib_node_runtime_t * node,
return;
}
counter_base[L2LEARN_ERROR_MAC_MOVE] += 1;
if (result0->fields.static_mac)
{
/*
@@ -185,6 +188,13 @@ l2learn_process (vlib_node_runtime_t * node,
* TODO: check global/bridge domain/interface learn limits
*/
result0->fields.sw_if_index = sw_if_index0;
if (result0->fields.age_not) /* The mac was provisioned */
{
msm->global_learn_count++;
result0->fields.age_not = 0;
}
result0->fields.lrn_evt = (msm->client_pid != 0);
counter_base[L2LEARN_ERROR_MAC_MOVE] += 1;
}
/* Update the entry */
@@ -479,7 +489,7 @@ VLIB_NODE_FUNCTION_MULTIARCH (l2learn_node, l2learn_node_fn)
* Set the default number of dynamically learned macs to the number
* of buckets.
*/
mp->global_learn_limit = L2FIB_NUM_BUCKETS * 16;
mp->global_learn_limit = L2LEARN_DEFAULT_LIMIT;
return 0;
}
+5
View File
@@ -34,6 +34,10 @@ typedef struct
/* maximum number of dynamically learned mac entries */
u32 global_learn_limit;
/* client waiting for L2 MAC events for learned and aged MACs */
u32 client_pid;
u32 client_index;
/* Next nodes for each feature */
u32 feat_next_node_index[32];
@@ -42,6 +46,7 @@ typedef struct
vnet_main_t *vnet_main;
} l2learn_main_t;
#define L2LEARN_DEFAULT_LIMIT (L2FIB_NUM_BUCKETS * 16)
l2learn_main_t l2learn_main;
+29 -4
View File
@@ -373,10 +373,19 @@ vl_api_l2_flags_t_print (vl_api_l2_flags_t * mp, void *handle)
s = format (s, "sw_if_index %d ", ntohl (mp->sw_if_index));
#define _(a,b) \
if (flags & L2INPUT_FEAT_ ## a) s = format (s, #a " ");
foreach_l2input_feat;
#undef _
if (flags & L2_LEARN)
s = format (s, "learn ");
if (flags & L2_FWD)
s = format (s, "forward ");
if (flags & L2_FLOOD)
s = format (s, "flood ");
if (flags & L2_UU_FLOOD)
s = format (s, "uu-flood ");
if (flags & L2_ARP_TERM)
s = format (s, "arp-term ");
if (mp->is_set == 0)
s = format (s, "clear ");
FINISH;
}
@@ -1783,6 +1792,21 @@ static void *vl_api_want_ip6_nd_events_t_print
FINISH;
}
static void *vl_api_want_l2_macs_events_t_print
(vl_api_want_l2_macs_events_t * mp, void *handle)
{
u8 *s;
s = format (0, "SCRIPT: want_l2_macs_events ");
s = format (s, "learn-limit %d ", ntohl (mp->learn_limit));
s = format (s, "scan-delay %d ", (u32) mp->scan_delay);
s = format (s, "max-entries %d ", (u32) mp->max_macs_in_event * 10);
if (mp->enable_disable == 0)
s = format (s, "disable");
FINISH;
}
static void *vl_api_input_acl_set_interface_t_print
(vl_api_input_acl_set_interface_t * mp, void *handle)
{
@@ -3066,6 +3090,7 @@ _(VXLAN_GPE_TUNNEL_DUMP, vxlan_gpe_tunnel_dump) \
_(INTERFACE_NAME_RENUMBER, interface_name_renumber) \
_(WANT_IP4_ARP_EVENTS, want_ip4_arp_events) \
_(WANT_IP6_ND_EVENTS, want_ip6_nd_events) \
_(WANT_L2_MACS_EVENTS, want_l2_macs_events) \
_(INPUT_ACL_SET_INTERFACE, input_acl_set_interface) \
_(IP_ADDRESS_DUMP, ip_address_dump) \
_(IP_DUMP, ip_dump) \