diff options
-rw-r--r-- | bgpd/bgp_bfd.c | 98 | ||||
-rw-r--r-- | lib/bfd.c | 152 | ||||
-rw-r--r-- | lib/bfd.h | 22 | ||||
-rw-r--r-- | lib/log.c | 2 | ||||
-rw-r--r-- | lib/zclient.c | 6 | ||||
-rw-r--r-- | lib/zclient.h | 2 | ||||
-rw-r--r-- | lib/zebra.h | 2 | ||||
-rw-r--r-- | ospf6d/ospf6_bfd.c | 95 | ||||
-rw-r--r-- | ospf6d/ospf6_bfd.h | 10 | ||||
-rw-r--r-- | ospf6d/ospf6_interface.c | 5 | ||||
-rw-r--r-- | ospf6d/ospf6_interface.h | 2 | ||||
-rw-r--r-- | ospf6d/ospf6_neighbor.c | 4 | ||||
-rw-r--r-- | ospf6d/ospf6_neighbor.h | 3 | ||||
-rw-r--r-- | ospfd/ospf_bfd.c | 117 | ||||
-rw-r--r-- | ospfd/ospf_bfd.h | 16 | ||||
-rw-r--r-- | ospfd/ospf_neighbor.c | 4 | ||||
-rw-r--r-- | ospfd/ospf_neighbor.h | 3 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 3 | ||||
-rw-r--r-- | zebra/zebra_ptm.c | 76 | ||||
-rw-r--r-- | zebra/zebra_ptm_null.c | 2 | ||||
-rw-r--r-- | zebra/zebra_ptm_redistribute.c | 11 | ||||
-rw-r--r-- | zebra/zebra_ptm_redistribute.h | 2 |
22 files changed, 497 insertions, 140 deletions
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 22b8adcdb..5505ced92 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -73,7 +73,8 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) static int bgp_bfd_is_peer_multihop(struct peer *peer) { - if((peer->sort == BGP_PEER_IBGP) || is_ebgp_multihop_configured(peer)) + if((peer->conf_if == NULL) && ((peer->sort == BGP_PEER_IBGP) || + is_ebgp_multihop_configured(peer))) return 1; else return 0; @@ -191,19 +192,46 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length) } /* - * bgp_interface_bfd_dest_down - Find the peer for which the BFD status - * has changed and bring down the peer - * connectivity. + * bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring + * down the peer if the BFD session went down from * up. + */ +static void +bgp_bfd_peer_status_update (struct peer *peer, int status) +{ + struct bfd_info *bfd_info; + int old_status; + + bfd_info = (struct bfd_info *)peer->bfd_info; + + if (bfd_info->status == status) + return; + + old_status = bfd_info->status; + bfd_info->status = status; + bfd_info->last_update = bgp_clock(); + + if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) + { + peer->last_reset = PEER_DOWN_BFD_DOWN; + BGP_EVENT_ADD (peer, BGP_Stop); + } +} + +/* + * bgp_bfd_dest_update - Find the peer for which the BFD status + * has changed and bring down the peer + * connectivity if the BFD session went down. */ static int -bgp_interface_bfd_dest_down (int command, struct zclient *zclient, +bgp_bfd_dest_update (int command, struct zclient *zclient, zebra_size_t length) { struct interface *ifp; struct prefix dp; struct prefix sp; + int status; - ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp); + ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp, &status); if (BGP_DEBUG (zebra, ZEBRA)) { @@ -211,14 +239,14 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient, prefix2str(&dp, buf[0], sizeof(buf[0])); if (ifp) { - zlog_debug("Zebra: interface %s bfd destination %s down", - ifp->name, buf[0]); + zlog_debug("Zebra: interface %s bfd destination %s %s", + ifp->name, buf[0], bfd_get_status_str(status)); } else { prefix2str(&sp, buf[1], sizeof(buf[1])); - zlog_debug("Zebra: source %s bfd destination %s down", - buf[1], buf[0]); + zlog_debug("Zebra: source %s bfd destination %s %s", + buf[1], buf[0], bfd_get_status_str(status)); } } @@ -253,8 +281,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient, if (ifp && (ifp == peer->nexthop.ifp)) { - peer->last_reset = PEER_DOWN_BFD_DOWN; - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_bfd_peer_status_update(peer, status); } else { @@ -279,8 +306,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient, else continue; - peer->last_reset = PEER_DOWN_BFD_DOWN; - BGP_EVENT_ADD (peer, BGP_Stop); + bgp_bfd_peer_status_update(peer, status); } } } @@ -299,8 +325,8 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx, struct listnode *node, *nnode; int command = 0; - bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult, - defaults, &command); + bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, + detect_mult, defaults, &command); if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { @@ -308,8 +334,8 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx, for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) { command = 0; - bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult, - defaults, &command); + bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx, + detect_mult, defaults, &command); if ((peer->status == Established) && (command == ZEBRA_BFD_DEST_REGISTER)) @@ -386,38 +412,8 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) void bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh) { - struct bfd_info *bfd_info; - json_object *json_bfd = NULL; - - if (!peer->bfd_info) - return; - - if (use_json) - json_bfd = json_object_new_object(); - - bfd_info = (struct bfd_info *)peer->bfd_info; - - if (use_json) - { - if (bgp_bfd_is_peer_multihop(peer)) - json_object_string_add(json_bfd, "bfdMultiHop", "yes"); - else - json_object_string_add(json_bfd, "bfdMultiHop", "no"); - json_object_int_add(json_bfd, "detectMultiplier", bfd_info->detect_mult); - json_object_int_add(json_bfd, "rxMinInterval", bfd_info->required_min_rx); - json_object_int_add(json_bfd, "txMinInterval", bfd_info->desired_min_tx); - json_object_object_add(json_neigh, "peerBfdInfo", json_bfd); - } - else - { - vty_out (vty, " BFD: Multi-hop: %s%s", - (bgp_bfd_is_peer_multihop(peer)) ? "yes" : "no", VTY_NEWLINE); - vty_out (vty, " Detect Mul: %d, Min Rx interval: %d," - " Min Tx interval: %d%s", - bfd_info->detect_mult, bfd_info->required_min_rx, - bfd_info->desired_min_tx, VTY_NEWLINE); - vty_out (vty, "%s", VTY_NEWLINE); - } + bfd_show_info(vty, (struct bfd_info *)peer->bfd_info, + bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh); } DEFUN (neighbor_bfd, @@ -501,7 +497,7 @@ void bgp_bfd_init(void) { /* Initialize BFD client functions */ - zclient->interface_bfd_dest_down = bgp_interface_bfd_dest_down; + zclient->interface_bfd_dest_update = bgp_bfd_dest_update; zclient->bfd_dest_replay = bgp_bfd_dest_replay; /* "neighbor bfd" commands. */ @@ -44,6 +44,8 @@ bfd_info_create(void) bfd_info = XCALLOC (MTYPE_BFD_INFO, sizeof (struct bfd_info)); assert(bfd_info); + bfd_info->status = BFD_STATUS_UNKNOWN; + bfd_info->last_update = 0; return bfd_info; } @@ -247,7 +249,8 @@ bfd_get_command_dbg_str(int command) * went down from the message sent from Zebra to clients. */ struct interface * -bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp) +bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp, + int *status) { unsigned int ifindex; struct interface *ifp = NULL; @@ -275,6 +278,9 @@ bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp) stream_get (&dp->u.prefix, s, plen); dp->prefixlen = stream_getc (s); + /* Get BFD status. */ + *status = stream_getl (s); + if (sp) { sp->family = stream_getc (s); @@ -285,3 +291,147 @@ bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp) } return ifp; } + +/* + * bfd_get_status_str - Convert BFD status to a display string. + */ +const char * +bfd_get_status_str(int status) +{ + switch (status) + { + case BFD_STATUS_DOWN: + return "Down"; + case BFD_STATUS_UP: + return "Up"; + case BFD_STATUS_UNKNOWN: + default: + return "Unknown"; + } +} + +/* + * bfd_last_update - Calculate the last BFD update time and convert it + * into a dd:hh:mm:ss display format. + */ +static void +bfd_last_update (time_t last_update, char *buf, size_t len) +{ + time_t curr; + time_t diff; + struct tm *tm; + struct timeval tv; + + /* If no BFD satatus update has ever been received, print `never'. */ + if (last_update == 0) + { + snprintf (buf, len, "never"); + return; + } + + /* Get current time. */ + quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv); + curr = tv.tv_sec; + diff = curr - last_update; + tm = gmtime (&diff); + + snprintf (buf, len, "%d:%02d:%02d:%02d", + tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +/* + * bfd_show_param - Show the BFD parameter information. + */ +void +bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, + int extra_space, u_char use_json, json_object *json_obj) +{ + json_object *json_bfd = NULL; + + if (!bfd_info) + return; + + if (use_json) + { + if (bfd_tag) + json_bfd = json_object_new_object(); + else + json_bfd = json_obj; + + json_object_int_add(json_bfd, "detectMultiplier", bfd_info->detect_mult); + json_object_int_add(json_bfd, "rxMinInterval", bfd_info->required_min_rx); + json_object_int_add(json_bfd, "txMinInterval", bfd_info->desired_min_tx); + if (bfd_tag) + json_object_object_add(json_obj, "peerBfdInfo", json_bfd); + } + else + { + vty_out (vty, " %s%sDetect Mul: %d, Min Rx interval: %d," + " Min Tx interval: %d%s", + (extra_space) ? " ": "", (bfd_tag) ? "BFD: " : " ", + bfd_info->detect_mult, bfd_info->required_min_rx, + bfd_info->desired_min_tx, VTY_NEWLINE); + } +} + +/* + * bfd_show_status - Show the BFD status information. + */ +static void +bfd_show_status(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, + int extra_space, u_char use_json, json_object *json_bfd) +{ + char time_buf[32]; + + if (!bfd_info) + return; + + bfd_last_update(bfd_info->last_update, time_buf, 32); + if (use_json) + { + json_object_string_add(json_bfd, "status", + bfd_get_status_str(bfd_info->status)); + json_object_string_add(json_bfd, "lastUpdate", time_buf); + } + else + { + vty_out (vty, " %s%sStatus: %s, Last update: %s%s", + (extra_space) ? " ": "", (bfd_tag) ? "BFD: " : " ", + bfd_get_status_str(bfd_info->status), time_buf, VTY_NEWLINE); + } +} + +/* + * bfd_show_info - Show the BFD information. + */ +void +bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop, + int extra_space, u_char use_json, json_object *json_obj) +{ + json_object *json_bfd = NULL; + + if (!bfd_info) + return; + + if (use_json) + { + json_bfd = json_object_new_object(); + if (multihop) + json_object_string_add(json_bfd, "type", "multi hop"); + else + json_object_string_add(json_bfd, "type", "single hop"); + } + else + { + vty_out (vty, " %sBFD: Type: %s%s", (extra_space) ? " " : "", + (multihop) ? "multi hop" : "single hop", VTY_NEWLINE); + } + + bfd_show_param(vty, bfd_info, 0, extra_space, use_json, json_bfd); + bfd_show_status(vty, bfd_info, 0, extra_space, use_json, json_bfd); + + if (use_json) + json_object_object_add(json_obj, "peerBfdInfo", json_bfd); + else + vty_out (vty, "%s", VTY_NEWLINE); +} @@ -24,6 +24,8 @@ #ifndef _ZEBRA_BFD_H #define _ZEBRA_BFD_H +#include "lib/json.h" + #define BFD_CMD_DETECT_MULT_RANGE "<2-255> " #define BFD_CMD_MIN_RX_RANGE "<50-60000> " #define BFD_CMD_MIN_TX_RANGE "<50-60000>" @@ -41,12 +43,18 @@ #define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */ #define BFD_FLAG_BFD_REG (1 << 1) /* Peer registered with BFD */ +#define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */ +#define BFD_STATUS_DOWN (1 << 1) /* BFD session status is down */ +#define BFD_STATUS_UP (1 << 2) /* BFD session status is up */ + struct bfd_info { u_int16_t flags; u_int8_t detect_mult; u_int32_t desired_min_tx; u_int32_t required_min_rx; + time_t last_update; + u_int8_t status; }; extern struct bfd_info * @@ -72,6 +80,18 @@ extern const char * bfd_get_command_dbg_str(int command); extern struct interface * -bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp); +bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp, + int *status); + +const char * +bfd_get_status_str(int status); + +extern void +bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag, + int extra_space, u_char use_json, json_object *json_obj); + +extern void +bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop, + int extra_space, u_char use_json, json_object *json_obj); #endif /* _ZEBRA_BFD_H */ @@ -836,7 +836,7 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY (ZEBRA_INTERFACE_NBR_ADDRESS_ADD), DESC_ENTRY (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE), DESC_ENTRY (ZEBRA_IMPORT_CHECK_UPDATE), - DESC_ENTRY (ZEBRA_INTERFACE_BFD_DEST_DOWN), + DESC_ENTRY (ZEBRA_INTERFACE_BFD_DEST_UPDATE), DESC_ENTRY (ZEBRA_BFD_DEST_REGISTER), DESC_ENTRY (ZEBRA_BFD_DEST_DEREGISTER), DESC_ENTRY (ZEBRA_BFD_DEST_UPDATE), diff --git a/lib/zclient.c b/lib/zclient.c index 39b6f8ec5..35b18cb95 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1208,9 +1208,9 @@ zclient_read (struct thread *thread) if (zclient->interface_address_delete) (*zclient->interface_address_delete) (command, zclient, length); break; - case ZEBRA_INTERFACE_BFD_DEST_DOWN: - if (zclient->interface_bfd_dest_down) - (*zclient->interface_bfd_dest_down) (command, zclient, length); + case ZEBRA_INTERFACE_BFD_DEST_UPDATE: + if (zclient->interface_bfd_dest_update) + (*zclient->interface_bfd_dest_update) (command, zclient, length); break; case ZEBRA_INTERFACE_NBR_ADDRESS_ADD: if (zclient->interface_nbr_address_add) diff --git a/lib/zclient.h b/lib/zclient.h index 26cae0434..6ed4fede4 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -85,7 +85,7 @@ struct zclient int (*interface_down) (int, struct zclient *, uint16_t); int (*interface_address_add) (int, struct zclient *, uint16_t); int (*interface_address_delete) (int, struct zclient *, uint16_t); - int (*interface_bfd_dest_down) (int, struct zclient *, uint16_t); + int (*interface_bfd_dest_update) (int, struct zclient *, uint16_t); int (*interface_nbr_address_add) (int, struct zclient *, uint16_t); int (*interface_nbr_address_delete) (int, struct zclient *, uint16_t); int (*ipv4_route_add) (int, struct zclient *, uint16_t); diff --git a/lib/zebra.h b/lib/zebra.h index 387cd6541..41de01ec2 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -429,7 +429,7 @@ struct in_pktinfo #define ZEBRA_NEXTHOP_UPDATE 26 #define ZEBRA_INTERFACE_NBR_ADDRESS_ADD 27 #define ZEBRA_INTERFACE_NBR_ADDRESS_DELETE 28 -#define ZEBRA_INTERFACE_BFD_DEST_DOWN 29 +#define ZEBRA_INTERFACE_BFD_DEST_UPDATE 29 #define ZEBRA_IMPORT_ROUTE_REGISTER 30 #define ZEBRA_IMPORT_ROUTE_UNREGISTER 31 #define ZEBRA_IMPORT_CHECK_UPDATE 32 diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c index e30f4962d..5ef4ab4ca 100644 --- a/ospf6d/ospf6_bfd.c +++ b/ospf6d/ospf6_bfd.c @@ -46,6 +46,27 @@ extern struct zclient *zclient; /* + * ospf6_bfd_info_free - Free BFD info structure + */ +void +ospf6_bfd_info_free(void **bfd_info) +{ + bfd_info_free((struct bfd_info **) bfd_info); +} + +/* + * ospf6_bfd_show_info - Show BFD info structure + */ +void +ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only) +{ + if (param_only) + bfd_show_param(vty, bfd_info, 1, 0, 0, NULL); + else + bfd_show_info(vty, bfd_info, 0, 1, 0, NULL); +} + +/* * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through * zebra for starting/stopping the monitoring of * the neighbor rechahability. @@ -102,6 +123,11 @@ ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface *oi, int command) for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on)) { + if (command != ZEBRA_BFD_DEST_DEREGISTER) + ospf6_bfd_info_nbr_create(oi, on); + else + bfd_info_free((struct bfd_info **)&on->bfd_info); + if (on->state < OSPF6_NEIGHBOR_TWOWAY) continue; @@ -151,13 +177,13 @@ ospf6_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length) } /* - * ospf6_bfd_interface_dest_down - Find the neighbor for which the BFD status - * has changed and bring down the neighbor - * connectivity. + * ospf6_bfd_interface_dest_update - Find the neighbor for which the BFD status + * has changed and bring down the neighbor + * connectivity if BFD down is received. */ static int -ospf6_bfd_interface_dest_down (int command, struct zclient *zclient, - zebra_size_t length) +ospf6_bfd_interface_dest_update (int command, struct zclient *zclient, + zebra_size_t length) { struct interface *ifp; struct ospf6_interface *oi; @@ -166,8 +192,12 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient, struct prefix sp; struct listnode *node, *nnode; char dst[64]; + int status; + int old_status; + struct bfd_info *bfd_info; + struct timeval tv; - ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp); + ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status); if ((ifp == NULL) || (dp.family != AF_INET6)) return 0; @@ -176,7 +206,8 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient, { char buf[128]; prefix2str(&dp, buf, sizeof(buf)); - zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf); + zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf, + bfd_get_status_str(status)); } @@ -192,17 +223,57 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient, if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) { inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst)); - zlog_debug ("[%s:%s]: BFD Down", ifp->name, dst); + zlog_debug ("[%s:%s]: BFD %s", ifp->name, dst, + bfd_get_status_str(status)); } - THREAD_OFF (on->inactivity_timer); - thread_add_event (master, inactivity_timer, on, 0); + if (!on->bfd_info) + continue; + + bfd_info = (struct bfd_info *)on->bfd_info; + if (bfd_info->status == status) + continue; + + old_status = bfd_info->status; + bfd_info->status = status; + quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv); + bfd_info->last_update = tv.tv_sec; + + if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) + { + THREAD_OFF (on->inactivity_timer); + thread_add_event (master, inactivity_timer, on, 0); + } } return 0; } /* + * ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor. + */ +void +ospf6_bfd_info_nbr_create (struct ospf6_interface *oi, + struct ospf6_neighbor *on) +{ + struct bfd_info *oi_bfd_info; + struct bfd_info *on_bfd_info; + + if (!oi->bfd_info) + return; + + oi_bfd_info = (struct bfd_info *)oi->bfd_info; + + if (!on->bfd_info) + on->bfd_info = bfd_info_create(); + + on_bfd_info = (struct bfd_info *)on->bfd_info; + on_bfd_info->detect_mult = oi_bfd_info->detect_mult; + on_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx; + on_bfd_info->required_min_rx = oi_bfd_info->required_min_rx; +} + +/* * ospf6_bfd_write_config - Write the interface BFD configuration. */ void @@ -321,7 +392,7 @@ DEFUN (no_ipv6_ospf6_bfd, if (oi->bfd_info) { ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER); - bfd_info_free(&(oi->bfd_info)); + bfd_info_free((struct bfd_info **)&(oi->bfd_info)); } return CMD_SUCCESS; @@ -331,7 +402,7 @@ void ospf6_bfd_init(void) { /* Initialize BFD client functions */ - zclient->interface_bfd_dest_down = ospf6_bfd_interface_dest_down; + zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update; zclient->bfd_dest_replay = ospf6_bfd_nbr_replay; /* Install BFD command */ diff --git a/ospf6d/ospf6_bfd.h b/ospf6d/ospf6_bfd.h index eaaf15785..11b13d66f 100644 --- a/ospf6d/ospf6_bfd.h +++ b/ospf6d/ospf6_bfd.h @@ -33,4 +33,14 @@ ospf6_bfd_trigger_event(struct ospf6_neighbor *nbr, int old_state, int state); extern void ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi); +extern void +ospf6_bfd_info_nbr_create (struct ospf6_interface *oi, + struct ospf6_neighbor *on); + +extern void +ospf6_bfd_info_free(void **bfd_info); + +extern void +ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only); + #endif /* OSPF6_BFD_H */ diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 63783cc8f..21751656b 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -29,7 +29,6 @@ #include "prefix.h" #include "plist.h" #include "zclient.h" -#include "bfd.h" #include "ospf6_lsa.h" #include "ospf6_lsdb.h" @@ -263,7 +262,7 @@ ospf6_interface_delete (struct ospf6_interface *oi) if (oi->plist_name) XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name); - bfd_info_free(&(oi->bfd_info)); + ospf6_bfd_info_free(&(oi->bfd_info)); XFREE (MTYPE_OSPF6_IF, oi); } @@ -977,7 +976,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp) for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa; lsa = ospf6_lsdb_next (lsa)) vty_out (vty, " %s%s", lsa->name, VNL); - + ospf6_bfd_show_info(vty, oi->bfd_info, 1); return 0; } diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 3f5c5f041..6ef9e3782 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -115,7 +115,7 @@ struct ospf6_interface char *plist_name; /* BFD information */ - struct bfd_info *bfd_info; + void *bfd_info; }; /* interface state */ diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index c5edd226d..1636c2628 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -103,6 +103,8 @@ ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi) on->lsack_list = ospf6_lsdb_create (on); listnode_add_sort (oi->neighbor_list, on); + + ospf6_bfd_info_nbr_create(oi, on); return on; } @@ -139,6 +141,7 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on) THREAD_OFF (on->thread_send_lsupdate); THREAD_OFF (on->thread_send_lsack); + ospf6_bfd_info_free(&on->bfd_info); XFREE (MTYPE_OSPF6_NEIGHBOR, on); } @@ -815,6 +818,7 @@ ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *on) lsa = ospf6_lsdb_next (lsa)) vty_out (vty, " %s%s", lsa->name, VNL); + ospf6_bfd_show_info(vty, on->bfd_info, 0); } DEFUN (show_ipv6_ospf6_neighbor, diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index cba2cb99d..fad7fd578 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -96,6 +96,9 @@ struct ospf6_neighbor struct thread *thread_send_lsreq; struct thread *thread_send_lsupdate; struct thread *thread_send_lsack; + + /* BFD information */ + void *bfd_info; }; /* Neighbor state */ diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index 054a806bb..46c1844e2 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -48,6 +48,15 @@ extern struct zclient *zclient; /* + * ospf_bfd_info_free - Free BFD info structure + */ +void +ospf_bfd_info_free(void **bfd_info) +{ + bfd_info_free((struct bfd_info **) bfd_info); +} + +/* * ospf_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through * zebra for starting/stopping the monitoring of * the neighbor rechahability. @@ -118,6 +127,11 @@ ospf_bfd_reg_dereg_all_nbr (struct interface *ifp, int command) if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self) continue; + if (command != ZEBRA_BFD_DEST_DEREGISTER) + ospf_bfd_info_nbr_create(oi, nbr); + else + bfd_info_free((struct bfd_info **)&nbr->bfd_info); + if (nbr->state < NSM_TwoWay) continue; @@ -179,13 +193,14 @@ ospf_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length) } /* - * ospf_bfd_interface_dest_down - Find the neighbor for which the BFD status - * has changed and bring down the neighbor - * connectivity. + * ospf_bfd_interface_dest_update - Find the neighbor for which the BFD status + * has changed and bring down the neighbor + * connectivity if the BFD status changed to + * down. */ static int -ospf_bfd_interface_dest_down (int command, struct zclient *zclient, - zebra_size_t length) +ospf_bfd_interface_dest_update (int command, struct zclient *zclient, + zebra_size_t length) { struct interface *ifp; struct ospf_interface *oi; @@ -193,8 +208,12 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient, struct ospf_neighbor *nbr; struct route_node *node; struct prefix p; + int status; + int old_status; + struct bfd_info *bfd_info; + struct timeval tv; - ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL); + ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL, &status); if ((ifp == NULL) || (p.family != AF_INET)) return 0; @@ -203,7 +222,8 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient, { char buf[128]; prefix2str(&p, buf, sizeof(buf)); - zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf); + zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf, + bfd_get_status_str(status)); } params = IF_DEF_PARAMS (ifp); @@ -216,20 +236,60 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient, continue; nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &p.u.prefix4); - if (!nbr) + if (!nbr || !nbr->bfd_info) + continue; + + bfd_info = (struct bfd_info *)nbr->bfd_info; + if (bfd_info->status == status) continue; - if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) - zlog_debug ("NSM[%s:%s]: BFD Down", - IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); + old_status = bfd_info->status; + bfd_info->status = status; + quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv); + bfd_info->last_update = tv.tv_sec; + + if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) + { + if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) + zlog_debug ("NSM[%s:%s]: BFD Down", + IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer); + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer); + } } return 0; } /* + * ospf_bfd_info_nbr_create - Create/update BFD information for a neighbor. + */ +void +ospf_bfd_info_nbr_create (struct ospf_interface *oi, struct ospf_neighbor *nbr) +{ + struct bfd_info *oi_bfd_info; + struct bfd_info *nbr_bfd_info; + struct interface *ifp = oi->ifp; + struct ospf_if_params *params; + + /* Check if BFD is enabled */ + params = IF_DEF_PARAMS (ifp); + + /* Check if BFD is enabled */ + if (!params->bfd_info) + return; + + oi_bfd_info = (struct bfd_info *)params->bfd_info; + if (!nbr->bfd_info) + nbr->bfd_info = bfd_info_create(); + + nbr_bfd_info = (struct bfd_info *)nbr->bfd_info; + nbr_bfd_info->detect_mult = oi_bfd_info->detect_mult; + nbr_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx; + nbr_bfd_info->required_min_rx = oi_bfd_info->required_min_rx; +} + +/* * ospf_bfd_write_config - Write the interface BFD configuration. */ void @@ -251,6 +311,32 @@ ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params) vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE); } +/* + * ospf_bfd_show_info - Show BFD info structure + */ +void +ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, + u_char use_json, int param_only) +{ + if (param_only) + bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, json_obj); + else + bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json, json_obj); +} + +/* + * ospf_bfd_interface_show - Show the interface BFD configuration. + */ +void +ospf_bfd_interface_show(struct vty *vty, struct interface *ifp, + json_object *json_interface_sub, u_char use_json) +{ + struct ospf_if_params *params; + + params = IF_DEF_PARAMS (ifp); + + ospf_bfd_show_info(vty, params->bfd_info, json_interface_sub, use_json, 1); +} /* * ospf_bfd_if_param_set - Set the configured BFD paramter values for @@ -265,13 +351,12 @@ ospf_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, params = IF_DEF_PARAMS (ifp); - bfd_set_param(&(params->bfd_info), min_rx, min_tx, detect_mult, - defaults, &command); + bfd_set_param((struct bfd_info **)&(params->bfd_info), min_rx, min_tx, + detect_mult, defaults, &command); if (command) ospf_bfd_reg_dereg_all_nbr(ifp, command); } - DEFUN (ip_ospf_bfd, ip_ospf_bfd_cmd, "ip ospf bfd", @@ -342,7 +427,7 @@ void ospf_bfd_init(void) { /* Initialize BFD client functions */ - zclient->interface_bfd_dest_down = ospf_bfd_interface_dest_down; + zclient->interface_bfd_dest_update = ospf_bfd_interface_dest_update; zclient->bfd_dest_replay = ospf_bfd_nbr_replay; /* Install BFD command */ diff --git a/ospfd/ospf_bfd.h b/ospfd/ospf_bfd.h index 436597c0b..793962dae 100644 --- a/ospfd/ospf_bfd.h +++ b/ospfd/ospf_bfd.h @@ -24,6 +24,8 @@ #ifndef _ZEBRA_OSPF_BFD_H #define _ZEBRA_OSPF_BFD_H +#include "json.h" + extern void ospf_bfd_init(void); @@ -33,4 +35,18 @@ ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params); extern void ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state); +extern void +ospf_bfd_interface_show(struct vty *vty, struct interface *ifp, + json_object *json_interface_sub, u_char use_json); + +extern void +ospf_bfd_info_nbr_create (struct ospf_interface *oi, struct ospf_neighbor *nbr); + +extern void +ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj, + u_char use_json, int param_only); + +extern void +ospf_bfd_info_free(void **bfd_info); + #endif /* _ZEBRA_OSPF_BFD_H */ diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c index 967ca15db..afc74d2b0 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -30,6 +30,7 @@ #include "stream.h" #include "table.h" #include "log.h" +#include "json.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_interface.h" @@ -42,6 +43,7 @@ #include "ospfd/ospf_network.h" #include "ospfd/ospf_flood.h" #include "ospfd/ospf_dump.h" +#include "ospfd/ospf_bfd.h" /* Fill in the the 'key' as appropriate to retrieve the entry for nbr * from the ospf_interface's nbrs table. Indexed by interface address @@ -98,6 +100,7 @@ ospf_nbr_new (struct ospf_interface *oi) nbr->crypt_seqnum = 0; + ospf_bfd_info_nbr_create(oi, nbr); return nbr; } @@ -141,6 +144,7 @@ ospf_nbr_free (struct ospf_neighbor *nbr) /* Cancel all events. *//* Thread lookup cost would be negligible. */ thread_cancel_event (master, nbr); + ospf_bfd_info_free(&nbr->bfd_info); XFREE (MTYPE_OSPF_NEIGHBOR, nbr); } diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index 25f135242..7118dd021 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -88,6 +88,9 @@ struct ospf_neighbor struct timeval ts_last_regress; /* last regressive NSM change */ const char *last_regress_str; /* Event which last regressed NSM */ u_int32_t state_change; /* NSM state change counter */ + + /* BFD information */ + void *bfd_info; }; /* Macros. */ diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 6caeda765..f2b34bab1 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3857,6 +3857,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, struct interface vty_out (vty, " Neighbor Count is %d, Adjacent neighbor count is %d%s", ospf_nbr_count (oi, 0), ospf_nbr_count (oi, NSM_Full), VTY_NEWLINE); + ospf_bfd_interface_show(vty, ifp, json_interface_sub, use_json); } } @@ -4622,6 +4623,8 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi, else json_object_object_add(json, inet_ntoa (nbr->router_id), json_sub); } + + ospf_bfd_show_info(vty, nbr->bfd_info, json, use_json, 0); } static int diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 6c85eaa89..0fecd17d5 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -33,6 +33,7 @@ #include "ptm_lib.h" #include "buffer.h" #include "zebra/zebra_ptm_redistribute.h" +#include "bfd.h" #define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */ #define ZEBRA_PTM_RECONNECT_TIME_MAX 300 @@ -68,6 +69,7 @@ const char ZEBRA_PTM_BFD_CLIENT_FIELD[] = "client"; const char ZEBRA_PTM_BFD_SEQID_FIELD[] = "seqid"; const char ZEBRA_PTM_BFD_IFNAME_FIELD[] = "ifName"; const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD[] = "maxHopCnt"; +const char ZEBRA_PTM_BFD_SEND_EVENT[] = "sendEvent"; extern struct zebra_t zebrad; @@ -341,7 +343,8 @@ zebra_ptm_install_commands (void) /* BFD session goes down, send message to the protocols. */ static void -if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp) +if_bfd_session_update (struct interface *ifp, struct prefix *dp, + struct prefix *sp, int status) { if (IS_ZEBRA_DEBUG_EVENT) { @@ -349,22 +352,24 @@ if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp if (ifp) { - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d on %s", - inet_ntop (dp->family, &dp->u.prefix, buf[0], - INET6_ADDRSTRLEN), dp->prefixlen, ifp->name); + zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s" + " %s event", + inet_ntop (dp->family, &dp->u.prefix, buf[0], + INET6_ADDRSTRLEN), dp->prefixlen, ifp->name, + bfd_get_status_str(status)); } else { - zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d " - "with src %s/%d", + zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d " + "with src %s/%d %s event", inet_ntop (dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN), dp->prefixlen, inet_ntop (sp->family, &sp->u.prefix, buf[1], INET6_ADDRSTRLEN), - sp->prefixlen); + sp->prefixlen, bfd_get_status_str(status)); } } - zebra_interface_bfd_update (ifp, dp, sp); + zebra_interface_bfd_update (ifp, dp, sp, status); } static int @@ -403,44 +408,25 @@ zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, struct interface *ifp) __func__, ifp ? ifp->name : "N/A", bfdst_str, dest_str, src_str); - /* we only care if bfd session goes down */ - if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) { - if (inet_pton(AF_INET, dest_str, &dest_prefix.u.prefix4) > 0) { - dest_prefix.family = AF_INET; - dest_prefix.prefixlen = IPV4_MAX_PREFIXLEN; - } -#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, dest_str, &dest_prefix.u.prefix6) > 0) { - dest_prefix.family = AF_INET6; - dest_prefix.prefixlen = IPV6_MAX_PREFIXLEN; - } -#endif /* HAVE_IPV6 */ - else { - zlog_err("%s: Peer addr %s not found", __func__, - dest_str); - return -1; - } + if (str2prefix(dest_str, &dest_prefix) == 0) { + zlog_err("%s: Peer addr %s not found", __func__, + dest_str); + return -1; + } - memset(&src_prefix, 0, sizeof(struct prefix)); - if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) { - if (inet_pton(AF_INET, src_str, &src_prefix.u.prefix4) > 0) { - src_prefix.family = AF_INET; - src_prefix.prefixlen = IPV4_MAX_PREFIXLEN; - } -#ifdef HAVE_IPV6 - else if (inet_pton(AF_INET6, src_str, &src_prefix.u.prefix6) > 0) { - src_prefix.family = AF_INET6; - src_prefix.prefixlen = IPV6_MAX_PREFIXLEN; - } -#endif /* HAVE_IPV6 */ - else { - zlog_err("%s: Local addr %s not found", __func__, - src_str); - return -1; - } + memset(&src_prefix, 0, sizeof(struct prefix)); + if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) { + if (str2prefix(src_str, &src_prefix) == 0) { + zlog_err("%s: Local addr %s not found", __func__, + src_str); + return -1; } + } - if_bfd_session_down(ifp, &dest_prefix, &src_prefix); + if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) { + if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_DOWN); + } else { + if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_UP); } return 0; @@ -718,6 +704,10 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, if_name); } + sprintf(tmp_buf, "%d", 1); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT, + tmp_buf); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); if (IS_ZEBRA_DEBUG_SEND) diff --git a/zebra/zebra_ptm_null.c b/zebra/zebra_ptm_null.c index ad48f2385..293db2e67 100644 --- a/zebra/zebra_ptm_null.c +++ b/zebra/zebra_ptm_null.c @@ -24,7 +24,7 @@ #include "zebra_ptm_redistribute.h" void zebra_interface_bfd_update (struct interface *a, struct prefix *dp, - struct prefix *sp) + struct prefix *sp, int status) { return; } void zebra_bfd_peer_replay_req (void) diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 6166fc002..1a81c7985 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -32,7 +32,7 @@ extern struct zebra_t zebrad; static int zsend_interface_bfd_update (int cmd, struct zserv *client, struct interface *ifp, struct prefix *dp, - struct prefix *sp) + struct prefix *sp, int status) { int blen; struct stream *s; @@ -56,6 +56,9 @@ zsend_interface_bfd_update (int cmd, struct zserv *client, stream_put (s, &dp->u.prefix, blen); stream_putc (s, dp->prefixlen); + /* BFD status */ + stream_putl(s, status); + /* BFD source prefix information. */ stream_putc (s, sp->family); blen = prefix_blen (sp); @@ -71,7 +74,7 @@ zsend_interface_bfd_update (int cmd, struct zserv *client, void zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp, - struct prefix *sp) + struct prefix *sp, int status) { struct listnode *node, *nnode; struct zserv *client; @@ -84,8 +87,8 @@ zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp, continue; /* Notify to the protocol daemons. */ - zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_DOWN, client, ifp, - dp, sp); + zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_UPDATE, client, ifp, + dp, sp, status); } } diff --git a/zebra/zebra_ptm_redistribute.h b/zebra/zebra_ptm_redistribute.h index b79d122af..d78390e89 100644 --- a/zebra/zebra_ptm_redistribute.h +++ b/zebra/zebra_ptm_redistribute.h @@ -23,6 +23,6 @@ #ifndef _ZEBRA_PTM_REDISTRIBUTE_H #define _ZEBRA_PTM_REDISTRIBUTE_H extern void zebra_interface_bfd_update (struct interface *, struct prefix *, - struct prefix *); + struct prefix *, int); extern void zebra_bfd_peer_replay_req (void); #endif /* _ZEBRA_PTM_REDISTRIBUTE_H */ |