}
static inline void
-ifa_send_notify(struct proto *p, unsigned c, struct ifa *a)
+ifa_send_notify(struct iface_subscription *s, unsigned c, struct ifa *a)
{
- if (p->ifa_notify &&
+ struct proto *p = SKIP_BACK(struct proto, iface_sub, s);
+
+ if (s->ifa_notify &&
(p->proto_state != PS_DOWN) &&
- (!p->vrf || p->vrf == a->iface->master))
- (!p->vrf_set || if_in_vrf(a->iface, p->vrf)))
++ (!p->vrf || if_in_vrf(a->iface, p->vrf)))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < address %N on interface %s %s",
}
static inline void
-if_send_notify(struct proto *p, unsigned c, struct iface *i)
+if_send_notify(struct iface_subscription *s, unsigned c, struct iface *i)
{
- if (p->if_notify &&
+ struct proto *p = SKIP_BACK(struct proto, iface_sub, s);
+
+ if (s->if_notify &&
(p->proto_state != PS_DOWN) &&
- (!p->vrf || p->vrf == i->master))
- (!p->vrf_set || if_in_vrf(i, p->vrf)))
++ (!p->vrf || if_in_vrf(i, p->vrf)))
{
if (p->debug & D_IFACES)
log(L_TRACE "%s < interface %s %s", p->name, i->name,
struct iface *if_get_by_name(const char *);
void if_recalc_all_preferred_addresses(void);
+ static inline int if_in_vrf(struct iface *i, struct iface *vrf)
+ { return (i->flags & IF_VRF) ? (i == vrf) : (i->master == vrf); }
+
+struct iface *if_walk_first(void);
+struct iface *if_walk_next(struct iface *);
+void if_walk_done(void);
+
+#define IFACE_WALK(_i) for (struct iface *_i = if_walk_first(); _i || (if_walk_done(), 0); _i = if_walk_next(_i))
/* The Neighbor Cache */
*addr = NULL;
/* Prefer SCOPE_HOST or longer prefix */
- WALK_LIST(i, iface_list)
- if ((!vrf_set || if_in_vrf(i, vrf)) && ((s = if_connected(a, i, &b, flags)) >= 0))
+ WALK_LIST(i, global_iface_list)
- if ((!vrf || vrf == i->master) && ((s = if_connected(a, i, &b, flags)) >= 0))
++ if ((!vrf || if_in_vrf(i,vrf)) && ((s = if_connected(a, i, &b, flags)) >= 0))
if (scope_better(s, scope) || (scope_remote(s, scope) && ifa_better(b, *addr)))
{
*iface = i;
return;
/* VRF-bound neighbors ignore changes in other VRFs */
- if (p->vrf && (p->vrf != iface->master))
- if (p->vrf_set && !if_in_vrf(iface, p->vrf))
++ if (p->vrf && !if_in_vrf(iface, p->vrf))
return;
scope = if_connected(n->addr, iface, &ifa, n->flags);
static void
babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
{
- struct iface *iface;
-
- WALK_LIST(iface, iface_list)
+ IFACE_WALK(iface)
{
- if (p->p.vrf && p->p.vrf != iface->master)
- if (p->p.vrf_set && !if_in_vrf(iface, p->p.vrf))
++ if (p->p.vrf && !if_in_vrf(iface, p->p.vrf))
continue;
if (!(iface->flags & IF_UP))
/* Handle next hop self option - also applies to gateway */
if (c->cf->next_hop_self && bgp_match_src(s, c->cf->next_hop_self))
- return 0;
+ return NULL;
+
+ eattr *nhea = ea_find(ra, &ea_gen_nexthop);
+ if (!nhea)
+ return NULL;
/* We need one valid global gateway */
- if ((ra->dest != RTD_UNICAST) || ra->nh.next || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw))
- return 0;
+ struct nexthop_adata *nhad = (struct nexthop_adata *) nhea->u.ptr;
+ if (!NEXTHOP_IS_REACHABLE(nhad) ||
+ !NEXTHOP_ONE(nhad) || ipa_zero(nhad->nh.gw) ||
+ ipa_is_link_local(nhad->nh.gw))
+ return NULL;
/* Check for non-matching AF */
- if ((ipa_is_ip4(ra->nh.gw) != bgp_channel_is_ipv4(c)) && !c->ext_next_hop)
- return 0;
+ if ((ipa_is_ip4(nhad->nh.gw) != bgp_channel_is_ipv4(c)) && !c->ext_next_hop)
+ return NULL;
/* Do not use gateway from different VRF */
- if (p->p.vrf && nhad->nh.iface && (p->p.vrf != nhad->nh.iface->master))
- if (p->p.vrf_set && ra->nh.iface && !if_in_vrf(ra->nh.iface, p->p.vrf))
++ if (p->p.vrf && nhad->nh.iface && !if_in_vrf(nhad->nh.iface, p->p.vrf))
return 0;
/* Use it when exported to internal peers */
static void
ospf_reconfigure_ifaces2(struct ospf_proto *p)
{
- struct iface *iface;
struct ifa *a;
- WALK_LIST(iface, iface_list)
+ IFACE_WALK(iface)
{
- if (p->p.vrf && p->p.vrf != iface->master)
- if (p->p.vrf_set && !if_in_vrf(iface, p->p.vrf))
++ if (p->p.vrf && !if_in_vrf(iface, p->p.vrf))
continue;
if (! (iface->flags & IF_UP))
static void
ospf_reconfigure_ifaces3(struct ospf_proto *p)
{
- struct iface *iface;
struct ifa *a;
- WALK_LIST(iface, iface_list)
+ IFACE_WALK(iface)
{
- if (p->p.vrf && p->p.vrf != iface->master)
- if (p->p.vrf_set && !if_in_vrf(iface, p->p.vrf))
++ if (p->p.vrf && !if_in_vrf(iface, p->p.vrf))
continue;
if (! (iface->flags & IF_UP))
/* We started to accept routes so we need to refeed them */
if (!old->propagate_routes && new->propagate_routes)
- channel_request_feeding(p->p.main_channel);
+ channel_request_feeding_dynamic(p->p.main_channel, CFRT_DIRECT);
- struct iface *iface;
- WALK_LIST(iface, iface_list)
+ IFACE_WALK(iface)
{
- if (p->p.vrf && p->p.vrf != iface->master)
- if (p->p.vrf_set && !if_in_vrf(iface, p->p.vrf))
++ if (p->p.vrf && !if_in_vrf(iface, p->p.vrf))
continue;
if (!(iface->flags & IF_UP))
static void
rip_reconfigure_ifaces(struct rip_proto *p, struct rip_config *cf)
{
- struct iface *iface;
-
- WALK_LIST(iface, iface_list)
+ IFACE_WALK(iface)
{
- if (p->p.vrf && p->p.vrf != iface->master)
- if (p->p.vrf_set && !if_in_vrf(iface, p->p.vrf))
++ if (p->p.vrf && !if_in_vrf(iface, p->p.vrf))
continue;
if (!(iface->flags & IF_UP))