IP-MAC,ND:wildcard events,fix sending multiple events

wildcard ND events publisher was sending the last event mutiple times

Change-Id: I6c30f2de03fa825e79df9005a3cfaaf68ff7ea2f
Signed-off-by: Eyal Bari <ebari@cisco.com>
This commit is contained in:
Eyal Bari
2017-09-20 11:29:17 +03:00
committed by John Lo
parent 03add7f5b5
commit c125eccc10
8 changed files with 288 additions and 103 deletions
+1
View File
@@ -216,6 +216,7 @@ _(to_netconf_client) \
_(from_netconf_client) \
_(oam_events) \
_(bfd_events) \
_(wc_ip6_nd_events) \
_(wc_ip4_arp_events)
typedef struct
+8 -4
View File
@@ -94,6 +94,7 @@ typedef struct
ethernet_proxy_arp_t *proxy_arps;
uword wc_ip4_arp_publisher_node;
uword wc_ip4_arp_publisher_et;
} ethernet_arp_main_t;
static ethernet_arp_main_t ethernet_arp_main;
@@ -1536,21 +1537,24 @@ vnet_arp_wc_publish_internal (vnet_main_t * vnm,
{
vlib_main_t *vm = vlib_get_main ();
ethernet_arp_main_t *am = &ethernet_arp_main;
if (am->wc_ip4_arp_publisher_node == (uword) ~ 0)
uword ni = am->wc_ip4_arp_publisher_node;
uword et = am->wc_ip4_arp_publisher_et;
if (ni == (uword) ~ 0)
return;
wc_arp_report_t *r =
vlib_process_signal_event_data (vm, am->wc_ip4_arp_publisher_node, 1, 1,
sizeof *r);
vlib_process_signal_event_data (vm, ni, et, 1, sizeof *r);
r->ip4 = args->a.ip4.as_u32;
r->sw_if_index = args->sw_if_index;
memcpy (r->mac, args->a.ethernet, sizeof r->mac);
}
void
wc_arp_set_publisher_node (uword node_index)
wc_arp_set_publisher_node (uword node_index, uword event_type)
{
ethernet_arp_main_t *am = &ethernet_arp_main;
am->wc_ip4_arp_publisher_node = node_index;
am->wc_ip4_arp_publisher_et = event_type;
}
/*
+1 -1
View File
@@ -543,7 +543,7 @@ int vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm,
uword type_opaque,
uword data, int is_add);
void wc_arp_set_publisher_node (uword inode_index);
void wc_arp_set_publisher_node (uword inode_index, uword event_type);
void ethernet_arp_change_mac (u32 sw_if_index);
void ethernet_ndp_change_mac (u32 sw_if_index);
+53 -20
View File
@@ -195,6 +195,9 @@ typedef struct
u32 limit_neighbor_cache_size;
u32 neighbor_delete_rotor;
/* Wildcard nd report publisher */
uword wc_ip6_nd_publisher_node;
uword wc_ip6_nd_publisher_et;
} ip6_neighbor_main_t;
/* ipv6 neighbor discovery - timer/event types */
@@ -216,6 +219,50 @@ typedef union
static ip6_neighbor_main_t ip6_neighbor_main;
static ip6_address_t ip6a_zero; /* ip6 address 0 */
static void wc_nd_signal_report (wc_nd_report_t * r);
/**
* @brief publish wildcard arp event
* @param sw_if_index The interface on which the ARP entires are acted
*/
static int
vnet_nd_wc_publish (u32 sw_if_index, u8 * mac, ip6_address_t * ip6)
{
wc_nd_report_t r = {
.sw_if_index = sw_if_index,
.ip6 = *ip6,
};
memcpy (r.mac, mac, sizeof r.mac);
void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
vl_api_rpc_call_main_thread (wc_nd_signal_report, (u8 *) & r, sizeof r);
return 0;
}
static void
wc_nd_signal_report (wc_nd_report_t * r)
{
vlib_main_t *vm = vlib_get_main ();
ip6_neighbor_main_t *nm = &ip6_neighbor_main;
uword ni = nm->wc_ip6_nd_publisher_node;
uword et = nm->wc_ip6_nd_publisher_et;
if (ni == (uword) ~ 0)
return;
wc_nd_report_t *q =
vlib_process_signal_event_data (vm, ni, et, 1, sizeof *q);
*q = *r;
}
void
wc_nd_set_publisher_node (uword node_index, uword event_type)
{
ip6_neighbor_main_t *nm = &ip6_neighbor_main;
nm->wc_ip6_nd_publisher_node = node_index;
nm->wc_ip6_nd_publisher_et = event_type;
}
static u8 *
format_ip6_neighbor_ip6_entry (u8 * s, va_list * va)
{
@@ -3931,6 +3978,8 @@ ip6_neighbor_init (vlib_main_t * vm)
/* default, configurable */
nm->limit_neighbor_cache_size = 50000;
nm->wc_ip6_nd_publisher_node = (uword) ~ 0;
#if 0
/* $$$$ Hack fix for today */
vec_validate_init_empty
@@ -4047,7 +4096,6 @@ vnet_ip6_nd_term (vlib_main_t * vm,
{
ip6_neighbor_main_t *nm = &ip6_neighbor_main;
icmp6_neighbor_solicitation_or_advertisement_header_t *ndh;
pending_resolution_t *mc;
ndh = ip6_next_header (ip);
if (ndh->icmp.type != ICMP6_neighbor_solicitation &&
@@ -4063,26 +4111,11 @@ vnet_ip6_nd_term (vlib_main_t * vm,
}
/* Check if anyone want ND events for L2 BDs */
uword *p = mhash_get (&nm->mac_changes_by_address, &ip6a_zero);
if (p && !ip6_address_is_link_local_unicast (&ip->src_address))
if (PREDICT_FALSE
(nm->wc_ip6_nd_publisher_node != (uword) ~ 0
&& !ip6_address_is_link_local_unicast (&ip->src_address)))
{
u32 next_index = p[0];
while (next_index != (u32) ~ 0)
{
int (*fp) (u32, u8 *, u32, ip6_address_t *);
int rv = 1;
mc = pool_elt_at_index (nm->mac_changes, next_index);
fp = mc->data_callback;
/* Call the callback, return 1 to suppress dup events */
if (fp)
rv = (*fp) (mc->data,
eth->src_address, sw_if_index, &ip->src_address);
/* Signal the resolver process */
if (rv == 0)
vlib_process_signal_event (vm, mc->node_index,
mc->type_opaque, mc->data);
next_index = mc->next_index;
}
vnet_nd_wc_publish (sw_if_index, eth->src_address, &ip->src_address);
}
/* Check if MAC entry exsist for solicited target IP */
+8
View File
@@ -89,6 +89,14 @@ extern int ip6_neighbor_proxy_add_del (u32 sw_if_index,
u32 ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index,
u32 is_add);
typedef struct
{
u32 sw_if_index;
ip6_address_t ip6;
u8 mac[6];
} wc_nd_report_t;
void wc_nd_set_publisher_node (uword node_index, uword event_type);
#endif /* included_ip6_neighbor_h */
+145 -76
View File
File diff suppressed because it is too large Load Diff
+66 -2
View File
@@ -168,6 +168,13 @@ class TestL2bdArpTerm(VppTestCase):
def arp_event_hosts(self, evs):
return {self.arp_event_host(e) for e in evs}
def nd_event_host(self, e):
return Host(mac=':'.join(['%02x' % ord(char) for char in e.new_mac]),
ip6=inet_ntop(AF_INET6, e.address))
def nd_event_hosts(self, evs):
return {self.nd_event_host(e) for e in evs}
@classmethod
def ns_req(cls, src_host, host):
nsma = in6_getnsma(inet_pton(AF_INET6, "fd10::ffff"))
@@ -178,7 +185,11 @@ class TestL2bdArpTerm(VppTestCase):
ICMPv6NDOptSrcLLAddr(lladdr=src_host.mac))
@classmethod
def ns_reqs(cls, src_host, entries):
def ns_reqs_dst(cls, entries, dst_host):
return [cls.ns_req(e, dst_host) for e in entries]
@classmethod
def ns_reqs_src(cls, src_host, entries):
return [cls.ns_req(src_host, e) for e in entries]
def na_resp_host(self, src_host, rx):
@@ -237,7 +248,7 @@ class TestL2bdArpTerm(VppTestCase):
self.assertEqual(len(resps ^ resp_hosts), 0)
def verify_nd(self, src_host, req_hosts, resp_hosts, bd_id=1):
reqs = self.ns_reqs(src_host, req_hosts)
reqs = self.ns_reqs_src(src_host, req_hosts)
for swif in self.bd_swifs(bd_id):
swif.add_stream(reqs)
@@ -423,6 +434,59 @@ class TestL2bdArpTerm(VppTestCase):
self.assertEqual(len(self.vapi.collect_events()), 0)
self.bd_add_del(1, is_add=0)
def test_l2bd_arp_term_12(self):
""" L2BD ND term - send NS packets verify reports
"""
self.vapi.want_ip6_nd_events(address=inet_pton(AF_INET6, "::0"))
dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44")
self.bd_add_del(1, is_add=1)
self.set_bd_flags(1, arp_term=True, flood=False,
uu_flood=False, learn=False)
macs = self.mac_list(range(10, 15))
hosts = self.ip6_hosts(5, 1, macs)
reqs = self.ns_reqs_dst(hosts, dst_host)
self.bd_swifs(1)[0].add_stream(reqs)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
evs = [self.vapi.wait_for_event(2, "ip6_nd_event")
for i in range(len(hosts))]
ev_hosts = self.nd_event_hosts(evs)
self.assertEqual(len(ev_hosts ^ hosts), 0)
def test_l2bd_arp_term_13(self):
""" L2BD ND term - send duplicate ns, verify suppression
"""
dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44")
macs = self.mac_list(range(10, 11))
hosts = self.ip6_hosts(5, 1, macs)
reqs = self.ns_reqs_dst(hosts, dst_host) * 5
self.bd_swifs(1)[0].add_stream(reqs)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
evs = [self.vapi.wait_for_event(2, "ip6_nd_event")
for i in range(len(hosts))]
ev_hosts = self.nd_event_hosts(evs)
self.assertEqual(len(ev_hosts ^ hosts), 0)
def test_l2bd_arp_term_14(self):
""" L2BD ND term - disable ip4 arp events,send ns, verify no events
"""
self.vapi.want_ip6_nd_events(enable_disable=0,
address=inet_pton(AF_INET6, "::0"))
dst_host = self.ip6_host(50, 50, "00:00:11:22:33:44")
macs = self.mac_list(range(10, 15))
hosts = self.ip6_hosts(5, 1, macs)
reqs = self.ns_reqs_dst(hosts, dst_host)
self.bd_swifs(1)[0].add_stream(reqs)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
self.sleep(1)
self.assertEqual(len(self.vapi.collect_events()), 0)
self.bd_add_del(1, is_add=0)
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)
+6
View File
@@ -425,6 +425,12 @@ class VppPapiProvider(object):
'address': address,
'pid': os.getpid(), })
def want_ip6_nd_events(self, enable_disable=1, address=0):
return self.api(self.papi.want_ip6_nd_events,
{'enable_disable': enable_disable,
'address': address,
'pid': os.getpid(), })
def l2fib_add_del(self, mac, bd_id, sw_if_index, is_add=1, static_mac=0,
filter_mac=0, bvi_mac=0):
"""Create/delete L2 FIB entry.