ARP/ND/API:fix arp reg + nd no identical regs

fixed arp registration without allocating the event
added protection against identical ND registrations

Change-Id: I4e2db4913b35d895d8686ada1f0818920f276ad6
Signed-off-by: Eyal Bari <ebari@cisco.com>
This commit is contained in:
Eyal Bari
2017-04-01 03:55:08 +03:00
committed by John Lo
parent 903fd513e3
commit f9f4065354
2 changed files with 60 additions and 66 deletions

View File

@ -3910,76 +3910,59 @@ vnet_add_del_ip6_nd_change_event (vnet_main_t * vnm,
{
ip6_neighbor_main_t *nm = &ip6_neighbor_main;
ip6_address_t *address = address_arg;
uword *p;
pending_resolution_t *mc;
void (*fp) (u32, u8 *) = data_callback;
/* Try to find an existing entry */
u32 *first = (u32 *) mhash_get (&nm->mac_changes_by_address, address);
u32 *p = first;
pending_resolution_t *mc;
while (p && *p != ~0)
{
mc = pool_elt_at_index (nm->mac_changes, *p);
if (mc->node_index == node_index && mc->type_opaque == type_opaque
&& mc->pid == pid)
break;
p = &mc->next_index;
}
int found = p && *p != ~0;
if (is_add)
{
if (found)
return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
pool_get (nm->mac_changes, mc);
*mc = (pending_resolution_t)
{
.next_index = ~0,.node_index = node_index,.type_opaque =
type_opaque,.data = data,.data_callback = data_callback,.pid =
pid,};
mc->next_index = ~0;
mc->node_index = node_index;
mc->type_opaque = type_opaque;
mc->data = data;
mc->data_callback = data_callback;
mc->pid = pid;
p = mhash_get (&nm->mac_changes_by_address, address);
/* Insert new resolution at the end of the list */
u32 new_idx = mc - nm->mac_changes;
if (p)
{
/* Insert new resolution at the head of the list */
mc->next_index = p[0];
mhash_unset (&nm->mac_changes_by_address, address, 0);
}
mhash_set (&nm->mac_changes_by_address, address,
mc - nm->mac_changes, 0);
return 0;
p[0] = new_idx;
else
mhash_set (&nm->mac_changes_by_address, address, new_idx, 0);
}
else
{
u32 index;
pending_resolution_t *mc_last = 0;
p = mhash_get (&nm->mac_changes_by_address, address);
if (p == 0)
if (!found)
return VNET_API_ERROR_NO_SUCH_ENTRY;
index = p[0];
/* Clients may need to clean up pool entries, too */
void (*fp) (u32, u8 *) = data_callback;
if (fp)
(*fp) (mc->data, 0 /* no new mac addrs */ );
while (index != (u32) ~ 0)
{
mc = pool_elt_at_index (nm->mac_changes, index);
if (mc->node_index == node_index &&
mc->type_opaque == type_opaque && mc->pid == pid)
{
/* Clients may need to clean up pool entries, too */
if (fp)
(*fp) (mc->data, 0 /* no new mac addrs */ );
if (index == p[0])
{
mhash_unset (&nm->mac_changes_by_address, address, 0);
if (mc->next_index != ~0)
mhash_set (&nm->mac_changes_by_address, address,
mc->next_index, 0);
pool_put (nm->mac_changes, mc);
return 0;
}
else
{
ASSERT (mc_last);
mc_last->next_index = mc->next_index;
pool_put (nm->mac_changes, mc);
return 0;
}
}
mc_last = mc;
index = mc->next_index;
}
/* Remove the entry from the list and delete the entry */
*p = mc->next_index;
pool_put (nm->mac_changes, mc);
return VNET_API_ERROR_NO_SUCH_ENTRY;
/* Remove from hash if we deleted the last entry */
if (*p == ~0 && p == first)
mhash_unset (&nm->mac_changes_by_address, address, 0);
}
return 0;
}
int

View File

@ -199,7 +199,7 @@ int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp);
void
static void
handle_ip4_arp_event (u32 pool_index)
{
vpe_api_main_t *vam = &vpe_api_main;
@ -1571,11 +1571,12 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
vpe_api_main_t *am = &vpe_api_main;
vnet_main_t *vnm = vnet_get_main ();
vl_api_want_ip4_arp_events_reply_t *rmp;
vl_api_ip4_arp_event_t *event;
int rv;
if (mp->enable_disable)
{
vl_api_ip4_arp_event_t *event;
pool_get (am->arp_events, event);
rv = vnet_add_del_ip4_arp_change_event
(vnm, arp_change_data_callback,
mp->pid, &mp->address /* addr, in net byte order */ ,
@ -1583,8 +1584,10 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
IP4_ARP_EVENT, event - am->arp_events, 1 /* is_add */ );
if (rv)
goto out;
pool_get (am->arp_events, event);
{
pool_put (am->arp_events, event);
goto out;
}
memset (event, 0, sizeof (*event));
event->_vl_msg_id = ntohs (VL_API_IP4_ARP_EVENT);
@ -1613,12 +1616,24 @@ vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
vpe_api_main_t *am = &vpe_api_main;
vnet_main_t *vnm = vnet_get_main ();
vl_api_want_ip6_nd_events_reply_t *rmp;
vl_api_ip6_nd_event_t *event;
int rv;
if (mp->enable_disable)
{
vl_api_ip6_nd_event_t *event;
pool_get (am->nd_events, event);
rv = vnet_add_del_ip6_nd_change_event
(vnm, nd_change_data_callback,
mp->pid, mp->address /* addr, in net byte order */ ,
vpe_resolver_process_node.index,
IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
if (rv)
{
pool_put (am->nd_events, event);
goto out;
}
memset (event, 0, sizeof (*event));
event->_vl_msg_id = ntohs (VL_API_IP6_ND_EVENT);
@ -1629,11 +1644,6 @@ vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
if (ip6_address_is_zero ((ip6_address_t *) mp->address))
event->mac_ip = 1;
rv = vnet_add_del_ip6_nd_change_event
(vnm, nd_change_data_callback,
mp->pid, mp->address /* addr, in net byte order */ ,
vpe_resolver_process_node.index,
IP6_ND_EVENT, event - am->nd_events, 1 /* is_add */ );
}
else
{
@ -1643,6 +1653,7 @@ vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
vpe_resolver_process_node.index,
IP6_ND_EVENT, ~0 /* pool index */ , 0 /* is_add */ );
}
out:
REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
}