Skip to content

Commit

Permalink
convert rta_index to offsets from pointers #12
Browse files Browse the repository at this point in the history
  • Loading branch information
dankamongmen committed Nov 1, 2019
1 parent d5f9138 commit d0f7f5d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 44 deletions.
50 changes: 28 additions & 22 deletions include/netstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,28 @@ struct netstack;

// each of these types corresponds to a different rtnetlink message type. we
// copy the payload directly from the netlink message to rtabuf, but that form
// requires o(n) to get to any given attribute. we store a table of o(1)
// pointers into this buffer at rta_indexed. if we're running on a newer
// kernel, we might get an attribute larger than we're prepared to handle.
// that's fine; interested parties can still extract it using rtnetlink(3)
// macros. the convenience functions netstack_*_attr() are provided for this
// purpose: each will retrieve the value via lookup if less than the MAX
// against which we were compiled, and do an o(n) check otherwise.
// requires o(n) to get to any given attribute. we store a table of n offsets
// into this buffer at rta_index. if we're running on a newer kernel, we might
// get an attribute larger than we're prepared to handle. that's fine.
// interested parties can still extract it using rtnetlink(3) macros. the
// convenience functions netstack_*_attr() are provided for this purpose: each
// will retrieve the value via lookup if less than the MAX against which we
// were compiled, and do an o(n) check otherwise.
typedef struct netstack_iface {
struct ifinfomsg ifi;
char name[IFNAMSIZ]; // NUL-terminated, safely processed from IFLA_NAME
struct rtattr* rtabuf; // copied directly from message
size_t rtabuflen; // number of bytes copied to rtabuf
// set up before invoking the user callback, these allow for o(1) index into
// rtabuf by attr type. NULL if that attr wasn't in the message.
const struct rtattr* rta_indexed[__IFLA_MAX];
// rtabuf by attr type. NULL if that attr wasn't in the message. We use
// offsets rather than pointers lest deep copy require recomputing the index.
size_t rta_index[__IFLA_MAX];
bool unknown_attrs; // are there attrs >= __IFLA_MAX?
struct netstack_iface* hnext; // next in the idx-hashed table ns->iface_slots
atomic_int refcount; // netstack and/or client(s) can share objects
} netstack_iface;

