summaryrefslogtreecommitdiff
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2018-07-31 18:40:38 +0200
committerOndrej Zajicek (work) <santiago@crfreenet.org>2018-07-31 18:40:38 +0200
commit5bd734317c05008a66eefaa14fc98a6d533cf9ef (patch)
treeafe7e898b8eca7916b52c71eaa0b133c2809f03c /proto/bgp/packets.c
parent318acb0f6cb77a32aad5d7f79e06f3c5065ac702 (diff)
BGP: Long-lived graceful restart
The patch implements long-lived graceful restart for BGP, namely draft-uttaro-idr-bgp-persistence-03.
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c75
1 files changed, 72 insertions, 3 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index c40b8ec2..ed1db04b 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -260,6 +260,9 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
caps->gr_flags = p->p.gr_recovery ? BGP_GRF_RESTART : 0;
}
+ if (p->cf->llgr_mode)
+ caps->llgr_aware = 1;
+
/* Allocate and fill per-AF fields */
WALK_LIST(c, p->p.channels)
{
@@ -280,6 +283,15 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
if (p->p.gr_recovery)
ac->gr_af_flags |= BGP_GRF_FORWARDING;
}
+
+ if (c->cf->llgr_able)
+ {
+ ac->llgr_able = 1;
+ ac->llgr_time = c->cf->llgr_time;
+
+ if (p->p.gr_recovery)
+ ac->llgr_flags |= BGP_LLGRF_FORWARDING;
+ }
}
/* Sort capability fields by AFI/SAFI */
@@ -289,9 +301,9 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
/* Create capability list in buffer */
/*
- * Note that max length is ~ 20+14*af_count. With max 12 channels that is
- * 188. Option limit is 253 and buffer size is 4096, so we cannot overflow
- * unless we add new capabilities or more AFs.
+ * Note that max length is ~ 22+21*af_count. With max 12 channels that is
+ * 274. Option limit is 253 and buffer size is 4096, so we cannot overflow
+ * unless we add new capabilities or more AFs. XXXXX
*/
WALK_AF_CAPS(caps, ac)
@@ -384,6 +396,24 @@ bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
*buf++ = 0; /* Capability data length */
}
+ if (caps->llgr_aware)
+ {
+ *buf++ = 71; /* Capability 71: Support for long-lived graceful restart */
+ *buf++ = 0; /* Capability data length, will be fixed later */
+ data = buf;
+
+ WALK_AF_CAPS(caps, ac)
+ if (ac->llgr_able)
+ {
+ put_af3(buf, ac->afi);
+ buf[3] = ac->llgr_flags;
+ put_u24(buf+4, ac->llgr_time);
+ buf += 7;
+ }
+
+ data[-1] = buf - data;
+ }
+
return buf;
}
@@ -508,11 +538,49 @@ bgp_read_capabilities(struct bgp_conn *conn, struct bgp_caps *caps, byte *pos, i
caps->enhanced_refresh = 1;
break;
+ case 71: /* Long lived graceful restart capability, RFC draft */
+ if (cl % 7)
+ goto err;
+
+ /* Presumably, only the last instance is valid */
+ WALK_AF_CAPS(caps, ac)
+ {
+ ac->llgr_able = 0;
+ ac->llgr_flags = 0;
+ ac->llgr_time = 0;
+ }
+
+ caps->llgr_aware = 1;
+
+ for (i = 0; i < cl; i += 7)
+ {
+ af = get_af3(pos+2+i);
+ ac = bgp_get_af_caps(caps, af);
+ ac->llgr_able = 1;
+ ac->llgr_flags = pos[2+i+3];
+ ac->llgr_time = get_u24(pos + 2+i+4);
+ }
+ break;
+
/* We can safely ignore all other capabilities */
}
ADVANCE(pos, len, 2 + cl);
}
+
+ /* The LLGR capability must be advertised together with the GR capability,
+ otherwise it must be disregarded */
+ if (!caps->gr_aware && caps->llgr_aware)
+ {
+ caps->llgr_aware = 0;
+ WALK_AF_CAPS(caps, ac)
+ {
+ ac->llgr_able = 0;
+ ac->llgr_flags = 0;
+ ac->llgr_time = 0;
+ }
+ }
+
return;
err:
@@ -1131,6 +1199,7 @@ bgp_rte_update(struct bgp_parse_state *s, net_addr *n, u32 path_id, rta *a0)
e->pflags = 0;
e->u.bgp.suppressed = 0;
+ e->u.bgp.stale = -1;
rte_update2(&s->channel->c, n, e, s->last_src);
}