diff options
23 files changed, 657 insertions, 606 deletions
diff --git a/.clang-format b/.clang-format index 3971384a36..5f21a3f324 100644 --- a/.clang-format +++ b/.clang-format @@ -103,6 +103,7 @@ ForEachMacros: - 'FOREACH_AFI_SAFI' - 'FOREACH_AFI_SAFI_NSF' - 'FOREACH_BE_APPLY_BATCH_IN_LIST' + - 'FOREACH_BE_CLIENT_BITS' - 'FOREACH_BE_TXN_BATCH_IN_LIST' - 'FOREACH_BE_TXN_IN_LIST' - 'FOREACH_CMT_REC' diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c index b7a5f94a31..c1dce30ab1 100644 --- a/bgpd/bgp_snmp_bgp4v2.c +++ b/bgpd/bgp_snmp_bgp4v2.c @@ -439,16 +439,22 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, unsigned int len; struct ipaddr paddr = {}; size_t namelen = v ? v->namelen : BGP4V2_NLRI_ENTRY_OFFSET; - sa_family_t family = name[namelen - 1] == 1 ? AF_INET : AF_INET6; - afi_t afi = AFI_IP; - size_t afi_len = IN_ADDR_SIZE; + sa_family_t family; + sa_family_t min_family = 0; /* family of the selected min path */ + afi_t afi; + safi_t safi; + size_t afi_len; + long prefix_type = 0; + long peer_addr_type = 0; + + /* Bgp4V2AddressFamilyIdentifierTC limited to IPv6 */ + if (name[namelen - 1] > IANA_AFI_IPV6) + return NULL; + afi = afi_iana2int(name[namelen - 1]); + afi_len = afi == AFI_IP ? IN_ADDR_SIZE : IN6_ADDR_SIZE; - if (family == AF_INET6) { - afi = AFI_IP6; - afi_len = IN6_ADDR_SIZE; - } +#define BGP_NLRI_ENTRY_OFFSET namelen -#define BGP_NLRI_ENTRY_OFFSET (afi_len + 1 + afi_len) sockunion_init(&su); @@ -456,28 +462,56 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, if (*length - namelen != BGP_NLRI_ENTRY_OFFSET) return NULL; - /* Set OID offset for prefix */ + /* Set OID offset for prefix type */ offset = name + namelen; - if (family == AF_INET) - oid2in_addr(offset, afi_len, &addr->u.prefix4); - else + + /* Bgp4V2SubsequentAddressFamilyIdentifierTC */ + /* limited to Labeled unicast */ + if (*offset > IANA_SAFI_LABELED_UNICAST) + return NULL; + safi = safi_iana2int(*offset); + offset++; + + /* get bgp4V2NlriPrefixType */ + prefix_type = *offset; + offset++; + + /* get bgp4V2NlriPrefix */ + if (prefix_type == IANA_AFI_IPV4) { + oid2in_addr(offset, IN_ADDR_SIZE, &addr->u.prefix4); + addr->family = AF_INET; + offset += IN_ADDR_SIZE; + } else if (prefix_type == IANA_AFI_IPV6) { oid2in6_addr(offset, &addr->u.prefix6); - offset += afi_len; + addr->family = AF_INET6; + offset += IN6_ADDR_SIZE; + } - /* Prefix length */ + /* get bgp4V2NlriPrefixLen */ addr->prefixlen = *offset; - addr->family = family; + offset++; + + /* get bgp4V2PeerRemoteAddrType */ + peer_addr_type = *offset; + if (peer_addr_type == IANA_AFI_IPV4) + family = AF_INET; + else + family = AF_INET6; offset++; /* Peer address */ su.sin.sin_family = family; + + /* get bgp4V2PeerRemoteAddr*/ if (family == AF_INET) - oid2in_addr(offset, afi_len, &su.sin.sin_addr); + oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr); else oid2in6_addr(offset, &su.sin6.sin6_addr); + /* bgp4V2NlriIndex currently ignored */ + /* Lookup node */ - dest = bgp_node_lookup(bgp->rib[afi][SAFI_UNICAST], addr); + dest = bgp_node_lookup(bgp->rib[afi][safi], addr); if (dest) { for (path = bgp_dest_get_bgp_path_info(dest); path; path = path->next) @@ -491,120 +525,191 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, return NULL; } + /* Set OID offset for prefix type */ offset = name + namelen; offsetlen = *length - namelen; len = offsetlen; if (offsetlen == 0) { dest = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); + safi = SAFI_UNICAST; } else { - if (len > afi_len) - len = afi_len; - if (family == AF_INET) - oid2in_addr(offset, len, &addr->u.prefix4); - else - oid2in6_addr(offset, &addr->u.prefix6); + /* bgp4V2NlriAfi is already get */ + /* it is comming from the name parameter */ + + /* get bgp4V2NlriSafi */ + /* Bgp4V2SubsequentAddressFamilyIdentifierTC */ + /* limited to Labeled unicast */ + if (*offset > IANA_SAFI_LABELED_UNICAST) + return NULL; + safi = safi_iana2int(*offset); + offset++; - offset += afi_len; - offsetlen -= afi_len; + /* get bgp4V2NlriPrefixType */ + prefix_type = *offset; + offset++; + /* get bgp4V2NlriPrefix */ + if (prefix_type == IANA_AFI_IPV4) { + oid2in_addr(offset, IN_ADDR_SIZE, &addr->u.prefix4); + addr->family = AF_INET; + offset += IN_ADDR_SIZE; + offsetlen -= IN_ADDR_SIZE; + } else if (prefix_type == IANA_AFI_IPV6) { + oid2in6_addr(offset, &addr->u.prefix6); + addr->family = AF_INET6; + offset += IN6_ADDR_SIZE; + offsetlen -= IN6_ADDR_SIZE; + } + /* get bgp4V2NlriPrefixLen */ if (offsetlen > 0) addr->prefixlen = *offset; else - addr->prefixlen = len * 8; - - addr->family = family; - - dest = bgp_node_get(bgp->rib[afi][SAFI_UNICAST], addr); + addr->prefixlen = afi_len * 8; offset++; offsetlen--; + + /* get node */ + dest = bgp_node_get(bgp->rib[afi][safi], addr); } + if (!dest) + return NULL; + if (offsetlen > 0) { len = offsetlen; if (len > afi_len) len = afi_len; + + /* get bgp4V2PeerRemoteAddrType */ + peer_addr_type = *offset; + if (peer_addr_type == IANA_AFI_IPV4) + family = AF_INET; + else + family = AF_INET6; + offset++; + if (family == AF_INET) - oid2in_addr(offset, len, &paddr.ip._v4_addr); + oid2in_addr(offset, IN_ADDR_SIZE, &paddr.ip._v4_addr); else oid2in6_addr(offset, &paddr.ip._v6_addr); } else { - if (family == AF_INET) - memset(&paddr.ip._v4_addr, 0, afi_len); + /* default case start with ipv4*/ + if (afi == AFI_IP) + family = AF_INET; else - memset(&paddr.ip._v6_addr, 0, afi_len); + family = AF_INET6; + memset(&paddr.ip._v4_addr, 0, sizeof(paddr.ip)); } - if (!dest) - return NULL; - do { min = NULL; + min_family = 0; for (path = bgp_dest_get_bgp_path_info(dest); path; path = path->next) { sa_family_t path_family = sockunion_family(&path->peer->connection->su); + /* the next addr must be > to the current */ + if (path_family < family) + continue; + + if (family == AF_INET + && IPV4_ADDR_CMP(&paddr.ip._v4_addr, + &path->peer->connection->su.sin.sin_addr) + >= 0) + continue; + else if (family == AF_INET6 + && IPV6_ADDR_CMP( + &paddr.ip._v6_addr, + &path->peer->connection->su.sin6.sin6_addr) + >= 0) + continue; - if (path_family == AF_INET && - IPV4_ADDR_CMP(&paddr.ip._v4_addr, - &path->peer->connection->su.sin - .sin_addr) < 0) { - if (!min || - (min && - IPV4_ADDR_CMP(&path->peer->connection->su - .sin.sin_addr, - &min->peer->connection->su - .sin.sin_addr) < 0)) - min = path; - } else if (path_family == AF_INET6 && - IPV6_ADDR_CMP(&paddr.ip._v6_addr, - &path->peer->connection->su - .sin6.sin6_addr) < 0) { - if (!min || - (min && - IPV6_ADDR_CMP(&path->peer->connection->su - .sin6.sin6_addr, - &min->peer->connection->su - .sin6.sin6_addr) < - 0)) - min = path; + /* first valid path its the min*/ + if (!min) { + min = path; + min_family = path_family; + continue; + } + + /* consider path < min */ + if (path_family < min_family) { + min = path; + min_family = path_family; + continue; + } + + if (path_family == AF_INET + && IPV4_ADDR_CMP(&path->peer->connection->su.sin.sin_addr, + &min->peer->connection->su.sin.sin_addr) + < 0) { + min = path; + min_family = path_family; + + } else if (path_family == AF_INET6 + && IPV6_ADDR_CMP( + &path->peer->connection->su.sin6.sin6_addr, + &min->peer->connection->su.sin6.sin6_addr) + < 0) { + min = path; + min_family = path_family; } } if (min) { const struct prefix *rn_p = bgp_dest_get_prefix(dest); - *length = namelen + BGP_NLRI_ENTRY_OFFSET; - offset = name + namelen; - /* Encode prefix into OID */ - if (family == AF_INET) + /* encode bgp4V2NlriSafi*/ + *offset = SAFI_UNICAST; + offset++; + /* encode bgp4V2NlriPrefixType into index*/ + /* encode bgp4V2NlriPrefix into index */ + if (rn_p->family == AF_INET) { + *offset = IANA_AFI_IPV4; + offset++; oid_copy_in_addr(offset, &rn_p->u.prefix4); - else + offset += IN_ADDR_SIZE; + } else { + *offset = IANA_AFI_IPV6; + offset++; oid_copy_in6_addr(offset, &rn_p->u.prefix6); - - offset += afi_len; + offset += IN6_ADDR_SIZE; + } + /* encode bgp4V2NlriPrefixLen into index*/ *offset = rn_p->prefixlen; offset++; - /* Encode peer's IP into OID */ - if (family == AF_INET) { + /* Encode bgp4V2PeerRemoteAddrType */ + /* Encode bgp4V2PeerRemoteAddr */ + if (min_family == AF_INET) { + *offset = IANA_AFI_IPV4; + offset++; oid_copy_in_addr(offset, - &min->peer->connection->su.sin - .sin_addr); + &min->peer->connection->su.sin.sin_addr); + offset += IN_ADDR_SIZE; addr->u.prefix4 = rn_p->u.prefix4; } else { - oid_copy_in6_addr(offset, - &min->peer->connection->su - .sin6.sin6_addr); + *offset = IANA_AFI_IPV6; + offset++; + oid_copy_in6_addr( + offset, &min->peer->connection->su.sin6.sin6_addr); + offset += IN6_ADDR_SIZE; addr->u.prefix6 = rn_p->u.prefix6; } + /* Encode bgp4V2NlriIndex*/ + + *offset = 1; + offset++; + + *length = offset - name; + addr->prefixlen = rn_p->prefixlen; addr->family = rn_p->family; @@ -613,10 +718,8 @@ bgp4v2PathAttrLookup(struct variable *v, oid name[], size_t *length, return min; } - if (family == AF_INET) - memset(&paddr.ip._v4_addr, 0, afi_len); - else - memset(&paddr.ip._v6_addr, 0, afi_len); + memset(&paddr.ip, 0, sizeof(paddr.ip)); + } while ((dest = bgp_route_next(dest))); return NULL; diff --git a/doc/user/snmp.rst b/doc/user/snmp.rst index 0bf3565b2e..3c2d11a6a7 100644 --- a/doc/user/snmp.rst +++ b/doc/user/snmp.rst @@ -126,54 +126,121 @@ An example below is how to query SNMP for BGP: $ # Information about the peers (bgp4V2PeerTable): $ snmpwalk -c public -v2c -On -Ln localhost .1.3.6.1.3.5.1.1.2 ... - .1.3.6.1.3.5.1.1.2.1.1.1.4.192.168.10.124 = Gauge32: 0 - .1.3.6.1.3.5.1.1.2.1.1.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 0 - .1.3.6.1.3.5.1.1.2.1.2.1.4.192.168.10.124 = INTEGER: 1 - .1.3.6.1.3.5.1.1.2.1.2.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 - .1.3.6.1.3.5.1.1.2.1.3.1.4.192.168.10.124 = Hex-STRING: C0 A8 0A 11 - .1.3.6.1.3.5.1.1.2.1.3.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 2A 02 47 80 0A BC 00 00 00 00 00 00 00 00 00 01 - .1.3.6.1.3.5.1.1.2.1.4.1.4.192.168.10.124 = INTEGER: 1 - .1.3.6.1.3.5.1.1.2.1.4.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 - .1.3.6.1.3.5.1.1.2.1.5.1.4.192.168.10.124 = Hex-STRING: C0 A8 0A 7C - .1.3.6.1.3.5.1.1.2.1.5.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 2A 02 47 80 0A BC 00 00 00 00 00 00 00 00 00 02 - .1.3.6.1.3.5.1.1.2.1.6.1.4.192.168.10.124 = Gauge32: 179 - .1.3.6.1.3.5.1.1.2.1.6.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 179 - .1.3.6.1.3.5.1.1.2.1.7.1.4.192.168.10.124 = Gauge32: 65002 - .1.3.6.1.3.5.1.1.2.1.7.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 65002 - .1.3.6.1.3.5.1.1.2.1.8.1.4.192.168.10.124 = Hex-STRING: C0 A8 0A 11 - .1.3.6.1.3.5.1.1.2.1.8.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: C0 A8 0A 11 - .1.3.6.1.3.5.1.1.2.1.9.1.4.192.168.10.124 = Gauge32: 41894 - .1.3.6.1.3.5.1.1.2.1.9.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 39960 - .1.3.6.1.3.5.1.1.2.1.10.1.4.192.168.10.124 = Gauge32: 65001 - .1.3.6.1.3.5.1.1.2.1.10.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 65001 - .1.3.6.1.3.5.1.1.2.1.11.1.4.192.168.10.124 = Hex-STRING: C8 C8 C8 CA - .1.3.6.1.3.5.1.1.2.1.11.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: C8 C8 C8 CA - .1.3.6.1.3.5.1.1.2.1.12.1.4.192.168.10.124 = INTEGER: 2 - .1.3.6.1.3.5.1.1.2.1.12.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 - .1.3.6.1.3.5.1.1.2.1.13.1.4.192.168.10.124 = INTEGER: 6 - .1.3.6.1.3.5.1.1.2.1.13.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 6 + .1.3.6.1.3.5.1.1.2.1.1.1.1.192.168.10.124 = Gauge32: 0 + .1.3.6.1.3.5.1.1.2.1.1.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 0 + .1.3.6.1.3.5.1.1.2.1.2.1.1.192.168.10.124 = INTEGER: 1 + .1.3.6.1.3.5.1.1.2.1.2.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 + .1.3.6.1.3.5.1.1.2.1.3.1.1.192.168.10.124 = Hex-STRING: C0 A8 0A 11 + .1.3.6.1.3.5.1.1.2.1.3.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 2A 02 47 80 0A BC 00 00 00 00 00 00 00 00 00 01 + .1.3.6.1.3.5.1.1.2.1.4.1.1.192.168.10.124 = INTEGER: 1 + .1.3.6.1.3.5.1.1.2.1.4.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 + .1.3.6.1.3.5.1.1.2.1.5.1.1.192.168.10.124 = Hex-STRING: C0 A8 0A 7C + .1.3.6.1.3.5.1.1.2.1.5.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 2A 02 47 80 0A BC 00 00 00 00 00 00 00 00 00 02 + .1.3.6.1.3.5.1.1.2.1.6.1.1.192.168.10.124 = Gauge32: 179 + .1.3.6.1.3.5.1.1.2.1.6.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 179 + .1.3.6.1.3.5.1.1.2.1.7.1.1.192.168.10.124 = Gauge32: 65002 + .1.3.6.1.3.5.1.1.2.1.7.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 65002 + .1.3.6.1.3.5.1.1.2.1.8.1.1.192.168.10.124 = Hex-STRING: C0 A8 0A 11 + .1.3.6.1.3.5.1.1.2.1.8.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: C0 A8 0A 11 + .1.3.6.1.3.5.1.1.2.1.9.1.1.192.168.10.124 = Gauge32: 41894 + .1.3.6.1.3.5.1.1.2.1.9.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 39960 + .1.3.6.1.3.5.1.1.2.1.10.1.1.192.168.10.124 = Gauge32: 65001 + .1.3.6.1.3.5.1.1.2.1.10.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 65001 + .1.3.6.1.3.5.1.1.2.1.11.1.1.192.168.10.124 = Hex-STRING: C8 C8 C8 CA + .1.3.6.1.3.5.1.1.2.1.11.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: C8 C8 C8 CA + .1.3.6.1.3.5.1.1.2.1.12.1.1.192.168.10.124 = INTEGER: 2 + .1.3.6.1.3.5.1.1.2.1.12.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 + .1.3.6.1.3.5.1.1.2.1.13.1.1.192.168.10.124 = INTEGER: 6 + .1.3.6.1.3.5.1.1.2.1.13.1.2.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = INTEGER: 6 $ # Information about the BGP table (bgp4V2NlriTable): $ snmpwalk -c public -v2c -On -Ln localhost .1.3.6.1.3.5.1.1.9 ... - .1.3.6.1.3.5.1.1.9.1.22.1.4.10.0.2.0.24.192.168.10.124 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.22.1.4.10.10.100.0.24.192.168.10.124 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.22.1.4.172.16.31.1.32.192.168.10.124 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.22.1.4.172.16.31.2.32.192.168.10.124 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.22.1.4.172.16.31.3.32.192.168.10.124 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.22.1.4.192.168.0.0.24.192.168.10.124 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.22.1.4.192.168.1.0.24.192.168.10.124 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.22.1.4.192.168.10.0.24.192.168.10.124 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.22.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.0.64.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Gauge32: 1 - .1.3.6.1.3.5.1.1.9.1.24.1.4.10.0.2.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 - .1.3.6.1.3.5.1.1.9.1.24.1.4.10.10.100.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 - .1.3.6.1.3.5.1.1.9.1.24.1.4.172.16.31.1.32.192.168.10.124 = Hex-STRING: 02 01 FD E9 - .1.3.6.1.3.5.1.1.9.1.24.1.4.172.16.31.2.32.192.168.10.124 = Hex-STRING: 02 01 FD E9 - .1.3.6.1.3.5.1.1.9.1.24.1.4.172.16.31.3.32.192.168.10.124 = Hex-STRING: 02 01 FD E9 - .1.3.6.1.3.5.1.1.9.1.24.1.4.192.168.0.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 - .1.3.6.1.3.5.1.1.9.1.24.1.4.192.168.1.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 - .1.3.6.1.3.5.1.1.9.1.24.1.4.192.168.10.0.24.192.168.10.124 = Hex-STRING: 02 01 FD E9 - .1.3.6.1.3.5.1.1.9.1.24.2.16.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.0.64.42.2.71.128.10.188.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.1.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.1.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.1.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.1.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.2.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.2.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.2.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 2 + .1.3.6.1.3.5.1.1.9.1.2.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 2 + .1.3.6.1.3.5.1.1.9.1.3.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.3.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.3.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.3.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.4.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.4.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.4.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 2 + .1.3.6.1.3.5.1.1.9.1.4.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 2 + .1.3.6.1.3.5.1.1.9.1.5.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Hex-STRING: 0A 00 00 00 + .1.3.6.1.3.5.1.1.9.1.5.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Hex-STRING: 0A 00 00 02 + .1.3.6.1.3.5.1.1.9.1.5.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Hex-STRING: 20 01 0D B8 00 00 00 00 00 00 00 00 00 00 00 01 + .1.3.6.1.3.5.1.1.9.1.5.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Hex-STRING: 20 01 0D B8 00 01 00 00 00 00 00 00 00 00 00 00 + .1.3.6.1.3.5.1.1.9.1.6.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Gauge32: 31 + .1.3.6.1.3.5.1.1.9.1.6.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Gauge32: 32 + .1.3.6.1.3.5.1.1.9.1.6.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 128 + .1.3.6.1.3.5.1.1.9.1.6.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 56 + .1.3.6.1.3.5.1.1.9.1.7.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.7.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.7.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.7.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.8.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.8.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.8.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.8.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 3 + .1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 3 + .1.3.6.1.3.5.1.1.9.1.10.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.10.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.10.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 4 + .1.3.6.1.3.5.1.1.9.1.10.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 4 + .1.3.6.1.3.5.1.1.9.1.11.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Hex-STRING: C0 A8 0C 01 + .1.3.6.1.3.5.1.1.9.1.11.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Hex-STRING: C0 A8 0C 01 + .1.3.6.1.3.5.1.1.9.1.11.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Hex-STRING: FE 80 00 00 00 00 00 00 30 39 84 FF FE 9A 24 2B + .1.3.6.1.3.5.1.1.9.1.11.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Hex-STRING: FE 80 00 00 00 00 00 00 30 39 84 FF FE 9A 24 2B + .1.3.6.1.3.5.1.1.9.1.14.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 0 + .1.3.6.1.3.5.1.1.9.1.14.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 0 + .1.3.6.1.3.5.1.1.9.1.14.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 0 + .1.3.6.1.3.5.1.1.9.1.14.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 0 + .1.3.6.1.3.5.1.1.9.1.15.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.15.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.15.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.15.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 0 + .1.3.6.1.3.5.1.1.9.1.16.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.16.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.16.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 1 + .1.3.6.1.3.5.1.1.9.1.16.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 1 + 1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Gauge32: 1 + 1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Gauge32: 2 + 1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 1 + 1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 2 + 1.3.6.1.3.5.1.1.9.1.18.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 0 + 1.3.6.1.3.5.1.1.9.1.18.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 0 + 1.3.6.1.3.5.1.1.9.1.18.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 0 + 1.3.6.1.3.5.1.1.9.1.18.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 0 + 1.3.6.1.3.5.1.1.9.1.19.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = INTEGER: 0 + 1.3.6.1.3.5.1.1.9.1.19.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = INTEGER: 0 + 1.3.6.1.3.5.1.1.9.1.19.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 0 + 1.3.6.1.3.5.1.1.9.1.19.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = INTEGER: 0 + 1.3.6.1.3.5.1.1.9.1.20.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Gauge32: 0 + 1.3.6.1.3.5.1.1.9.1.20.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Gauge32: 0 + 1.3.6.1.3.5.1.1.9.1.20.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 0 + 1.3.6.1.3.5.1.1.9.1.20.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 0 + 1.3.6.1.3.5.1.1.9.1.21.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Hex-STRING: 00 00 00 00 + 1.3.6.1.3.5.1.1.9.1.21.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Hex-STRING: 00 00 00 00 + 1.3.6.1.3.5.1.1.9.1.21.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Hex-STRING: 00 00 00 00 + 1.3.6.1.3.5.1.1.9.1.21.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Hex-STRING: 00 00 00 00 + 1.3.6.1.3.5.1.1.9.1.22.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Gauge32: 1 + 1.3.6.1.3.5.1.1.9.1.22.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.22.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Gauge32: 1 + .1.3.6.1.3.5.1.1.9.1.24.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Hex-STRING: 02 01 FD E9 + .1.3.6.1.3.5.1.1.9.1.24.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1 = Hex-STRING: 02 01 FD E9 + The AgentX protocol can be transported over a Unix socket or using TCP or UDP. It usually defaults to a Unix socket and depends on how NetSNMP was built. If diff --git a/lib/frrstr.c b/lib/frrstr.c index e5440c5093..bb112afef7 100644 --- a/lib/frrstr.c +++ b/lib/frrstr.c @@ -3,6 +3,7 @@ * FRR string processing utilities. * Copyright (C) 2018 Cumulus Networks, Inc. * Quentin Young + * Copyright (c) 2023, LabN Consulting, L.L.C. */ #include "zebra.h" @@ -225,3 +226,26 @@ char *frrstr_hex(char *buff, size_t bufsiz, const uint8_t *str, size_t num) return buff; } + +const char *frrstr_skip_over_char(const char *s, int skipc) +{ + int c, quote = 0; + + while ((c = *s++)) { + if (c == '\\') { + if (!*s++) + return NULL; + continue; + } + if (quote) { + if (c == quote) + quote = 0; + continue; + } + if (c == skipc) + return s; + if (c == '"' || c == '\'') + quote = c; + } + return NULL; +} diff --git a/lib/frrstr.h b/lib/frrstr.h index 19ba09e213..9a4fe257a2 100644 --- a/lib/frrstr.h +++ b/lib/frrstr.h @@ -3,6 +3,7 @@ * FRR string processing utilities. * Copyright (C) 2018 Cumulus Networks, Inc. * Quentin Young + * Copyright (c) 2023, LabN Consulting, L.L.C. */ #ifndef _FRRSTR_H_ @@ -166,6 +167,13 @@ int all_digit(const char *str); */ char *frrstr_hex(char *buff, size_t bufsiz, const uint8_t *str, size_t num); + +/* + * Advance past a given char `skipc` in a string, while honoring quoting and + * backslash escapes (i.e., ignore `skipc` which occur in quoted sections). + */ +const char *frrstr_skip_over_char(const char *s, int skipc); + #ifdef __cplusplus } #endif diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c index be10dcf6a1..762ace1361 100644 --- a/lib/mgmt_be_client.c +++ b/lib/mgmt_be_client.c @@ -118,13 +118,6 @@ struct mgmt_be_client { struct debug mgmt_dbg_be_client = {0, "Management backend client operations"}; -const char *mgmt_be_client_names[MGMTD_BE_CLIENT_ID_MAX + 1] = { -#ifdef HAVE_STATICD - [MGMTD_BE_CLIENT_ID_STATICD] = "staticd", -#endif - [MGMTD_BE_CLIENT_ID_MAX] = "Unknown/Invalid", -}; - static int mgmt_be_client_send_msg(struct mgmt_be_client *client_ctx, Mgmtd__BeMessage *be_msg) { diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h index 4ad5ca5957..051c908a37 100644 --- a/lib/mgmt_be_client.h +++ b/lib/mgmt_be_client.h @@ -17,27 +17,6 @@ extern "C" { #include "mgmtd/mgmt_defines.h" /*************************************************************** - * Client IDs - ***************************************************************/ - -/* - * Add enum value for each supported component, wrap with - * #ifdef HAVE_COMPONENT - */ -enum mgmt_be_client_id { - MGMTD_BE_CLIENT_ID_MIN = 0, - MGMTD_BE_CLIENT_ID_INIT = -1, -#ifdef HAVE_STATICD - MGMTD_BE_CLIENT_ID_STATICD, -#endif - MGMTD_BE_CLIENT_ID_MAX -}; - -#define FOREACH_MGMTD_BE_CLIENT_ID(id) \ - for ((id) = MGMTD_BE_CLIENT_ID_MIN; \ - (id) < MGMTD_BE_CLIENT_ID_MAX; (id)++) - -/*************************************************************** * Constants ***************************************************************/ @@ -108,29 +87,6 @@ struct mgmt_be_client_cbs { * Global data exported ***************************************************************/ -extern const char *mgmt_be_client_names[MGMTD_BE_CLIENT_ID_MAX + 1]; - -static inline const char *mgmt_be_client_id2name(enum mgmt_be_client_id id) -{ - if (id > MGMTD_BE_CLIENT_ID_MAX) - id = MGMTD_BE_CLIENT_ID_MAX; - return mgmt_be_client_names[id]; -} - -static inline enum mgmt_be_client_id -mgmt_be_client_name2id(const char *name) -{ - enum mgmt_be_client_id id; - - FOREACH_MGMTD_BE_CLIENT_ID (id) { - if (!strncmp(mgmt_be_client_names[id], name, - MGMTD_CLIENT_NAME_MAX_LEN)) - return id; - } - - return MGMTD_BE_CLIENT_ID_MAX; -} - extern struct debug mgmt_dbg_be_client; /*************************************************************** diff --git a/lib/northbound.c b/lib/northbound.c index be49d92841..080f3d002e 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -305,8 +305,6 @@ struct nb_config *nb_config_new(struct lyd_node *dnode) config->dnode = yang_dnode_new(ly_native_ctx, true); config->version = 0; - RB_INIT(nb_config_cbs, &config->cfg_chgs); - return config; } @@ -314,7 +312,7 @@ void nb_config_free(struct nb_config *config) { if (config->dnode) yang_dnode_free(config->dnode); - nb_config_diff_del_changes(&config->cfg_chgs); + XFREE(MTYPE_NB_CONFIG, config); } @@ -326,8 +324,6 @@ struct nb_config *nb_config_dup(const struct nb_config *config) dup->dnode = yang_dnode_dup(config->dnode); dup->version = config->version; - RB_INIT(nb_config_cbs, &dup->cfg_chgs); - return dup; } @@ -753,65 +749,6 @@ int nb_candidate_edit(struct nb_config *candidate, return NB_OK; } -static void nb_update_candidate_changes(struct nb_config *candidate, - struct nb_cfg_change *change, - uint32_t *seq) -{ - enum nb_operation oper = change->operation; - char *xpath = change->xpath; - struct lyd_node *root = NULL; - struct lyd_node *dnode; - struct nb_config_cbs *cfg_chgs = &candidate->cfg_chgs; - int op; - - switch (oper) { - case NB_OP_CREATE: - case NB_OP_MODIFY: - root = yang_dnode_get(candidate->dnode, xpath); - break; - case NB_OP_DESTROY: - root = yang_dnode_get(running_config->dnode, xpath); - /* code */ - break; - case NB_OP_MOVE: - case NB_OP_PRE_VALIDATE: - case NB_OP_APPLY_FINISH: - case NB_OP_GET_ELEM: - case NB_OP_GET_NEXT: - case NB_OP_GET_KEYS: - case NB_OP_LOOKUP_ENTRY: - case NB_OP_RPC: - break; - default: - assert(!"non-enum value, invalid"); - } - - if (!root) - return; - - LYD_TREE_DFS_BEGIN (root, dnode) { - op = nb_lyd_diff_get_op(dnode); - switch (op) { - case 'c': /* create */ - nb_config_diff_created(dnode, seq, cfg_chgs); - LYD_TREE_DFS_continue = 1; - break; - case 'd': /* delete */ - nb_config_diff_deleted(dnode, seq, cfg_chgs); - LYD_TREE_DFS_continue = 1; - break; - case 'r': /* replace */ - nb_config_diff_add_change(cfg_chgs, NB_OP_MODIFY, seq, - dnode); - break; - case 'n': /* none */ - default: - break; - } - LYD_TREE_DFS_END(root, dnode); - } -} - static bool nb_is_operation_allowed(struct nb_node *nb_node, struct nb_cfg_change *change) { @@ -829,8 +766,6 @@ void nb_candidate_edit_config_changes( size_t num_cfg_changes, const char *xpath_base, const char *curr_xpath, int xpath_index, char *err_buf, int err_bufsize, bool *error) { - uint32_t seq = 0; - if (error) *error = false; @@ -900,7 +835,6 @@ void nb_candidate_edit_config_changes( *error = true; continue; } - nb_update_candidate_changes(candidate_config, change, &seq); } if (error && *error) { diff --git a/lib/northbound.h b/lib/northbound.h index 1723a87e4e..5cf6e85b4b 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -703,7 +703,6 @@ struct nb_transaction { struct nb_config { struct lyd_node *dnode; uint32_t version; - struct nb_config_cbs cfg_chgs; }; /* Callback function used by nb_oper_data_iterate(). */ diff --git a/lib/yang.c b/lib/yang.c index 4dd8654217..7046091baa 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -254,15 +254,8 @@ struct lysc_node *yang_find_snode(struct ly_ctx *ly_ctx, const char *xpath, uint32_t options) { struct lysc_node *snode; - struct ly_set *set; - LY_ERR err; - err = lys_find_xpath(ly_native_ctx, NULL, xpath, options, &set); - if (err || !set->count) - return NULL; - - snode = set->snodes[0]; - ly_set_free(set, NULL); + snode = (struct lysc_node *)lys_find_path(ly_ctx, NULL, xpath, 0); return snode; } diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c index 5ab11ea491..8330f6f36b 100644 --- a/mgmtd/mgmt_be_adapter.c +++ b/mgmtd/mgmt_be_adapter.c @@ -10,6 +10,7 @@ #include <zebra.h> #include "darr.h" #include "frrevent.h" +#include "frrstr.h" #include "sockopt.h" #include "network.h" #include "libfrr.h" @@ -28,29 +29,27 @@ #define FOREACH_ADAPTER_IN_LIST(adapter) \ frr_each_safe (mgmt_be_adapters, &mgmt_be_adapters, (adapter)) -/* - * Mapping of YANG XPath regular expressions to - * their corresponding backend clients. - */ -struct mgmt_be_xpath_map { - char *xpath_regexp; - uint subscr_info[MGMTD_BE_CLIENT_ID_MAX]; -}; +/* ---------- */ +/* Client IDs */ +/* ---------- */ -struct mgmt_be_client_xpath { - const char *xpath; - uint subscribed; +const char *mgmt_be_client_names[MGMTD_BE_CLIENT_ID_MAX + 1] = { +#ifdef HAVE_STATICD + [MGMTD_BE_CLIENT_ID_STATICD] = "staticd", +#endif + [MGMTD_BE_CLIENT_ID_MAX] = "Unknown/Invalid", }; -struct mgmt_be_client_xpath_map { - struct mgmt_be_client_xpath *xpaths; - uint nxpaths; -}; +/* ------------- */ +/* XPATH MAPPING */ +/* ------------- */ -struct mgmt_be_get_adapter_config_params { - struct mgmt_be_client_adapter *adapter; - struct nb_config_cbs *cfg_chgs; - uint32_t seq; +/* + * Mapping of YANG XPath prefixes to their corresponding backend clients. + */ +struct mgmt_be_xpath_map { + char *xpath_prefix; + uint64_t clients; }; /* @@ -58,31 +57,23 @@ struct mgmt_be_get_adapter_config_params { * above map as well. */ #if HAVE_STATICD -static struct mgmt_be_client_xpath staticd_xpaths[] = { - { - .xpath = "/frr-vrf:lib/*", - .subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG, - }, - { - .xpath = "/frr-interface:lib/*", - .subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG, - }, - { - .xpath = - "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/*", - .subscribed = MGMT_SUBSCR_VALIDATE_CFG | MGMT_SUBSCR_NOTIFY_CFG, - }, +static const char *const staticd_xpaths[] = { + "/frr-vrf:lib", + "/frr-interface:lib", + "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd", + NULL, }; #endif -static struct mgmt_be_client_xpath_map - mgmt_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { +static const char *const *be_client_xpaths[MGMTD_BE_CLIENT_ID_MAX] = { + #ifdef HAVE_STATICD - [MGMTD_BE_CLIENT_ID_STATICD] = {staticd_xpaths, - array_size(staticd_xpaths)}, + [MGMTD_BE_CLIENT_ID_STATICD] = staticd_xpaths, #endif }; +static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {}; + /* * We would like to have a better ADT than one with O(n) comparisons * @@ -91,7 +82,9 @@ static struct mgmt_be_client_xpath_map * says this probably involves exact match/no-match on a stem in the map array * or something like that. */ -static struct mgmt_be_xpath_map *mgmt_xpath_map; + +static struct mgmt_be_xpath_map *be_cfg_xpath_map; +static struct mgmt_be_xpath_map *be_oper_xpath_map; static struct event_loop *mgmt_loop; static struct msg_server mgmt_be_server = {.fd = -1}; @@ -101,12 +94,34 @@ static struct mgmt_be_adapters_head mgmt_be_adapters; static struct mgmt_be_client_adapter *mgmt_be_adapters_by_id[MGMTD_BE_CLIENT_ID_MAX]; + /* Forward declarations */ static void mgmt_be_adapter_sched_init_event(struct mgmt_be_client_adapter *adapter); -static uint mgmt_be_get_subscr_for_xpath_and_client( - const char *xpath, enum mgmt_be_client_id client_id, uint subscr_mask); +static bool be_is_client_interested(const char *xpath, + enum mgmt_be_client_id id, bool config); + + +static const char *mgmt_be_client_id2name(enum mgmt_be_client_id id) +{ + if (id > MGMTD_BE_CLIENT_ID_MAX) + return "invalid client id"; + return mgmt_be_client_names[id]; +} + +static enum mgmt_be_client_id mgmt_be_client_name2id(const char *name) +{ + enum mgmt_be_client_id id; + + FOREACH_MGMTD_BE_CLIENT_ID (id) { + if (!strncmp(mgmt_be_client_names[id], name, + MGMTD_CLIENT_NAME_MAX_LEN)) + return id; + } + + return MGMTD_BE_CLIENT_ID_MAX; +} static struct mgmt_be_client_adapter * mgmt_be_find_adapter_by_fd(int conn_fd) @@ -135,178 +150,91 @@ mgmt_be_find_adapter_by_name(const char *name) } static void mgmt_register_client_xpath(enum mgmt_be_client_id id, - const char *xpath, uint subscribed) + const char *xpath, bool config) { - struct mgmt_be_xpath_map *map; + struct mgmt_be_xpath_map **maps, *map; - darr_foreach_p (mgmt_xpath_map, map) - if (!strcmp(xpath, map->xpath_regexp)) { - map->subscr_info[id] = subscribed; + maps = config ? &be_cfg_xpath_map : &be_oper_xpath_map; + + darr_foreach_p (*maps, map) { + if (!strcmp(xpath, map->xpath_prefix)) { + map->clients |= (1u << id); return; } + } /* we didn't find a matching entry */ - map = darr_append(mgmt_xpath_map); - map->xpath_regexp = XSTRDUP(MTYPE_MGMTD_XPATH, xpath); - map->subscr_info[id] = subscribed; + map = darr_append(*maps); + map->xpath_prefix = XSTRDUP(MTYPE_MGMTD_XPATH, xpath); + map->clients = (1ul << id); } /* - * Load the initial mapping from static init map + * initial the combined maps from per client maps */ static void mgmt_be_xpath_map_init(void) { - struct mgmt_be_client_xpath *init, *end; enum mgmt_be_client_id id; + const char *const *init; MGMTD_BE_ADAPTER_DBG("Init XPath Maps"); FOREACH_MGMTD_BE_CLIENT_ID (id) { - init = mgmt_client_xpaths[id].xpaths; - end = init + mgmt_client_xpaths[id].nxpaths; - for (; init < end; init++) { - MGMTD_BE_ADAPTER_DBG(" - XPATH: '%s'", init->xpath); - mgmt_register_client_xpath(id, init->xpath, - init->subscribed); + /* Initialize the common config init map */ + for (init = be_client_xpaths[id]; init && *init; init++) { + MGMTD_BE_ADAPTER_DBG(" - CFG XPATH: '%s'", *init); + mgmt_register_client_xpath(id, *init, true); + } + + /* Initialize the common oper init map */ + for (init = be_client_oper_xpaths[id]; init && *init; init++) { + MGMTD_BE_ADAPTER_DBG(" - OPER XPATH: '%s'", *init); + mgmt_register_client_xpath(id, *init, false); } } - MGMTD_BE_ADAPTER_DBG("Total XPath Maps: %u", darr_len(mgmt_xpath_map)); + MGMTD_BE_ADAPTER_DBG("Total Cfg XPath Maps: %u", + darr_len(be_cfg_xpath_map)); + MGMTD_BE_ADAPTER_DBG("Total Oper XPath Maps: %u", + darr_len(be_oper_xpath_map)); } static void mgmt_be_xpath_map_cleanup(void) { struct mgmt_be_xpath_map *map; - darr_foreach_p (mgmt_xpath_map, map) - XFREE(MTYPE_MGMTD_XPATH, map->xpath_regexp); - darr_free(mgmt_xpath_map); -} - -static int mgmt_be_eval_regexp_match(const char *xpath_regexp, - const char *xpath) -{ - int match_len = 0, re_indx = 0, xp_indx = 0; - int rexp_len, xpath_len; - bool match = true, re_wild = false, xp_wild = false; - bool delim = false, enter_wild_match = false; - char wild_delim = 0; - - rexp_len = strlen(xpath_regexp); - xpath_len = strlen(xpath); - - /* - * Remove the trailing wildcard from the regexp and Xpath. - */ - if (rexp_len && xpath_regexp[rexp_len-1] == '*') - rexp_len--; - if (xpath_len && xpath[xpath_len-1] == '*') - xpath_len--; + darr_foreach_p (be_cfg_xpath_map, map) + XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix); + darr_free(be_cfg_xpath_map); - if (!rexp_len || !xpath_len) - return 0; + darr_foreach_p (be_oper_xpath_map, map) + XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix); + darr_free(be_oper_xpath_map); +} - for (re_indx = 0, xp_indx = 0; - match && re_indx < rexp_len && xp_indx < xpath_len;) { - match = (xpath_regexp[re_indx] == xpath[xp_indx]); - /* - * Check if we need to enter wildcard matching. - */ - if (!enter_wild_match && !match && - (xpath_regexp[re_indx] == '*' - || xpath[xp_indx] == '*')) { - /* - * Found wildcard - */ - enter_wild_match = - (xpath_regexp[re_indx-1] == '/' - || xpath_regexp[re_indx-1] == '\'' - || xpath[xp_indx-1] == '/' - || xpath[xp_indx-1] == '\''); - if (enter_wild_match) { - if (xpath_regexp[re_indx] == '*') { - /* - * Begin RE wildcard match. - */ - re_wild = true; - wild_delim = xpath_regexp[re_indx-1]; - } else if (xpath[xp_indx] == '*') { - /* - * Begin XP wildcard match. - */ - xp_wild = true; - wild_delim = xpath[xp_indx-1]; - } - } - } - - /* - * Check if we need to exit wildcard matching. - */ - if (enter_wild_match) { - if (re_wild && xpath[xp_indx] == wild_delim) { - /* - * End RE wildcard matching. - */ - re_wild = false; - if (re_indx < rexp_len-1) - re_indx++; - enter_wild_match = false; - } else if (xp_wild - && xpath_regexp[re_indx] == wild_delim) { - /* - * End XP wildcard matching. - */ - xp_wild = false; - if (xp_indx < xpath_len-1) - xp_indx++; - enter_wild_match = false; - } - } - - match = (xp_wild || re_wild - || xpath_regexp[re_indx] == xpath[xp_indx]); +/* + * Check if either path or xpath is a prefix of the other. Before checking the + * xpath is converted to a regular path string (e..g, removing key value + * specifiers). + */ +static bool mgmt_be_xpath_prefix(const char *path, const char *xpath) +{ + int xc, pc; - /* - * Check if we found a delimiter in both the Xpaths - */ - if ((xpath_regexp[re_indx] == '/' - && xpath[xp_indx] == '/') - || (xpath_regexp[re_indx] == ']' - && xpath[xp_indx] == ']') - || (xpath_regexp[re_indx] == '[' - && xpath[xp_indx] == '[')) { - /* - * Increment the match count if we have a - * new delimiter. - */ - if (match && re_indx && xp_indx && !delim) - match_len++; - delim = true; - } else { - delim = false; + while ((xc = *xpath++)) { + if (xc == '[') { + xpath = frrstr_skip_over_char(xpath, ']'); + if (!xpath) + return false; + continue; } - - /* - * Proceed to the next character in the RE/XP string as - * necessary. - */ - if (!re_wild) - re_indx++; - if (!xp_wild) - xp_indx++; + pc = *path++; + if (!pc) + return true; + if (pc != xc) + return false; } - - /* - * If we finished matching and the last token was a full match - * increment the match count appropriately. - */ - if (match && !delim && - (xpath_regexp[re_indx] == '/' - || xpath_regexp[re_indx] == ']')) - match_len++; - - return match_len; + return true; } static void mgmt_be_adapter_delete(struct mgmt_be_client_adapter *adapter) @@ -596,16 +524,26 @@ static void mgmt_be_adapter_process_msg(uint8_t version, uint8_t *data, mgmtd__be_message__free_unpacked(be_msg, NULL); } +/* + * Args for callback + */ +struct mgmt_be_get_adapter_config_params { + struct mgmt_be_client_adapter *adapter; + struct nb_config_cbs *cfg_chgs; + uint32_t seq; +}; + +/* + * Callback to store the change a node in the datastore if it should be sync'd + * to the adapter (i.e., if the adapter is subscribed to it). + */ static void mgmt_be_iter_and_get_cfg(const char *xpath, struct lyd_node *node, struct nb_node *nb_node, void *ctx) { struct mgmt_be_get_adapter_config_params *parms = ctx; struct mgmt_be_client_adapter *adapter = parms->adapter; - uint subscr; - subscr = mgmt_be_get_subscr_for_xpath_and_client( - xpath, adapter->id, MGMT_SUBSCR_NOTIFY_CFG); - if (subscr) + if (be_is_client_interested(xpath, adapter->id, true)) nb_config_diff_created(node, &parms->seq, parms->cfg_chgs); } @@ -752,6 +690,10 @@ mgmt_be_get_adapter_by_name(const char *name) return mgmt_be_find_adapter_by_name(name); } +/* + * Get a full set of changes for all the config that an adapter is subscribed to + * receive. + */ int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter, struct nb_config_cbs **cfg_chgs) { @@ -780,72 +722,65 @@ int mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter, return 0; } -void mgmt_be_get_subscr_info_for_xpath( - const char *xpath, struct mgmt_be_client_subscr_info *subscr_info) +uint64_t mgmt_be_interested_clients(const char *xpath, bool config) { - struct mgmt_be_xpath_map *map; + struct mgmt_be_xpath_map *maps, *map; enum mgmt_be_client_id id; + uint64_t clients; - memset(subscr_info, 0, sizeof(*subscr_info)); + maps = config ? be_cfg_xpath_map : be_oper_xpath_map; + + clients = 0; MGMTD_BE_ADAPTER_DBG("XPATH: '%s'", xpath); - darr_foreach_p (mgmt_xpath_map, map) { - if (!mgmt_be_eval_regexp_match(map->xpath_regexp, xpath)) - continue; - FOREACH_MGMTD_BE_CLIENT_ID (id) { - subscr_info->xpath_subscr[id] |= map->subscr_info[id]; - } - } + darr_foreach_p (maps, map) + if (mgmt_be_xpath_prefix(map->xpath_prefix, xpath)) + clients |= map->clients; if (DEBUG_MODE_CHECK(&mgmt_debug_be, DEBUG_MODE_ALL)) { - FOREACH_MGMTD_BE_CLIENT_ID (id) { - if (!subscr_info->xpath_subscr[id]) - continue; - MGMTD_BE_ADAPTER_DBG("Cient: %s: subscribed: 0x%x", - mgmt_be_client_id2name(id), - subscr_info->xpath_subscr[id]); - } + FOREACH_BE_CLIENT_BITS (id, clients) + MGMTD_BE_ADAPTER_DBG("Cient: %s: subscribed", + mgmt_be_client_id2name(id)); } + return clients; } /** - * Return the subscription info bits for a given `xpath` for a given - * `client_id`. + * Return true if `client_id` is interested in `xpath` for `config` + * or oper (!`config`). * * Args: - * xpath - the xpath to check for subscription information. + * xpath - the xpath to check for interest. * client_id - the BE client being checked for. - * subscr_mask - The subscr bits the caller is interested in seeing - * if set. + * bool - check for config (vs oper) subscription. * * Returns: - * The subscription info bits. + * Interested or not. */ -static uint mgmt_be_get_subscr_for_xpath_and_client( - const char *xpath, enum mgmt_be_client_id client_id, uint subscr_mask) +static bool be_is_client_interested(const char *xpath, + enum mgmt_be_client_id id, bool config) { - struct mgmt_be_client_xpath_map *map; - uint subscr = 0; - uint i; + const char *const *xpaths; - assert(client_id < MGMTD_BE_CLIENT_ID_MAX); + assert(id < MGMTD_BE_CLIENT_ID_MAX); MGMTD_BE_ADAPTER_DBG("Checking client: %s for xpath: '%s'", - mgmt_be_client_id2name(client_id), xpath); - - map = &mgmt_client_xpaths[client_id]; - for (i = 0; i < map->nxpaths; i++) { - if (!mgmt_be_eval_regexp_match(map->xpaths[i].xpath, xpath)) - continue; - MGMTD_BE_ADAPTER_DBG("xpath: %s: matched: %s", - map->xpaths[i].xpath, xpath); - subscr |= map->xpaths[i].subscribed; - if ((subscr & subscr_mask) == subscr_mask) - break; + mgmt_be_client_id2name(id), xpath); + + xpaths = config ? be_client_xpaths[id] : be_client_oper_xpaths[id]; + if (xpaths) { + for (; *xpaths; xpaths++) { + if (mgmt_be_xpath_prefix(*xpaths, xpath)) { + MGMTD_BE_ADAPTER_DBG("xpath: %s: matched: %s", + *xpaths, xpath); + return true; + } + } } - MGMTD_BE_ADAPTER_DBG("client: %s: subscribed: 0x%x", - mgmt_be_client_id2name(client_id), subscr); - return subscr; + + MGMTD_BE_ADAPTER_DBG("client: %s: not interested", + mgmt_be_client_id2name(id)); + return false; } void mgmt_be_adapter_status_write(struct vty *vty) @@ -872,56 +807,49 @@ void mgmt_be_adapter_status_write(struct vty *vty) (int)mgmt_be_adapters_count(&mgmt_be_adapters)); } -void mgmt_be_xpath_register_write(struct vty *vty) +static void be_show_xpath_register(struct vty *vty, + struct mgmt_be_xpath_map *map) { - struct mgmt_be_xpath_map *map; enum mgmt_be_client_id id; - struct mgmt_be_client_adapter *adapter; - uint info; - - vty_out(vty, "MGMTD Backend XPath Registry\n"); - - darr_foreach_p (mgmt_xpath_map, map) { - vty_out(vty, " - XPATH: '%s'\n", map->xpath_regexp); - FOREACH_MGMTD_BE_CLIENT_ID (id) { - info = map->subscr_info[id]; - if (!info) - continue; - vty_out(vty, - " -- Client: '%s'\tValidate:%d, Notify:%d, Own:%d\n", - mgmt_be_client_id2name(id), - (info & MGMT_SUBSCR_VALIDATE_CFG) != 0, - (info & MGMT_SUBSCR_NOTIFY_CFG) != 0, - (info & MGMT_SUBSCR_OPER_OWN) != 0); - adapter = mgmt_be_get_adapter_by_id(id); - if (adapter) - vty_out(vty, " -- Adapter: %p\n", adapter); - } + const char *astr; + + vty_out(vty, " - xpath: '%s'\n", map->xpath_prefix); + FOREACH_BE_CLIENT_BITS (id, map->clients) { + astr = mgmt_be_get_adapter_by_id(id) ? "active" : "inactive"; + vty_out(vty, " -- %s-client: '%s'\n", astr, + mgmt_be_client_id2name(id)); } +} +void mgmt_be_xpath_register_write(struct vty *vty) +{ + struct mgmt_be_xpath_map *map; - vty_out(vty, "Total XPath Registries: %u\n", darr_len(mgmt_xpath_map)); + vty_out(vty, "MGMTD Backend CFG XPath Registry: Count: %u\n", + darr_len(be_oper_xpath_map)); + darr_foreach_p (be_cfg_xpath_map, map) + be_show_xpath_register(vty, map); + + vty_out(vty, "\nMGMTD Backend OPER XPath Registry: Count: %u\n", + darr_len(be_oper_xpath_map)); + darr_foreach_p (be_oper_xpath_map, map) + be_show_xpath_register(vty, map); } -void mgmt_be_xpath_subscr_info_write(struct vty *vty, const char *xpath) +void mgmt_be_show_xpath_registries(struct vty *vty, const char *xpath) { - struct mgmt_be_client_subscr_info subscr; enum mgmt_be_client_id id; struct mgmt_be_client_adapter *adapter; - uint info; + uint64_t cclients, oclients, combined; - mgmt_be_get_subscr_info_for_xpath(xpath, &subscr); + cclients = mgmt_be_interested_clients(xpath, true); + oclients = mgmt_be_interested_clients(xpath, false); + combined = cclients | oclients; vty_out(vty, "XPath: '%s'\n", xpath); - FOREACH_MGMTD_BE_CLIENT_ID (id) { - info = subscr.xpath_subscr[id]; - if (!info) - continue; - vty_out(vty, - " -- Client: '%s'\tValidate:%d, Notify:%d, Own:%d\n", - mgmt_be_client_id2name(id), - (info & MGMT_SUBSCR_VALIDATE_CFG) != 0, - (info & MGMT_SUBSCR_NOTIFY_CFG) != 0, - (info & MGMT_SUBSCR_OPER_OWN) != 0); + FOREACH_BE_CLIENT_BITS (id, combined) { + vty_out(vty, " -- Client: '%s'\tconfig:%d oper:%d\n", + mgmt_be_client_id2name(id), IS_IDBIT_SET(cclients, id), + IS_IDBIT_SET(oclients, id)); adapter = mgmt_be_get_adapter_by_id(id); if (adapter) vty_out(vty, " -- Adapter: %p\n", adapter); diff --git a/mgmtd/mgmt_be_adapter.h b/mgmtd/mgmt_be_adapter.h index ca8f55c457..0597136c8a 100644 --- a/mgmtd/mgmt_be_adapter.h +++ b/mgmtd/mgmt_be_adapter.h @@ -20,6 +20,22 @@ #define MGMTD_FIND_ADAPTER_BY_INDEX(adapter_index) \ mgmt_adaptr_ref[adapter_index] +/** + * CLIENT-ID + * + * Add enum value for each supported component, wrap with + * #ifdef HAVE_COMPONENT + */ +enum mgmt_be_client_id { + MGMTD_BE_CLIENT_ID_MIN = 0, + MGMTD_BE_CLIENT_ID_INIT = -1, +#ifdef HAVE_STATICD + MGMTD_BE_CLIENT_ID_STATICD, +#endif + MGMTD_BE_CLIENT_ID_MAX +}; + + enum mgmt_be_req_type { MGMTD_BE_REQ_NONE = 0, MGMTD_BE_REQ_CFG_VALIDATE, @@ -49,8 +65,6 @@ struct mgmt_be_client_adapter { enum mgmt_be_client_id id; uint32_t flags; char name[MGMTD_CLIENT_NAME_MAX_LEN]; - uint8_t num_xpath_reg; - char xpath_reg[MGMTD_MAX_NUM_XPATH_REG][MGMTD_MAX_XPATH_LEN]; int refcount; @@ -81,9 +95,36 @@ DECLARE_LIST(mgmt_be_adapters, struct mgmt_be_client_adapter, list_linkage); #define MGMT_SUBSCR_OPER_OWN 0x4 #define MGMT_SUBSCR_ALL 0x7 -struct mgmt_be_client_subscr_info { - uint xpath_subscr[MGMTD_BE_CLIENT_ID_MAX]; -}; +/* --------- */ +/* CLIENT-ID */ +/* --------- */ + +#define FOREACH_MGMTD_BE_CLIENT_ID(id) \ + for ((id) = MGMTD_BE_CLIENT_ID_MIN; (id) < MGMTD_BE_CLIENT_ID_MAX; \ + (id)++) + +#define IS_IDBIT_SET(v, id) (!IS_IDBIT_UNSET(v, id)) +#define IS_IDBIT_UNSET(v, id) (!((v) & (1ull << (id)))) + +#define __GET_NEXT_SET(id, bits) \ + ({ \ + enum mgmt_be_client_id __id = (id); \ + \ + for (; __id < MGMTD_BE_CLIENT_ID_MAX && \ + IS_IDBIT_UNSET(bits, __id); \ + __id++) \ + ; \ + __id; \ + }) + +#define FOREACH_BE_CLIENT_BITS(id, bits) \ + for ((id) = __GET_NEXT_SET(MGMTD_BE_CLIENT_ID_MIN, bits); \ + (id) < MGMTD_BE_CLIENT_ID_MAX; \ + (id) = __GET_NEXT_SET((id) + 1, bits)) + +/* ---------- */ +/* Prototypes */ +/* ---------- */ /* Initialise backend adapter module. */ extern void mgmt_be_adapter_init(struct event_loop *tm); @@ -177,17 +218,13 @@ extern void mgmt_be_xpath_register_write(struct vty *vty); * * Args: * xpath - the xpath to check for subscription information. - * subscr_info - An array of uint indexed by client id - * each eleemnt holds the subscription info - * for that client. + * config - true for config interest false for oper interest. */ -extern void mgmt_be_get_subscr_info_for_xpath( - const char *xpath, struct mgmt_be_client_subscr_info *subscr_info); +extern uint64_t mgmt_be_interested_clients(const char *xpath, bool config); /* * Dump backend client information for a given xpath to vty. */ -extern void mgmt_be_xpath_subscr_info_write(struct vty *vty, - const char *xpath); +extern void mgmt_be_show_xpath_registries(struct vty *vty, const char *xpath); #endif /* _FRR_MGMTD_BE_ADAPTER_H_ */ diff --git a/mgmtd/mgmt_ds.c b/mgmtd/mgmt_ds.c index a0e610c7c7..8ed15b1726 100644 --- a/mgmtd/mgmt_ds.c +++ b/mgmtd/mgmt_ds.c @@ -93,14 +93,6 @@ static int mgmt_ds_replace_dst_with_src_ds(struct mgmt_ds_ctx *src, dst->root.dnode_root = yang_dnode_dup(src->root.dnode_root); } - if (src->ds_id == MGMTD_DS_CANDIDATE) { - /* - * Drop the changes in scratch-buffer. - */ - MGMTD_DS_DBG("Emptying Candidate Scratch buffer!"); - nb_config_diff_del_changes(&src->root.cfg_root->cfg_chgs); - } - return 0; } @@ -126,14 +118,6 @@ static int mgmt_ds_merge_src_with_dst_ds(struct mgmt_ds_ctx *src, return ret; } - if (src->ds_id == MGMTD_DS_CANDIDATE) { - /* - * Drop the changes in scratch-buffer. - */ - MGMTD_DS_DBG("Emptying Candidate Scratch buffer!"); - nb_config_diff_del_changes(&src->root.cfg_root->cfg_chgs); - } - return 0; } diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c index ebad48e832..765def7bac 100644 --- a/mgmtd/mgmt_txn.c +++ b/mgmtd/mgmt_txn.c @@ -80,7 +80,6 @@ struct mgmt_txn_be_cfg_batch { uint64_t batch_id; enum mgmt_be_client_id be_id; struct mgmt_be_client_adapter *be_adapter; - uint xp_subscr[MGMTD_MAX_CFG_CHANGES_IN_BATCH]; Mgmtd__YangCfgDataReq cfg_data[MGMTD_MAX_CFG_CHANGES_IN_BATCH]; Mgmtd__YangCfgDataReq *cfg_datap[MGMTD_MAX_CFG_CHANGES_IN_BATCH]; Mgmtd__YangData data[MGMTD_MAX_CFG_CHANGES_IN_BATCH]; @@ -125,7 +124,7 @@ struct mgmt_commit_cfg_req { * Details on all the Backend Clients associated with * this commit. */ - struct mgmt_be_client_subscr_info subscr_info; + uint64_t clients; /* * List of backend batches for this commit to be validated @@ -546,8 +545,7 @@ static void mgmt_txn_req_free(struct mgmt_txn_req **txn_req) * send a txn delete message */ adapter = mgmt_be_get_adapter_by_id(id); - if (adapter && cleanup && - ccreq->subscr_info.xpath_subscr[id]) + if (adapter && cleanup && IS_IDBIT_SET(ccreq->clients, id)) mgmt_txn_send_be_txn_delete((*txn_req)->txn, adapter); } @@ -915,7 +913,7 @@ mgmt_try_move_commit_to_next_phase(struct mgmt_txn_ctx *txn, * Check if all clients has moved to next phase or not. */ FOREACH_MGMTD_BE_CLIENT_ID (id) { - if (cmtcfg_req->subscr_info.xpath_subscr[id] && + if (IS_IDBIT_SET(cmtcfg_req->clients, id) && mgmt_txn_batches_count(&cmtcfg_req->curr_batches[id])) { /* * There's atleast once client who hasn't moved to @@ -991,13 +989,15 @@ mgmt_move_be_commit_to_next_phase(struct mgmt_txn_ctx *txn, return 0; } +/* + * This is the real workhorse + */ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req, struct nb_config_cbs *changes) { struct nb_config_cb *cb, *nxt; struct nb_config_change *chg; struct mgmt_txn_be_cfg_batch *batch; - struct mgmt_be_client_subscr_info subscr_info; char *xpath = NULL, *value = NULL; char err_buf[1024]; enum mgmt_be_client_id id; @@ -1006,6 +1006,7 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req, bool found_validator; int num_chgs = 0; int xpath_len, value_len; + uint64_t clients; cmtcfg_req = &txn_req->req.commit_cfg; @@ -1032,17 +1033,16 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req, MGMTD_TXN_DBG("XPATH: %s, Value: '%s'", xpath, value ? value : "NIL"); - mgmt_be_get_subscr_info_for_xpath(xpath, &subscr_info); + clients = mgmt_be_interested_clients(xpath, true); + cmtcfg_req->clients |= clients; + if (clients) + found_validator = true; + else + found_validator = false; xpath_len = strlen(xpath) + 1; value_len = strlen(value) + 1; - found_validator = false; - FOREACH_MGMTD_BE_CLIENT_ID (id) { - if (!(subscr_info.xpath_subscr[id] & - (MGMT_SUBSCR_VALIDATE_CFG | - MGMT_SUBSCR_NOTIFY_CFG))) - continue; - + FOREACH_BE_CLIENT_BITS (id, clients) { adapter = mgmt_be_get_adapter_by_id(id); if (!adapter) continue; @@ -1058,9 +1058,6 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req, } batch->buf_space_left -= (xpath_len + value_len); - memcpy(&batch->xp_subscr[batch->num_cfg_data], - &subscr_info.xpath_subscr[id], - sizeof(batch->xp_subscr[0])); mgmt_yang_cfg_data_req_init( &batch->cfg_data[batch->num_cfg_data]); @@ -1089,12 +1086,6 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req, value; value = NULL; - if (subscr_info.xpath_subscr[id] & - MGMT_SUBSCR_VALIDATE_CFG) - found_validator = true; - - cmtcfg_req->subscr_info.xpath_subscr[id] |= - subscr_info.xpath_subscr[id]; MGMTD_TXN_DBG(" -- %s, batch-id: %" PRIu64 " item:%d", adapter->name, batch->batch_id, (int)batch->num_cfg_data); @@ -1193,25 +1184,11 @@ static int mgmt_txn_prepare_config(struct mgmt_txn_ctx *txn) goto mgmt_txn_prepare_config_done; } - /* - * Check for diffs from scratch buffer. If found empty - * get the diff from Candidate DS itself. - */ - cfg_chgs = &nb_config->cfg_chgs; - if (RB_EMPTY(nb_config_cbs, cfg_chgs)) { - /* - * This could be the case when the config is directly - * loaded onto the candidate DS from a file. Get the - * diff from a full comparison of the candidate and - * running DSs. - */ - nb_config_diff(mgmt_ds_get_nb_config( - txn->commit_cfg_req->req.commit_cfg - .dst_ds_ctx), - nb_config, &changes); - cfg_chgs = &changes; - del_cfg_chgs = true; - } + nb_config_diff(mgmt_ds_get_nb_config(txn->commit_cfg_req->req.commit_cfg + .dst_ds_ctx), + nb_config, &changes); + cfg_chgs = &changes; + del_cfg_chgs = true; if (RB_EMPTY(nb_config_cbs, cfg_chgs)) { /* @@ -1237,7 +1214,7 @@ static int mgmt_txn_prepare_config(struct mgmt_txn_ctx *txn) nb_ctx.client = NB_CLIENT_MGMTD_SERVER; nb_ctx.user = (void *)txn; - ret = nb_candidate_validate_yang(nb_config, false, err_buf, + ret = nb_candidate_validate_yang(nb_config, true, err_buf, sizeof(err_buf) - 1); if (ret != NB_OK) { if (strncmp(err_buf, " ", strlen(err_buf)) == 0) @@ -1318,7 +1295,7 @@ static int mgmt_txn_send_be_txn_create(struct mgmt_txn_ctx *txn) cmtcfg_req = &txn->commit_cfg_req->req.commit_cfg; FOREACH_MGMTD_BE_CLIENT_ID (id) { - if (cmtcfg_req->subscr_info.xpath_subscr[id]) { + if (IS_IDBIT_SET(cmtcfg_req->clients, id)) { adapter = mgmt_be_get_adapter_by_id(id); if (mgmt_be_send_txn_req(adapter, txn->txn_id, true)) { (void)mgmt_txn_send_commit_cfg_reply( @@ -1364,7 +1341,7 @@ static int mgmt_txn_send_be_cfg_data(struct mgmt_txn_ctx *txn, assert(txn->type == MGMTD_TXN_TYPE_CONFIG && txn->commit_cfg_req); cmtcfg_req = &txn->commit_cfg_req->req.commit_cfg; - assert(cmtcfg_req->subscr_info.xpath_subscr[adapter->id]); + assert(IS_IDBIT_SET(cmtcfg_req->clients, adapter->id)); indx = 0; num_batches = @@ -1417,7 +1394,7 @@ static int mgmt_txn_send_be_txn_delete(struct mgmt_txn_ctx *txn, assert(txn->type == MGMTD_TXN_TYPE_CONFIG); assert(!mgmt_txn_batches_count(&cmtcfg_req->curr_batches[adapter->id])); - if (!cmtcfg_req->subscr_info.xpath_subscr[adapter->id]) + if (IS_IDBIT_UNSET(cmtcfg_req->clients, adapter->id)) return 0; return mgmt_be_send_txn_req(adapter, txn->txn_id, false); @@ -1476,8 +1453,7 @@ static int mgmt_txn_send_be_cfg_apply(struct mgmt_txn_ctx *txn) } FOREACH_MGMTD_BE_CLIENT_ID (id) { - if (cmtcfg_req->subscr_info.xpath_subscr[id] & - MGMT_SUBSCR_NOTIFY_CFG) { + if (IS_IDBIT_SET(cmtcfg_req->clients, id)) { adapter = mgmt_be_get_adapter_by_id(id); if (!adapter) return -1; @@ -2365,9 +2341,8 @@ int mgmt_txn_notify_be_adapter_conn(struct mgmt_be_client_adapter *adapter, ? &txn->commit_cfg_req->req .commit_cfg : NULL; - if (cmtcfg_req && - cmtcfg_req->subscr_info - .xpath_subscr[adapter->id]) { + if (cmtcfg_req && IS_IDBIT_SET(cmtcfg_req->clients, + adapter->id)) { mgmt_txn_send_commit_cfg_reply( txn, MGMTD_INTERNAL_ERROR, "Backend daemon disconnected while processing commit!"); diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c index d8f5976f4d..e7d6966710 100644 --- a/mgmtd/mgmt_vty.c +++ b/mgmtd/mgmt_vty.c @@ -273,7 +273,7 @@ DEFPY(show_mgmt_map_xpath, "Get YANG Backend Subscription\n" "XPath expression specifying the YANG data path\n") { - mgmt_be_xpath_subscr_info_write(vty, path); + mgmt_be_show_xpath_registries(vty, path); return CMD_SUCCESS; } diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py index 6bf0078daa..f83ee2971c 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py @@ -70,6 +70,11 @@ def test_bgp_dynamic_capability_addpath(): } }, }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, } } return topotest.json_cmp(output, expected) @@ -108,6 +113,11 @@ def test_bgp_dynamic_capability_addpath(): } }, }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, "messageStats": { "notificationsRecv": 0, "capabilityRecv": 1, diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py index db1eb2723b..b7e2090eee 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py @@ -68,6 +68,11 @@ def test_bgp_dynamic_capability_graceful_restart(): "gracefulRestart": "advertisedAndReceived", "longLivedGracefulRestart": "advertisedAndReceived", }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, "gracefulRestartInfo": { "nBit": True, "timers": { @@ -116,6 +121,11 @@ def test_bgp_dynamic_capability_graceful_restart(): "gracefulRestart": "advertisedAndReceived", "longLivedGracefulRestart": "advertisedAndReceived", }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, "gracefulRestartInfo": { "nBit": True, "timers": { diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py index 49c7e554eb..f1ad74c05c 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py @@ -64,6 +64,11 @@ def test_bgp_dynamic_capability_orf(): "neighborCapabilities": { "dynamic": "advertisedAndReceived", }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, } } return topotest.json_cmp(output, expected) @@ -116,6 +121,7 @@ def test_bgp_dynamic_capability_orf(): }, "addressFamilyInfo": { "ipv4Unicast": { + "acceptedPrefixCounter": 1, "afDependentCap": { "orfPrefixList": { "sendMode": "advertisedAndReceived", diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py index da45110e39..700d4c130d 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py @@ -66,6 +66,11 @@ def test_bgp_dynamic_capability_role(): "neighborCapabilities": { "dynamic": "advertisedAndReceived", }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, } } return topotest.json_cmp(output, expected) @@ -108,6 +113,11 @@ def test_bgp_dynamic_capability_role(): "dynamic": "advertisedAndReceived", "role": "advertisedAndReceived", }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, "messageStats": { "notificationsRecv": 0, "capabilityRecv": 1, diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py index a653da4655..11840b4c61 100644 --- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py +++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py @@ -68,6 +68,11 @@ def test_bgp_dynamic_capability_software_version(): "receivedSoftwareVersion": None, }, }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, } } return topotest.json_cmp(output, expected) @@ -129,6 +134,11 @@ def test_bgp_dynamic_capability_software_version(): "receivedSoftwareVersion": rcv, }, }, + "addressFamilyInfo": { + "ipv4Unicast": { + "acceptedPrefixCounter": 3, + } + }, "messageStats": { "notificationsRecv": 0, "capabilityRecv": 1, diff --git a/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py b/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py index 18a8575793..4d87621fa9 100755 --- a/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py +++ b/tests/topotests/bgp_snmp_bgp4v2mib/test_bgp_snmp_bgp4v2mib.py @@ -198,10 +198,10 @@ def test_bgp_snmp_bgp4v2(): def _snmpwalk_origin(): expected = { - "1.3.6.1.3.5.1.1.9.1.9.1.1.10.0.0.0.31.192.168.12.1": "1", - "1.3.6.1.3.5.1.1.9.1.9.1.1.10.0.0.2.32.192.168.12.1": "3", - "1.3.6.1.3.5.1.1.9.1.9.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "1", - "1.3.6.1.3.5.1.1.9.1.9.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "3", + "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1": "3", + "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "1", + "1.3.6.1.3.5.1.1.9.1.9.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "3", } # bgp4V2NlriOrigin @@ -216,14 +216,15 @@ def test_bgp_snmp_bgp4v2(): def _snmpwalk_med(): expected = { - "1.3.6.1.3.5.1.1.9.1.17.1.1.10.0.0.0.31.192.168.12.1": "1", - "1.3.6.1.3.5.1.1.9.1.17.1.1.10.0.0.2.32.192.168.12.1": "2", - "1.3.6.1.3.5.1.1.9.1.17.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "1", - "1.3.6.1.3.5.1.1.9.1.17.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1": "2", + "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.0.31.1.192.168.12.1.1": "1", + "1.3.6.1.3.5.1.1.9.1.17.1.1.1.1.10.0.0.2.32.1.192.168.12.1.1": "2", + "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.0.0.0.0.0.0.0.0.0.0.1.128.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "1", + "1.3.6.1.3.5.1.1.9.1.17.1.2.1.2.32.1.13.184.0.1.0.0.0.0.0.0.0.0.0.0.56.2.32.1.13.184.0.0.0.0.0.0.0.0.0.18.0.1.1": "2", } # bgp4V2NlriMed output, _ = snmp.walk(".1.3.6.1.3.5.1.1.9.1.17") + # tgen.mininet_cli() return output == expected _, result = topotest.run_and_expect(_snmpwalk_med, True, count=10, wait=1) diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl index d007c1d325..e3788bde16 100755 --- a/tools/checkpatch.pl +++ b/tools/checkpatch.pl @@ -547,7 +547,7 @@ our $Operators = qr{ our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x; our $Iterators = qr{ - frr_each|frr_each_safe|frr_each_from| + darr_foreach_p|darr_foreach_i|frr_each|frr_each_safe|frr_each_from| frr_with_mutex|frr_with_privs| LIST_FOREACH|LIST_FOREACH_SAFE| SLIST_FOREACH|SLIST_FOREACH_SAFE|SLIST_FOREACH_PREVPTR| @@ -563,6 +563,7 @@ our $Iterators = qr{ SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE| SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE| AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI| + FOREACH_BE_CLIENT_BITS|FOREACH_MGMTD_BE_CLIENT_ID| LSDB_LOOP }x; diff --git a/tools/checkpatch.sh b/tools/checkpatch.sh index 6071f4804d..bf63057b02 100755 --- a/tools/checkpatch.sh +++ b/tools/checkpatch.sh @@ -3,7 +3,8 @@ usage="./checkpatch.sh <patch> <tree>" patch=$1 tree=$2 -checkpatch="$tree/tools/checkpatch.pl --no-tree -f" +scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" +checkpatch="$scriptdir/checkpatch.pl --no-tree -f" ignore="ldpd\|babeld" cwd=${PWD##*/} dirty=0 |
