summaryrefslogtreecommitdiff
path: root/proto/bgp/packets.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/bgp/packets.c')
-rw-r--r--proto/bgp/packets.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index f0049d3a..0d1a3414 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -231,6 +231,32 @@ bgp_put_cap_err(struct bgp_proto *p UNUSED, byte *buf)
return buf;
}
+static byte *
+bgp_put_cap_llgr1(struct bgp_proto *p, byte *buf)
+{
+ *buf++ = 71; /* Capability 71: Support for long-lived graceful restart */
+ *buf++ = 7; /* Capability data length */
+
+ *buf++ = 0; /* Appropriate AF */
+ *buf++ = BGP_AF;
+ *buf++ = 1; /* and SAFI 1 */
+
+ /* Next is 8bit flags and 24bit time */
+ put_u32(buf, p->cf->llgr_time);
+ buf[0] = p->p.gr_recovery ? BGP_LLGRF_FORWARDING : 0;
+ buf += 4;
+
+ return buf;
+}
+
+static byte *
+bgp_put_cap_llgr2(struct bgp_proto *p UNUSED, byte *buf)
+{
+ *buf++ = 71; /* Capability 71: Support for long-lived graceful restart */
+ *buf++ = 0; /* Capability data length */
+ return buf;
+}
+
static byte *
bgp_create_open(struct bgp_conn *conn, byte *buf)
@@ -285,6 +311,11 @@ bgp_create_open(struct bgp_conn *conn, byte *buf)
if (p->cf->enable_extended_messages)
cap = bgp_put_cap_ext_msg(p, cap);
+ if (p->cf->llgr_mode == BGP_LLGR_ABLE)
+ cap = bgp_put_cap_llgr1(p, cap);
+ else if (p->cf->llgr_mode == BGP_LLGR_AWARE)
+ cap = bgp_put_cap_llgr2(p, cap);
+
cap_len = cap - buf - 12;
if (cap_len > 0)
{
@@ -872,11 +903,38 @@ bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
conn->peer_enhanced_refresh_support = 1;
break;
+ case 71: /* Long-lived graceful restart capability, RFC draft */
+ if (cl % 7)
+ goto err;
+ conn->peer_llgr_aware = 1;
+ conn->peer_llgr_able = 0;
+ conn->peer_llgr_time = 0;
+ conn->peer_llgr_aflags = 0;
+ for (i = 0; i < cl; i += 4)
+ if (opt[2+i+0] == 0 && opt[2+i+1] == BGP_AF && opt[2+i+2] == 1) /* Match AFI/SAFI */
+ {
+ conn->peer_llgr_able = 1;
+ conn->peer_llgr_time = get_u32(opt + 2+i+3) & 0xffffff;
+ conn->peer_llgr_aflags = opt[2+i+3];
+ }
+ break;
+
/* We can safely ignore all other capabilities */
}
len -= 2 + cl;
opt += 2 + cl;
}
+
+ /* The LLGR capability must be advertised together with the GR capability,
+ otherwise it must be disregarded */
+ if (!conn->peer_gr_aware && conn->peer_llgr_aware)
+ {
+ conn->peer_llgr_aware = 0;
+ conn->peer_llgr_able = 0;
+ conn->peer_llgr_time = 0;
+ conn->peer_llgr_aflags = 0;
+ }
+
return;
err:
@@ -1034,7 +1092,8 @@ bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
p->as4_session = p->cf->enable_as4 && conn->peer_as4_support;
p->add_path_rx = (p->cf->add_path & ADD_PATH_RX) && (conn->peer_add_path & ADD_PATH_TX);
p->add_path_tx = (p->cf->add_path & ADD_PATH_TX) && (conn->peer_add_path & ADD_PATH_RX);
- p->gr_ready = p->cf->gr_mode && conn->peer_gr_able;
+ p->gr_ready = (p->cf->gr_mode && conn->peer_gr_able) ||
+ (p->cf->llgr_mode && conn->peer_llgr_able);
p->ext_messages = p->cf->enable_extended_messages && conn->peer_ext_messages_support;
/* Update RA mode */
@@ -1125,6 +1184,7 @@ bgp_rte_update(struct bgp_proto *p, ip_addr prefix, int pxlen,
e->net = n;
e->pflags = 0;
e->u.bgp.suppressed = 0;
+ e->u.bgp.stale = -1;
rte_update2(p->p.main_ahook, n, e, *src);
}