From: radhika Date: Thu, 21 Apr 2016 22:39:38 +0000 (-0700) Subject: Addition on hidden command "bfd multihop/singlehop" and "ptm-enable" per interface... X-Git-Tag: frr-2.0-rc1~958^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=986aa00f94cdfcecbb806d13e9594017d0a02b82;p=mirror%2Ffrr.git Addition on hidden command "bfd multihop/singlehop" and "ptm-enable" per interface command CM-10435 Issue: IBGP BFD sessions are created as multi-hop even though peer is single-hop away. This is causing an interop issue with ICOS. Root Cause: By design all IBGP peers are registered with BFD as multi-hop. Fix: • Changed the default behavior of always treating IBGP BFD sessions as mult-hop. shared_network variable is used to determine whether the IBGP peer is single hop or multi-hop away. The logic for determining whether EBGP peer is single hop or multi-hop has not been changed. • Since the default behavior has been changed, it will cause interop issues between 2.5 and 3.0 IBGP BFD sessions. A new hidden command “bfd multihop/singlehop” has been introduced to overcome the interop issues. dell-s6000-10(config-router)# neighbor 30.0.2.6 bfd <2-255> Detect Multiplier dell-s6000-10(config-router)# neighbor 30.0.2.6 bfd multihop dell-s6000-10(config-router)# no neighbor 30.0.2.6 bfd multihop dell-s6000-10(config-router)# dell-s6000-10(config-router)# neighbor 30.0.2.6 bfd multihop dell-s6000-10(config-router)# do show running-config ! router bgp 100 neighbor igroup peer-group neighbor igroup bfd 5 500 500 neighbor igroup bfd multihop neighbor 30.0.2.2 remote-as 100 neighbor 30.0.2.2 peer-group igroup neighbor 3101:abc:bcad::2 remote-as 100 neighbor 3101:abc:bcad::2 peer-group igroup neighbor 30.0.2.6 remote-as 200 neighbor 30.0.2.6 bfd multihop neighbor 3102:abc:bcad::6 remote-as 200 neighbor 3102:abc:bcad::6 bfd neighbor 3102:abc:bcad::6 ebgp-multihop 255 ! CM-10260 Issue: “Unable to connect to socket” message keeps getting logged when ptmd process doesn’t exist. Root Cause: BFD clients (bgpd, ospfd and ospf6d) during initialization try to register with BFD/PTM by default. This results in continuous logging If PTM does not exist since there is no max on number of retries. Fix: • Stop the retries to connect to PTM after max reconnect timer of 5 mins is reached. • Added zebra debug event wrapper to message logging to prevent it from showing by default. CM-4541 Issue: Addition of a new command "ptm-enable" or "no ptm-enable" per interface to enable/disable PTM link status checks for an interface. Fix: Currently there is only one ptm-enable global command that enables/disables PTM status updates for all interfaces. This new command will give the handle to individually stop interface from reacting on the PTM status updates. • by default interface uses the ptm-enable global configuration • "no ptm-enable" on an interface will disable PTM status updates from taking affect for that interface. This can bring the interface up if it was brought down due to PTM status update. • "ptm-enable" on an interface will cause the interface to fallback to the global ptm-enable configuration value and will bring the interface up or down based on the last stored PTM status update if global ptm is enabled. Ticket: CM-10435, CM-10260 and CM-4541 Signed-off-by: Radhika Mahankali Reviewed-by: Donald Sharp, Kanna Rajagopal --- diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 118d8f64c2..da50fd2bae 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -65,6 +65,7 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) bfd_info->required_min_rx = conf_bfd_info->required_min_rx; bfd_info->desired_min_tx = conf_bfd_info->desired_min_tx; bfd_info->detect_mult = conf_bfd_info->detect_mult; + bfd_info->type = conf_bfd_info->type; } /* @@ -73,8 +74,16 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) static int bgp_bfd_is_peer_multihop(struct peer *peer) { - if((peer->conf_if == NULL) && ((peer->sort == BGP_PEER_IBGP) || - is_ebgp_multihop_configured(peer))) + struct bfd_info *bfd_info; + + bfd_info = (struct bfd_info *)peer->bfd_info; + + if (!bfd_info) + return 0; + + if((bfd_info->type == BFD_TYPE_MULTIHOP) || + ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network) || + is_ebgp_multihop_configured(peer)) return 1; else return 0; @@ -89,24 +98,37 @@ bgp_bfd_peer_sendmsg (struct peer *peer, int command) { struct bfd_info *bfd_info; vrf_id_t vrf_id = VRF_DEFAULT; + int multihop; bfd_info = (struct bfd_info *)peer->bfd_info; if (peer->bgp && (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF)) vrf_id = peer->bgp->vrf_id; + if (command == ZEBRA_BFD_DEST_DEREGISTER) + { + multihop = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); + UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); + } + else + { + multihop = bgp_bfd_is_peer_multihop(peer); + if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop) + SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); + } + if (peer->su.sa.sa_family == AF_INET) bfd_peer_sendmsg (zclient, bfd_info, AF_INET, &peer->su.sin.sin_addr, (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL, (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, - peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1, vrf_id); + peer->ttl, multihop, command, 1, vrf_id); else if (peer->su.sa.sa_family == AF_INET6) bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, &peer->su.sin6.sin6_addr, (peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL, (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, - peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1, vrf_id); + peer->ttl, multihop, command, 1, vrf_id); } /* @@ -170,6 +192,46 @@ bgp_bfd_update_peer (struct peer *peer) bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE); } +/* + * bgp_bfd_update_type - update session type with BFD through zebra. + */ +static void +bgp_bfd_update_type (struct peer *peer) +{ + struct bfd_info *bfd_info; + int multihop; + + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; + + /* Check if the peer has been registered with BFD*/ + if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) + return; + + if (bfd_info->type == BFD_TYPE_NOT_CONFIGURED) + { + multihop = bgp_bfd_is_peer_multihop(peer); + if ((multihop && !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)) || + (!multihop && CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP))) + { + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); + } + } + else + { + if ((bfd_info->type == BFD_TYPE_MULTIHOP && + !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)) || + (bfd_info->type == BFD_TYPE_SINGLEHOP && + CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP))) + { + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); + } + } +} + /* * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled * to zebra @@ -367,7 +429,7 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx, } /* - * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer. + * bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for peer. */ static int bgp_bfd_peer_param_unset (struct peer *peer) @@ -396,6 +458,61 @@ bgp_bfd_peer_param_unset (struct peer *peer) return 0; } +/* + * bgp_bfd_peer_param_type_set - set the BFD session type (multihop or singlehop) + */ +static int +bgp_bfd_peer_param_type_set (struct peer *peer, enum bfd_sess_type type) +{ + struct peer_group *group; + struct listnode *node, *nnode; + int command = 0; + struct bfd_info *bfd_info; + + if (!peer->bfd_info) + bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX, + BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, 1, &command); + + bfd_info = (struct bfd_info *)peer->bfd_info; + bfd_info->type = type; + + if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + { + group = peer->group; + for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) + { + command = 0; + if (!peer->bfd_info) + bfd_set_param((struct bfd_info **)&(peer->bfd_info), + BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1, &command); + + bfd_info = (struct bfd_info *)peer->bfd_info; + bfd_info->type = type; + + if (peer->status == Established) + { + if (command == ZEBRA_BFD_DEST_REGISTER) + bgp_bfd_register_peer(peer); + else + bgp_bfd_update_type(peer); + } + } + } + else + { + if (peer->status == Established) + { + if (command == ZEBRA_BFD_DEST_REGISTER) + bgp_bfd_register_peer(peer); + else + bgp_bfd_update_type(peer); + } + } + + return 0; +} + /* * bgp_bfd_peer_config_write - Write the peer BFD configuration. */ @@ -413,7 +530,14 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) vty_out (vty, " neighbor %s bfd %d %d %d%s", addr, bfd_info->detect_mult, bfd_info->required_min_rx, bfd_info->desired_min_tx, VTY_NEWLINE); - else + + if (bfd_info->type != BFD_TYPE_NOT_CONFIGURED) + vty_out (vty, " neighbor %s bfd %s%s", addr, + (bfd_info->type == BFD_TYPE_MULTIHOP) ? "multihop" : "singlehop", + VTY_NEWLINE); + + if (!CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG) && + (bfd_info->type == BFD_TYPE_NOT_CONFIGURED)) vty_out (vty, " neighbor %s bfd%s", addr, VTY_NEWLINE); } @@ -482,6 +606,36 @@ DEFUN (neighbor_bfd_param, } +DEFUN_HIDDEN (neighbor_bfd_type, + neighbor_bfd_type_cmd, + NEIGHBOR_CMD2 "bfd " BFD_CMD_TYPE, + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Enables BFD support\n" + "Session type\n") +{ + struct peer *peer; + enum bfd_sess_type type; + int ret; + + peer = peer_and_group_lookup_vty (vty, argv[0]); + if (!peer) + return CMD_WARNING; + + if (!strcmp(argv[1], "singlehop")) + type = BFD_TYPE_SINGLEHOP; + else if (!strcmp(argv[1], "multihop")) + type = BFD_TYPE_MULTIHOP; + else + return CMD_WARNING; + + ret = bgp_bfd_peer_param_type_set (peer, type); + if (ret != 0) + return bgp_vty_return (vty, ret); + + return CMD_SUCCESS; +} + DEFUN (no_neighbor_bfd, no_neighbor_bfd_cmd, NO_NEIGHBOR_CMD2 "bfd", @@ -515,6 +669,32 @@ ALIAS (no_neighbor_bfd, "Required min receive interval\n" "Desired min transmit interval\n") +DEFUN_HIDDEN (no_neighbor_bfd_type, + no_neighbor_bfd_type_cmd, + NO_NEIGHBOR_CMD2 "bfd " BFD_CMD_TYPE, + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Disables BFD support\n" + "Session type\n") +{ + struct peer *peer; + int ret; + + peer = peer_and_group_lookup_vty (vty, argv[0]); + if (! peer) + return CMD_WARNING; + + if (!peer->bfd_info) + return 0; + + ret = bgp_bfd_peer_param_type_set(peer, BFD_TYPE_NOT_CONFIGURED); + if (ret != 0) + return bgp_vty_return (vty, ret); + + return CMD_SUCCESS; +} + void bgp_bfd_init(void) { @@ -525,8 +705,10 @@ bgp_bfd_init(void) /* "neighbor bfd" commands. */ install_element (BGP_NODE, &neighbor_bfd_cmd); install_element (BGP_NODE, &neighbor_bfd_param_cmd); + install_element (BGP_NODE, &neighbor_bfd_type_cmd); install_element (BGP_NODE, &no_neighbor_bfd_cmd); install_element (BGP_NODE, &no_neighbor_bfd_val_cmd); + install_element (BGP_NODE, &no_neighbor_bfd_type_cmd); /* Send the client registration */ bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); diff --git a/lib/bfd.c b/lib/bfd.c index 4a29b3267d..ddf03d4f1c 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -45,6 +45,7 @@ bfd_info_create(void) assert(bfd_info); bfd_info->status = BFD_STATUS_UNKNOWN; + bfd_info->type = BFD_TYPE_NOT_CONFIGURED; bfd_info->last_update = 0; return bfd_info; } diff --git a/lib/bfd.h b/lib/bfd.h index b001ae9670..31e542d8b7 100644 --- a/lib/bfd.h +++ b/lib/bfd.h @@ -29,6 +29,7 @@ #define BFD_CMD_DETECT_MULT_RANGE "<2-255> " #define BFD_CMD_MIN_RX_RANGE "<50-60000> " #define BFD_CMD_MIN_TX_RANGE "<50-60000>" +#define BFD_CMD_TYPE "(multihop|singlehop)" #define BFD_DEF_MIN_RX 300 #define BFD_MIN_MIN_RX 50 @@ -42,19 +43,27 @@ #define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */ #define BFD_FLAG_BFD_REG (1 << 1) /* Peer registered with BFD */ +#define BFD_FLAG_BFD_TYPE_MULTIHOP (1 << 2) /* Peer registered with BFD as multihop */ #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 */ +enum bfd_sess_type { + BFD_TYPE_NOT_CONFIGURED, + BFD_TYPE_SINGLEHOP, + BFD_TYPE_MULTIHOP +}; + 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; + 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; + enum bfd_sess_type type; }; extern struct bfd_info * diff --git a/zebra/interface.c b/zebra/interface.c index a6f130da68..760b1a9852 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -66,6 +66,7 @@ if_zebra_new_hook (struct interface *ifp) zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + zebra_ptm_if_init(zebra_if); ifp->ptm_enable = zebra_ptm_get_enable_state(); #if defined (HAVE_RTADV) @@ -453,6 +454,8 @@ if_add_update (struct interface *ifp) else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF) if_unset_flags (ifp, IFF_MULTICAST); + zebra_ptm_if_set_ptm_state(ifp, if_data); + zebra_interface_add_update (ifp); if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) @@ -1842,6 +1845,7 @@ DEFUN (no_ip_address, return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL); } + #ifdef HAVE_NETLINK DEFUN (ip_address_label, ip_address_label_cmd, @@ -2085,6 +2089,8 @@ if_config_write (struct vty *vty) { if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) vty_out (vty, " shutdown%s", VTY_NEWLINE); + + zebra_ptm_if_write(vty, if_data); } if (ifp->desc) diff --git a/zebra/interface.h b/zebra/interface.h index 9beabb62f8..bb76612ff1 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -211,6 +211,9 @@ struct zebra_if */ u_char primary_state; #endif /* SUNOS_5 */ + + /* ptm enable configuration */ + u_char ptm_enable; }; diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index a124f739da..949514f27b 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -227,13 +227,15 @@ zebra_ptm_connect (struct thread *t) } zebra_ptm_send_status_req(); ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; - } else { + } else if (ptm_cb.reconnect_time < ZEBRA_PTM_RECONNECT_TIME_MAX){ ptm_cb.reconnect_time *= 2; if (ptm_cb.reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX) ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX; ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time); + } else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX){ + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; } return(errno); @@ -246,17 +248,23 @@ DEFUN (zebra_ptm_enable, { struct listnode *i; struct interface *ifp; + struct zebra_if *if_data; vrf_iter_t iter; - ptm_cb.ptm_enable = 1; + ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), i, ifp)) if (!ifp->ptm_enable) { - ifp->ptm_enable = 1; + if_data = (struct zebra_if *)ifp->info; + if (if_data && + (if_data->ptm_enable == ZEBRA_IF_PTM_ENABLE_UNSPEC)) + { + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_ON; + } /* Assign a default unknown status */ - ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; } zebra_ptm_connect(NULL); @@ -270,11 +278,84 @@ DEFUN (no_zebra_ptm_enable, NO_STR "Enable neighbor check with specified topology\n") { - ptm_cb.ptm_enable = 0; + ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; zebra_ptm_reset_status(1); return CMD_SUCCESS; } +DEFUN (zebra_ptm_enable_if, + zebra_ptm_enable_if_cmd, + "ptm-enable", + "Enable neighbor check with specified topology\n") +{ + struct interface *ifp; + struct zebra_if *if_data; + int old_ptm_enable; + int send_linkdown = 0; + + ifp = (struct interface *) vty->index; + if (ifp->ifindex == IFINDEX_INTERNAL) + { + return CMD_SUCCESS; + } + + old_ptm_enable = ifp->ptm_enable; + ifp->ptm_enable = ptm_cb.ptm_enable; + + if (if_is_no_ptm_operative(ifp)) + send_linkdown = 1; + + if (!old_ptm_enable && ptm_cb.ptm_enable) + { + if (!if_is_operative (ifp) && send_linkdown) + { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("%s: Bringing down interface %s\n", __func__, + ifp->name); + if_down (ifp); + } + } + + if_data = ifp->info; + if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; + + return CMD_SUCCESS; +} + +DEFUN (no_zebra_ptm_enable_if, + no_zebra_ptm_enable_if_cmd, + "no ptm-enable", + NO_STR + "Enable neighbor check with specified topology\n") +{ + struct interface *ifp; + int send_linkup = 0; + struct zebra_if *if_data; + + ifp = (struct interface *) vty->index; + + if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable)) + { + if (!if_is_operative(ifp)) + send_linkup = 1; + + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + if (if_is_no_ptm_operative (ifp) && send_linkup) + { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("%s: Bringing up interface %s\n", __func__, + ifp->name); + if_up (ifp); + } + } + + if_data = ifp->info; + if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; + + return CMD_SUCCESS; +} + + void zebra_ptm_write (struct vty *vty) { @@ -307,7 +388,8 @@ zebra_ptm_socket_init (void) sizeof (addr.sun_family)+sizeof (ZEBRA_PTM_SOCK_NAME)-1); if (ret < 0) { - zlog_warn("%s: Unable to connect to socket %s [%s]", + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Unable to connect to socket %s [%s]", __func__, ZEBRA_PTM_SOCK_NAME, safe_strerror(errno)); close (sock); return -1; @@ -321,6 +403,8 @@ zebra_ptm_install_commands (void) { install_element (CONFIG_NODE, &zebra_ptm_enable_cmd); install_element (CONFIG_NODE, &no_zebra_ptm_enable_cmd); + install_element (INTERFACE_NODE, &zebra_ptm_enable_if_cmd); + install_element (INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd); } /* BFD session goes down, send message to the protocols. */ @@ -981,21 +1065,41 @@ zebra_ptm_reset_status(int ptm_disable) { send_linkup = 0; if (ifp->ptm_enable) - { - if (!if_is_operative(ifp)) - send_linkup = 1; + { + if (!if_is_operative(ifp)) + send_linkup = 1; if (ptm_disable) - ifp->ptm_enable = 0; + ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF; ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; - if (if_is_operative (ifp) && send_linkup) - { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug ("%s: Bringing up interface %s", __func__, - ifp->name); - if_up (ifp); + if (if_is_operative (ifp) && send_linkup) + { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("%s: Bringing up interface %s", __func__, + ifp->name); + if_up (ifp); } } } } + +void +zebra_ptm_if_init(struct zebra_if *zebra_ifp) +{ + zebra_ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC; +} + +void +zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp) +{ + if (zebra_ifp && zebra_ifp->ptm_enable != ZEBRA_IF_PTM_ENABLE_UNSPEC) + ifp->ptm_enable = zebra_ifp->ptm_enable; +} + +void +zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp) +{ + if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF) + vty_out (vty, " no ptm-enable%s", VTY_NEWLINE); +} diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index dec1fe31af..190ae996ec 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -50,6 +50,11 @@ struct zebra_ptm_cb #define ZEBRA_PTM_STATUS_UP 1 #define ZEBRA_PTM_STATUS_UNKNOWN 2 +/* For interface ptm-enable configuration. */ +#define ZEBRA_IF_PTM_ENABLE_OFF 0 +#define ZEBRA_IF_PTM_ENABLE_ON 1 +#define ZEBRA_IF_PTM_ENABLE_UNSPEC 2 + void zebra_ptm_init (void); void zebra_ptm_finish(void); int zebra_ptm_connect (struct thread *t); @@ -64,4 +69,7 @@ void zebra_ptm_show_status(struct vty *vty, struct interface *ifp); int zebra_ptm_bfd_client_register (struct zserv *client, int sock, u_short length); +void zebra_ptm_if_init(struct zebra_if *zebra_ifp); +void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp); +void zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp); #endif