diff options
Diffstat (limited to 'proto/ospf')
-rw-r--r-- | proto/ospf/config.Y | 1 | ||||
-rw-r--r-- | proto/ospf/hello.c | 3 | ||||
-rw-r--r-- | proto/ospf/iface.c | 14 | ||||
-rw-r--r-- | proto/ospf/neighbor.c | 30 | ||||
-rw-r--r-- | proto/ospf/neighbor.h | 1 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 4 | ||||
-rw-r--r-- | proto/ospf/topology.c | 3 |
7 files changed, 55 insertions, 1 deletions
diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 3f5419dd..68efa230 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -309,6 +309,7 @@ ospf_iface_item: | TX PRIORITY expr { OSPF_PATT->tx_priority = $3; } | TTL SECURITY bool { OSPF_PATT->ttl_security = $3; } | TTL SECURITY TX ONLY { OSPF_PATT->ttl_security = 2; } + | BFD bool { OSPF_PATT->bfd = $2; cf_check_bfd($2); } | password_list ; diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 68c345f4..b6b11004 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -151,6 +151,9 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa, #ifdef OSPFv3 n->iface_id = ntohl(ps->iface_id); #endif + + if (n->ifa->cf->bfd) + ospf_neigh_update_bfd(n, n->ifa->bfd); } #ifdef OSPFv3 /* NOTE: this could also be relevant for OSPFv2 on PtP ifaces */ else if (!ipa_equal(faddr, n->ip)) diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 63c26466..f1409840 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -536,6 +536,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i ifa->check_link = ip->check_link; ifa->ecmp_weight = ip->ecmp_weight; ifa->check_ttl = (ip->ttl_security == 1); + ifa->bfd = ip->bfd; #ifdef OSPFv2 ifa->autype = ip->autype; @@ -840,6 +841,19 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) ifa->ecmp_weight = new->ecmp_weight; } + /* BFD */ + if (ifa->bfd != new->bfd) + { + OSPF_TRACE(D_EVENTS, "%s BFD on interface %s", + new->bfd ? "Enabling" : "Disabling", ifname); + ifa->bfd = new->bfd; + + struct ospf_neighbor *n; + WALK_LIST(n, ifa->neigh_list) + ospf_neigh_update_bfd(n, ifa->bfd); + } + + /* instance_id is not updated - it is part of key */ return 1; diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index 26d81dce..61224ec2 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -582,6 +582,36 @@ ospf_neigh_remove(struct ospf_neighbor *n) OSPF_TRACE(D_EVENTS, "Deleting neigbor."); } +static void +ospf_neigh_bfd_hook(struct bfd_request *req) +{ + struct ospf_neighbor *n = req->data; + struct proto *p = &n->ifa->oa->po->proto; + + if (req->down) + { + OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s", + n->ip, n->ifa->iface->name); + + ospf_neigh_remove(n); + } +} + +void +ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd) +{ + if (use_bfd && !n->bfd_req) + n->bfd_req = bfd_request_session(n->pool, n->ip, n->ifa->addr->ip, n->ifa->iface, + ospf_neigh_bfd_hook, n); + + if (!use_bfd && n->bfd_req) + { + rfree(n->bfd_req); + n->bfd_req = NULL; + } +} + + void ospf_sh_neigh_info(struct ospf_neighbor *n) { diff --git a/proto/ospf/neighbor.h b/proto/ospf/neighbor.h index f593faed..e674927d 100644 --- a/proto/ospf/neighbor.h +++ b/proto/ospf/neighbor.h @@ -16,6 +16,7 @@ void bdr_election(struct ospf_iface *ifa); struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid); struct ospf_neighbor *find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip); void ospf_neigh_remove(struct ospf_neighbor *n); +void ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd); void ospf_sh_neigh_info(struct ospf_neighbor *n); #endif /* _BIRD_OSPF_NEIGHBOR_H_ */ diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index f1409af3..46a1c3c1 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -46,6 +46,7 @@ do { if ((p->debug & D_PACKETS) || OSPF_FORCE_DEBUG) \ #include "nest/route.h" #include "nest/cli.h" #include "nest/locks.h" +#include "nest/bfd.h" #include "conf/conf.h" #include "lib/string.h" @@ -276,6 +277,7 @@ struct ospf_iface u8 ecmp_weight; /* Weight used for ECMP */ u8 ptp_netmask; /* Send real netmask for P2P */ u8 check_ttl; /* Check incoming packets for TTL 255 */ + u8 bfd; /* Use BFD on iface */ }; struct ospf_md5 @@ -708,6 +710,7 @@ struct ospf_neighbor #define ACKL_DIRECT 0 #define ACKL_DELAY 1 timer *ackd_timer; /* Delayed ack timer */ + struct bfd_request *bfd_req; /* BFD request, if BFD is used */ u32 csn; /* Last received crypt seq number (for MD5) */ }; @@ -818,6 +821,7 @@ struct ospf_iface_patt u8 real_bcast; /* Not really used in OSPFv3 */ u8 ptp_netmask; /* bool + 2 for unspecified */ u8 ttl_security; /* bool + 2 for TX only */ + u8 bfd; #ifdef OSPFv2 list *passwords; diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 5d93c0e9..f25db9a7 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -103,7 +103,8 @@ lsab_alloc(struct proto_ospf *po, unsigned size) if (po->lsab_used > po->lsab_size) { po->lsab_size = MAX(po->lsab_used, 2 * po->lsab_size); - po->lsab = mb_realloc(po->proto.pool, po->lsab, po->lsab_size); + po->lsab = po->lsab ? mb_realloc(po->lsab, po->lsab_size): + mb_alloc(po->proto.pool, po->lsab_size); } return ((byte *) po->lsab) + offset; } |