mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-10 05:08:42 +00:00
Neighbors: Locking and asynchronous notifications
This commit is contained in:
parent
c651cef737
commit
d37513a372
66
nest/iface.c
66
nest/iface.c
@ -36,10 +36,12 @@
|
||||
|
||||
static pool *if_pool;
|
||||
|
||||
DOMAIN(attrs) iface_domain;
|
||||
list global_iface_list;
|
||||
struct iface default_vrf;
|
||||
|
||||
static void if_recalc_preferred(struct iface *i);
|
||||
static void ifa_delete_locked(struct ifa *a);
|
||||
|
||||
/**
|
||||
* ifa_dump - dump interface address
|
||||
@ -50,6 +52,7 @@ static void if_recalc_preferred(struct iface *i);
|
||||
void
|
||||
ifa_dump(struct ifa *a)
|
||||
{
|
||||
IFACE_LEGACY_ACCESS;
|
||||
debug("\t%I, net %N bc %I -> %I%s%s%s%s\n", a->ip, &a->prefix, a->brd, a->opposite,
|
||||
(a->flags & IA_PRIMARY) ? " PRIMARY" : "",
|
||||
(a->flags & IA_SECONDARY) ? " SEC" : "",
|
||||
@ -69,6 +72,7 @@ if_dump(struct iface *i)
|
||||
{
|
||||
struct ifa *a;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
debug("IF%d: %s", i->index, i->name);
|
||||
if (i->flags & IF_SHUTDOWN)
|
||||
debug(" SHUTDOWN");
|
||||
@ -110,6 +114,7 @@ if_dump_all(void)
|
||||
{
|
||||
struct iface *i;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
debug("Known network interfaces:\n");
|
||||
WALK_LIST(i, global_iface_list)
|
||||
if_dump(i);
|
||||
@ -307,6 +312,9 @@ if_update(struct iface *new)
|
||||
if (!new->master)
|
||||
new->master = &default_vrf;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
IFACE_LOCK;
|
||||
|
||||
WALK_LIST(i, global_iface_list)
|
||||
if (!strcmp(new->name, i->name))
|
||||
{
|
||||
@ -328,6 +336,8 @@ if_update(struct iface *new)
|
||||
}
|
||||
|
||||
if_copy(i, new);
|
||||
IFACE_UNLOCK;
|
||||
|
||||
if (c)
|
||||
if_notify_change(c, i);
|
||||
|
||||
@ -341,6 +351,8 @@ newif:
|
||||
init_list(&i->neighbors);
|
||||
i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */
|
||||
add_tail(&global_iface_list, &i->n);
|
||||
IFACE_UNLOCK;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -350,6 +362,7 @@ if_start_update(void)
|
||||
struct iface *i;
|
||||
struct ifa *a;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
WALK_LIST(i, global_iface_list)
|
||||
{
|
||||
i->flags &= ~IF_UPDATED;
|
||||
@ -361,6 +374,8 @@ if_start_update(void)
|
||||
void
|
||||
if_end_partial_update(struct iface *i)
|
||||
{
|
||||
IFACE_LEGACY_ACCESS;
|
||||
|
||||
if (i->flags & IF_NEEDS_RECALC)
|
||||
if_recalc_preferred(i);
|
||||
|
||||
@ -374,6 +389,7 @@ if_end_update(void)
|
||||
struct iface *i;
|
||||
struct ifa *a, *b;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
WALK_LIST(i, global_iface_list)
|
||||
{
|
||||
if (!(i->flags & IF_UPDATED))
|
||||
@ -382,7 +398,11 @@ if_end_update(void)
|
||||
{
|
||||
WALK_LIST_DELSAFE(a, b, i->addrs)
|
||||
if (!(a->flags & IA_UPDATED))
|
||||
ifa_delete(a);
|
||||
{
|
||||
IFACE_LOCK;
|
||||
ifa_delete_locked(a);
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
if_end_partial_update(i);
|
||||
}
|
||||
}
|
||||
@ -391,6 +411,7 @@ if_end_update(void)
|
||||
void
|
||||
if_flush_ifaces(struct proto *p)
|
||||
{
|
||||
IFACE_LEGACY_ACCESS;
|
||||
if (p->debug & D_EVENTS)
|
||||
log(L_TRACE "%s: Flushing interfaces", p->name);
|
||||
if_start_update();
|
||||
@ -410,6 +431,8 @@ if_feed_baby(struct proto *p)
|
||||
struct iface *i;
|
||||
struct ifa *a;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
|
||||
if (!p->if_notify && !p->ifa_notify) /* shortcut */
|
||||
return;
|
||||
DBG("Announcing interfaces to new protocol %s\n", p->name);
|
||||
@ -435,9 +458,15 @@ if_find_by_index(unsigned idx)
|
||||
{
|
||||
struct iface *i;
|
||||
|
||||
IFACE_LOCK;
|
||||
WALK_LIST(i, global_iface_list)
|
||||
if (i->index == idx && !(i->flags & IF_SHUTDOWN))
|
||||
{
|
||||
IFACE_UNLOCK;
|
||||
return i;
|
||||
}
|
||||
|
||||
IFACE_UNLOCK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -454,9 +483,15 @@ if_find_by_name(const char *name)
|
||||
{
|
||||
struct iface *i;
|
||||
|
||||
IFACE_LOCK;
|
||||
WALK_LIST(i, global_iface_list)
|
||||
if (!strcmp(i->name, name) && !(i->flags & IF_SHUTDOWN))
|
||||
{
|
||||
IFACE_UNLOCK;
|
||||
return i;
|
||||
}
|
||||
|
||||
IFACE_UNLOCK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -465,17 +500,21 @@ if_get_by_name(const char *name)
|
||||
{
|
||||
struct iface *i;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
|
||||
WALK_LIST(i, global_iface_list)
|
||||
if (!strcmp(i->name, name))
|
||||
return i;
|
||||
|
||||
/* No active iface, create a dummy */
|
||||
IFACE_LOCK;
|
||||
i = mb_allocz(if_pool, sizeof(struct iface));
|
||||
strncpy(i->name, name, sizeof(i->name)-1);
|
||||
i->flags = IF_SHUTDOWN;
|
||||
init_list(&i->addrs);
|
||||
init_list(&i->neighbors);
|
||||
add_tail(&global_iface_list, &i->n);
|
||||
IFACE_UNLOCK;
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -561,6 +600,8 @@ if_recalc_all_preferred_addresses(void)
|
||||
{
|
||||
struct iface *i;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
|
||||
WALK_LIST(i, global_iface_list)
|
||||
{
|
||||
if_recalc_preferred(i);
|
||||
@ -591,6 +632,8 @@ ifa_update(struct ifa *a)
|
||||
struct iface *i = a->iface;
|
||||
struct ifa *b;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
|
||||
WALK_LIST(b, i->addrs)
|
||||
if (ifa_same(b, a))
|
||||
{
|
||||
@ -609,10 +652,12 @@ ifa_update(struct ifa *a)
|
||||
if ((a->prefix.type == NET_IP4) && (i->flags & IF_BROADCAST) && ipa_zero(a->brd))
|
||||
log(L_WARN "Missing broadcast address for interface %s", i->name);
|
||||
|
||||
IFACE_LOCK;
|
||||
b = mb_alloc(if_pool, sizeof(struct ifa));
|
||||
memcpy(b, a, sizeof(struct ifa));
|
||||
add_tail(&i->addrs, &b->n);
|
||||
b->flags |= IA_UPDATED;
|
||||
IFACE_UNLOCK;
|
||||
|
||||
i->flags |= IF_NEEDS_RECALC;
|
||||
if (i->flags & IF_UP)
|
||||
@ -637,6 +682,17 @@ ifa_delete(struct ifa *a)
|
||||
WALK_LIST(b, i->addrs)
|
||||
if (ifa_same(b, a))
|
||||
{
|
||||
IFACE_LOCK;
|
||||
ifa_delete_locked(b);
|
||||
IFACE_UNLOCK;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ifa_delete_locked(struct ifa *b)
|
||||
{
|
||||
struct iface *i = b->iface;
|
||||
rem_node(&b->n);
|
||||
|
||||
if (b->flags & IA_PRIMARY)
|
||||
@ -660,7 +716,6 @@ ifa_delete(struct ifa *a)
|
||||
mb_free(b);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u32
|
||||
if_choose_router_id(struct iface_patt *mask, u32 old_id)
|
||||
@ -668,6 +723,8 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
|
||||
struct iface *i;
|
||||
struct ifa *a, *b;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
|
||||
b = NULL;
|
||||
WALK_LIST(i, global_iface_list)
|
||||
{
|
||||
@ -715,6 +772,7 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id)
|
||||
void
|
||||
if_init(void)
|
||||
{
|
||||
iface_domain = DOMAIN_NEW(attrs, "Interfaces");
|
||||
if_pool = rp_new(&root_pool, &main_birdloop, "Interfaces");
|
||||
init_list(&global_iface_list);
|
||||
strcpy(default_vrf.name, "default");
|
||||
@ -844,6 +902,8 @@ if_show(void)
|
||||
struct ifa *a;
|
||||
char *type;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
|
||||
WALK_LIST(i, global_iface_list)
|
||||
{
|
||||
if (i->flags & IF_SHUTDOWN)
|
||||
@ -886,6 +946,8 @@ if_show_summary(void)
|
||||
{
|
||||
struct iface *i;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
|
||||
cli_msg(-2005, "%-10s %-6s %-18s %s", "Interface", "State", "IPv4 address", "IPv6 address");
|
||||
WALK_LIST(i, global_iface_list)
|
||||
{
|
||||
|
11
nest/iface.h
11
nest/iface.h
@ -9,10 +9,20 @@
|
||||
#ifndef _BIRD_IFACE_H_
|
||||
#define _BIRD_IFACE_H_
|
||||
|
||||
#include "lib/event.h"
|
||||
#include "lib/lists.h"
|
||||
#include "lib/ip.h"
|
||||
#include "lib/locking.h"
|
||||
|
||||
DEFINE_DOMAIN(attrs);
|
||||
extern list global_iface_list;
|
||||
extern DOMAIN(attrs) iface_domain;
|
||||
|
||||
#define IFACE_LEGACY_ACCESS ASSERT_DIE(birdloop_inside(&main_birdloop))
|
||||
|
||||
#define IFACE_LOCK LOCK_DOMAIN(attrs, iface_domain)
|
||||
#define IFACE_UNLOCK UNLOCK_DOMAIN(attrs, iface_domain)
|
||||
#define ASSERT_IFACE_LOCKED ASSERT_DIE(DOMAIN_IS_LOCKED(attrs, iface_domain))
|
||||
|
||||
struct proto;
|
||||
struct pool;
|
||||
@ -131,6 +141,7 @@ typedef struct neighbor {
|
||||
struct ifa *ifa; /* Ifa on related iface */
|
||||
struct iface *iface; /* Interface it's connected to */
|
||||
struct iface *ifreq; /* Requested iface, NULL for any */
|
||||
struct event event; /* Notification event */
|
||||
struct proto *proto; /* Protocol this belongs to */
|
||||
void *data; /* Protocol-specific data */
|
||||
uint aux; /* Protocol-specific data */
|
||||
|
@ -59,6 +59,7 @@
|
||||
|
||||
static slab *neigh_slab;
|
||||
static list neigh_hash_table[NEIGH_HASH_SIZE], sticky_neigh_list;
|
||||
static void neigh_do_notify(void *);
|
||||
|
||||
static inline uint
|
||||
neigh_hash(struct proto *p, ip_addr a, struct iface *i)
|
||||
@ -210,36 +211,40 @@ if_intersect(struct iface *ia, struct iface *ib)
|
||||
neighbor *
|
||||
neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
||||
{
|
||||
ASSERT_DIE(birdloop_inside(&main_birdloop));
|
||||
|
||||
neighbor *n;
|
||||
int class, scope = -1;
|
||||
uint h = neigh_hash(p, a, iface);
|
||||
struct iface *ifreq = iface;
|
||||
struct ifa *addr = NULL;
|
||||
|
||||
IFACE_LOCK;
|
||||
WALK_LIST(n, neigh_hash_table[h]) /* Search the cache */
|
||||
if ((n->proto == p) && ipa_equal(n->addr, a) && (n->ifreq == iface))
|
||||
{
|
||||
IFACE_UNLOCK;
|
||||
return n;
|
||||
}
|
||||
|
||||
#define NOT_FOUND goto not_found
|
||||
|
||||
if (flags & NEF_IFACE)
|
||||
{
|
||||
if (ipa_nonzero(a) || !iface)
|
||||
return NULL;
|
||||
NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
class = ipa_classify(a);
|
||||
if (class < 0) /* Invalid address */
|
||||
return NULL;
|
||||
NOT_FOUND;
|
||||
if (((class & IADDR_SCOPE_MASK) == SCOPE_HOST) ||
|
||||
(((class & IADDR_SCOPE_MASK) == SCOPE_LINK) && !iface) ||
|
||||
!(class & IADDR_HOST))
|
||||
return NULL; /* Bad scope or a somecast */
|
||||
NOT_FOUND; /* Bad scope or a somecast */
|
||||
}
|
||||
|
||||
if ((flags & NEF_ONLINK) && !iface)
|
||||
return NULL;
|
||||
NOT_FOUND;
|
||||
|
||||
if (iface)
|
||||
{
|
||||
@ -253,7 +258,7 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
||||
/* scope >= 0 <=> iface != NULL */
|
||||
|
||||
if ((scope < 0) && !(flags & NEF_STICKY))
|
||||
return NULL;
|
||||
NOT_FOUND;
|
||||
|
||||
n = sl_allocz(neigh_slab);
|
||||
add_tail(&neigh_hash_table[h], &n->n);
|
||||
@ -265,8 +270,23 @@ neigh_find(struct proto *p, ip_addr a, struct iface *iface, uint flags)
|
||||
n->proto = p;
|
||||
n->flags = flags;
|
||||
n->scope = scope;
|
||||
n->event = (event) { .hook = neigh_do_notify, .data = n };
|
||||
ASSERT_DIE(birdloop_inside(p->loop));
|
||||
|
||||
if (p->loop == &main_birdloop)
|
||||
n->event.list = &global_event_list;
|
||||
else
|
||||
{
|
||||
birdloop_link(p->loop);
|
||||
n->event.list = birdloop_event_list(p->loop);
|
||||
}
|
||||
|
||||
IFACE_UNLOCK;
|
||||
return n;
|
||||
|
||||
not_found:
|
||||
IFACE_UNLOCK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -300,11 +320,15 @@ neigh_dump_all(void)
|
||||
neighbor *n;
|
||||
int i;
|
||||
|
||||
IFACE_LOCK;
|
||||
|
||||
debug("Known neighbors:\n");
|
||||
for(i=0; i<NEIGH_HASH_SIZE; i++)
|
||||
WALK_LIST(n, neigh_hash_table[i])
|
||||
neigh_dump(n);
|
||||
debug("\n");
|
||||
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -313,7 +337,16 @@ neigh_notify(neighbor *n)
|
||||
if (!n->proto->neigh_notify)
|
||||
return;
|
||||
|
||||
PROTO_LOCKED_FROM_MAIN(n->proto)
|
||||
ev_send(n->event.list, &n->event);
|
||||
}
|
||||
|
||||
static void
|
||||
neigh_do_notify(void *data)
|
||||
{
|
||||
neighbor *n = data;
|
||||
|
||||
ASSERT_DIE(birdloop_inside(n->proto->loop));
|
||||
|
||||
if (n->proto->proto_state != PS_STOP)
|
||||
n->proto->neigh_notify(n);
|
||||
}
|
||||
@ -351,6 +384,8 @@ neigh_free(neighbor *n)
|
||||
{
|
||||
rem_node(&n->n);
|
||||
rem_node(&n->if_n);
|
||||
ev_postpone(&n->event);
|
||||
birdloop_unlink(n->proto->loop);
|
||||
sl_free(neigh_slab, n);
|
||||
}
|
||||
|
||||
@ -366,6 +401,8 @@ neigh_free(neighbor *n)
|
||||
void
|
||||
neigh_update(neighbor *n, struct iface *iface)
|
||||
{
|
||||
ASSERT_IFACE_LOCKED;
|
||||
|
||||
struct proto *p = n->proto;
|
||||
struct ifa *ifa = NULL;
|
||||
int scope = -1;
|
||||
@ -439,6 +476,8 @@ neigh_if_up(struct iface *i)
|
||||
neighbor *n;
|
||||
node *x, *y;
|
||||
|
||||
IFACE_LOCK;
|
||||
|
||||
/* Update neighbors that might be better off with the new iface */
|
||||
WALK_LIST(ii, global_iface_list)
|
||||
if (!EMPTY_LIST(ii->neighbors) && (ii != i) && if_intersect(i, ii))
|
||||
@ -447,6 +486,8 @@ neigh_if_up(struct iface *i)
|
||||
|
||||
WALK_LIST2_DELSAFE(n, x, y, sticky_neigh_list, if_n)
|
||||
neigh_update(n, i);
|
||||
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -463,8 +504,12 @@ neigh_if_down(struct iface *i)
|
||||
neighbor *n;
|
||||
node *x, *y;
|
||||
|
||||
IFACE_LOCK;
|
||||
|
||||
WALK_LIST2_DELSAFE(n, x, y, i->neighbors, if_n)
|
||||
neigh_update(n, i);
|
||||
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -480,8 +525,12 @@ neigh_if_link(struct iface *i)
|
||||
neighbor *n;
|
||||
node *x, *y;
|
||||
|
||||
IFACE_LOCK;
|
||||
|
||||
WALK_LIST2_DELSAFE(n, x, y, i->neighbors, if_n)
|
||||
neigh_notify(n);
|
||||
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -501,6 +550,8 @@ neigh_ifa_up(struct ifa *a)
|
||||
neighbor *n;
|
||||
node *x, *y;
|
||||
|
||||
IFACE_LOCK;
|
||||
|
||||
/* Update neighbors that might be better off with the new ifa */
|
||||
WALK_LIST(ii, global_iface_list)
|
||||
if (!EMPTY_LIST(ii->neighbors) && ifa_intersect(a, ii))
|
||||
@ -510,6 +561,8 @@ neigh_ifa_up(struct ifa *a)
|
||||
/* Wake up all sticky neighbors that are reachable now */
|
||||
WALK_LIST2_DELSAFE(n, x, y, sticky_neigh_list, if_n)
|
||||
neigh_update(n, i);
|
||||
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -519,10 +572,14 @@ neigh_ifa_down(struct ifa *a)
|
||||
neighbor *n;
|
||||
node *x, *y;
|
||||
|
||||
IFACE_LOCK;
|
||||
|
||||
/* Update all neighbors whose scope has changed */
|
||||
WALK_LIST2_DELSAFE(n, x, y, i->neighbors, if_n)
|
||||
if (n->ifa == a)
|
||||
neigh_update(n, i);
|
||||
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -548,10 +605,14 @@ neigh_prune(void)
|
||||
node *m;
|
||||
int i;
|
||||
|
||||
IFACE_LOCK;
|
||||
|
||||
DBG("Pruning neighbors\n");
|
||||
for(i=0; i<NEIGH_HASH_SIZE; i++)
|
||||
WALK_LIST_DELSAFE(n, m, neigh_hash_table[i])
|
||||
neigh_prune_one(n);
|
||||
|
||||
IFACE_UNLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,7 +86,6 @@ const char * rta_dest_names[RTD_MAX] = {
|
||||
[RTD_PROHIBIT] = "prohibited",
|
||||
};
|
||||
|
||||
DEFINE_DOMAIN(attrs);
|
||||
static DOMAIN(attrs) src_domain;
|
||||
|
||||
#define SRC_LOCK LOCK_DOMAIN(attrs, src_domain)
|
||||
|
@ -1907,6 +1907,7 @@ babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
|
||||
{
|
||||
struct iface *iface;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
WALK_LIST(iface, global_iface_list)
|
||||
{
|
||||
if (!(iface->flags & IF_UP))
|
||||
|
@ -1225,6 +1225,7 @@ ospf_reconfigure_ifaces2(struct ospf_proto *p)
|
||||
struct iface *iface;
|
||||
struct ifa *a;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
WALK_LIST(iface, global_iface_list)
|
||||
{
|
||||
if (! (iface->flags & IF_UP))
|
||||
@ -1271,6 +1272,7 @@ ospf_reconfigure_ifaces3(struct ospf_proto *p)
|
||||
struct iface *iface;
|
||||
struct ifa *a;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
WALK_LIST(iface, global_iface_list)
|
||||
{
|
||||
if (! (iface->flags & IF_UP))
|
||||
|
@ -663,6 +663,7 @@ radv_reconfigure(struct proto *P, struct proto_config *CF)
|
||||
if (!old->propagate_routes && new->propagate_routes)
|
||||
channel_request_feeding(p->p.main_channel);
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
struct iface *iface;
|
||||
WALK_LIST(iface, global_iface_list)
|
||||
{
|
||||
|
@ -776,6 +776,7 @@ rip_reconfigure_ifaces(struct rip_proto *p, struct rip_config *cf)
|
||||
{
|
||||
struct iface *iface;
|
||||
|
||||
IFACE_LEGACY_ACCESS;
|
||||
WALK_LIST(iface, global_iface_list)
|
||||
{
|
||||
if (!(iface->flags & IF_UP))
|
||||
|
@ -242,6 +242,7 @@ krt_send_route(struct krt_proto *p, int cmd, const rte *e)
|
||||
*/
|
||||
if (!i)
|
||||
{
|
||||
IFACE_LOCK;
|
||||
WALK_LIST(j, global_iface_list)
|
||||
{
|
||||
if (j->flags & IF_LOOPBACK)
|
||||
@ -250,6 +251,7 @@ krt_send_route(struct krt_proto *p, int cmd, const rte *e)
|
||||
break;
|
||||
}
|
||||
}
|
||||
IFACE_UNLOCK;
|
||||
|
||||
if (!i)
|
||||
{
|
||||
|
@ -1147,6 +1147,7 @@ kif_do_scan(struct kif_proto *p UNUSED)
|
||||
log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
|
||||
|
||||
/* Re-resolve master interface for slaves */
|
||||
IFACE_LEGACY_ACCESS;
|
||||
struct iface *i;
|
||||
WALK_LIST(i, global_iface_list)
|
||||
if (i->master_index)
|
||||
|
Loading…
Reference in New Issue
Block a user