From 631487aa2d45aa2078a08f1852e4a7482abbc2b5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 8 Dec 2011 05:53:53 +0100 Subject: Make NEF_STICKY work with fixed interfaces and allow specifying interface names --- nest/iface.h | 2 ++ nest/neighbor.c | 35 ++++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/nest/iface.h b/nest/iface.h index 6d333a1..315dda5 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -106,6 +106,7 @@ typedef struct neighbor { node if_n; /* Node in per-interface neighbor list */ ip_addr addr; /* Address of the neighbor */ struct iface *iface; /* Interface it's connected to */ + char bound_iface[16]; /* Name of the interface it's bound to */ struct proto *proto; /* Protocol this belongs to */ void *data; /* Protocol-specific data */ unsigned aux; /* Protocol-specific data */ @@ -118,6 +119,7 @@ typedef struct neighbor { neighbor *neigh_find(struct proto *, ip_addr *, unsigned flags); neighbor *neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags); +neighbor *neigh_find_ifname(struct proto *, ip_addr *, char *, unsigned flags); static inline int neigh_connected_to(struct proto *p, ip_addr *a, struct iface *i) { diff --git a/nest/neighbor.c b/nest/neighbor.c index cf1b2e9..de75b1d 100644 --- a/nest/neighbor.c +++ b/nest/neighbor.c @@ -49,6 +49,9 @@ static slab *neigh_slab; static list sticky_neigh_list, neigh_hash_table[NEIGH_HASH_SIZE]; +static neighbor * +neigh_find_internal(struct proto *p, ip_addr *a, struct iface *ifa, char *bound_iface, unsigned flags); + static inline unsigned int neigh_hash(struct proto *p, ip_addr *a) { @@ -108,15 +111,26 @@ if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */ neighbor * neigh_find(struct proto *p, ip_addr *a, unsigned flags) { - return neigh_find2(p, a, NULL, flags); + return neigh_find_internal(p, a, NULL, NULL, flags); } - neighbor * neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) +{ + return neigh_find_internal(p, a, ifa, ifa ? ifa->name : NULL, flags); +} + +neighbor * +neigh_find_ifname(struct proto *p, ip_addr *a, char *ifname, unsigned flags) +{ + return neigh_find_internal(p, a, ifname ? if_find_by_name(ifname) : NULL, ifname, flags); +} + +static neighbor * +neigh_find_internal(struct proto *p, ip_addr *a, struct iface *ifa, char *ifname, unsigned flags) { neighbor *n; - int class, scope = -1; ; + int class, scope = -1; unsigned int h = neigh_hash(p, a); struct iface *i; @@ -128,7 +142,7 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) if (class < 0) /* Invalid address */ return NULL; if (((class & IADDR_SCOPE_MASK) == SCOPE_HOST) || - (((class & IADDR_SCOPE_MASK) == SCOPE_LINK) && (ifa == NULL)) || + (((class & IADDR_SCOPE_MASK) == SCOPE_LINK) && (ifa == NULL) && (ifname == NULL)) || !(class & IADDR_HOST)) return NULL; /* Bad scope or a somecast */ @@ -139,7 +153,7 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) if ((scope < 0) && (flags & NEF_ONLINK)) scope = class & IADDR_SCOPE_MASK; } - else + else if (ifname == NULL) WALK_LIST(i, iface_list) if ((scope = if_connected(a, i)) >= 0) { @@ -162,8 +176,6 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) } else { - /* sticky flag does not work for link-local neighbors; - fortunately, we don't use this combination */ add_tail(&sticky_neigh_list, &n->n); ifa = NULL; scope = -1; @@ -174,6 +186,8 @@ neigh_find2(struct proto *p, ip_addr *a, struct iface *ifa, unsigned flags) n->aux = 0; n->flags = flags; n->scope = scope; + strncpy(n->bound_iface, ifname ?: "", sizeof(n->bound_iface)-1); + return n; } @@ -195,6 +209,8 @@ neigh_dump(neighbor *n) debug("%s %p %08x scope %s", n->proto->name, n->data, n->aux, ip_scope_text(n->scope)); if (n->flags & NEF_STICKY) debug(" STICKY"); + if (*n->bound_iface) + debug(" bound to %s", n->bound_iface); debug("\n"); } @@ -230,7 +246,7 @@ neigh_dump_all(void) * addresses belonging to prefixes of the interface belonging to @ifa * and causes all unreachable neighbors to be flushed * - * A change of the scope of a neighbor is handle as a remove with + * A change of the scope of a neighbor is handled as a remove with * a consequent add */ void @@ -262,7 +278,8 @@ neigh_ifa_update(struct ifa *a) /* Traverse the sticky neighbor list to find neighbors that are reachable now */ WALK_LIST_DELSAFE(n, next, sticky_neigh_list) - if ((scope = if_connected(&n->addr, i)) >= 0) + if ((!(*n->bound_iface) || strcmp(n->bound_iface, i->name) == 0) + && (scope = if_connected(&n->addr, i)) >= 0) { n->iface = i; n->scope = scope; -- cgit v1.2.3