Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion modules/ip/control/address.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <gr_module.h>
#include <gr_net_types.h>
#include <gr_queue.h>
#include <gr_rcu.h>
#include <gr_vec.h>

#include <event2/event.h>
Expand Down Expand Up @@ -108,7 +109,20 @@ static struct api_out addr_add(const void *request, struct api_ctx *) {
if (ret < 0)
return api_out(-ret, 0, NULL);

gr_vec_add(ifaddrs->nh, nh);
// gr_vec_add may realloc() and free the old vector
// Duplicate the whole vector and append to the clone.
gr_vec struct nexthop **nhs_copy = NULL;
gr_vec struct nexthop **nhs_old = ifaddrs->nh;
gr_vec_cap_set(nhs_copy, gr_vec_len(nhs_old) + 1); // avoid malloc+realloc
gr_vec_extend(nhs_copy, nhs_old);
gr_vec_add(nhs_copy, nh);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gr_vec_clone will to do a malloc, gr_vec_add will do a realloc, it could be optimized:
gr_vec_grow(nhs_copy, gr_vec_len(nhs_old) +1) ;
gr_vec_extend(nhs_copy, nh_old);
gr_vec_add(nhs_copy, nh);

no ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could change this to:

        gr_vec struct nexthop **nhs_copy = NULL;
        gr_vec struct nexthop **nhs_old = ifaddrs->nh;
        gr_vec_cap_set(nhs_copy, gr_vec_len(nhs_old) + 1);
        gr_vec_extend(nhs_copy, ifaddrs->nh);
        gr_vec_add(nhs_copy, nh);
        ifaddrs->nh = nhs_copy;

But it is less readable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really mind. Let me know what you prefer.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer this one, it is still readable, more efficient

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

ifaddrs->nh = nhs_copy;
if (nhs_old != NULL) {
// Once all datapath workers have seen the new clone, free the old one.
rte_rcu_qsbr_synchronize(gr_datapath_rcu(), RTE_QSBR_THRID_INVALID);
gr_vec_free(nhs_old);
}

gr_event_push(GR_EVENT_IP_ADDR_ADD, &req->addr);

return api_out(0, 0, NULL);
Expand Down
31 changes: 29 additions & 2 deletions modules/ip6/control/address.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <gr_module.h>
#include <gr_net_types.h>
#include <gr_queue.h>
#include <gr_rcu.h>
#include <gr_vec.h>

#include <event2/event.h>
Expand Down Expand Up @@ -138,7 +139,20 @@ static int mcast6_addr_add(const struct iface *iface, const struct rte_ipv6_addr
}

nexthop_incref(nh);
gr_vec_add(maddrs->nh, nh);

// gr_vec_add may realloc() and free the old vector
// Duplicate the whole vector and append to the clone.
gr_vec struct nexthop **nhs_copy = NULL;
gr_vec struct nexthop **nhs_old = maddrs->nh;
gr_vec_cap_set(nhs_copy, gr_vec_len(nhs_old) + 1); // avoid malloc+realloc
gr_vec_extend(nhs_copy, nhs_old);
gr_vec_add(nhs_copy, nh);
maddrs->nh = nhs_copy;
if (nhs_old != NULL) {
// Once all datapath workers have seen the new clone, free the old one.
rte_rcu_qsbr_synchronize(gr_datapath_rcu(), RTE_QSBR_THRID_INVALID);
gr_vec_free(nhs_old);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having a real gc, not doing synchronize barrier every where seems more and more needed for grout...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. We will soon need to implement such a thing.

}

// add ethernet filter
return iface_add_eth_addr(iface->id, &mac);
Expand Down Expand Up @@ -228,7 +242,20 @@ iface6_addr_add(const struct iface *iface, const struct rte_ipv6_addr *ip, uint8
if (ret < 0)
return errno_set(-ret);

gr_vec_add(addrs->nh, nh);
// gr_vec_add may realloc() and free the old vector
// Duplicate the whole vector and append to the clone.
gr_vec struct nexthop **nhs_copy = NULL;
gr_vec struct nexthop **nhs_old = addrs->nh;
gr_vec_cap_set(nhs_copy, gr_vec_len(nhs_old) + 1); // avoid malloc+realloc
gr_vec_extend(nhs_copy, nhs_old);
gr_vec_add(nhs_copy, nh);
addrs->nh = nhs_copy;
if (nhs_old != NULL) {
// Once all datapath workers have seen the new clone, free the old one.
rte_rcu_qsbr_synchronize(gr_datapath_rcu(), RTE_QSBR_THRID_INVALID);
gr_vec_free(nhs_old);
}

gr_event_push(
GR_EVENT_IP6_ADDR_ADD,
&(struct gr_ip6_ifaddr) {
Expand Down