Static: Support for dual-AF IGP tables
When recursive routes with hybrid next hops (e.g. IPv6 route with IPv4 next hop) are allowed, we need both IPv4 and IPv6 IGP tables.
This commit is contained in:
parent
2faf519cf9
commit
ffb38dfb8b
4 changed files with 53 additions and 29 deletions
|
@ -1732,6 +1732,8 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
|
||||||
return same;
|
return same;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bgp_channel_reconfigure(struct channel *C, struct channel_config *CC)
|
bgp_channel_reconfigure(struct channel *C, struct channel_config *CC)
|
||||||
{
|
{
|
||||||
|
@ -1746,12 +1748,8 @@ bgp_channel_reconfigure(struct channel *C, struct channel_config *CC)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check change in IGP tables */
|
/* Check change in IGP tables */
|
||||||
rtable *old4 = old->igp_table_ip4 ? old->igp_table_ip4->table : NULL;
|
if ((IGP_TABLE(old, ip4) != IGP_TABLE(new, ip4)) ||
|
||||||
rtable *old6 = old->igp_table_ip6 ? old->igp_table_ip6->table : NULL;
|
(IGP_TABLE(old, ip6) != IGP_TABLE(new, ip6)))
|
||||||
rtable *new4 = new->igp_table_ip4 ? new->igp_table_ip4->table : NULL;
|
|
||||||
rtable *new6 = new->igp_table_ip6 ? new->igp_table_ip6->table : NULL;
|
|
||||||
|
|
||||||
if ((old4 != new4) || (old6 != new6))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
c->cf = new;
|
c->cf = new;
|
||||||
|
|
|
@ -59,7 +59,14 @@ static_proto:
|
||||||
| static_proto proto_item ';'
|
| static_proto proto_item ';'
|
||||||
| static_proto proto_channel ';' { this_proto->net_type = $2->net_type; }
|
| static_proto proto_channel ';' { this_proto->net_type = $2->net_type; }
|
||||||
| static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
|
| static_proto CHECK LINK bool ';' { STATIC_CFG->check_link = $4; }
|
||||||
| static_proto IGP TABLE rtable ';' { STATIC_CFG->igp_table = $4; }
|
| static_proto IGP TABLE rtable ';' {
|
||||||
|
if ($4->addr_type == NET_IP4)
|
||||||
|
STATIC_CFG->igp_table_ip4 = $4;
|
||||||
|
else if ($4->addr_type == NET_IP6)
|
||||||
|
STATIC_CFG->igp_table_ip6 = $4;
|
||||||
|
else
|
||||||
|
cf_error("Incompatible IGP table type");
|
||||||
|
}
|
||||||
| static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
|
| static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -49,13 +49,6 @@
|
||||||
|
|
||||||
static linpool *static_lp;
|
static linpool *static_lp;
|
||||||
|
|
||||||
static inline rtable *
|
|
||||||
p_igp_table(struct static_proto *p)
|
|
||||||
{
|
|
||||||
struct static_config *cf = (void *) p->p.cf;
|
|
||||||
return cf->igp_table ? cf->igp_table->table : p->p.main_channel->table;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
static_announce_rte(struct static_proto *p, struct static_route *r)
|
static_announce_rte(struct static_proto *p, struct static_route *r)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +88,10 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r->dest == RTDX_RECURSIVE)
|
if (r->dest == RTDX_RECURSIVE)
|
||||||
rta_set_recursive_next_hop(p->p.main_channel->table, a, p_igp_table(p), r->via, IPA_NONE, r->mls);
|
{
|
||||||
|
rtable *tab = ipa_is_ip4(r->via) ? p->igp_table_ip4 : p->igp_table_ip6;
|
||||||
|
rta_set_recursive_next_hop(p->p.main_channel->table, a, tab, r->via, IPA_NONE, r->mls);
|
||||||
|
}
|
||||||
|
|
||||||
/* Already announced */
|
/* Already announced */
|
||||||
if (r->state == SRS_CLEAN)
|
if (r->state == SRS_CLEAN)
|
||||||
|
@ -370,6 +366,16 @@ static_postconfig(struct proto_config *CF)
|
||||||
if (EMPTY_LIST(CF->channels))
|
if (EMPTY_LIST(CF->channels))
|
||||||
cf_error("Channel not specified");
|
cf_error("Channel not specified");
|
||||||
|
|
||||||
|
struct channel_config *cc = proto_cf_main_channel(CF);
|
||||||
|
|
||||||
|
if (!cf->igp_table_ip4)
|
||||||
|
cf->igp_table_ip4 = (cc->table->addr_type == NET_IP4) ?
|
||||||
|
cc->table : cf->c.global->def_tables[NET_IP4];
|
||||||
|
|
||||||
|
if (!cf->igp_table_ip6)
|
||||||
|
cf->igp_table_ip6 = (cc->table->addr_type == NET_IP6) ?
|
||||||
|
cc->table : cf->c.global->def_tables[NET_IP6];
|
||||||
|
|
||||||
WALK_LIST(r, cf->routes)
|
WALK_LIST(r, cf->routes)
|
||||||
if (r->net && (r->net->type != CF->net_type))
|
if (r->net && (r->net->type != CF->net_type))
|
||||||
cf_error("Route %N incompatible with channel type", r->net);
|
cf_error("Route %N incompatible with channel type", r->net);
|
||||||
|
@ -379,14 +385,20 @@ static struct proto *
|
||||||
static_init(struct proto_config *CF)
|
static_init(struct proto_config *CF)
|
||||||
{
|
{
|
||||||
struct proto *P = proto_new(CF);
|
struct proto *P = proto_new(CF);
|
||||||
// struct static_proto *p = (void *) P;
|
struct static_proto *p = (void *) P;
|
||||||
// struct static_config *cf = (void *) CF;
|
struct static_config *cf = (void *) CF;
|
||||||
|
|
||||||
P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
|
P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
|
||||||
|
|
||||||
P->neigh_notify = static_neigh_notify;
|
P->neigh_notify = static_neigh_notify;
|
||||||
P->rte_mergable = static_rte_mergable;
|
P->rte_mergable = static_rte_mergable;
|
||||||
|
|
||||||
|
if (cf->igp_table_ip4)
|
||||||
|
p->igp_table_ip4 = cf->igp_table_ip4->table;
|
||||||
|
|
||||||
|
if (cf->igp_table_ip6)
|
||||||
|
p->igp_table_ip6 = cf->igp_table_ip6->table;
|
||||||
|
|
||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,8 +412,11 @@ static_start(struct proto *P)
|
||||||
if (!static_lp)
|
if (!static_lp)
|
||||||
static_lp = lp_new(&root_pool, 1008);
|
static_lp = lp_new(&root_pool, 1008);
|
||||||
|
|
||||||
if (cf->igp_table)
|
if (p->igp_table_ip4)
|
||||||
rt_lock_table(cf->igp_table->table);
|
rt_lock_table(p->igp_table_ip4);
|
||||||
|
|
||||||
|
if (p->igp_table_ip6)
|
||||||
|
rt_lock_table(p->igp_table_ip6);
|
||||||
|
|
||||||
p->event = ev_new(p->p.pool);
|
p->event = ev_new(p->p.pool);
|
||||||
p->event->hook = static_announce_marked;
|
p->event->hook = static_announce_marked;
|
||||||
|
@ -435,10 +450,13 @@ static_shutdown(struct proto *P)
|
||||||
static void
|
static void
|
||||||
static_cleanup(struct proto *P)
|
static_cleanup(struct proto *P)
|
||||||
{
|
{
|
||||||
struct static_config *cf = (void *) P->cf;
|
struct static_proto *p = (void *) P;
|
||||||
|
|
||||||
if (cf->igp_table)
|
if (p->igp_table_ip4)
|
||||||
rt_unlock_table(cf->igp_table->table);
|
rt_unlock_table(p->igp_table_ip4);
|
||||||
|
|
||||||
|
if (p->igp_table_ip6)
|
||||||
|
rt_unlock_table(p->igp_table_ip6);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -465,11 +483,7 @@ static_dump(struct proto *P)
|
||||||
static_dump_rte(r);
|
static_dump_rte(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline rtable *
|
#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
|
||||||
cf_igp_table(struct static_config *cf)
|
|
||||||
{
|
|
||||||
return cf->igp_table ? cf->igp_table->table : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
static_cmp_rte(const void *X, const void *Y)
|
static_cmp_rte(const void *X, const void *Y)
|
||||||
|
@ -486,7 +500,9 @@ static_reconfigure(struct proto *P, struct proto_config *CF)
|
||||||
struct static_config *n = (void *) CF;
|
struct static_config *n = (void *) CF;
|
||||||
struct static_route *r, *r2, *or, *nr;
|
struct static_route *r, *r2, *or, *nr;
|
||||||
|
|
||||||
if (cf_igp_table(o) != cf_igp_table(n))
|
/* Check change in IGP tables */
|
||||||
|
if ((IGP_TABLE(o, ip4) != IGP_TABLE(n, ip4)) ||
|
||||||
|
(IGP_TABLE(o, ip6) != IGP_TABLE(n, ip6)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
|
if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
|
||||||
|
|
|
@ -17,7 +17,8 @@ struct static_config {
|
||||||
struct proto_config c;
|
struct proto_config c;
|
||||||
list routes; /* List of static routes (struct static_route) */
|
list routes; /* List of static routes (struct static_route) */
|
||||||
int check_link; /* Whether iface link state is used */
|
int check_link; /* Whether iface link state is used */
|
||||||
struct rtable_config *igp_table; /* Table used for recursive next hop lookups */
|
struct rtable_config *igp_table_ip4; /* Table for recursive IPv4 next hop lookups */
|
||||||
|
struct rtable_config *igp_table_ip6; /* Table for recursive IPv6 next hop lookups */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct static_proto {
|
struct static_proto {
|
||||||
|
@ -25,6 +26,8 @@ struct static_proto {
|
||||||
|
|
||||||
struct event *event; /* Event for announcing updated routes */
|
struct event *event; /* Event for announcing updated routes */
|
||||||
BUFFER(struct static_route *) marked; /* Routes marked for reannouncement */
|
BUFFER(struct static_route *) marked; /* Routes marked for reannouncement */
|
||||||
|
rtable *igp_table_ip4; /* Table for recursive IPv4 next hop lookups */
|
||||||
|
rtable *igp_table_ip6; /* Table for recursive IPv6 next hop lookups */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct static_route {
|
struct static_route {
|
||||||
|
|
Loading…
Reference in a new issue