static inline const struct rtattr *
static inline const struct rtattr*
netstack_extract_rta_attr(const struct rtattr* rtabuf, size_t rlen, int rtype){
while(RTA_OK(rtabuf, rlen)){
if(rtabuf->rta_type == rtype){
Expand All @@ -60,13 +61,18 @@ netstack_extract_rta_attr(const struct rtattr* rtabuf, size_t rlen, int rtype){
return NULL;
}

static inline const struct rtattr *
static inline const struct rtattr*
index_into_rta(const struct rtattr* rtabuf, size_t offset){
return (const struct rtattr*)(((char*)rtabuf) + offset);
}

static inline const struct rtattr*
netstack_iface_attr(const netstack_iface* ni, int attridx){
if(attridx < 0){
return NULL;
}
if((size_t)attridx < sizeof(ni->rta_indexed) / sizeof(*ni->rta_indexed)){
return ni->rta_indexed[attridx];
if((size_t)attridx < sizeof(ni->rta_index) / sizeof(*ni->rta_index)){
return index_into_rta(ni->rtabuf, ni->rta_index[attridx]);
}
if(!ni->unknown_attrs){
return NULL;
Expand Down Expand Up @@ -114,7 +120,7 @@ typedef struct netstack_addr {
struct ifaddrmsg ifa;
struct rtattr* rtabuf; // copied directly from message
size_t rtabuflen;
const struct rtattr* rta_indexed[__IFA_MAX];
size_t rta_index[__IFA_MAX];
bool unknown_attrs; // are there attrs >= __IFA_MAX?
} netstack_addr;

Expand All @@ -123,8 +129,8 @@ netstack_addr_attr(const netstack_addr* na, int attridx){
if(attridx < 0){
return NULL;
}
if((size_t)attridx < sizeof(na->rta_indexed) / sizeof(*na->rta_indexed)){
return na->rta_indexed[attridx];
if((size_t)attridx < sizeof(na->rta_index) / sizeof(*na->rta_index)){
return index_into_rta(na->rtabuf, na->rta_index[attridx]);
}
if(!na->unknown_attrs){
return NULL;
Expand All @@ -136,7 +142,7 @@ typedef struct netstack_route {
struct rtmsg rt;
struct rtattr* rtabuf; // copied directly from message
size_t rtabuflen;
const struct rtattr* rta_indexed[__RTA_MAX];
size_t rta_index[__RTA_MAX];
bool unknown_attrs; // are there attrs >= __RTA_MAX?
} netstack_route;

Expand All @@ -145,8 +151,8 @@ netstack_route_attr(const netstack_route* nr, int attridx){
if(attridx < 0){
return NULL;
}
if((size_t)attridx < sizeof(nr->rta_indexed) / sizeof(*nr->rta_indexed)){
return nr->rta_indexed[attridx];
if((size_t)attridx < sizeof(nr->rta_index) / sizeof(*nr->rta_index)){
return index_into_rta(nr->rtabuf, nr->rta_index[attridx]);
}
if(!nr->unknown_attrs){
return NULL;
Expand Down Expand Up @@ -226,7 +232,7 @@ typedef struct netstack_neigh {
struct ndmsg nd;
struct rtattr* rtabuf; // copied directly from message
size_t rtabuflen;
const struct rtattr* rta_indexed[__NDA_MAX];
size_t rta_index[__NDA_MAX];
bool unknown_attrs; // are there attrs >= __NDA_MAX?
} netstack_neigh;

Expand All @@ -235,8 +241,8 @@ netstack_neigh_attr(const netstack_neigh* nn, int attridx){
if(attridx < 0){
return NULL;
}
if((size_t)attridx < sizeof(nn->rta_indexed) / sizeof(*nn->rta_indexed)){
return nn->rta_indexed[attridx];
if((size_t)attridx < sizeof(nn->rta_index) / sizeof(*nn->rta_index)){
return index_into_rta(nn->rtabuf, nn->rta_index[attridx]);
}
if(!nn->unknown_attrs){
return NULL;
Expand Down
41 changes: 19 additions & 22 deletions src/lib/netstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,8 @@ iface_rta_handler(netstack_iface* ni, const struct ifinfomsg* ifi,
ni->unknown_attrs = true;
return true;
}
if(ni->rta_indexed[rta->rta_type] == NULL){ // shouldn't see attrs twice
ni->rta_indexed[rta->rta_type] =
(const struct rtattr*)(((const char*)ni->rtabuf) + rtaoff);
if(ni->rta_index[rta->rta_type] == 0){ // shouldn't see attrs twice
ni->rta_index[rta->rta_type] = rtaoff;
}
return true;
}
Expand Down Expand Up @@ -195,9 +194,8 @@ addr_rta_handler(netstack_addr* na, const struct ifaddrmsg* ifa,
na->unknown_attrs = true;
return true;
}
if(na->rta_indexed[rta->rta_type] == NULL){ // shouldn't see attrs twice
na->rta_indexed[rta->rta_type] =
(const struct rtattr*)(((const char*)na->rtabuf) + rtaoff);
if(na->rta_index[rta->rta_type] == 0){ // shouldn't see attrs twice
na->rta_index[rta->rta_type] = rtaoff;
}
return true;
}
Expand Down Expand Up @@ -247,9 +245,8 @@ route_rta_handler(netstack_route* nr, const struct rtmsg* rt,
nr->unknown_attrs = true;
return true;
}
if(nr->rta_indexed[rta->rta_type] == NULL){ // shouldn't see attrs twice
nr->rta_indexed[rta->rta_type] =
(const struct rtattr*)(((const char*)nr->rtabuf) + rtaoff);
if(nr->rta_index[rta->rta_type] == 0){ // shouldn't see attrs twice
nr->rta_index[rta->rta_type] = rtaoff;
}
return true;
}
Expand Down Expand Up @@ -281,9 +278,8 @@ neigh_rta_handler(netstack_neigh* nn, const struct ndmsg* nd,
nn->unknown_attrs = true;
return true;
}
if(nn->rta_indexed[rta->rta_type] == NULL){ // shouldn't see attrs twice
nn->rta_indexed[rta->rta_type] =
(const struct rtattr*)(((const char*)nn->rtabuf) + rtaoff);
if(nn->rta_index[rta->rta_type] == 0){ // shouldn't see attrs twice
nn->rta_index[rta->rta_type] = rtaoff;
}
return true;
}
Expand Down Expand Up @@ -320,10 +316,11 @@ memdup(const void* v, size_t n){

static inline struct rtattr*
rtas_dup(const struct rtattr* rtas, int rlen,
const struct rtattr* rta_indexed[], size_t rtamax){
size_t* rta_index, size_t rtamax){
struct rtattr* ret = memdup(rtas, rlen);
// we needn't recompute this table, since it's all relative offsets
if(ret){
memset(rta_indexed, 0, sizeof(*rta_indexed) * rtamax);
memset(rta_index, 0, sizeof(*rta_index) * rtamax);
}
return ret;
}
Expand All @@ -334,8 +331,8 @@ create_iface(const struct rtattr* rtas, int rlen){
ni = malloc(sizeof(*ni));
memset(ni, 0, sizeof(*ni));
atomic_init(&ni->refcount, 1);
ni->rtabuf = rtas_dup(rtas, rlen, ni->rta_indexed,
sizeof(ni->rta_indexed) / sizeof(*ni->rta_indexed));
ni->rtabuf = rtas_dup(rtas, rlen, ni->rta_index,
sizeof(ni->rta_index) / sizeof(*ni->rta_index));
return ni;
}

Expand All @@ -349,8 +346,8 @@ create_addr(const struct rtattr* rtas, int rlen){
netstack_addr* na;
na = malloc(sizeof(*na));
memset(na, 0, sizeof(*na));
na->rtabuf = rtas_dup(rtas, rlen, na->rta_indexed,
sizeof(na->rta_indexed) / sizeof(*na->rta_indexed));
na->rtabuf = rtas_dup(rtas, rlen, na->rta_index,
sizeof(na->rta_index) / sizeof(*na->rta_index));
return na;
}

Expand All @@ -364,8 +361,8 @@ create_route(const struct rtattr* rtas, int rlen){
netstack_route* nr;
nr = malloc(sizeof(*nr));
memset(nr, 0, sizeof(*nr));
nr->rtabuf = rtas_dup(rtas, rlen, nr->rta_indexed,
sizeof(nr->rta_indexed) / sizeof(*nr->rta_indexed));
nr->rtabuf = rtas_dup(rtas, rlen, nr->rta_index,
sizeof(nr->rta_index) / sizeof(*nr->rta_index));
return nr;
}

Expand All @@ -379,8 +376,8 @@ create_neigh(const struct rtattr* rtas, int rlen){
netstack_neigh* nn;
nn = malloc(sizeof(*nn));
memset(nn, 0, sizeof(*nn));
nn->rtabuf = rtas_dup(rtas, rlen, nn->rta_indexed,
sizeof(nn->rta_indexed) / sizeof(*nn->rta_indexed));
nn->rtabuf = rtas_dup(rtas, rlen, nn->rta_index,
sizeof(nn->rta_index) / sizeof(*nn->rta_index));
return nn;
}

Expand Down

0 comments on commit d0f7f5d

Please sign in to comment.