Commit ffb38dfb authored by Ondřej Zajíček's avatar Ondřej Zajíček Committed by Jan Moskyto Matejka
Browse files

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.
parent 2faf519c
......@@ -1732,6 +1732,8 @@ bgp_reconfigure(struct proto *P, struct proto_config *CF)
return same;
}
#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
static int
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;
/* Check change in IGP tables */
rtable *old4 = old->igp_table_ip4 ? old->igp_table_ip4->table : NULL;
rtable *old6 = old->igp_table_ip6 ? old->igp_table_ip6->table : NULL;
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))
if ((IGP_TABLE(old, ip4) != IGP_TABLE(new, ip4)) ||
(IGP_TABLE(old, ip6) != IGP_TABLE(new, ip6)))
return 0;
c->cf = new;
......
......@@ -59,7 +59,14 @@ static_proto:
| static_proto proto_item ';'
| static_proto proto_channel ';' { this_proto->net_type = $2->net_type; }
| 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(); }
;
......
......@@ -49,13 +49,6 @@
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_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)
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 */
if (r->state == SRS_CLEAN)
......@@ -370,6 +366,16 @@ static_postconfig(struct proto_config *CF)
if (EMPTY_LIST(CF->channels))
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)
if (r->net && (r->net->type != CF->net_type))
cf_error("Route %N incompatible with channel type", r->net);
......@@ -379,14 +385,20 @@ static struct proto *
static_init(struct proto_config *CF)
{
struct proto *P = proto_new(CF);
// struct static_proto *p = (void *) P;
// struct static_config *cf = (void *) CF;
struct static_proto *p = (void *) P;
struct static_config *cf = (void *) CF;
P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
P->neigh_notify = static_neigh_notify;
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;
}
......@@ -400,8 +412,11 @@ static_start(struct proto *P)
if (!static_lp)
static_lp = lp_new(&root_pool, 1008);
if (cf->igp_table)
rt_lock_table(cf->igp_table->table);
if (p->igp_table_ip4)
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->hook = static_announce_marked;
......@@ -435,10 +450,13 @@ static_shutdown(struct proto *P)
static void
static_cleanup(struct proto *P)
{
struct static_config *cf = (void *) P->cf;
struct static_proto *p = (void *) P;
if (p->igp_table_ip4)
rt_unlock_table(p->igp_table_ip4);
if (cf->igp_table)
rt_unlock_table(cf->igp_table->table);
if (p->igp_table_ip6)
rt_unlock_table(p->igp_table_ip6);
}
static void
......@@ -465,11 +483,7 @@ static_dump(struct proto *P)
static_dump_rte(r);
}
static inline rtable *
cf_igp_table(struct static_config *cf)
{
return cf->igp_table ? cf->igp_table->table : NULL;
}
#define IGP_TABLE(cf, sym) ((cf)->igp_table_##sym ? (cf)->igp_table_##sym ->table : NULL )
static inline int
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_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;
if (!proto_configure_channel(P, &P->main_channel, proto_cf_main_channel(CF)))
......
......@@ -17,7 +17,8 @@ struct static_config {
struct proto_config c;
list routes; /* List of static routes (struct static_route) */
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 {
......@@ -25,6 +26,8 @@ struct static_proto {
struct event *event; /* Event for announcing updated routes */
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 {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment