diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 9923f94923..9c06c74aac 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -2806,13 +2806,15 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, } size_t -bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, +bgp_packet_mpattr_start (struct stream *s, struct peer *peer, + afi_t afi, safi_t safi, struct bpacket_attr_vec_arr *vecarr, struct attr *attr) { size_t sizep; iana_afi_t pkt_afi; safi_t pkt_safi; + afi_t nh_afi; /* Set extended bit always to encode the attribute length as 2 bytes */ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); @@ -2826,10 +2828,18 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, stream_putw (s, pkt_afi); /* AFI */ stream_putc (s, pkt_safi); /* SAFI */ - if (afi == AFI_L2VPN) - nh_afi = AFI_L2VPN; - else if (nh_afi == AFI_MAX) - nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->extra->mp_nexthop_len); + + /* Nexthop AFI */ + if (peer_cap_enhe(peer, afi, safi)) { + nh_afi = AFI_IP6; + } else { + if (afi == AFI_L2VPN) + nh_afi = AFI_L2VPN; + else if (safi == SAFI_LABELED_UNICAST) + nh_afi = afi; + else + nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->extra->mp_nexthop_len); + } /* Nexthop */ switch (nh_afi) @@ -3126,10 +3136,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, { size_t mpattrlen_pos = 0; - mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, - (peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : - AFI_MAX), /* get from NH */ - vecarr, attr); + mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi, vecarr, attr); bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag, addpath_encode, addpath_tx_id, attr); bgp_packet_mpattr_end(s, mpattrlen_pos); diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 7dfd397bb9..f25df3a8b9 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -297,8 +297,8 @@ bgp_attr_flush_encap(struct attr *attr); * one for each NLRI that needs to be encoded into the UPDATE message, and * finally the _end() function. */ -extern size_t bgp_packet_mpattr_start(struct stream *s, afi_t afi, safi_t safi, - afi_t nh_afi, +extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, + afi_t afi, safi_t safi, struct bpacket_attr_vec_arr *vecarr, struct attr *attr); extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, diff --git a/bgpd/bgp_encap.c b/bgpd/bgp_encap.c index 2e58072bc5..a1a0c1710b 100644 --- a/bgpd/bgp_encap.c +++ b/bgpd/bgp_encap.c @@ -213,7 +213,7 @@ DEFUN (encap_network, int idx_ipv4 = 1; int idx_rd = 3; int idx_word = 5; - return bgp_static_set_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg, + return bgp_static_set_safi (AFI_IP, SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL); } @@ -232,7 +232,7 @@ DEFUN (no_encap_network, int idx_ipv4 = 2; int idx_rd = 4; int idx_word = 6; - return bgp_static_unset_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg, + return bgp_static_unset_safi (AFI_IP, SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg, 0, NULL, NULL, NULL); } diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 4850a8f13a..e91a6d9bfd 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -705,7 +705,7 @@ DEFUN(evpnrt5_network, int idx_ethtag = 5; int idx_routermac = 13; int idx_rmap = 15; - return bgp_static_set_safi(SAFI_EVPN, vty, + return bgp_static_set_safi(AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, @@ -739,7 +739,7 @@ DEFUN(no_evpnrt5_network, int idx_ethtag = 6; int idx_esi = 10; int idx_gwip = 12; - return bgp_static_unset_safi(SAFI_EVPN, vty, + return bgp_static_unset_safi(AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg, EVPN_IP_PREFIX, diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index c553af6d1d..a25e0be22d 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1025,7 +1025,7 @@ bgp_stop (struct peer *peer) zlog_info ("%%ADJCHANGE: neighbor %s(%s) in vrf %s Down %s", peer->host, (peer->hostname) ? peer->hostname : "Unknown", - (vrf->vrf_id != VRF_DEFAULT) ? vrf->name : "Default", + vrf ? ((vrf->vrf_id != VRF_DEFAULT) ? vrf->name : "Default") : "", peer_down_str [(int) peer->last_reset]); } diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 4234934a6a..2d13d05c00 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -471,7 +471,7 @@ DEFUN (vpnv4_network, int idx_ipv4_prefixlen = 1; int idx_ext_community = 3; int idx_word = 5; - return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, + return bgp_static_set_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL); } @@ -491,7 +491,7 @@ DEFUN (vpnv4_network_route_map, int idx_ext_community = 3; int idx_word = 5; int idx_word_2 = 7; - return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, + return bgp_static_set_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); } @@ -510,7 +510,7 @@ DEFUN (no_vpnv4_network, int idx_ipv4_prefixlen = 2; int idx_ext_community = 4; int idx_word = 6; - return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, + return bgp_static_unset_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, 0, NULL, NULL, NULL); } @@ -532,9 +532,9 @@ DEFUN (vpnv6_network, int idx_word = 5; int idx_word_2 = 7; if (argc == 8) - return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); + return bgp_static_set_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL); else - return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL); + return bgp_static_set_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL); } /* For testing purpose, static route of MPLS-VPN. */ @@ -552,7 +552,7 @@ DEFUN (no_vpnv6_network, int idx_ipv6_prefix = 2; int idx_ext_community = 4; int idx_word = 6; - return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, 0, NULL, NULL, NULL); + return bgp_static_unset_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, 0, NULL, NULL, NULL); } int diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index daee3d19e1..126a920944 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1129,7 +1129,10 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) else peer->v_holdtime = send_holdtime; - peer->v_keepalive = peer->v_holdtime / 3; + if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)) + peer->v_keepalive = peer->keepalive; + else + peer->v_keepalive = peer->v_holdtime / 3; /* Open option part parse. */ if (optlen != 0) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 41966192d8..0f719d5536 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4540,7 +4540,7 @@ bgp_purge_static_redist_routes (struct bgp *bgp) * I think it can probably be factored with bgp_static_set. */ int -bgp_static_set_safi (safi_t safi, struct vty *vty, const char *ip_str, +bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *ip_str, const char *rd_str, const char *tag_str, const char *rmap_str, int evpn_type, const char *esi, const char *gwip, const char *ethtag, const char *routermac) @@ -4554,14 +4554,8 @@ bgp_static_set_safi (safi_t safi, struct vty *vty, const char *ip_str, struct bgp_table *table; struct bgp_static *bgp_static; u_char tag[3]; - afi_t afi; struct prefix gw_ip; - if(safi == SAFI_EVPN) - afi = AFI_L2VPN; - else - afi = AFI_IP; - /* validate ip prefix */ ret = str2prefix (ip_str, &p); if (! ret) @@ -4686,7 +4680,7 @@ bgp_static_set_safi (safi_t safi, struct vty *vty, const char *ip_str, /* Configure static BGP network. */ int -bgp_static_unset_safi(safi_t safi, struct vty *vty, const char *ip_str, +bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, const char *ip_str, const char *rd_str, const char *tag_str, int evpn_type, const char *esi, const char *gwip, const char *ethtag) { @@ -4699,12 +4693,6 @@ bgp_static_unset_safi(safi_t safi, struct vty *vty, const char *ip_str, struct bgp_table *table; struct bgp_static *bgp_static; u_char tag[3]; - afi_t afi; - - if(safi == SAFI_EVPN) - afi = AFI_L2VPN; - else - afi = AFI_IP; /* Convert IP prefix string to struct prefix. */ ret = str2prefix (ip_str, &p); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 96c9bd0035..3d179e07be 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -333,11 +333,11 @@ extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static afi_t, safi_t); extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t); -extern int bgp_static_set_safi (safi_t safi, struct vty *vty, const char *, +extern int bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *, const char *, const char *, const char *, int, const char *, const char *, const char *, const char *); -extern int bgp_static_unset_safi (safi_t safi, struct vty *, const char *, +extern int bgp_static_unset_safi (afi_t afi, safi_t safi, struct vty *, const char *, const char *, const char *, int, const char *, const char *, const char *); diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 95e9360d43..7e524dd347 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -762,14 +762,18 @@ subgroup_update_packet (struct update_subgroup *subgrp) if (rn->prn) prd = (struct prefix_rd *) &rn->prn->p; - tag = bgp_adv_label(rn, binfo, peer, afi, safi); + + if (safi == SAFI_LABELED_UNICAST) + tag = bgp_adv_label(rn, binfo, peer, afi, safi); + else + if (binfo && binfo->extra) + tag = binfo->extra->tag; + if (bgp_labeled_safi(safi)) sprintf (label_buf, "label %u", label_pton(tag)); if (stream_empty (snlri)) - mpattrlen_pos = bgp_packet_mpattr_start (snlri, afi, safi, - (peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : - AFI_MAX), /* get from NH */ + mpattrlen_pos = bgp_packet_mpattr_start (snlri, peer, afi, safi, &vecarr, adv->baa->attr); bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index eaede36427..5059104e92 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2812,7 +2812,12 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, } peer = peer_lookup_by_conf_if (bgp, conf_if); - if (!peer) + if (peer) + { + if (as_str) + ret = peer_remote_as (bgp, &su, conf_if, &as, as_type, afi, safi); + } + else { if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) && afi == AFI_IP && safi == SAFI_UNICAST) @@ -2836,8 +2841,9 @@ peer_conf_interface_get (struct vty *vty, const char *conf_if, afi_t afi, if (peer->ifp) bgp_zebra_initiate_radv (bgp, peer); } - else if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) || - (!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))) + + if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) || + (!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))) { if (v6only) SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); @@ -8106,6 +8112,7 @@ bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *js u_int16_t i; u_char *msg; json_object *json_neigh = NULL; + time_t epoch_tbuf; bgp = p->bgp; @@ -8295,8 +8302,11 @@ bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *js uptime = bgp_clock(); uptime -= p->uptime; tm = gmtime(&uptime); + epoch_tbuf = time(NULL) - uptime; json_object_int_add(json_neigh, "bgpTimerUp", (tm->tm_sec * 1000) + (tm->tm_min * 60000) + (tm->tm_hour * 3600000)); + json_object_string_add(json_neigh, "bgpTimerUpString", peer_uptime (p->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL)); + json_object_int_add(json_neigh, "bgpTimerUpEstablishedEpoch", epoch_tbuf); } else if (p->status == Active) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 1c519f0999..655431b015 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6350,7 +6350,7 @@ peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi, char * peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object *json) { - time_t uptime1; + time_t uptime1, epoch_tbuf; struct tm *tm; /* Check buffer length. */ @@ -6404,8 +6404,10 @@ peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object if (use_json) { + epoch_tbuf = time(NULL) - uptime1; json_object_string_add(json, "peerUptime", buf); json_object_long_add(json, "peerUptimeMsec", uptime1 * 1000); + json_object_int_add(json, "peerUptimeEstablishedEpoch", epoch_tbuf); } return buf; diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index 5694ca49f9..c6ff7b5a80 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -646,7 +646,8 @@ DEFUN (no_eigrp_if_delay, DEFUN (eigrp_if_bandwidth, eigrp_if_bandwidth_cmd, - "bandwidth (1-10000000)", + "eigrp bandwidth (1-10000000)", + "EIGRP specific commands\n" "Set bandwidth informational parameter\n" "Bandwidth in kilobits\n") { @@ -671,8 +672,9 @@ DEFUN (eigrp_if_bandwidth, DEFUN (no_eigrp_if_bandwidth, no_eigrp_if_bandwidth_cmd, - "no bandwidth [(1-10000000)]", + "no eigrp bandwidth [(1-10000000)]", NO_STR + "EIGRP specific commands\n" "Set bandwidth informational parameter\n" "Bandwidth in kilobits\n") { diff --git a/ldpd/lde.c b/ldpd/lde.c index bef35f3194..8d2a9dd9dc 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -1623,6 +1623,8 @@ zclient_sync_init(u_short instance) log_warnx("Error connecting synchronous zclient!"); sleep(1); } + /* make socket non-blocking */ + sock_set_nonblock(zclient_sync->sock); /* Connect to label manager */ while (lm_label_manager_connect(zclient_sync) != 0) { @@ -1647,8 +1649,6 @@ lde_get_label_chunk(void) ret = lm_get_label_chunk(zclient_sync, 0, CHUNK_SIZE, &start, &end); if (ret < 0) { log_warnx("Error getting label chunk!"); - close(zclient_sync->sock); - zclient_sync->sock = -1; return -1; } diff --git a/lib/command.c b/lib/command.c index 452a559998..84d59f076c 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1372,11 +1372,6 @@ DEFUN (frr_version_defaults, "set of configuration defaults used\n" "version string\n") { - if (vty->type == VTY_TERM || vty->type == VTY_SHELL) - /* only print this when the user tries to do run it */ - vty_out (vty, "%% NOTE: This command currently does nothing.%s" - "%% It is written to the configuration for future reference.%s", - VTY_NEWLINE, VTY_NEWLINE); return CMD_SUCCESS; } diff --git a/lib/zclient.c b/lib/zclient.c index 9823bc8d99..a53e8112c8 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1512,6 +1512,47 @@ zebra_interface_vrf_update_read (struct stream *s, vrf_id_t vrf_id, *new_vrf_id = new_id; return ifp; } + +/* filter unwanted messages until the expected one arrives */ +static int +zclient_read_sync_response (struct zclient *zclient, u_int16_t expected_cmd) +{ + struct stream *s; + u_int16_t size; + u_char marker; + u_char version; + vrf_id_t vrf_id; + u_int16_t cmd; + fd_set readfds; + int ret; + + ret = 0; + cmd = expected_cmd + 1; + while (ret == 0 && cmd != expected_cmd) + { + s = zclient->ibuf; + stream_reset (s); + + /* wait until response arrives */ + FD_ZERO (&readfds); + FD_SET (zclient->sock, &readfds); + select (zclient->sock+1, &readfds, NULL, NULL, NULL); + if (!FD_ISSET(zclient->sock, &readfds)) + continue; + /* read response */ + ret = zclient_read_header (s, zclient->sock, &size, &marker, &version, + &vrf_id, &cmd); + if (zclient_debug) + zlog_debug ("%s: Response (%d bytes) received", __func__, size); + } + if (ret != 0) + { + zlog_err ("%s: Invalid Sync Message Reply", __func__); + return -1; + } + + return 0; +} /** * Connect to label manager in a syncronous way * @@ -1527,11 +1568,6 @@ lm_label_manager_connect (struct zclient *zclient) int ret; struct stream *s; u_char result; - u_int16_t size; - u_char marker; - u_char version; - vrf_id_t vrf_id; - u_int16_t cmd; if (zclient_debug) zlog_debug ("Connecting to Label Manager"); @@ -1571,20 +1607,15 @@ lm_label_manager_connect (struct zclient *zclient) zlog_debug ("%s: Label manager connect request (%d bytes) sent", __func__, ret); /* read response */ - s = zclient->ibuf; - stream_reset (s); + if (zclient_read_sync_response (zclient, ZEBRA_LABEL_MANAGER_CONNECT) != 0) + return -1; - ret = zclient_read_header (s, zclient->sock, &size, &marker, &version, - &vrf_id, &cmd); - if (ret != 0 || cmd != ZEBRA_LABEL_MANAGER_CONNECT) { - zlog_err ("%s: Invalid Label Manager Connect Message Reply Header", __func__); - return -1; - } /* result */ + s = zclient->ibuf; result = stream_getc(s); if (zclient_debug) - zlog_debug ("%s: Label Manager connect response (%d bytes) received, result %u", - __func__, size, result); + zlog_debug ("%s: Label Manager connect response received, result %u", + __func__, result); return (int)result; } @@ -1608,11 +1639,6 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, { int ret; struct stream *s; - u_int16_t size; - u_char marker; - u_char version; - vrf_id_t vrf_id; - u_int16_t cmd; u_char response_keep; if (zclient_debug) @@ -1651,18 +1677,10 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, zlog_debug ("%s: Label chunk request (%d bytes) sent", __func__, ret); /* read response */ + if (zclient_read_sync_response (zclient, ZEBRA_GET_LABEL_CHUNK) != 0) + return -1; + s = zclient->ibuf; - stream_reset (s); - - ret = zclient_read_header (s, zclient->sock, &size, &marker, &version, - &vrf_id, &cmd); - if (ret != 0 || cmd != ZEBRA_GET_LABEL_CHUNK) { - zlog_err ("%s: Invalid Get Label Chunk Message Reply Header", __func__); - return -1; - } - if (zclient_debug) - zlog_debug ("%s: Label chunk response (%d bytes) received", __func__, size); - /* keep */ response_keep = stream_getc(s); /* start and end labels */ @@ -1670,18 +1688,20 @@ lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, *end = stream_getl(s); /* not owning this response */ - if (keep != response_keep) { - zlog_err ("%s: Invalid Label chunk: %u - %u, keeps mismatch %u != %u", - __func__, *start, *end, keep, response_keep); - } + if (keep != response_keep) + { + zlog_err ("%s: Invalid Label chunk: %u - %u, keeps mismatch %u != %u", + __func__, *start, *end, keep, response_keep); + } /* sanity */ if (*start > *end || *start < MPLS_MIN_UNRESERVED_LABEL - || *end > MPLS_MAX_UNRESERVED_LABEL) { - zlog_err ("%s: Invalid Label chunk: %u - %u", __func__, - *start, *end); - return -1; - } + || *end > MPLS_MAX_UNRESERVED_LABEL) + { + zlog_err ("%s: Invalid Label chunk: %u - %u", __func__, + *start, *end); + return -1; + } if (zclient_debug) zlog_debug ("Label Chunk assign: %u - %u (%u) ", diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 2cd77ac42c..9f02a414de 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -405,26 +405,11 @@ ospf6_area_show (struct vty *vty, struct ospf6_area *oa) } -#define OSPF6_CMD_AREA_LOOKUP(str, oa) \ -{ \ - u_int32_t area_id = 0; \ - if (inet_pton (AF_INET, str, &area_id) != 1) \ - { \ - vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \ - return CMD_SUCCESS; \ - } \ - oa = ospf6_area_lookup (area_id, ospf6); \ - if (oa == NULL) \ - { \ - vty_out (vty, "No such Area: %s%s", str, VNL); \ - return CMD_SUCCESS; \ - } \ -} - #define OSPF6_CMD_AREA_GET(str, oa) \ { \ - u_int32_t area_id = 0; \ - if (inet_pton (AF_INET, str, &area_id) != 1) \ + char *ep; \ + u_int32_t area_id = htonl (strtol(str, &ep, 10)); \ + if (*ep && inet_pton (AF_INET, str, &area_id) != 1) \ { \ vty_out (vty, "Malformed Area-ID: %s%s", str, VNL); \ return CMD_SUCCESS; \ diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index 40ff0c7a07..8e619f74c7 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -2454,7 +2454,7 @@ ospf_apiserver_clients_notify_nsm_change (struct ospf_neighbor *nbr) { struct msg *msg; struct in_addr ifaddr = { .s_addr = 0L }; - struct in_addr nbraddr; + struct in_addr nbraddr = { .s_addr = 0L }; assert (nbr); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index da07dcb4ac..c1bce0a222 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -5320,11 +5320,16 @@ DEFUN (interface_ip_pim_hello, pim_ifp = ifp->info; - if (!pim_ifp) { - vty_out(vty, "Pim not enabled on this interface%s", VTY_NEWLINE); - return CMD_WARNING; - } + if (!pim_ifp) + { + if (!pim_cmd_interface_add(ifp)) + { + vty_out(vty, "Could not enable PIM SM on interface%s", VTY_NEWLINE); + return CMD_WARNING; + } + } + pim_ifp = ifp->info; pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10); if (argc == idx_hold + 1) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index d4dbcb383d..9b79c032c8 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -147,7 +147,6 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) /* SGRpt entry could have empty oil */ if (ch->upstream->channel_oil) pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask); - pim_channel_del_oif (ch->upstream->channel_oil, ch->interface, mask); /* * Do we have any S,G's that are inheriting? * Nuke from on high too. @@ -178,6 +177,10 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) pim_upstream_update_join_desired(ch->upstream); } + /* upstream is common across ifchannels, check if upstream's + ifchannel list is empty before deleting upstream_del + ref count will take care of it. + */ pim_upstream_del(ch->upstream, __PRETTY_FUNCTION__); ch->upstream = NULL; @@ -199,6 +202,9 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) hash_release(pim_ifp->pim_ifchannel_hash, ch); listnode_delete(pim_ifchannel_list, ch); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s: ifchannel entry %s is deleted ", __PRETTY_FUNCTION__, ch->sg_str); + pim_ifchannel_free(ch); } @@ -570,14 +576,18 @@ pim_ifchannel_add(struct interface *ifp, listnode_add_sort(up->ifchannels, ch); + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("%s: ifchannel %s is created ", __PRETTY_FUNCTION__, ch->sg_str); + return ch; } -static void ifjoin_to_noinfo(struct pim_ifchannel *ch) +static void ifjoin_to_noinfo(struct pim_ifchannel *ch, bool ch_del) { pim_forward_stop(ch); pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch, PIM_IFJOIN_NOINFO); - delete_on_noinfo(ch); + if (ch_del) + delete_on_noinfo(ch); } static int on_ifjoin_expiry_timer(struct thread *t) @@ -586,7 +596,7 @@ static int on_ifjoin_expiry_timer(struct thread *t) ch = THREAD_ARG(t); - ifjoin_to_noinfo(ch); + ifjoin_to_noinfo(ch, true); /* ch may have been deleted */ return 0; @@ -608,10 +618,6 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) pim_ifp = ifp->info; send_prune_echo = (listcount(pim_ifp->pim_neighbor_list) > 1); - //ch->ifjoin_state transition to NOINFO - ifjoin_to_noinfo(ch); - /* from here ch may have been deleted */ - if (send_prune_echo) { struct pim_rpf rpf; @@ -620,6 +626,23 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) rpf.rpf_addr.u.prefix4 = pim_ifp->primary_address; pim_jp_agg_single_upstream_send(&rpf, ch->upstream, 0); } + /* If SGRpt flag is set on ifchannel, Trigger SGRpt + message on RP path upon prune timer expiry. + */ + if (PIM_IF_FLAG_TEST_S_G_RPT (ch->flags)) + { + if (ch->upstream) + pim_upstream_update_join_desired(ch->upstream); + /* + ch->ifjoin_state transition to NOINFO state + ch_del is set to 0 for not deleteing from here. + Holdtime expiry (ch_del set to 1) delete the entry. + */ + ifjoin_to_noinfo(ch, false); + } + else + ifjoin_to_noinfo(ch, true); + /* from here ch may have been deleted */ } else { @@ -796,7 +819,7 @@ void pim_ifchannel_join_add(struct interface *ifp, (ch->upstream->parent->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) && !(ch->upstream->flags & PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) { - pim_upstream_ref (ch->upstream, PIM_UPSTREAM_FLAG_MASK_SRC_LHR); + pim_upstream_ref (ch->upstream, PIM_UPSTREAM_FLAG_MASK_SRC_LHR, __PRETTY_FUNCTION__); pim_upstream_keep_alive_timer_start (ch->upstream, qpim_keep_alive_time); } break; @@ -889,8 +912,10 @@ void pim_ifchannel_prune(struct interface *ifp, case PIM_IFJOIN_NOINFO: if (source_flags & PIM_ENCODE_RPT_BIT) { - PIM_IF_FLAG_SET_S_G_RPT(ch->flags); - ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; + if (!(source_flags & PIM_ENCODE_WC_BIT)) + PIM_IF_FLAG_SET_S_G_RPT(ch->flags); + + ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING; if (listcount(pim_ifp->pim_neighbor_list) > 1) jp_override_interval_msec = pim_if_jp_override_interval_msec(ifp); else @@ -1296,7 +1321,7 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom, uint8_t if (up) { if (PIM_DEBUG_TRACE) - zlog_debug ("%s: del inherit oif from up %s", __PRETTY_FUNCTION__, up->sg_str); + zlog_debug ("%s: SGRpt Set, del inherit oif from up %s", __PRETTY_FUNCTION__, up->sg_str); pim_channel_del_oif (up->channel_oil, ch->interface, PIM_OIF_FLAG_PROTO_STAR); } } diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 76ec812b3f..c883a2c8bb 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -38,6 +38,7 @@ #include "pim_zebra.h" static void group_timer_off(struct igmp_group *group); +static int pim_igmp_general_query(struct thread *t); /* This socket is used for TXing IGMP packets only, IGMP RX happens * in pim_mroute_msg() @@ -168,8 +169,11 @@ static int pim_igmp_other_querier_expire(struct thread *t) /* We are the current querier, then re-start sending general queries. + RFC 2236 - sec 7 Other Querier + present timer expired (Send General + Query, Set Gen. Query. timer) */ - pim_igmp_general_query_on(igmp); + pim_igmp_general_query(t); return 0; } @@ -490,8 +494,6 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) return -1; } -static int pim_igmp_general_query(struct thread *t); - void pim_igmp_general_query_on(struct igmp_sock *igmp) { struct pim_interface *pim_ifp; diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index f69165ef7f..01ba2039fb 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -566,7 +566,7 @@ pim_ecmp_nexthop_search (struct pim_nexthop_cache *pnc, //PIM ECMP flag is enable then choose ECMP path. hash_val = pim_compute_ecmp_hash (src, grp); mod_val = hash_val % pnc->nexthop_num; - if (PIM_DEBUG_TRACE) + if (PIM_DEBUG_PIM_TRACE_DETAIL) zlog_debug ("%s: hash_val %u mod_val %u ", __PRETTY_FUNCTION__, hash_val, mod_val); } @@ -913,7 +913,7 @@ pim_ecmp_nexthop_lookup (struct pim_nexthop *nexthop, struct in_addr addr, { hash_val = pim_compute_ecmp_hash (src, grp); mod_val = hash_val % num_ifindex; - if (PIM_DEBUG_TRACE) + if (PIM_DEBUG_PIM_TRACE_DETAIL) zlog_debug ("%s: hash_val %u mod_val %u", __PRETTY_FUNCTION__, hash_val, mod_val); } @@ -1036,7 +1036,7 @@ int pim_ecmp_fib_lookup_if_vif_index(struct in_addr addr, { hash_val = pim_compute_ecmp_hash (src, grp); mod_val = hash_val % num_ifindex; - if (PIM_DEBUG_TRACE) + if (PIM_DEBUG_PIM_TRACE_DETAIL) zlog_debug ("%s: hash_val %u mod_val %u", __PRETTY_FUNCTION__, hash_val, mod_val); } diff --git a/pimd/pim_register.c b/pimd/pim_register.c index f631632484..682a6401ca 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -353,7 +353,7 @@ pim_register_recv (struct interface *ifp, zlog_debug("%s: Sending register-Stop to %s and dropping mr. packet", __func__, "Sender"); /* Drop Packet Silently */ - return 1; + return 0; } } @@ -415,5 +415,5 @@ pim_register_recv (struct interface *ifp, pim_register_stop_send (ifp, &sg, dest_addr, src_addr); } - return 1; + return 0; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index d06703ccb3..bebe56567d 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -77,9 +77,17 @@ pim_upstream_remove_children (struct pim_upstream *up) while (!list_isempty (up->sources)) { child = listnode_head (up->sources); - child->parent = NULL; listnode_delete (up->sources, child); + if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) + { + PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); + child = pim_upstream_del(child, __PRETTY_FUNCTION__); + } + if (child) + child->parent = NULL; } + list_delete(up->sources); + up->sources = NULL; } /* @@ -148,10 +156,14 @@ void pim_upstream_free(struct pim_upstream *up) static void upstream_channel_oil_detach(struct pim_upstream *up) { - if (up->channel_oil) { - pim_channel_oil_del(up->channel_oil); - up->channel_oil = NULL; - } + if (up->channel_oil) + { + /* Detaching from channel_oil, channel_oil may exist post del, + but upstream would not keep reference of it + */ + pim_channel_oil_del(up->channel_oil); + up->channel_oil = NULL; + } } struct pim_upstream * @@ -162,7 +174,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) if (PIM_DEBUG_TRACE) zlog_debug ("%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)", - __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags, + __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags, up->channel_oil->oil_ref_count); --up->ref_count; @@ -194,26 +206,12 @@ pim_upstream_del(struct pim_upstream *up, const char *name) } pim_upstream_remove_children (up); + if (up->sources) + list_delete (up->sources); + up->sources = NULL; pim_mroute_del (up->channel_oil, __PRETTY_FUNCTION__); upstream_channel_oil_detach(up); - if (up->sources) - { - struct listnode *node, *nnode; - struct pim_upstream *child; - for (ALL_LIST_ELEMENTS (up->sources, node, nnode, child)) - { - if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(child->flags)) - { - PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(child->flags); - pim_upstream_del(child, __PRETTY_FUNCTION__); - } - } - - list_delete (up->sources); - } - up->sources = NULL; - list_delete (up->ifchannels); up->ifchannels = NULL; @@ -222,11 +220,10 @@ pim_upstream_del(struct pim_upstream *up, const char *name) into pim_upstream_free() because the later is called by list_delete_all_node() */ - if (up->parent) - { - listnode_delete (up->parent->sources, up); - up->parent = NULL; - } + if (up->parent && up->parent->sources) + listnode_delete (up->parent->sources, up); + up->parent = NULL; + listnode_delete (pim_upstream_list, up); hash_release (pim_upstream_hash, up); @@ -533,13 +530,14 @@ pim_upstream_switch(struct pim_upstream *up, { enum pim_upstream_state old_state = up->join_state; - if (PIM_DEBUG_PIM_EVENTS) { - zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", + if (PIM_DEBUG_PIM_EVENTS) + { + zlog_debug ("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s", __PRETTY_FUNCTION__, up->sg_str, pim_upstream_state2str (up->join_state), pim_upstream_state2str (new_state)); - } + } up->join_state = new_state; if (old_state != new_state) @@ -579,7 +577,17 @@ pim_upstream_switch(struct pim_upstream *up, if (old_state == PIM_UPSTREAM_JOINED) pim_msdp_up_join_state_changed(up); - pim_jp_agg_single_upstream_send(&up->rpf, up, 0 /* prune */); + /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT */ + if (pim_upstream_is_sg_rpt(up) && up->parent) + { + if (PIM_DEBUG_PIM_TRACE_DETAIL) + zlog_debug ("%s: *,G IIF %s S,G IIF %s ", __PRETTY_FUNCTION__, + up->parent->rpf.source_nexthop.interface->name, + up->rpf.source_nexthop.interface->name); + pim_jp_agg_single_upstream_send(&up->parent->rpf, up->parent, 1 /* (W,G) Join */); + } + else + pim_jp_agg_single_upstream_send(&up->rpf, up, 0 /* prune */); join_timer_stop(up); } } @@ -712,9 +720,9 @@ pim_upstream_new (struct prefix_sg *sg, if (PIM_DEBUG_TRACE) { - zlog_debug ("%s: Created Upstream %s upstream_addr %s", + zlog_debug ("%s: Created Upstream %s upstream_addr %s ref count %d increment", __PRETTY_FUNCTION__, up->sg_str, - inet_ntoa (up->upstream_addr)); + inet_ntoa (up->upstream_addr), up->ref_count); } return up; @@ -745,6 +753,9 @@ pim_upstream_find_or_add(struct prefix_sg *sg, { up->flags |= flags; up->ref_count++; + if (PIM_DEBUG_TRACE) + zlog_debug ("%s(%s): upstream %s ref count %d increment", + __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); } } else @@ -754,10 +765,13 @@ pim_upstream_find_or_add(struct prefix_sg *sg, } void -pim_upstream_ref(struct pim_upstream *up, int flags) +pim_upstream_ref(struct pim_upstream *up, int flags, const char *name) { up->flags |= flags; ++up->ref_count; + if (PIM_DEBUG_TRACE) + zlog_debug ("%s(%s): upstream %s ref count %d increment", + __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); } struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, @@ -768,7 +782,7 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, int found = 0; up = pim_upstream_find(sg); if (up) { - pim_upstream_ref(up, flags); + pim_upstream_ref(up, flags, name); found = 1; } else { @@ -781,10 +795,11 @@ struct pim_upstream *pim_upstream_add(struct prefix_sg *sg, { char buf[PREFIX2STR_BUFFER]; prefix2str (&up->rpf.rpf_addr, buf, sizeof (buf)); - zlog_debug("%s(%s): %s, iif %s found: %d: ref_count: %d", + zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d", __PRETTY_FUNCTION__, name, - up->sg_str, buf, found, - up->ref_count); + up->sg_str, buf, up->rpf.source_nexthop.interface ? + up->rpf.source_nexthop.interface->name : "NIL" , + found, up->ref_count); } else zlog_debug("%s(%s): (%s) failure to create", @@ -1644,7 +1659,7 @@ pim_upstream_sg_running (void *arg) if (PIM_DEBUG_TRACE) zlog_debug ("source reference created on kat restart %s", up->sg_str); - pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM); + pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __PRETTY_FUNCTION__); PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); pim_upstream_fhr_kat_start(up); } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 1de8adcc02..87b45059f3 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -144,7 +144,7 @@ struct pim_upstream *pim_upstream_find_or_add (struct prefix_sg *sg, struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, struct interface *ifp, int flags, const char *name); -void pim_upstream_ref (struct pim_upstream *up, int flags); +void pim_upstream_ref (struct pim_upstream *up, int flags, const char *name); struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name); int pim_upstream_evaluate_join_desired(struct pim_upstream *up); diff --git a/tools/frr-reload.py b/tools/frr-reload.py index c91392da15..a7a04be639 100755 --- a/tools/frr-reload.py +++ b/tools/frr-reload.py @@ -109,9 +109,12 @@ class Config(object): log.info('Loading Config object from file %s', filename) try: - file_output = subprocess.check_output(['/usr/bin/vtysh', '-m', '-f', filename]) + file_output = subprocess.check_output(['/usr/bin/vtysh', '-m', '-f', filename], + stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - raise VtyshMarkException(str(e)) + ve = VtyshMarkException(e) + ve.output = e.output + raise ve for line in file_output.split('\n'): line = line.strip() @@ -134,9 +137,11 @@ class Config(object): try: config_text = subprocess.check_output( "/usr/bin/vtysh -c 'show run' | /usr/bin/tail -n +4 | /usr/bin/vtysh -m -f -", - shell=True) + shell=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: - raise VtyshMarkException(str(e)) + ve = VtyshMarkException(e) + ve.output = e.output + raise ve for line in config_text.split('\n'): line = line.strip() @@ -342,10 +347,12 @@ end # the keywords that we know are single line contexts. bgp in this case # is not the main router bgp block, but enabling multi-instance oneline_ctx_keywords = ("access-list ", + "agentx", "bgp ", "debug ", "dump ", "enable ", + "frr ", "hostname ", "ip ", "ipv6 ", @@ -815,6 +822,14 @@ def compare_context_objects(newconf, running): elif "router bgp" in running_ctx_keys[0] and len(running_ctx_keys) > 1 and delete_bgpd: continue + elif ("router bgp" in running_ctx_keys[0] and + len(running_ctx_keys) > 1 and + running_ctx_keys[1].startswith('address-family')): + # There's no 'no address-family' support and so we have to + # delete each line individually again + for line in running_ctx.lines: + lines_to_del.append((running_ctx_keys, line)) + # Non-global context elif running_ctx_keys and not any("address-family" in key for key in running_ctx_keys): lines_to_del.append((running_ctx_keys, None)) @@ -890,11 +905,15 @@ if __name__ == '__main__': # Verify the new config file is valid if not os.path.isfile(args.filename): - print "Filename %s does not exist" % args.filename + msg = "Filename %s does not exist" % args.filename + print msg + log.error(msg) sys.exit(1) if not os.path.getsize(args.filename): - print "Filename %s is an empty file" % args.filename + msg = "Filename %s is an empty file" % args.filename + print msg + log.error(msg) sys.exit(1) # Verify that 'service integrated-vtysh-config' is configured @@ -911,7 +930,9 @@ if __name__ == '__main__': break if not service_integrated_vtysh_config: - print "'service integrated-vtysh-config' is not configured, this is required for 'service frr reload'" + msg = "'service integrated-vtysh-config' is not configured, this is required for 'service frr reload'" + print msg + log.error(msg) sys.exit(1) if args.debug: @@ -922,6 +943,7 @@ if __name__ == '__main__': # Create a Config object from the config generated by newconf newconf = Config() newconf.load_from_file(args.filename) + reload_ok = True if args.test: @@ -1064,7 +1086,7 @@ if __name__ == '__main__': # 'no ip ospf authentication message-digest 1.1.1.1' in # our example above # - Split that last entry by whitespace and drop the last word - log.warning('Failed to execute %s', ' '.join(cmd)) + log.info('Failed to execute %s', ' '.join(cmd)) last_arg = cmd[-1].split(' ') if len(last_arg) <= 2: @@ -1099,9 +1121,25 @@ if __name__ == '__main__': with open(filename, 'w') as fh: for line in lines_to_configure: fh.write(line + '\n') - subprocess.call(['/usr/bin/vtysh', '-f', filename]) + + output = subprocess.check_output(['/usr/bin/vtysh', '-f', filename]) + + # exit non-zero if we see these errors + for x in ('BGP instance name and AS number mismatch', + 'BGP instance is already running', + '% not a local address'): + for line in output.splitlines(): + if x in line: + msg = "ERROR: %s" % x + log.error(msg) + print msg + reload_ok = False + os.unlink(filename) # Make these changes persistent if args.overwrite or args.filename != '/etc/frr/frr.conf': subprocess.call(['/usr/bin/vtysh', '-c', 'write']) + + if not reload_ok: + sys.exit(1) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index face057d67..19b8f2fd8b 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -323,7 +323,11 @@ vtysh_execute_func (const char *line, int pager) { vtysh_execute("exit-vnc"); } - else if ((saved_node == KEYCHAIN_KEY_NODE) && (tried == 1)) + else if ((saved_node == KEYCHAIN_KEY_NODE + || saved_node == LDP_PSEUDOWIRE_NODE + || saved_node == LDP_IPV4_IFACE_NODE + || saved_node == LDP_IPV6_IFACE_NODE) + && (tried == 1)) { vtysh_execute("exit"); } @@ -641,7 +645,7 @@ vtysh_mark_file (const char *filename) } } /* This is the end */ - fprintf(stdout, "end\n"); + fprintf(stdout, "\nend\n"); vty_close(vty); XFREE(MTYPE_VTYSH_CMD, vty_buf_copy); diff --git a/zebra/interface.c b/zebra/interface.c index 7ff782f7cc..7b0d31338d 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -709,6 +709,10 @@ if_delete_update (struct interface *ifp) interface deletion message. */ ifp->ifindex = IFINDEX_INTERNAL; ifp->node = NULL; + + /* if the ifp is in a vrf, move it to default so vrf can be deleted if desired */ + if (ifp->vrf_id) + if_handle_vrf_change (ifp, VRF_DEFAULT); } /* VRF change for an interface */ diff --git a/zebra/label_manager.c b/zebra/label_manager.c index cbb35631ac..fbe4cea467 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -55,6 +55,80 @@ static void delete_label_chunk(void *val) XFREE(MTYPE_LM_CHUNK, val); } +static int relay_response_back(struct zserv *zserv) +{ + int ret = 0; + struct stream *src, *dst; + u_int16_t size = 0; + u_char marker; + u_char version; + vrf_id_t vrf_id; + u_int16_t resp_cmd; + + src = zclient->ibuf; + dst = zserv->obuf; + + stream_reset(src); + + ret = zclient_read_header(src, zclient->sock, &size, &marker, &version, + &vrf_id, &resp_cmd); + if (ret < 0 && errno != EAGAIN) { + zlog_err("%s: Error reading Label Manager response: %s", __func__, + strerror(errno)); + return -1; + } + zlog_debug("%s: Label Manager response received, %d bytes", __func__, + size); + if (size == 0) + return -1; + + /* send response back */ + stream_copy(dst, src); + ret = writen(zserv->sock, dst->data, stream_get_endp(dst)); + if (ret <= 0) { + zlog_err("%s: Error sending Label Manager response back: %s", + __func__, strerror(errno)); + return -1; + } + zlog_debug("%s: Label Manager response (%d bytes) sent back", __func__, + ret); + + return 0; +} + +static int lm_zclient_read(struct thread *t) +{ + struct zserv *zserv; + int ret; + + /* Get socket to zebra. */ + zserv = THREAD_ARG(t); + zclient->t_read = NULL; + + /* read response and send it back */ + ret = relay_response_back(zserv); + + return ret; +} + +static int reply_error (int cmd, struct zserv *zserv, vrf_id_t vrf_id) +{ + struct stream *s; + + s = zserv->obuf; + stream_reset (s); + + zserv_create_header (s, cmd, vrf_id); + + /* result */ + stream_putc (s, 1); + + /* Write packet size. */ + stream_putw_at (s, 0, stream_get_endp (s)); + + return writen (zserv->sock, s->data, stream_get_endp (s)); + +} /** * Receive a request to get or release a label chunk and forward it to external * label manager. @@ -63,19 +137,25 @@ static void delete_label_chunk(void *val) * proxy. * * @param cmd Type of request (connect, get or release) - * @param src Input buffer from zserv + * @param zserv * @return 0 on success, -1 otherwise */ -int zread_relay_label_manager_request(int cmd, struct zserv *zserv) +int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf_id) { struct stream *src, *dst; - int ret; + int ret = 0; if (zclient->sock < 0) { zlog_err("%s: Error relaying label chunk request: no zclient socket", __func__); + reply_error (cmd, zserv, vrf_id); return -1; } + + /* in case there's any incoming message enqueued, read and forward it */ + while (ret == 0) + ret = relay_response_back(zserv); + /* Send request to external label manager */ src = zserv->ibuf; dst = zclient->obuf; @@ -86,6 +166,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv) if (ret <= 0) { zlog_err("%s: Error relaying label chunk request: %s", __func__, strerror(errno)); + reply_error (cmd, zserv, vrf_id); return -1; } zlog_debug("%s: Label chunk request relayed. %d bytes sent", __func__, @@ -95,43 +176,15 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv) if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) return 0; - /* read response */ - src = zclient->ibuf; - dst = zserv->obuf; - - stream_reset(src); - - u_int16_t size; - u_char marker; - u_char version; - vrf_id_t vrf_id; - u_int16_t resp_cmd; - ret = zclient_read_header(src, zclient->sock, &size, &marker, &version, - &vrf_id, &resp_cmd); - if (ret < 0) { - zlog_err("%s: Error reading label chunk response: %s", __func__, - strerror(errno)); - return -1; - } - zlog_debug("%s: Label chunk response received, %d bytes", __func__, - size); - - /* send response back */ - stream_copy(dst, src); - stream_copy(zserv->obuf, zclient->ibuf); - ret = writen(zserv->sock, dst->data, stream_get_endp(dst)); - if (ret <= 0) { - zlog_err("%s: Error sending label chunk response back: %s", - __func__, strerror(errno)); - return -1; - } - zlog_debug("%s: Label chunk response (%d bytes) sent back", __func__, - ret); + /* make sure we listen to the response */ + if (!zclient->t_read) + thread_add_read(zclient->master, lm_zclient_read, zserv, + zclient->sock, &zclient->t_read); return 0; } -static int zclient_connect(struct thread *t) +static int lm_zclient_connect(struct thread *t) { zclient->t_connect = NULL; @@ -140,11 +193,15 @@ static int zclient_connect(struct thread *t) if (zclient_socket_connect(zclient) < 0) { zlog_err("Error connecting synchronous zclient!"); - thread_add_timer(zebrad.master, zclient_connect, zclient, + thread_add_timer(zebrad.master, lm_zclient_connect, zclient, CONNECTION_DELAY, &zclient->t_connect); return -1; } + /* make socket non-blocking */ + if (set_nonblocking(zclient->sock) < 0) + zlog_warn("%s: set_nonblocking(%d) failed", __func__, zclient->sock); + return 0; } @@ -163,7 +220,7 @@ static void lm_zclient_init(char *lm_zserv_path) zclient = zclient_new(zebrad.master); zclient->sock = -1; zclient->t_connect = NULL; - zclient_connect (NULL); + lm_zclient_connect(NULL); } /** diff --git a/zebra/label_manager.h b/zebra/label_manager.h index a68c301f16..b7d6118a0e 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -61,7 +61,7 @@ struct label_manager { bool lm_is_external; -int zread_relay_label_manager_request(int cmd, struct zserv *zserv); +int zread_relay_label_manager_request(int cmd, struct zserv *zserv, vrf_id_t vrf_id); void label_manager_init(char *lm_zserv_path); struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, u_char keep, uint32_t size); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 95e84ffc3c..1493bd9cb6 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -106,45 +106,41 @@ zebra_redistribute_default (struct zserv *client, vrf_id_t vrf_id) /* Redistribute routes. */ static void -zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t vrf_id) +zebra_redistribute (struct zserv *client, int type, u_short instance, vrf_id_t vrf_id, int afi) { struct rib *newrib; struct route_table *table; struct route_node *rn; - int afi; - for (afi = AFI_IP; afi <= AFI_IP6; afi++) - { - table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id); - if (! table) - continue; + table = zebra_vrf_table (afi, SAFI_UNICAST, vrf_id); + if (! table) + return; - for (rn = route_top (table); rn; rn = route_next (rn)) - RNODE_FOREACH_RIB (rn, newrib) - { - struct prefix *dst_p, *src_p; - srcdest_rnode_prefixes(rn, &dst_p, &src_p); + for (rn = route_top (table); rn; rn = route_next (rn)) + RNODE_FOREACH_RIB (rn, newrib) + { + struct prefix *dst_p, *src_p; + srcdest_rnode_prefixes(rn, &dst_p, &src_p); - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, " - "zebra_check_addr=%d", __func__, - CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED), - newrib->type, newrib->distance, - zebra_check_addr (dst_p)); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: checking: selected=%d, type=%d, distance=%d, " + "zebra_check_addr=%d", __func__, + CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED), + newrib->type, newrib->distance, + zebra_check_addr (dst_p)); - if (! CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)) - continue; - if ((type != ZEBRA_ROUTE_ALL && - (newrib->type != type || newrib->instance != instance))) - continue; - if (newrib->distance == DISTANCE_INFINITY) - continue; - if (! zebra_check_addr (dst_p)) - continue; + if (! CHECK_FLAG (newrib->flags, ZEBRA_FLAG_SELECTED)) + continue; + if ((type != ZEBRA_ROUTE_ALL && + (newrib->type != type || newrib->instance != instance))) + continue; + if (newrib->distance == DISTANCE_INFINITY) + continue; + if (! zebra_check_addr (dst_p)) + continue; - zsend_redistribute_route (1, client, dst_p, src_p, newrib); - } - } + zsend_redistribute_route (1, client, dst_p, src_p, newrib); + } } /* Either advertise a route for redistribution to registered clients or */ @@ -264,13 +260,13 @@ zebra_redistribute_add (int command, struct zserv *client, int length, if (! redist_check_instance (&client->mi_redist[afi][type], instance)) { redist_add_instance (&client->mi_redist[afi][type], instance); - zebra_redistribute (client, type, instance, zvrf_id (zvrf)); + zebra_redistribute (client, type, instance, zvrf_id (zvrf), afi); } } else { if (! vrf_bitmap_check (client->redist[afi][type], zvrf_id (zvrf))) { vrf_bitmap_set (client->redist[afi][type], zvrf_id (zvrf)); - zebra_redistribute (client, type, 0, zvrf_id (zvrf)); + zebra_redistribute (client, type, 0, zvrf_id (zvrf), afi); } } } diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 20b0c13a40..16c157e307 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -554,7 +554,7 @@ zebra_rnh_process_static_routes (vrf_id_t vrfid, int family, { RNODE_FOREACH_RIB(static_rn, srib) { - if (srib->type == ZEBRA_ROUTE_STATIC) + if (srib->type != ZEBRA_ROUTE_STATIC) continue; /* Set the filter flag for the correct nexthop - static route may diff --git a/zebra/zserv.c b/zebra/zserv.c index a59ef3031d..76c0756ada 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -2045,10 +2045,7 @@ zread_label_manager_request (int cmd, struct zserv *client, vrf_id_t vrf_id) /* external label manager */ if (lm_is_external) - { - if (zread_relay_label_manager_request (cmd, client) != 0) - zsend_label_manager_connect_response (client, vrf_id, 1); - } + zread_relay_label_manager_request (cmd, client, vrf_id); /* this is a label manager */ else {