Merge branch 'master' into cleanup

This commit is contained in:
Donald Sharp 2017-01-13 14:48:16 -05:00 committed by GitHub
commit 9aa7f43f7e
58 changed files with 2092 additions and 3651 deletions

1
.gitignore vendored
View File

@ -41,6 +41,7 @@ build
m4/*.m4 m4/*.m4
!m4/ax_sys_weak_alias.m4 !m4/ax_sys_weak_alias.m4
!m4/ax_compare_version.m4 !m4/ax_compare_version.m4
!m4/ax_prog_perl_modules.m4
debian/autoreconf.after debian/autoreconf.after
debian/autoreconf.before debian/autoreconf.before
debian/files debian/files

6
README
View File

@ -1,9 +1,9 @@
Quagga is free software that manages various IPv4 and IPv6 routing Free Range Routing is free software that manages various IPv4 and IPv6 routing
protocols. protocols.
Currently Quagga supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, Currently Free Range Routing supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1,
RIPv2, RIPng, PIM-SSM and LDP as well as very early support for IS-IS. RIPv2, RIPng, PIM-SSM and LDP as well as very early support for IS-IS.
See the file REPORTING-BUGS to report bugs. See the file REPORTING-BUGS to report bugs.
Quagga is free software. See the file COPYING for copying conditions. Free Range Routing is free software. See the file COPYING for copying conditions.

View File

@ -1849,8 +1849,8 @@ int
bgp_mp_reach_parse (struct bgp_attr_parser_args *args, bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
struct bgp_nlri *mp_update) struct bgp_nlri *mp_update)
{ {
afi_t afi; afi_t pkt_afi, afi;
safi_t safi; safi_t pkt_safi, safi;
bgp_size_t nlri_len; bgp_size_t nlri_len;
size_t start; size_t start;
struct stream *s; struct stream *s;
@ -1874,8 +1874,20 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
} }
/* Load AFI, SAFI. */ /* Load AFI, SAFI. */
afi = stream_getw (s); pkt_afi = stream_getw (s);
safi = stream_getc (s); pkt_safi = stream_getc (s);
/* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
{
/* Log if AFI or SAFI is unrecognized. This is not an error unless
* the attribute is otherwise malformed.
*/
if (bgp_debug_update(peer, NULL, NULL, 0))
zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized",
peer->host, pkt_afi, pkt_safi);
return BGP_ATTR_PARSE_ERROR;
}
/* Get nexthop length. */ /* Get nexthop length. */
attre->mp_nexthop_len = stream_getc (s); attre->mp_nexthop_len = stream_getc (s);
@ -1988,8 +2000,8 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
struct bgp_nlri *mp_withdraw) struct bgp_nlri *mp_withdraw)
{ {
struct stream *s; struct stream *s;
afi_t afi; afi_t pkt_afi, afi;
safi_t safi; safi_t pkt_safi, safi;
u_int16_t withdraw_len; u_int16_t withdraw_len;
struct peer *const peer = args->peer; struct peer *const peer = args->peer;
struct attr *const attr = args->attr; struct attr *const attr = args->attr;
@ -2001,8 +2013,20 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE)) if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
afi = stream_getw (s); pkt_afi = stream_getw (s);
safi = stream_getc (s); pkt_safi = stream_getc (s);
/* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
{
/* Log if AFI or SAFI is unrecognized. This is not an error unless
* the attribute is otherwise malformed.
*/
if (bgp_debug_update(peer, NULL, NULL, 0))
zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized",
peer->host, pkt_afi, pkt_safi);
return BGP_ATTR_PARSE_ERROR;
}
withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE; withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE;
@ -2624,6 +2648,8 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
struct attr *attr) struct attr *attr)
{ {
size_t sizep; size_t sizep;
afi_t pkt_afi;
safi_t pkt_safi;
/* Set extended bit always to encode the attribute length as 2 bytes */ /* Set extended bit always to encode the attribute length as 2 bytes */
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
@ -2631,8 +2657,12 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
sizep = stream_get_endp (s); sizep = stream_get_endp (s);
stream_putw (s, 0); /* Marker: Attribute length. */ stream_putw (s, 0); /* Marker: Attribute length. */
stream_putw (s, afi);
stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); /* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
stream_putw (s, pkt_afi); /* AFI */
stream_putc (s, pkt_safi); /* SAFI */
/* Nexthop */ /* Nexthop */
switch (nh_afi) switch (nh_afi)
@ -3249,6 +3279,8 @@ size_t
bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi) bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
{ {
unsigned long attrlen_pnt; unsigned long attrlen_pnt;
afi_t pkt_afi;
safi_t pkt_safi;
/* Set extended bit always to encode the attribute length as 2 bytes */ /* Set extended bit always to encode the attribute length as 2 bytes */
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
@ -3257,8 +3289,12 @@ bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
attrlen_pnt = stream_get_endp (s); attrlen_pnt = stream_get_endp (s);
stream_putw (s, 0); /* Length of this attribute. */ stream_putw (s, 0); /* Length of this attribute. */
stream_putw (s, afi); /* Convert AFI, SAFI to values for packet. */
stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
stream_putw (s, pkt_afi);
stream_putc (s, pkt_safi);
return attrlen_pnt; return attrlen_pnt;
} }

View File

@ -79,9 +79,13 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
if (hdr->code == CAPABILITY_CODE_MP) if (hdr->code == CAPABILITY_CODE_MP)
{ {
afi_t afi;
safi_t safi;
bgp_map_afi_safi_iana2int (ntohs(mpc.afi), mpc.safi, &afi, &safi);
if (use_json) if (use_json)
{ {
switch (ntohs (mpc.afi)) switch (afi)
{ {
case AFI_IP: case AFI_IP:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv4"); json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv4");
@ -93,7 +97,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
json_object_int_add(json_cap, "capabilityErrorMultiProtocolAfiUnknown", ntohs (mpc.afi)); json_object_int_add(json_cap, "capabilityErrorMultiProtocolAfiUnknown", ntohs (mpc.afi));
break; break;
} }
switch (mpc.safi) switch (safi)
{ {
case SAFI_UNICAST: case SAFI_UNICAST:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "unicast"); json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "unicast");
@ -101,7 +105,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
case SAFI_MULTICAST: case SAFI_MULTICAST:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast"); json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast");
break; break;
case SAFI_MPLS_LABELED_VPN: case SAFI_MPLS_VPN:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN"); json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN");
break; break;
case SAFI_ENCAP: case SAFI_ENCAP:
@ -115,7 +119,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
else else
{ {
vty_out (vty, " Capability error for: Multi protocol "); vty_out (vty, " Capability error for: Multi protocol ");
switch (ntohs (mpc.afi)) switch (afi)
{ {
case AFI_IP: case AFI_IP:
vty_out (vty, "AFI IPv4, "); vty_out (vty, "AFI IPv4, ");
@ -127,7 +131,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi)); vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
break; break;
} }
switch (mpc.safi) switch (safi)
{ {
case SAFI_UNICAST: case SAFI_UNICAST:
vty_out (vty, "SAFI Unicast"); vty_out (vty, "SAFI Unicast");
@ -135,7 +139,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
case SAFI_MULTICAST: case SAFI_MULTICAST:
vty_out (vty, "SAFI Multicast"); vty_out (vty, "SAFI Multicast");
break; break;
case SAFI_MPLS_LABELED_VPN: case SAFI_MPLS_VPN:
vty_out (vty, "SAFI MPLS-labeled VPN"); vty_out (vty, "SAFI MPLS-labeled VPN");
break; break;
case SAFI_ENCAP: case SAFI_ENCAP:
@ -178,35 +182,6 @@ bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
mpc->safi = stream_getc (s); mpc->safi = stream_getc (s);
} }
int
bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
{
switch (afi)
{
case AFI_IP:
case AFI_IP6:
switch (*safi)
{
/* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
case SAFI_MPLS_LABELED_VPN:
*safi = SAFI_MPLS_VPN;
case SAFI_UNICAST:
case SAFI_MULTICAST:
case SAFI_MPLS_VPN:
case SAFI_ENCAP:
return 1;
}
break;
case AFI_ETHER:
default:
break;
}
zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
return 0;
}
/* Set negotiated capability value. */ /* Set negotiated capability value. */
static int static int
bgp_capability_mp (struct peer *peer, struct capability_header *hdr) bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
@ -228,7 +203,8 @@ bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
peer->host, mpc.afi, mpc.safi); peer->host, mpc.afi, mpc.safi);
if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi)) /* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_iana2int (mpc.afi, mpc.safi, &mpc.afi, &mpc.safi))
return -1; return -1;
/* Now safi remapped, and afi/safi are valid array indices */ /* Now safi remapped, and afi/safi are valid array indices */
@ -271,8 +247,8 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
{ {
struct stream *s = BGP_INPUT (peer); struct stream *s = BGP_INPUT (peer);
struct capability_orf_entry entry; struct capability_orf_entry entry;
afi_t afi; afi_t pkt_afi, afi;
safi_t safi; safi_t pkt_safi, safi;
u_char type; u_char type;
u_char mode; u_char mode;
u_int16_t sm_cap = 0; /* capability send-mode receive */ u_int16_t sm_cap = 0; /* capability send-mode receive */
@ -282,22 +258,25 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
/* ORF Entry header */ /* ORF Entry header */
bgp_capability_mp_data (s, &entry.mpc); bgp_capability_mp_data (s, &entry.mpc);
entry.num = stream_getc (s); entry.num = stream_getc (s);
afi = entry.mpc.afi; pkt_afi = entry.mpc.afi;
safi = entry.mpc.safi; pkt_safi = entry.mpc.safi;
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u", zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
peer->host, entry.mpc.afi, entry.mpc.safi); peer->host, entry.mpc.afi, entry.mpc.safi);
/* Check AFI and SAFI. */ /* Convert AFI, SAFI to internal values, check. */
if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi)) if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
{ {
zlog_info ("%s Addr-family %d/%d not supported." zlog_info ("%s Addr-family %d/%d not supported."
" Ignoring the ORF capability", " Ignoring the ORF capability",
peer->host, entry.mpc.afi, entry.mpc.safi); peer->host, pkt_afi, pkt_safi);
return 0; return 0;
} }
entry.mpc.afi = afi;
entry.mpc.safi = safi;
/* validate number field */ /* validate number field */
if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length) if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length)
{ {
@ -321,7 +300,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
case ORF_MODE_RECEIVE: case ORF_MODE_RECEIVE:
break; break;
default: default:
bgp_capability_orf_not_support (peer, afi, safi, type, mode); bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
continue; continue;
} }
/* ORF Type and afi/safi error checks */ /* ORF Type and afi/safi error checks */
@ -334,7 +313,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
case ORF_TYPE_PREFIX: case ORF_TYPE_PREFIX:
break; break;
default: default:
bgp_capability_orf_not_support (peer, afi, safi, type, mode); bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
continue; continue;
} }
break; break;
@ -344,12 +323,12 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
case ORF_TYPE_PREFIX_OLD: case ORF_TYPE_PREFIX_OLD:
break; break;
default: default:
bgp_capability_orf_not_support (peer, afi, safi, type, mode); bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
continue; continue;
} }
break; break;
default: default:
bgp_capability_orf_not_support (peer, afi, safi, type, mode); bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
continue; continue;
} }
@ -358,7 +337,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
|| (afi == AFI_IP && safi == SAFI_MULTICAST) || (afi == AFI_IP && safi == SAFI_MULTICAST)
|| (afi == AFI_IP6 && safi == SAFI_UNICAST))) || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
{ {
bgp_capability_orf_not_support (peer, afi, safi, type, mode); bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
continue; continue;
} }
@ -367,7 +346,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
" as %s for afi/safi: %d/%d", " as %s for afi/safi: %d/%d",
peer->host, LOOKUP (orf_type_str, type), peer->host, LOOKUP (orf_type_str, type),
LOOKUP (orf_mode_str, mode), LOOKUP (orf_mode_str, mode),
entry.mpc.afi, safi); pkt_afi, pkt_safi);
if (hdr->code == CAPABILITY_CODE_ORF) if (hdr->code == CAPABILITY_CODE_ORF)
{ {
@ -381,7 +360,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
} }
else else
{ {
bgp_capability_orf_not_support (peer, afi, safi, type, mode); bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
continue; continue;
} }
@ -437,23 +416,26 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
while (stream_get_getp (s) + 4 <= end) while (stream_get_getp (s) + 4 <= end)
{ {
afi_t afi = stream_getw (s); afi_t afi;
safi_t safi = stream_getc (s); safi_t safi;
afi_t pkt_afi = stream_getw (s);
safi_t pkt_safi = stream_getc (s);
u_char flag = stream_getc (s); u_char flag = stream_getc (s);
if (!bgp_afi_safi_valid_indices (afi, &safi)) /* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
{ {
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
" Ignore the Graceful Restart capability for this AFI/SAFI", " Ignore the Graceful Restart capability for this AFI/SAFI",
peer->host, afi, safi); peer->host, pkt_afi, pkt_safi);
} }
else if (!peer->afc[afi][safi]) else if (!peer->afc[afi][safi])
{ {
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
" Ignore the Graceful Restart capability", " Ignore the Graceful Restart capability",
peer->host, afi, safi); peer->host, pkt_afi, pkt_safi);
} }
else else
{ {
@ -512,22 +494,25 @@ bgp_capability_addpath (struct peer *peer, struct capability_header *hdr)
while (stream_get_getp (s) + 4 <= end) while (stream_get_getp (s) + 4 <= end)
{ {
afi_t afi = stream_getw (s); afi_t afi;
safi_t safi = stream_getc (s); safi_t safi;
afi_t pkt_afi = stream_getw (s);
safi_t pkt_safi = stream_getc (s);
u_char send_receive = stream_getc (s); u_char send_receive = stream_getc (s);
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s OPEN has AddPath CAP for afi/safi: %u/%u%s%s", zlog_debug ("%s OPEN has AddPath CAP for afi/safi: %u/%u%s%s",
peer->host, afi, safi, peer->host, pkt_afi, pkt_safi,
(send_receive & BGP_ADDPATH_RX) ? ", receive" : "", (send_receive & BGP_ADDPATH_RX) ? ", receive" : "",
(send_receive & BGP_ADDPATH_TX) ? ", transmit" : ""); (send_receive & BGP_ADDPATH_TX) ? ", transmit" : "");
if (!bgp_afi_safi_valid_indices (afi, &safi)) /* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
{ {
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
" Ignore the Addpath Attribute for this AFI/SAFI", " Ignore the Addpath Attribute for this AFI/SAFI",
peer->host, afi, safi); peer->host, pkt_afi, pkt_safi);
continue; continue;
} }
else if (!peer->afc[afi][safi]) else if (!peer->afc[afi][safi])
@ -535,7 +520,7 @@ bgp_capability_addpath (struct peer *peer, struct capability_header *hdr)
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
" Ignore the AddPath capability for this AFI/SAFI", " Ignore the AddPath capability for this AFI/SAFI",
peer->host, afi, safi); peer->host, pkt_afi, pkt_safi);
continue; continue;
} }
@ -565,20 +550,21 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr)
while (stream_get_getp (s) + 6 <= end) while (stream_get_getp (s) + 6 <= end)
{ {
afi_t afi = stream_getw (s); afi_t afi, pkt_afi = stream_getw (s);
safi_t safi = stream_getw (s); safi_t safi, pkt_safi = stream_getw (s);
afi_t nh_afi = stream_getw (s); afi_t nh_afi, pkt_nh_afi = stream_getw (s);
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Received with afi/safi/next-hop afi: %u/%u/%u", zlog_debug ("%s Received with afi/safi/next-hop afi: %u/%u/%u",
peer->host, afi, safi, nh_afi); peer->host, pkt_afi, pkt_safi, pkt_nh_afi);
if (!bgp_afi_safi_valid_indices (afi, &safi)) /* Convert AFI, SAFI to internal values, check. */
if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
{ {
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
" Ignore the ENHE Attribute for this AFI/SAFI", " Ignore the ENHE Attribute for this AFI/SAFI",
peer->host, afi, safi); peer->host, pkt_afi, pkt_safi);
continue; continue;
} }
@ -587,11 +573,13 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr)
* possibilities, so we ignore other values with a log. Also, only * possibilities, so we ignore other values with a log. Also, only
* Unicast SAFI is currently supported (and expected). * Unicast SAFI is currently supported (and expected).
*/ */
nh_afi = afi_iana2int (pkt_nh_afi);
if (afi != AFI_IP || safi != SAFI_UNICAST || nh_afi != AFI_IP6) if (afi != AFI_IP || safi != SAFI_UNICAST || nh_afi != AFI_IP6)
{ {
zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u " zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u "
"in Extended Next-hop capability, ignoring", "in Extended Next-hop capability, ignoring",
peer->host, afi, safi, nh_afi); peer->host, pkt_afi, pkt_safi, pkt_nh_afi);
continue; continue;
} }
@ -1174,9 +1162,11 @@ bgp_open_capability_orf (struct stream *s, struct peer *peer,
unsigned long orfp; unsigned long orfp;
unsigned long numberp; unsigned long numberp;
int number_of_orfs = 0; int number_of_orfs = 0;
afi_t pkt_afi;
safi_t pkt_safi;
if (safi == SAFI_MPLS_VPN) /* Convert AFI, SAFI to values for packet. */
safi = SAFI_MPLS_LABELED_VPN; bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, BGP_OPEN_OPT_CAP);
capp = stream_get_endp (s); /* Set Capability Len Pointer */ capp = stream_get_endp (s); /* Set Capability Len Pointer */
@ -1184,9 +1174,9 @@ bgp_open_capability_orf (struct stream *s, struct peer *peer,
stream_putc (s, code); /* Capability Code */ stream_putc (s, code); /* Capability Code */
orfp = stream_get_endp (s); /* Set ORF Len Pointer */ orfp = stream_get_endp (s); /* Set ORF Len Pointer */
stream_putc (s, 0); /* ORF Length */ stream_putc (s, 0); /* ORF Length */
stream_putw (s, afi); stream_putw (s, pkt_afi);
stream_putc (s, 0); stream_putc (s, 0);
stream_putc (s, safi); stream_putc (s, pkt_safi);
numberp = stream_get_endp (s); /* Set Number Pointer */ numberp = stream_get_endp (s); /* Set Number Pointer */
stream_putc (s, 0); /* Number of ORFs */ stream_putc (s, 0); /* Number of ORFs */
@ -1235,8 +1225,8 @@ bgp_open_capability (struct stream *s, struct peer *peer)
{ {
u_char len; u_char len;
unsigned long cp, capp, rcapp; unsigned long cp, capp, rcapp;
afi_t afi; afi_t afi, pkt_afi;
safi_t safi; safi_t safi, pkt_safi;
as_t local_as; as_t local_as;
u_int32_t restart_time; u_int32_t restart_time;
u_char afi_safi_count = 0; u_char afi_safi_count = 0;
@ -1254,55 +1244,29 @@ bgp_open_capability (struct stream *s, struct peer *peer)
|| CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
return; return;
/* IPv4 unicast. */ /* MP capability for configured AFI, SAFI */
if (peer->afc[AFI_IP][SAFI_UNICAST]) for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
{ for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1; {
stream_putc (s, BGP_OPEN_OPT_CAP); if (peer->afc[afi][safi])
stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); {
stream_putc (s, CAPABILITY_CODE_MP); /* Convert AFI, SAFI to values for packet. */
stream_putc (s, CAPABILITY_CODE_MP_LEN); bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
stream_putw (s, AFI_IP);
stream_putc (s, 0); peer->afc_adv[afi][safi] = 1;
stream_putc (s, SAFI_UNICAST); stream_putc (s, BGP_OPEN_OPT_CAP);
} stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
/* IPv4 multicast. */ stream_putc (s, CAPABILITY_CODE_MP);
if (peer->afc[AFI_IP][SAFI_MULTICAST]) stream_putc (s, CAPABILITY_CODE_MP_LEN);
{ stream_putw (s, pkt_afi);
peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1; stream_putc (s, 0);
stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, pkt_safi);
stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); }
stream_putc (s, CAPABILITY_CODE_MP); }
stream_putc (s, CAPABILITY_CODE_MP_LEN);
stream_putw (s, AFI_IP); /* Extended nexthop capability - currently supporting RFC-5549 for
stream_putc (s, 0); * Link-Local peering only
stream_putc (s, SAFI_MULTICAST); */
}
/* IPv4 VPN */
if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
{
peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
stream_putc (s, CAPABILITY_CODE_MP);
stream_putc (s, CAPABILITY_CODE_MP_LEN);
stream_putw (s, AFI_IP);
stream_putc (s, 0);
stream_putc (s, SAFI_MPLS_LABELED_VPN);
}
/* ENCAP */
if (peer->afc[AFI_IP][SAFI_ENCAP])
{
peer->afc_adv[AFI_IP][SAFI_ENCAP] = 1;
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
stream_putc (s, CAPABILITY_CODE_MP);
stream_putc (s, CAPABILITY_CODE_MP_LEN);
stream_putw (s, AFI_IP);
stream_putc (s, 0);
stream_putc (s, SAFI_ENCAP);
}
/* Currently supporting RFC-5549 for Link-Local peering only */
if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) && if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) &&
peer->su.sa.sa_family == AF_INET6 && peer->su.sa.sa_family == AF_INET6 &&
IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
@ -1322,54 +1286,6 @@ bgp_open_capability (struct stream *s, struct peer *peer)
if (CHECK_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_RCV)) if (CHECK_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_RCV))
SET_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_NEGO); SET_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_NEGO);
} }
/* IPv6 unicast. */
if (peer->afc[AFI_IP6][SAFI_UNICAST])
{
peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
stream_putc (s, CAPABILITY_CODE_MP);
stream_putc (s, CAPABILITY_CODE_MP_LEN);
stream_putw (s, AFI_IP6);
stream_putc (s, 0);
stream_putc (s, SAFI_UNICAST);
}
/* IPv6 multicast. */
if (peer->afc[AFI_IP6][SAFI_MULTICAST])
{
peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
stream_putc (s, CAPABILITY_CODE_MP);
stream_putc (s, CAPABILITY_CODE_MP_LEN);
stream_putw (s, AFI_IP6);
stream_putc (s, 0);
stream_putc (s, SAFI_MULTICAST);
}
/* IPv6 VPN. */
if (peer->afc[AFI_IP6][SAFI_MPLS_VPN])
{
peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1;
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
stream_putc (s, CAPABILITY_CODE_MP);
stream_putc (s, CAPABILITY_CODE_MP_LEN);
stream_putw (s, AFI_IP6);
stream_putc (s, 0);
stream_putc (s, SAFI_MPLS_LABELED_VPN);
}
/* IPv6 ENCAP. */
if (peer->afc[AFI_IP6][SAFI_ENCAP])
{
peer->afc_adv[AFI_IP6][SAFI_ENCAP] = 1;
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
stream_putc (s, CAPABILITY_CODE_MP);
stream_putc (s, CAPABILITY_CODE_MP_LEN);
stream_putw (s, AFI_IP6);
stream_putc (s, 0);
stream_putc (s, SAFI_ENCAP);
}
/* Route refresh. */ /* Route refresh. */
SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
@ -1418,8 +1334,11 @@ bgp_open_capability (struct stream *s, struct peer *peer)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
if (peer->afc[afi][safi]) if (peer->afc[afi][safi])
{ {
stream_putw (s, afi); /* Convert AFI, SAFI to values for packet. */
stream_putc (s, safi); bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
stream_putw (s, pkt_afi);
stream_putc (s, pkt_safi);
if (adv_addpath_tx) if (adv_addpath_tx)
{ {
@ -1533,8 +1452,10 @@ bgp_open_capability (struct stream *s, struct peer *peer)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
if (peer->afc[afi][safi]) if (peer->afc[afi][safi])
{ {
stream_putw (s, afi); /* Convert AFI, SAFI to values for packet. */
stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
stream_putw (s, pkt_afi);
stream_putc (s, pkt_safi);
if (bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD)) if (bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD))
stream_putc (s, RESTART_F_BIT); stream_putc (s, RESTART_F_BIT);
else else

View File

@ -115,6 +115,5 @@ extern int bgp_open_option_parse (struct peer *, u_char, int *);
extern void bgp_open_capability (struct stream *, struct peer *); extern void bgp_open_capability (struct stream *, struct peer *);
extern void bgp_capability_vty_out (struct vty *, struct peer *, u_char, json_object *); extern void bgp_capability_vty_out (struct vty *, struct peer *, u_char, json_object *);
extern as_t peek_for_as4_capability (struct peer *, u_char); extern as_t peek_for_as4_capability (struct peer *, u_char);
extern int bgp_afi_safi_valid_indices (afi_t, safi_t *);
#endif /* _QUAGGA_BGP_OPEN_H */ #endif /* _QUAGGA_BGP_OPEN_H */

View File

@ -147,6 +147,8 @@ static struct stream *
bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi) bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
{ {
struct stream *s; struct stream *s;
afi_t pkt_afi;
safi_t pkt_safi;
if (DISABLE_BGP_ANNOUNCE) if (DISABLE_BGP_ANNOUNCE)
return NULL; return NULL;
@ -169,13 +171,16 @@ bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
} }
else else
{ {
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
/* Total Path Attribute Length */ /* Total Path Attribute Length */
stream_putw (s, 6); stream_putw (s, 6);
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI); stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
stream_putc (s, 3); stream_putc (s, 3);
stream_putw (s, afi); stream_putw (s, pkt_afi);
stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); stream_putc (s, pkt_safi);
} }
bgp_packet_set_size (s); bgp_packet_set_size (s);
@ -690,15 +695,16 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
struct stream *s; struct stream *s;
struct bgp_filter *filter; struct bgp_filter *filter;
int orf_refresh = 0; int orf_refresh = 0;
afi_t pkt_afi;
safi_t pkt_safi;
if (DISABLE_BGP_ANNOUNCE) if (DISABLE_BGP_ANNOUNCE)
return; return;
filter = &peer->filter[afi][safi]; filter = &peer->filter[afi][safi];
/* Adjust safi code. */ /* Convert AFI, SAFI to values for packet. */
if (safi == SAFI_MPLS_VPN) bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
safi = SAFI_MPLS_LABELED_VPN;
s = stream_new (BGP_MAX_PACKET_SIZE); s = stream_new (BGP_MAX_PACKET_SIZE);
@ -709,9 +715,9 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD); bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
/* Encode Route Refresh message. */ /* Encode Route Refresh message. */
stream_putw (s, afi); stream_putw (s, pkt_afi);
stream_putc (s, 0); stream_putc (s, 0);
stream_putc (s, safi); stream_putc (s, pkt_safi);
if (orf_type == ORF_TYPE_PREFIX if (orf_type == ORF_TYPE_PREFIX
|| orf_type == ORF_TYPE_PREFIX_OLD) || orf_type == ORF_TYPE_PREFIX_OLD)
@ -734,7 +740,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d", zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
peer->host, orf_type, peer->host, orf_type,
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"), (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
afi, safi); pkt_afi, pkt_safi);
} }
else else
{ {
@ -746,7 +752,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d", zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
peer->host, orf_type, peer->host, orf_type,
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"), (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
afi, safi); pkt_afi, pkt_safi);
} }
/* Total ORF Entry Len. */ /* Total ORF Entry Len. */
@ -761,7 +767,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
{ {
if (! orf_refresh) if (! orf_refresh)
zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d", zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
peer->host, afi, safi); peer->host, pkt_afi, pkt_safi);
} }
/* Add packet to the peer. */ /* Add packet to the peer. */
@ -776,10 +782,11 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
int capability_code, int action) int capability_code, int action)
{ {
struct stream *s; struct stream *s;
afi_t pkt_afi;
safi_t pkt_safi;
/* Adjust safi code. */ /* Convert AFI, SAFI to values for packet. */
if (safi == SAFI_MPLS_VPN) bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
safi = SAFI_MPLS_LABELED_VPN;
s = stream_new (BGP_MAX_PACKET_SIZE); s = stream_new (BGP_MAX_PACKET_SIZE);
@ -792,14 +799,14 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
stream_putc (s, action); stream_putc (s, action);
stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP);
stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putc (s, CAPABILITY_CODE_MP_LEN);
stream_putw (s, afi); stream_putw (s, pkt_afi);
stream_putc (s, 0); stream_putc (s, 0);
stream_putc (s, safi); stream_putc (s, pkt_safi);
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d", zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
peer->host, action == CAPABILITY_ACTION_SET ? peer->host, action == CAPABILITY_ACTION_SET ?
"Advertising" : "Removing", afi, safi); "Advertising" : "Removing", pkt_afi, pkt_safi);
} }
/* Set packet size. */ /* Set packet size. */
@ -1329,7 +1336,6 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
case SAFI_MULTICAST: case SAFI_MULTICAST:
return bgp_nlri_parse_ip (peer, attr, packet); return bgp_nlri_parse_ip (peer, attr, packet);
case SAFI_MPLS_VPN: case SAFI_MPLS_VPN:
case SAFI_MPLS_LABELED_VPN:
return bgp_nlri_parse_vpn (peer, attr, packet); return bgp_nlri_parse_vpn (peer, attr, packet);
case SAFI_ENCAP: case SAFI_ENCAP:
return bgp_nlri_parse_encap (peer, attr, packet); return bgp_nlri_parse_encap (peer, attr, packet);
@ -1508,26 +1514,6 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
if (!nlris[i].nlri) if (!nlris[i].nlri)
continue; continue;
/* We use afi and safi as indices into tables and what not. It would
* be impossible, at this time, to support unknown afi/safis. And
* anyway, the peer needs to be configured to enable the afi/safi
* explicitly which requires UI support.
*
* Ignore unknown afi/safi NLRIs.
*
* Note: This means nlri[x].afi/safi still can not be trusted for
* indexing later in this function!
*
* Note2: This will also remap the wire code-point for VPN safi to the
* internal safi_t point, as needs be.
*/
if(!bgp_afi_safi_valid_indices (nlris[i].afi, &nlris[i].safi))
{
zlog_info ("%s [Info] UPDATE with unsupported AFI/SAFI %u/%u",
peer->host, nlris[i].afi, nlris[i].safi);
continue;
}
/* NLRI is processed iff the peer if configured for the specific afi/safi */ /* NLRI is processed iff the peer if configured for the specific afi/safi */
if (!peer->afc[nlris[i].afi][nlris[i].safi]) if (!peer->afc[nlris[i].afi][nlris[i].safi])
{ {
@ -1586,9 +1572,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
safi = SAFI_UNICAST; safi = SAFI_UNICAST;
} }
else if (attr.flag & ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI) else if (attr.flag & ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI)
&& nlris[NLRI_MP_WITHDRAW].length == 0 && nlris[NLRI_MP_WITHDRAW].length == 0)
&& bgp_afi_safi_valid_indices (nlris[NLRI_MP_WITHDRAW].afi,
&nlris[NLRI_MP_WITHDRAW].safi))
{ {
afi = nlris[NLRI_MP_WITHDRAW].afi; afi = nlris[NLRI_MP_WITHDRAW].afi;
safi = nlris[NLRI_MP_WITHDRAW].safi; safi = nlris[NLRI_MP_WITHDRAW].safi;
@ -1727,8 +1711,8 @@ bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
static void static void
bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
{ {
afi_t afi; afi_t pkt_afi, afi;
safi_t safi; safi_t pkt_safi, safi;
struct stream *s; struct stream *s;
struct peer_af *paf; struct peer_af *paf;
struct update_group *updgrp; struct update_group *updgrp;
@ -1757,28 +1741,22 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
s = peer->ibuf; s = peer->ibuf;
/* Parse packet. */ /* Parse packet. */
afi = stream_getw (s); pkt_afi = stream_getw (s);
(void)stream_getc (s); (void)stream_getc (s);
safi = stream_getc (s); pkt_safi = stream_getc (s);
if (bgp_debug_update(peer, NULL, NULL, 0)) if (bgp_debug_update(peer, NULL, NULL, 0))
zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d", zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
peer->host, afi, safi); peer->host, pkt_afi, pkt_safi);
/* Check AFI and SAFI. */ /* Convert AFI, SAFI to internal values and check. */
if ((afi != AFI_IP && afi != AFI_IP6) if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
|| (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
&& safi != SAFI_MPLS_LABELED_VPN))
{ {
zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored", zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
peer->host, afi, safi); peer->host, pkt_afi, pkt_safi);
return; return;
} }
/* Adjust safi code. */
if (safi == SAFI_MPLS_LABELED_VPN)
safi = SAFI_MPLS_VPN;
if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
{ {
u_char *end; u_char *end;
@ -1954,8 +1932,8 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
struct capability_mp_data mpc; struct capability_mp_data mpc;
struct capability_header *hdr; struct capability_header *hdr;
u_char action; u_char action;
afi_t afi; afi_t pkt_afi, afi;
safi_t safi; safi_t pkt_safi, safi;
end = pnt + length; end = pnt + length;
@ -1999,18 +1977,19 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
/* We know MP Capability Code. */ /* We know MP Capability Code. */
if (hdr->code == CAPABILITY_CODE_MP) if (hdr->code == CAPABILITY_CODE_MP)
{ {
afi = ntohs (mpc.afi); pkt_afi = ntohs (mpc.afi);
safi = mpc.safi; pkt_safi = mpc.safi;
/* Ignore capability when override-capability is set. */ /* Ignore capability when override-capability is set. */
if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
continue; continue;
if (!bgp_afi_safi_valid_indices (afi, &safi)) /* Convert AFI, SAFI to internal values. */
if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
{ {
if (bgp_debug_neighbor_events(peer)) if (bgp_debug_neighbor_events(peer))
zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid " zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
"(%u/%u)", peer->host, afi, safi); "(%u/%u)", peer->host, pkt_afi, pkt_safi);
continue; continue;
} }
@ -2020,7 +1999,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
peer->host, peer->host,
action == CAPABILITY_ACTION_SET action == CAPABILITY_ACTION_SET
? "Advertising" : "Removing", ? "Advertising" : "Removing",
ntohs(mpc.afi) , mpc.safi); pkt_afi, pkt_safi);
if (action == CAPABILITY_ACTION_SET) if (action == CAPABILITY_ACTION_SET)
{ {

View File

@ -2113,6 +2113,9 @@ int
bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
safi_t safi, int always) safi_t safi, int always)
{ {
afi_t pkt_afi;
safi_t pkt_safi;
if (!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) if (!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
return 0; return 0;
@ -2130,15 +2133,15 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
return 0; return 0;
/* Convert AFI, SAFI to values for packet. */
pkt_afi = afi_int2iana (afi);
pkt_safi = safi_int2iana (safi);
{ {
u_int8_t ndata[7]; u_int8_t ndata[7];
if (safi == SAFI_MPLS_VPN) ndata[0] = (pkt_afi >> 8);
safi = SAFI_MPLS_LABELED_VPN; ndata[1] = pkt_afi;
ndata[2] = pkt_safi;
ndata[0] = (afi >> 8);
ndata[1] = afi;
ndata[2] = safi;
ndata[3] = (peer->pmax[afi][safi] >> 24); ndata[3] = (peer->pmax[afi][safi] >> 24);
ndata[4] = (peer->pmax[afi][safi] >> 16); ndata[4] = (peer->pmax[afi][safi] >> 16);
ndata[5] = (peer->pmax[afi][safi] >> 8); ndata[5] = (peer->pmax[afi][safi] >> 8);

View File

@ -2944,12 +2944,14 @@ DEFUN (neighbor_local_as,
int idx_number = 3; int idx_number = 3;
struct peer *peer; struct peer *peer;
int ret; int ret;
as_t as;
peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg);
if (! peer) if (! peer)
return CMD_WARNING; return CMD_WARNING;
ret = peer_local_as_set (peer, atoi (argv[idx_number]->arg), 0, 0); VTY_GET_INTEGER_RANGE ("Local AS", as, argv[idx_number]->arg, 1, BGP_AS4_MAX);
ret = peer_local_as_set (peer, as, 0, 0);
return bgp_vty_return (vty, ret); return bgp_vty_return (vty, ret);
} }
@ -2966,12 +2968,14 @@ DEFUN (neighbor_local_as_no_prepend,
int idx_number = 3; int idx_number = 3;
struct peer *peer; struct peer *peer;
int ret; int ret;
as_t as;
peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg);
if (! peer) if (! peer)
return CMD_WARNING; return CMD_WARNING;
ret = peer_local_as_set (peer, atoi (argv[idx_number]->arg), 1, 0); VTY_GET_INTEGER_RANGE ("Local AS", as, argv[idx_number]->arg, 1, BGP_AS4_MAX);
ret = peer_local_as_set (peer, as, 1, 0);
return bgp_vty_return (vty, ret); return bgp_vty_return (vty, ret);
} }
@ -2989,12 +2993,14 @@ DEFUN (neighbor_local_as_no_prepend_replace_as,
int idx_number = 3; int idx_number = 3;
struct peer *peer; struct peer *peer;
int ret; int ret;
as_t as;
peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg);
if (! peer) if (! peer)
return CMD_WARNING; return CMD_WARNING;
ret = peer_local_as_set (peer, atoi (argv[idx_number]->arg), 1, 1); VTY_GET_INTEGER_RANGE ("Local AS", as, argv[idx_number]->arg, 1, BGP_AS4_MAX);
ret = peer_local_as_set (peer, as, 1, 1);
return bgp_vty_return (vty, ret); return bgp_vty_return (vty, ret);
} }

View File

@ -651,6 +651,35 @@ bgp_listen_limit_unset (struct bgp *bgp)
return 0; return 0;
} }
int
bgp_map_afi_safi_iana2int (afi_t pkt_afi, safi_t pkt_safi,
afi_t *afi, safi_t *safi)
{
/* Map from IANA values to internal values, return error if
* values are unrecognized.
*/
*afi = afi_iana2int (pkt_afi);
*safi = safi_iana2int (pkt_safi);
if (*afi == AFI_MAX || *safi == SAFI_MAX)
return -1;
return 0;
}
int
bgp_map_afi_safi_int2iana (afi_t afi, safi_t safi,
afi_t *pkt_afi, safi_t *pkt_safi)
{
/* Map from internal values to IANA values, return error if
* internal values are bad (unexpected).
*/
if (afi == AFI_MAX || safi == SAFI_MAX)
return -1;
*pkt_afi = afi_int2iana (afi);
*pkt_safi = safi_int2iana (safi);
return 0;
}
struct peer_af * struct peer_af *
peer_af_create (struct peer *peer, afi_t afi, safi_t safi) peer_af_create (struct peer *peer, afi_t afi, safi_t safi)
{ {

View File

@ -1078,10 +1078,6 @@ struct bgp_nlri
#define BGP_DEFAULT_RESTART_TIME 120 #define BGP_DEFAULT_RESTART_TIME 120
#define BGP_DEFAULT_STALEPATH_TIME 360 #define BGP_DEFAULT_STALEPATH_TIME 360
/* RFC4364 */
#define SAFI_MPLS_LABELED_VPN 128
#define BGP_SAFI_VPN 128
/* BGP uptime string length. */ /* BGP uptime string length. */
#define BGP_UPTIME_LEN 25 #define BGP_UPTIME_LEN 25
@ -1358,6 +1354,13 @@ extern void bgp_route_map_terminate(void);
extern int peer_cmp (struct peer *p1, struct peer *p2); extern int peer_cmp (struct peer *p1, struct peer *p2);
extern int
bgp_map_afi_safi_iana2int (afi_t pkt_afi, safi_t pkt_safi,
afi_t *afi, safi_t *safi);
extern int
bgp_map_afi_safi_int2iana (afi_t afi, safi_t safi,
afi_t *pkt_afi, safi_t *pkt_safi);
extern struct peer_af * peer_af_create (struct peer *, afi_t, safi_t); extern struct peer_af * peer_af_create (struct peer *, afi_t, safi_t);
extern struct peer_af * peer_af_find (struct peer *, afi_t, safi_t); extern struct peer_af * peer_af_find (struct peer *, afi_t, safi_t);
extern int peer_af_delete (struct peer *, afi_t, safi_t); extern int peer_af_delete (struct peer *, afi_t, safi_t);

View File

@ -4086,7 +4086,6 @@ rfapiBgpInfoFilteredImportFunction (safi_t safi)
switch (safi) switch (safi)
{ {
case SAFI_MPLS_VPN: case SAFI_MPLS_VPN:
case BGP_SAFI_VPN:
return rfapiBgpInfoFilteredImportVPN; return rfapiBgpInfoFilteredImportVPN;
case SAFI_ENCAP: case SAFI_ENCAP:
@ -4203,7 +4202,7 @@ rfapiProcessUpdate (
label); label);
} }
if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPN) if (safi == SAFI_MPLS_VPN)
{ {
vnc_direct_bgp_rh_add_route (bgp, afi, p, peer, attr); vnc_direct_bgp_rh_add_route (bgp, afi, p, peer, attr);
} }
@ -4332,7 +4331,7 @@ rfapiProcessWithdraw (
} }
/* TBD the deletion should happen after the lifetime expires */ /* TBD the deletion should happen after the lifetime expires */
if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPN) if (safi == SAFI_MPLS_VPN)
vnc_direct_bgp_rh_del_route (bgp, afi, p, peer); vnc_direct_bgp_rh_del_route (bgp, afi, p, peer);
if (safi == SAFI_MPLS_VPN) if (safi == SAFI_MPLS_VPN)

View File

@ -292,6 +292,8 @@ if test $ac_cv_lib_json_c_json_object_get = no; then
fi fi
fi fi
AX_PROG_PERL_MODULES(XML::LibXML, , AC_MSG_ERROR(XML::LibXML perl module is needed to compile))
AC_ARG_ENABLE([dev_build], AC_ARG_ENABLE([dev_build],
AS_HELP_STRING([--enable-dev-build], [build for development])) AS_HELP_STRING([--enable-dev-build], [build for development]))

View File

@ -544,6 +544,14 @@ lsp_update (struct isis_lsp *lsp, struct stream *stream,
if (dnode) if (dnode)
dnode_destroy (dict_delete (area->lspdb[level - 1], dnode)); dnode_destroy (dict_delete (area->lspdb[level - 1], dnode));
if (lsp->own_lsp)
{
zlog_err("ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP",
area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id));
lsp_clear_data(lsp);
lsp->own_lsp = 0;
}
/* rebuild the lsp data */ /* rebuild the lsp data */
lsp_update_data (lsp, stream, area, level); lsp_update_data (lsp, stream, area, level);

2
ldpd/.gitignore vendored
View File

@ -15,4 +15,4 @@ TAGS
.arch-ids .arch-ids
*~ *~
*.loT *.loT
ldp_vty_cmds.c

View File

@ -9,6 +9,8 @@ AM_CFLAGS = $(WERROR)
noinst_LIBRARIES = libldp.a noinst_LIBRARIES = libldp.a
sbin_PROGRAMS = ldpd sbin_PROGRAMS = ldpd
BUILT_SOURCES = ldp_vty_cmds.c
libldp_a_SOURCES = \ libldp_a_SOURCES = \
accept.c address.c adjacency.c control.c hello.c init.c interface.c \ accept.c address.c adjacency.c control.c hello.c init.c interface.c \
keepalive.c l2vpn.c labelmapping.c lde.c lde_lib.c ldpd.c \ keepalive.c l2vpn.c labelmapping.c lde.c lde_lib.c ldpd.c \
@ -19,6 +21,9 @@ libldp_a_SOURCES = \
noinst_HEADERS = \ noinst_HEADERS = \
control.h lde.h ldpd.h ldpe.h ldp.h log.h ldp_debug.h ldp_vty.h control.h lde.h ldpd.h ldpe.h ldp.h log.h ldp_debug.h ldp_vty.h
ldp_vty_cmds.c: $(srcdir)/ldp_vty.xml $(srcdir)/../tools/xml2cli.pl
@PERL@ $(srcdir)/../tools/xml2cli.pl $(srcdir)/ldp_vty.xml > $@
ldpd_SOURCES = ldpd.c ldpd_SOURCES = ldpd.c
ldpd_LDADD = libldp.a ../lib/libzebra.la @LIBCAP@ ldpd_LDADD = libldp.a ../lib/libzebra.la @LIBCAP@

View File

@ -25,12 +25,55 @@
#include "ldpe.h" #include "ldpe.h"
#include "log.h" #include "log.h"
static __inline int adj_compare(struct adj *, struct adj *);
static int adj_itimer(struct thread *); static int adj_itimer(struct thread *);
static void tnbr_del(struct tnbr *); static __inline int tnbr_compare(struct tnbr *, struct tnbr *);
static void tnbr_del(struct ldpd_conf *, struct tnbr *);
static int tnbr_hello_timer(struct thread *); static int tnbr_hello_timer(struct thread *);
static void tnbr_start_hello_timer(struct tnbr *); static void tnbr_start_hello_timer(struct tnbr *);
static void tnbr_stop_hello_timer(struct tnbr *); static void tnbr_stop_hello_timer(struct tnbr *);
RB_GENERATE(global_adj_head, adj, global_entry, adj_compare)
RB_GENERATE(nbr_adj_head, adj, nbr_entry, adj_compare)
RB_GENERATE(ia_adj_head, adj, ia_entry, adj_compare)
RB_GENERATE(tnbr_head, tnbr, entry, tnbr_compare)
static __inline int
adj_compare(struct adj *a, struct adj *b)
{
if (a->source.type < b->source.type)
return (-1);
if (a->source.type > b->source.type)
return (1);
switch (a->source.type) {
case HELLO_LINK:
if (strcmp(a->source.link.ia->iface->name,
b->source.link.ia->iface->name) < 0)
return (-1);
if (strcmp(a->source.link.ia->iface->name,
b->source.link.ia->iface->name) > 0)
return (1);
if (a->source.link.ia->af < b->source.link.ia->af)
return (-1);
if (a->source.link.ia->af > b->source.link.ia->af)
return (1);
return (ldp_addrcmp(a->source.link.ia->af,
&a->source.link.src_addr, &b->source.link.src_addr));
case HELLO_TARGETED:
if (a->source.target->af < b->source.target->af)
return (-1);
if (a->source.target->af > b->source.target->af)
return (1);
return (ldp_addrcmp(a->source.target->af,
&a->source.target->addr, &b->source.target->addr));
default:
fatalx("adj_get_af: unknown hello type");
}
return (0);
}
struct adj * struct adj *
adj_new(struct in_addr lsr_id, struct hello_source *source, adj_new(struct in_addr lsr_id, struct hello_source *source,
union ldpd_addr *addr) union ldpd_addr *addr)
@ -48,11 +91,11 @@ adj_new(struct in_addr lsr_id, struct hello_source *source,
adj->source = *source; adj->source = *source;
adj->trans_addr = *addr; adj->trans_addr = *addr;
LIST_INSERT_HEAD(&global.adj_list, adj, global_entry); RB_INSERT(global_adj_head, &global.adj_tree, adj);
switch (source->type) { switch (source->type) {
case HELLO_LINK: case HELLO_LINK:
LIST_INSERT_HEAD(&source->link.ia->adj_list, adj, ia_entry); RB_INSERT(ia_adj_head, &source->link.ia->adj_tree, adj);
break; break;
case HELLO_TARGETED: case HELLO_TARGETED:
source->target->adj = adj; source->target->adj = adj;
@ -70,12 +113,12 @@ adj_del_single(struct adj *adj)
adj_stop_itimer(adj); adj_stop_itimer(adj);
LIST_REMOVE(adj, global_entry); RB_REMOVE(global_adj_head, &global.adj_tree, adj);
if (adj->nbr) if (adj->nbr)
LIST_REMOVE(adj, nbr_entry); RB_REMOVE(nbr_adj_head, &adj->nbr->adj_tree, adj);
switch (adj->source.type) { switch (adj->source.type) {
case HELLO_LINK: case HELLO_LINK:
LIST_REMOVE(adj, ia_entry); RB_REMOVE(ia_adj_head, &adj->source.link.ia->adj_tree, adj);
break; break;
case HELLO_TARGETED: case HELLO_TARGETED:
adj->source.target->adj = NULL; adj->source.target->adj = NULL;
@ -99,7 +142,7 @@ adj_del(struct adj *adj, uint32_t notif_status)
* then delete it. * then delete it.
*/ */
if (nbr && nbr_adj_count(nbr, nbr->af) == 0) { if (nbr && nbr_adj_count(nbr, nbr->af) == 0) {
LIST_FOREACH_SAFE(adj, &nbr->adj_list, nbr_entry, atmp) RB_FOREACH_SAFE(adj, nbr_adj_head, &nbr->adj_tree, atmp)
adj_del_single(adj); adj_del_single(adj);
session_shutdown(nbr, notif_status, 0, 0); session_shutdown(nbr, notif_status, 0, 0);
nbr_del(nbr); nbr_del(nbr);
@ -109,27 +152,9 @@ adj_del(struct adj *adj, uint32_t notif_status)
struct adj * struct adj *
adj_find(struct hello_source *source) adj_find(struct hello_source *source)
{ {
struct adj *adj; struct adj adj;
adj.source = *source;
LIST_FOREACH(adj, &global.adj_list, global_entry) { return (RB_FIND(global_adj_head, &global.adj_tree, &adj));
if (adj->source.type != source->type)
continue;
switch (source->type) {
case HELLO_LINK:
if (ldp_addrcmp(source->link.ia->af,
&adj->source.link.src_addr,
&source->link.src_addr) == 0)
return (adj);
break;
case HELLO_TARGETED:
if (adj->source.target == source->target)
return (adj);
break;
}
}
return (NULL);
} }
int int
@ -161,7 +186,7 @@ adj_itimer(struct thread *thread)
if (!(adj->source.target->flags & F_TNBR_CONFIGURED) && if (!(adj->source.target->flags & F_TNBR_CONFIGURED) &&
adj->source.target->pw_count == 0) { adj->source.target->pw_count == 0) {
/* remove dynamic targeted neighbor */ /* remove dynamic targeted neighbor */
tnbr_del(adj->source.target); tnbr_del(leconf, adj->source.target);
return (0); return (0);
} }
adj->source.target->adj = NULL; adj->source.target->adj = NULL;
@ -188,6 +213,17 @@ adj_stop_itimer(struct adj *adj)
/* targeted neighbors */ /* targeted neighbors */
static __inline int
tnbr_compare(struct tnbr *a, struct tnbr *b)
{
if (a->af < b->af)
return (-1);
if (a->af > b->af)
return (1);
return (ldp_addrcmp(a->af, &a->addr, &b->addr));
}
struct tnbr * struct tnbr *
tnbr_new(int af, union ldpd_addr *addr) tnbr_new(int af, union ldpd_addr *addr)
{ {
@ -204,34 +240,30 @@ tnbr_new(int af, union ldpd_addr *addr)
} }
static void static void
tnbr_del(struct tnbr *tnbr) tnbr_del(struct ldpd_conf *xconf, struct tnbr *tnbr)
{ {
tnbr_stop_hello_timer(tnbr); tnbr_stop_hello_timer(tnbr);
if (tnbr->adj) if (tnbr->adj)
adj_del(tnbr->adj, S_SHUTDOWN); adj_del(tnbr->adj, S_SHUTDOWN);
LIST_REMOVE(tnbr, entry); RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr);
free(tnbr); free(tnbr);
} }
struct tnbr * struct tnbr *
tnbr_find(struct ldpd_conf *xconf, int af, union ldpd_addr *addr) tnbr_find(struct ldpd_conf *xconf, int af, union ldpd_addr *addr)
{ {
struct tnbr *tnbr; struct tnbr tnbr;
tnbr.af = af;
LIST_FOREACH(tnbr, &xconf->tnbr_list, entry) tnbr.addr = *addr;
if (af == tnbr->af && return (RB_FIND(tnbr_head, &xconf->tnbr_tree, &tnbr));
ldp_addrcmp(af, addr, &tnbr->addr) == 0)
return (tnbr);
return (NULL);
} }
struct tnbr * struct tnbr *
tnbr_check(struct tnbr *tnbr) tnbr_check(struct ldpd_conf *xconf, struct tnbr *tnbr)
{ {
if (!(tnbr->flags & (F_TNBR_CONFIGURED|F_TNBR_DYNAMIC)) && if (!(tnbr->flags & (F_TNBR_CONFIGURED|F_TNBR_DYNAMIC)) &&
tnbr->pw_count == 0) { tnbr->pw_count == 0) {
tnbr_del(tnbr); tnbr_del(xconf, tnbr);
return (NULL); return (NULL);
} }
@ -276,7 +308,7 @@ tnbr_update_all(int af)
struct tnbr *tnbr; struct tnbr *tnbr;
/* update targeted neighbors */ /* update targeted neighbors */
LIST_FOREACH(tnbr, &leconf->tnbr_list, entry) RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree)
if (tnbr->af == af || af == AF_UNSPEC) if (tnbr->af == af || af == AF_UNSPEC)
tnbr_update(tnbr); tnbr_update(tnbr);
} }

View File

@ -261,7 +261,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
if (tnbr && (tnbr->flags & F_TNBR_DYNAMIC) && if (tnbr && (tnbr->flags & F_TNBR_DYNAMIC) &&
!((flags & F_HELLO_REQ_TARG))) { !((flags & F_HELLO_REQ_TARG))) {
tnbr->flags &= ~F_TNBR_DYNAMIC; tnbr->flags &= ~F_TNBR_DYNAMIC;
tnbr = tnbr_check(tnbr); tnbr = tnbr_check(leconf, tnbr);
} }
if (!tnbr) { if (!tnbr) {
@ -273,7 +273,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
tnbr = tnbr_new(af, src); tnbr = tnbr_new(af, src);
tnbr->flags |= F_TNBR_DYNAMIC; tnbr->flags |= F_TNBR_DYNAMIC;
tnbr_update(tnbr); tnbr_update(tnbr);
LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry); RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr);
} }
source.type = HELLO_TARGETED; source.type = HELLO_TARGETED;
@ -364,7 +364,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
adj = adj_new(lsr_id, &source, &trans_addr); adj = adj_new(lsr_id, &source, &trans_addr);
if (nbr) { if (nbr) {
adj->nbr = nbr; adj->nbr = nbr;
LIST_INSERT_HEAD(&nbr->adj_list, adj, nbr_entry); RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj);
} }
} }

View File

@ -26,6 +26,7 @@
#include "sockopt.h" #include "sockopt.h"
static __inline int iface_compare(struct iface *, struct iface *);
static struct if_addr *if_addr_new(struct kaddr *); static struct if_addr *if_addr_new(struct kaddr *);
static struct if_addr *if_addr_lookup(struct if_addr_head *, struct kaddr *); static struct if_addr *if_addr_lookup(struct if_addr_head *, struct kaddr *);
static int if_start(struct iface *, int); static int if_start(struct iface *, int);
@ -39,6 +40,14 @@ static int if_leave_ipv4_group(struct iface *, struct in_addr *);
static int if_join_ipv6_group(struct iface *, struct in6_addr *); static int if_join_ipv6_group(struct iface *, struct in6_addr *);
static int if_leave_ipv6_group(struct iface *, struct in6_addr *); static int if_leave_ipv6_group(struct iface *, struct in6_addr *);
RB_GENERATE(iface_head, iface, entry, iface_compare)
static __inline int
iface_compare(struct iface *a, struct iface *b)
{
return (strcmp(a->name, b->name));
}
struct iface * struct iface *
if_new(struct kif *kif) if_new(struct kif *kif)
{ {
@ -57,30 +66,18 @@ if_new(struct kif *kif)
iface->ipv4.iface = iface; iface->ipv4.iface = iface;
iface->ipv4.enabled = 0; iface->ipv4.enabled = 0;
iface->ipv4.state = IF_STA_DOWN; iface->ipv4.state = IF_STA_DOWN;
LIST_INIT(&iface->ipv4.adj_list); RB_INIT(&iface->ipv4.adj_tree);
/* ipv6 */ /* ipv6 */
iface->ipv6.af = AF_INET6; iface->ipv6.af = AF_INET6;
iface->ipv6.iface = iface; iface->ipv6.iface = iface;
iface->ipv6.enabled = 0; iface->ipv6.enabled = 0;
iface->ipv6.state = IF_STA_DOWN; iface->ipv6.state = IF_STA_DOWN;
LIST_INIT(&iface->ipv6.adj_list); RB_INIT(&iface->ipv6.adj_tree);
return (iface); return (iface);
} }
struct iface *
if_lookup(struct ldpd_conf *xconf, unsigned short ifindex)
{
struct iface *iface;
LIST_FOREACH(iface, &xconf->iface_list, entry)
if (iface->ifindex == ifindex)
return (iface);
return (NULL);
}
void void
if_exit(struct iface *iface) if_exit(struct iface *iface)
{ {
@ -100,17 +97,25 @@ if_exit(struct iface *iface)
} }
struct iface * struct iface *
if_lookup_name(struct ldpd_conf *xconf, const char *ifname) if_lookup(struct ldpd_conf *xconf, unsigned short ifindex)
{ {
struct iface *iface; struct iface *iface;
LIST_FOREACH(iface, &xconf->iface_list, entry) RB_FOREACH(iface, iface_head, &xconf->iface_tree)
if (strcmp(iface->name, ifname) == 0) if (iface->ifindex == ifindex)
return (iface); return (iface);
return (NULL); return (NULL);
} }
struct iface *
if_lookup_name(struct ldpd_conf *xconf, const char *ifname)
{
struct iface iface;
strlcpy(iface.name, ifname, sizeof(iface.name));
return (RB_FIND(iface_head, &xconf->iface_tree, &iface));
}
void void
if_update_info(struct iface *iface, struct kif *kif) if_update_info(struct iface *iface, struct kif *kif)
{ {
@ -288,7 +293,7 @@ if_reset(struct iface *iface, int af)
ia = iface_af_get(iface, af); ia = iface_af_get(iface, af);
if_stop_hello_timer(ia); if_stop_hello_timer(ia);
while ((adj = LIST_FIRST(&ia->adj_list)) != NULL) while ((adj = RB_ROOT(&ia->adj_tree)) != NULL)
adj_del(adj, S_SHUTDOWN); adj_del(adj, S_SHUTDOWN);
/* try to cleanup */ /* try to cleanup */
@ -380,7 +385,7 @@ if_update_all(int af)
{ {
struct iface *iface; struct iface *iface;
LIST_FOREACH(iface, &leconf->iface_list, entry) RB_FOREACH(iface, iface_head, &leconf->iface_tree)
if_update(iface, af); if_update(iface, af);
} }
@ -460,7 +465,7 @@ if_to_ctl(struct iface_af *ia)
ictl.uptime = 0; ictl.uptime = 0;
ictl.adj_cnt = 0; ictl.adj_cnt = 0;
LIST_FOREACH(adj, &ia->adj_list, ia_entry) RB_FOREACH(adj, ia_adj_head, &ia->adj_tree)
ictl.adj_cnt++; ictl.adj_cnt++;
return (&ictl); return (&ictl);

View File

@ -26,7 +26,20 @@
#include "lde.h" #include "lde.h"
#include "log.h" #include "log.h"
static void l2vpn_pw_fec(struct l2vpn_pw *, struct fec *); static void l2vpn_pw_fec(struct l2vpn_pw *, struct fec *);
static __inline int l2vpn_compare(struct l2vpn *, struct l2vpn *);
static __inline int l2vpn_if_compare(struct l2vpn_if *, struct l2vpn_if *);
static __inline int l2vpn_pw_compare(struct l2vpn_pw *, struct l2vpn_pw *);
RB_GENERATE(l2vpn_head, l2vpn, entry, l2vpn_compare)
RB_GENERATE(l2vpn_if_head, l2vpn_if, entry, l2vpn_if_compare)
RB_GENERATE(l2vpn_pw_head, l2vpn_pw, entry, l2vpn_pw_compare)
static __inline int
l2vpn_compare(struct l2vpn *a, struct l2vpn *b)
{
return (strcmp(a->name, b->name));
}
struct l2vpn * struct l2vpn *
l2vpn_new(const char *name) l2vpn_new(const char *name)
@ -42,9 +55,9 @@ l2vpn_new(const char *name)
l2vpn->mtu = DEFAULT_L2VPN_MTU; l2vpn->mtu = DEFAULT_L2VPN_MTU;
l2vpn->pw_type = DEFAULT_PW_TYPE; l2vpn->pw_type = DEFAULT_PW_TYPE;
LIST_INIT(&l2vpn->if_list); RB_INIT(&l2vpn->if_tree);
LIST_INIT(&l2vpn->pw_list); RB_INIT(&l2vpn->pw_tree);
LIST_INIT(&l2vpn->pw_inactive_list); RB_INIT(&l2vpn->pw_inactive_tree);
return (l2vpn); return (l2vpn);
} }
@ -52,13 +65,9 @@ l2vpn_new(const char *name)
struct l2vpn * struct l2vpn *
l2vpn_find(struct ldpd_conf *xconf, const char *name) l2vpn_find(struct ldpd_conf *xconf, const char *name)
{ {
struct l2vpn *l2vpn; struct l2vpn l2vpn;
strlcpy(l2vpn.name, name, sizeof(l2vpn.name));
LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) return (RB_FIND(l2vpn_head, &xconf->l2vpn_tree, &l2vpn));
if (strcmp(l2vpn->name, name) == 0)
return (l2vpn);
return (NULL);
} }
void void
@ -67,16 +76,16 @@ l2vpn_del(struct l2vpn *l2vpn)
struct l2vpn_if *lif; struct l2vpn_if *lif;
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) { while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) {
LIST_REMOVE(lif, entry); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif); free(lif);
} }
while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) { while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) {
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
free(pw); free(pw);
} }
while ((pw = LIST_FIRST(&l2vpn->pw_inactive_list)) != NULL) { while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) {
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
free(pw); free(pw);
} }
@ -88,7 +97,7 @@ l2vpn_init(struct l2vpn *l2vpn)
{ {
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
LIST_FOREACH(pw, &l2vpn->pw_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
l2vpn_pw_init(pw); l2vpn_pw_init(pw);
} }
@ -97,10 +106,16 @@ l2vpn_exit(struct l2vpn *l2vpn)
{ {
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
LIST_FOREACH(pw, &l2vpn->pw_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
l2vpn_pw_exit(pw); l2vpn_pw_exit(pw);
} }
static __inline int
l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b)
{
return (strcmp(a->ifname, b->ifname));
}
struct l2vpn_if * struct l2vpn_if *
l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif)
{ {
@ -122,7 +137,7 @@ l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex)
{ {
struct l2vpn_if *lif; struct l2vpn_if *lif;
LIST_FOREACH(lif, &l2vpn->if_list, entry) RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
if (lif->ifindex == ifindex) if (lif->ifindex == ifindex)
return (lif); return (lif);
@ -132,15 +147,16 @@ l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex)
struct l2vpn_if * struct l2vpn_if *
l2vpn_if_find_name(struct l2vpn *l2vpn, const char *ifname) l2vpn_if_find_name(struct l2vpn *l2vpn, const char *ifname)
{ {
struct l2vpn_if *lif; struct l2vpn_if lif;
strlcpy(lif.ifname, ifname, sizeof(lif.ifname));
LIST_FOREACH(lif, &l2vpn->if_list, entry) return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif));
if (strcmp(lif->ifname, ifname) == 0)
return (lif);
return (NULL);
} }
static __inline int
l2vpn_pw_compare(struct l2vpn_pw *a, struct l2vpn_pw *b)
{
return (strcmp(a->ifname, b->ifname));
}
struct l2vpn_pw * struct l2vpn_pw *
l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif)
@ -162,10 +178,10 @@ l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex)
{ {
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
LIST_FOREACH(pw, &l2vpn->pw_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
if (pw->ifindex == ifindex) if (pw->ifindex == ifindex)
return (pw); return (pw);
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
if (pw->ifindex == ifindex) if (pw->ifindex == ifindex)
return (pw); return (pw);
@ -176,15 +192,13 @@ struct l2vpn_pw *
l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname) l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname)
{ {
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
struct l2vpn_pw s;
LIST_FOREACH(pw, &l2vpn->pw_list, entry) strlcpy(s.ifname, ifname, sizeof(s.ifname));
if (strcmp(pw->ifname, ifname) == 0) pw = RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s);
return (pw); if (pw)
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) return (pw);
if (strcmp(pw->ifname, ifname) == 0) return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
return (pw);
return (NULL);
} }
void void
@ -399,8 +413,8 @@ l2vpn_sync_pws(int af, union ldpd_addr *addr)
struct fec_node *fn; struct fec_node *fn;
struct fec_nh *fnh; struct fec_nh *fnh;
LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) { RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
LIST_FOREACH(pw, &l2vpn->pw_list, entry) { RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr)) if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr))
continue; continue;
@ -428,8 +442,8 @@ l2vpn_pw_ctl(pid_t pid)
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
static struct ctl_pw pwctl; static struct ctl_pw pwctl;
LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree)
LIST_FOREACH(pw, &l2vpn->pw_list, entry) { RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
memset(&pwctl, 0, sizeof(pwctl)); memset(&pwctl, 0, sizeof(pwctl));
strlcpy(pwctl.l2vpn_name, pw->l2vpn->name, strlcpy(pwctl.l2vpn_name, pw->l2vpn->name,
sizeof(pwctl.l2vpn_name)); sizeof(pwctl.l2vpn_name));
@ -459,7 +473,7 @@ l2vpn_binding_ctl(pid_t pid)
fn = (struct fec_node *)f; fn = (struct fec_node *)f;
if (fn->local_label == NO_LABEL && if (fn->local_label == NO_LABEL &&
LIST_EMPTY(&fn->downstream)) RB_EMPTY(&fn->downstream))
continue; continue;
memset(&pwctl, 0, sizeof(pwctl)); memset(&pwctl, 0, sizeof(pwctl));
@ -477,7 +491,7 @@ l2vpn_binding_ctl(pid_t pid)
} else } else
pwctl.local_label = NO_LABEL; pwctl.local_label = NO_LABEL;
LIST_FOREACH(me, &fn->downstream, entry) RB_FOREACH(me, lde_map_head, &fn->downstream)
if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr) if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr)
break; break;
@ -508,7 +522,7 @@ ldpe_l2vpn_init(struct l2vpn *l2vpn)
{ {
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
LIST_FOREACH(pw, &l2vpn->pw_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
ldpe_l2vpn_pw_init(pw); ldpe_l2vpn_pw_init(pw);
} }
@ -517,7 +531,7 @@ ldpe_l2vpn_exit(struct l2vpn *l2vpn)
{ {
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
LIST_FOREACH(pw, &l2vpn->pw_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
ldpe_l2vpn_pw_exit(pw); ldpe_l2vpn_pw_exit(pw);
} }
@ -530,7 +544,7 @@ ldpe_l2vpn_pw_init(struct l2vpn_pw *pw)
if (tnbr == NULL) { if (tnbr == NULL) {
tnbr = tnbr_new(pw->af, &pw->addr); tnbr = tnbr_new(pw->af, &pw->addr);
tnbr_update(tnbr); tnbr_update(tnbr);
LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry); RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr);
} }
tnbr->pw_count++; tnbr->pw_count++;
@ -544,6 +558,6 @@ ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw)
tnbr = tnbr_find(leconf, pw->af, &pw->addr); tnbr = tnbr_find(leconf, pw->af, &pw->addr);
if (tnbr) { if (tnbr) {
tnbr->pw_count--; tnbr->pw_count--;
tnbr_check(tnbr); tnbr_check(leconf, tnbr);
} }
} }

View File

@ -45,12 +45,14 @@ static struct lde_nbr *lde_nbr_find(uint32_t);
static void lde_nbr_clear(void); static void lde_nbr_clear(void);
static void lde_nbr_addr_update(struct lde_nbr *, static void lde_nbr_addr_update(struct lde_nbr *,
struct lde_addr *, int); struct lde_addr *, int);
static __inline int lde_map_compare(struct lde_map *, struct lde_map *);
static void lde_map_free(void *); static void lde_map_free(void *);
static int lde_address_add(struct lde_nbr *, struct lde_addr *); static int lde_address_add(struct lde_nbr *, struct lde_addr *);
static int lde_address_del(struct lde_nbr *, struct lde_addr *); static int lde_address_del(struct lde_nbr *, struct lde_addr *);
static void lde_address_list_free(struct lde_nbr *); static void lde_address_list_free(struct lde_nbr *);
RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare) RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare)
RB_GENERATE(lde_map_head, lde_map, entry, lde_map_compare)
struct ldpd_conf *ldeconf; struct ldpd_conf *ldeconf;
struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs); struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs);
@ -471,10 +473,10 @@ lde_dispatch_parent(struct thread *thread)
fatal(NULL); fatal(NULL);
memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
LIST_INIT(&nconf->iface_list); RB_INIT(&nconf->iface_tree);
LIST_INIT(&nconf->tnbr_list); RB_INIT(&nconf->tnbr_tree);
LIST_INIT(&nconf->nbrp_list); RB_INIT(&nconf->nbrp_tree);
LIST_INIT(&nconf->l2vpn_list); RB_INIT(&nconf->l2vpn_tree);
break; break;
case IMSG_RECONF_IFACE: case IMSG_RECONF_IFACE:
if ((niface = malloc(sizeof(struct iface))) == NULL) if ((niface = malloc(sizeof(struct iface))) == NULL)
@ -482,37 +484,37 @@ lde_dispatch_parent(struct thread *thread)
memcpy(niface, imsg.data, sizeof(struct iface)); memcpy(niface, imsg.data, sizeof(struct iface));
LIST_INIT(&niface->addr_list); LIST_INIT(&niface->addr_list);
LIST_INIT(&niface->ipv4.adj_list); RB_INIT(&niface->ipv4.adj_tree);
LIST_INIT(&niface->ipv6.adj_list); RB_INIT(&niface->ipv6.adj_tree);
niface->ipv4.iface = niface; niface->ipv4.iface = niface;
niface->ipv6.iface = niface; niface->ipv6.iface = niface;
LIST_INSERT_HEAD(&nconf->iface_list, niface, entry); RB_INSERT(iface_head, &nconf->iface_tree, niface);
break; break;
case IMSG_RECONF_TNBR: case IMSG_RECONF_TNBR:
if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL) if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
fatal(NULL); fatal(NULL);
memcpy(ntnbr, imsg.data, sizeof(struct tnbr)); memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry); RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
break; break;
case IMSG_RECONF_NBRP: case IMSG_RECONF_NBRP:
if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL) if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
fatal(NULL); fatal(NULL);
memcpy(nnbrp, imsg.data, sizeof(struct nbr_params)); memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry); RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp);
break; break;
case IMSG_RECONF_L2VPN: case IMSG_RECONF_L2VPN:
if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL) if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
fatal(NULL); fatal(NULL);
memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn)); memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
LIST_INIT(&nl2vpn->if_list); RB_INIT(&nl2vpn->if_tree);
LIST_INIT(&nl2vpn->pw_list); RB_INIT(&nl2vpn->pw_tree);
LIST_INIT(&nl2vpn->pw_inactive_list); RB_INIT(&nl2vpn->pw_inactive_tree);
LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry); RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
break; break;
case IMSG_RECONF_L2VPN_IF: case IMSG_RECONF_L2VPN_IF:
if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL) if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
@ -520,7 +522,7 @@ lde_dispatch_parent(struct thread *thread)
memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
nlif->l2vpn = nl2vpn; nlif->l2vpn = nl2vpn;
LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry); RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
break; break;
case IMSG_RECONF_L2VPN_PW: case IMSG_RECONF_L2VPN_PW:
if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
@ -528,7 +530,7 @@ lde_dispatch_parent(struct thread *thread)
memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
npw->l2vpn = nl2vpn; npw->l2vpn = nl2vpn;
LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
break; break;
case IMSG_RECONF_L2VPN_IPW: case IMSG_RECONF_L2VPN_IPW:
if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
@ -536,7 +538,7 @@ lde_dispatch_parent(struct thread *thread)
memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
npw->l2vpn = nl2vpn; npw->l2vpn = nl2vpn;
LIST_INSERT_HEAD(&nl2vpn->pw_inactive_list, npw, entry); RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
break; break;
case IMSG_RECONF_END: case IMSG_RECONF_END:
merge_config(ldeconf, nconf); merge_config(ldeconf, nconf);
@ -1141,6 +1143,13 @@ lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed)
} }
} }
static __inline int
lde_map_compare(struct lde_map *a, struct lde_map *b)
{
return (ldp_addrcmp(AF_INET, (union ldpd_addr *)&a->nexthop->id,
(union ldpd_addr *)&b->nexthop->id));
}
struct lde_map * struct lde_map *
lde_map_add(struct lde_nbr *ln, struct fec_node *fn, int sent) lde_map_add(struct lde_nbr *ln, struct fec_node *fn, int sent)
{ {
@ -1154,13 +1163,15 @@ lde_map_add(struct lde_nbr *ln, struct fec_node *fn, int sent)
me->nexthop = ln; me->nexthop = ln;
if (sent) { if (sent) {
LIST_INSERT_HEAD(&fn->upstream, me, entry); RB_INSERT(lde_map_head, &fn->upstream, me);
me->head = &fn->upstream;
if (fec_insert(&ln->sent_map, &me->fec)) if (fec_insert(&ln->sent_map, &me->fec))
log_warnx("failed to add %s to sent map", log_warnx("failed to add %s to sent map",
log_fec(&me->fec)); log_fec(&me->fec));
/* XXX on failure more cleanup is needed */ /* XXX on failure more cleanup is needed */
} else { } else {
LIST_INSERT_HEAD(&fn->downstream, me, entry); RB_INSERT(lde_map_head, &fn->downstream, me);
me->head = &fn->downstream;
if (fec_insert(&ln->recv_map, &me->fec)) if (fec_insert(&ln->recv_map, &me->fec))
log_warnx("failed to add %s to recv map", log_warnx("failed to add %s to recv map",
log_fec(&me->fec)); log_fec(&me->fec));
@ -1185,7 +1196,7 @@ lde_map_free(void *ptr)
{ {
struct lde_map *map = ptr; struct lde_map *map = ptr;
LIST_REMOVE(map, entry); RB_REMOVE(lde_map_head, map->head, map);
free(map); free(map);
} }

View File

@ -62,10 +62,13 @@ struct lde_req {
/* mapping entries */ /* mapping entries */
struct lde_map { struct lde_map {
struct fec fec; struct fec fec;
LIST_ENTRY(lde_map) entry; struct lde_map_head *head; /* fec_node's upstream/downstream */
RB_ENTRY(lde_map) entry;
struct lde_nbr *nexthop; struct lde_nbr *nexthop;
struct map map; struct map map;
}; };
RB_HEAD(lde_map_head, lde_map);
RB_PROTOTYPE(lde_map_head, lde_map, entry, lde_map_cmp);
/* withdraw entries */ /* withdraw entries */
struct lde_wdraw { struct lde_wdraw {
@ -112,8 +115,8 @@ struct fec_node {
struct fec fec; struct fec fec;
LIST_HEAD(, fec_nh) nexthops; /* fib nexthops */ LIST_HEAD(, fec_nh) nexthops; /* fib nexthops */
LIST_HEAD(, lde_map) downstream; /* recv mappings */ struct lde_map_head downstream; /* recv mappings */
LIST_HEAD(, lde_map) upstream; /* sent mappings */ struct lde_map_head upstream; /* sent mappings */
uint32_t local_label; uint32_t local_label;
void *data; /* fec specific data */ void *data; /* fec specific data */

View File

@ -159,7 +159,7 @@ rt_dump(pid_t pid)
RB_FOREACH(f, fec_tree, &ft) { RB_FOREACH(f, fec_tree, &ft) {
fn = (struct fec_node *)f; fn = (struct fec_node *)f;
if (fn->local_label == NO_LABEL && if (fn->local_label == NO_LABEL &&
LIST_EMPTY(&fn->downstream)) RB_EMPTY(&fn->downstream))
continue; continue;
rtctl.first = 1; rtctl.first = 1;
@ -179,7 +179,7 @@ rt_dump(pid_t pid)
} }
rtctl.local_label = fn->local_label; rtctl.local_label = fn->local_label;
LIST_FOREACH(me, &fn->downstream, entry) { RB_FOREACH(me, lde_map_head, &fn->downstream) {
rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop); rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop);
rtctl.nexthop = me->nexthop->id; rtctl.nexthop = me->nexthop->id;
rtctl.remote_label = me->map.label; rtctl.remote_label = me->map.label;
@ -188,7 +188,7 @@ rt_dump(pid_t pid)
&rtctl, sizeof(rtctl)); &rtctl, sizeof(rtctl));
rtctl.first = 0; rtctl.first = 0;
} }
if (LIST_EMPTY(&fn->downstream)) { if (RB_EMPTY(&fn->downstream)) {
rtctl.in_use = 0; rtctl.in_use = 0;
rtctl.nexthop.s_addr = INADDR_ANY; rtctl.nexthop.s_addr = INADDR_ANY;
rtctl.remote_label = NO_LABEL; rtctl.remote_label = NO_LABEL;
@ -224,10 +224,10 @@ fec_free(void *arg)
while ((fnh = LIST_FIRST(&fn->nexthops))) while ((fnh = LIST_FIRST(&fn->nexthops)))
fec_nh_del(fnh); fec_nh_del(fnh);
if (!LIST_EMPTY(&fn->downstream)) if (!RB_EMPTY(&fn->downstream))
log_warnx("%s: fec %s downstream list not empty", __func__, log_warnx("%s: fec %s downstream list not empty", __func__,
log_fec(&fn->fec)); log_fec(&fn->fec));
if (!LIST_EMPTY(&fn->upstream)) if (!RB_EMPTY(&fn->upstream))
log_warnx("%s: fec %s upstream list not empty", __func__, log_warnx("%s: fec %s upstream list not empty", __func__,
log_fec(&fn->fec)); log_fec(&fn->fec));
@ -251,8 +251,8 @@ fec_add(struct fec *fec)
fn->fec = *fec; fn->fec = *fec;
fn->local_label = NO_LABEL; fn->local_label = NO_LABEL;
LIST_INIT(&fn->upstream); RB_INIT(&fn->upstream);
LIST_INIT(&fn->downstream); RB_INIT(&fn->downstream);
LIST_INIT(&fn->nexthops); LIST_INIT(&fn->nexthops);
if (fec_insert(&ft, &fn->fec)) if (fec_insert(&ft, &fn->fec))
@ -774,8 +774,8 @@ lde_gc_timer(struct thread *thread)
fn = (struct fec_node *) fec; fn = (struct fec_node *) fec;
if (!LIST_EMPTY(&fn->nexthops) || if (!LIST_EMPTY(&fn->nexthops) ||
!LIST_EMPTY(&fn->downstream) || !RB_EMPTY(&fn->downstream) ||
!LIST_EMPTY(&fn->upstream)) !RB_EMPTY(&fn->upstream))
continue; continue;
fec_remove(&ft, &fn->fec); fec_remove(&ft, &fn->fec);

View File

@ -74,7 +74,7 @@ ldp_vty_debug(struct vty *vty, struct vty_arg *args[])
DEBUG_OFF(event, EVENT); DEBUG_OFF(event, EVENT);
else else
DEBUG_ON(event, EVENT); DEBUG_ON(event, EVENT);
} else if (strcmp(type_str, "messages") == 0) { } else if (strcmp(type_str, "messages") == 0) {
all = (vty_get_arg_value(args, "all")) ? 1 : 0; all = (vty_get_arg_value(args, "all")) ? 1 : 0;
dir_str = vty_get_arg_value(args, "dir"); dir_str = vty_get_arg_value(args, "dir");
if (dir_str == NULL) if (dir_str == NULL)
@ -99,7 +99,7 @@ ldp_vty_debug(struct vty *vty, struct vty_arg *args[])
DEBUG_ON(msg, MSG_SEND_ALL); DEBUG_ON(msg, MSG_SEND_ALL);
} }
} }
} else if (strcmp(type_str, "zebra") == 0) { } else if (strcmp(type_str, "zebra") == 0) {
if (disable) if (disable)
DEBUG_OFF(zebra, ZEBRA); DEBUG_OFF(zebra, ZEBRA);
else else

File diff suppressed because it is too large Load Diff

View File

@ -142,7 +142,7 @@ ldp_af_iface_config_write(struct vty *vty, int af)
struct iface *iface; struct iface *iface;
struct iface_af *ia; struct iface_af *ia;
LIST_FOREACH(iface, &ldpd_conf->iface_list, entry) { RB_FOREACH(iface, iface_head, &ldpd_conf->iface_tree) {
ia = iface_af_get(iface, af); ia = iface_af_get(iface, af);
if (!ia->enabled) if (!ia->enabled)
continue; continue;
@ -213,7 +213,7 @@ ldp_af_config_write(struct vty *vty, int af, struct ldpd_conf *conf,
vty_out(vty, " session holdtime %u%s", af_conf->keepalive, vty_out(vty, " session holdtime %u%s", af_conf->keepalive,
VTY_NEWLINE); VTY_NEWLINE);
LIST_FOREACH(tnbr, &ldpd_conf->tnbr_list, entry) { RB_FOREACH(tnbr, tnbr_head, &ldpd_conf->tnbr_tree) {
if (tnbr->af == af) { if (tnbr->af == af) {
vty_out(vty, " !%s", VTY_NEWLINE); vty_out(vty, " !%s", VTY_NEWLINE);
vty_out(vty, " neighbor %s targeted%s", vty_out(vty, " neighbor %s targeted%s",
@ -265,7 +265,7 @@ ldp_config_write(struct vty *vty)
if (ldpd_conf->flags & F_LDPD_DS_CISCO_INTEROP) if (ldpd_conf->flags & F_LDPD_DS_CISCO_INTEROP)
vty_out(vty, " dual-stack cisco-interop%s", VTY_NEWLINE); vty_out(vty, " dual-stack cisco-interop%s", VTY_NEWLINE);
LIST_FOREACH(nbrp, &ldpd_conf->nbrp_list, entry) { RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) {
if (nbrp->flags & F_NBRP_KEEPALIVE) if (nbrp->flags & F_NBRP_KEEPALIVE)
vty_out(vty, " neighbor %s session holdtime %u%s", vty_out(vty, " neighbor %s session holdtime %u%s",
inet_ntoa(nbrp->lsr_id), nbrp->keepalive, inet_ntoa(nbrp->lsr_id), nbrp->keepalive,
@ -341,7 +341,7 @@ ldp_l2vpn_config_write(struct vty *vty)
struct l2vpn_if *lif; struct l2vpn_if *lif;
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
LIST_FOREACH(l2vpn, &ldpd_conf->l2vpn_list, entry) { RB_FOREACH(l2vpn, l2vpn_head, &ldpd_conf->l2vpn_tree) {
vty_out(vty, "l2vpn %s type vpls%s", l2vpn->name, VTY_NEWLINE); vty_out(vty, "l2vpn %s type vpls%s", l2vpn->name, VTY_NEWLINE);
if (l2vpn->pw_type != DEFAULT_PW_TYPE) if (l2vpn->pw_type != DEFAULT_PW_TYPE)
@ -354,13 +354,13 @@ ldp_l2vpn_config_write(struct vty *vty)
vty_out(vty, " bridge %s%s", l2vpn->br_ifname, vty_out(vty, " bridge %s%s", l2vpn->br_ifname,
VTY_NEWLINE); VTY_NEWLINE);
LIST_FOREACH(lif, &l2vpn->if_list, entry) RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
vty_out(vty, " member interface %s%s", lif->ifname, vty_out(vty, " member interface %s%s", lif->ifname,
VTY_NEWLINE); VTY_NEWLINE);
LIST_FOREACH(pw, &l2vpn->pw_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
ldp_l2vpn_pw_config_write(vty, pw); ldp_l2vpn_pw_config_write(vty, pw);
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
ldp_l2vpn_pw_config_write(vty, pw); ldp_l2vpn_pw_config_write(vty, pw);
vty_out(vty, " !%s", VTY_NEWLINE); vty_out(vty, " !%s", VTY_NEWLINE);
@ -393,7 +393,7 @@ ldp_iface_is_configured(struct ldpd_conf *xconf, const char *ifname)
if (if_lookup_name(xconf, ifname)) if (if_lookup_name(xconf, ifname))
return (1); return (1);
LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) { RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
if (l2vpn_if_find_name(l2vpn, ifname)) if (l2vpn_if_find_name(l2vpn, ifname))
return (1); return (1);
if (l2vpn_pw_find_name(l2vpn, ifname)) if (l2vpn_pw_find_name(l2vpn, ifname))
@ -740,7 +740,7 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[])
} else { } else {
if (nbrp == NULL) { if (nbrp == NULL) {
nbrp = nbr_params_new(lsr_id); nbrp = nbr_params_new(lsr_id);
LIST_INSERT_HEAD(&vty_conf->nbrp_list, nbrp, entry); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
} else if (nbrp->keepalive == secs) } else if (nbrp->keepalive == secs)
goto cancel; goto cancel;
@ -857,7 +857,7 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
ia = iface_af_get(iface, af); ia = iface_af_get(iface, af);
ia->enabled = 1; ia->enabled = 1;
LIST_INSERT_HEAD(&vty_conf->iface_list, iface, entry); RB_INSERT(iface_head, &vty_conf->iface_tree, iface);
ldp_reload_ref(vty_conf, (void **)&iface); ldp_reload_ref(vty_conf, (void **)&iface);
} else { } else {
memset(&kif, 0, sizeof(kif)); memset(&kif, 0, sizeof(kif));
@ -955,7 +955,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[])
if (tnbr == NULL) if (tnbr == NULL)
goto cancel; goto cancel;
LIST_REMOVE(tnbr, entry); RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr);
free(tnbr); free(tnbr);
ldp_reload(vty_conf); ldp_reload(vty_conf);
return (CMD_SUCCESS); return (CMD_SUCCESS);
@ -966,7 +966,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[])
tnbr = tnbr_new(af, &addr); tnbr = tnbr_new(af, &addr);
tnbr->flags |= F_TNBR_CONFIGURED; tnbr->flags |= F_TNBR_CONFIGURED;
LIST_INSERT_HEAD(&vty_conf->tnbr_list, tnbr, entry); RB_INSERT(tnbr_head, &vty_conf->tnbr_tree, tnbr);
ldp_reload(vty_conf); ldp_reload(vty_conf);
@ -1129,7 +1129,7 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[])
} else { } else {
if (nbrp == NULL) { if (nbrp == NULL) {
nbrp = nbr_params_new(lsr_id); nbrp = nbr_params_new(lsr_id);
LIST_INSERT_HEAD(&vty_conf->nbrp_list, nbrp, entry); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
} else if (nbrp->auth.method == AUTH_MD5SIG && } else if (nbrp->auth.method == AUTH_MD5SIG &&
strcmp(nbrp->auth.md5key, password_str) == 0) strcmp(nbrp->auth.md5key, password_str) == 0)
goto cancel; goto cancel;
@ -1195,7 +1195,7 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[])
} else { } else {
if (nbrp == NULL) { if (nbrp == NULL) {
nbrp = nbr_params_new(lsr_id); nbrp = nbr_params_new(lsr_id);
LIST_INSERT_HEAD(&vty_conf->nbrp_list, nbrp, entry); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp);
} }
nbrp->flags |= F_NBRP_GTSM; nbrp->flags |= F_NBRP_GTSM;
@ -1235,7 +1235,7 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
if (l2vpn == NULL) if (l2vpn == NULL)
goto cancel; goto cancel;
LIST_REMOVE(l2vpn, entry); RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
l2vpn_del(l2vpn); l2vpn_del(l2vpn);
ldp_reload(vty_conf); ldp_reload(vty_conf);
return (CMD_SUCCESS); return (CMD_SUCCESS);
@ -1248,9 +1248,9 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
l2vpn = l2vpn_new(name_str); l2vpn = l2vpn_new(name_str);
l2vpn->type = L2VPN_TYPE_VPLS; l2vpn->type = L2VPN_TYPE_VPLS;
LIST_INSERT_HEAD(&vty_conf->l2vpn_list, l2vpn, entry); RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
ldp_reload(vty_conf); ldp_reload_ref(vty_conf, (void **)&l2vpn);
VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn);
return (CMD_SUCCESS); return (CMD_SUCCESS);
@ -1369,7 +1369,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
if (lif == NULL) if (lif == NULL)
goto cancel; goto cancel;
LIST_REMOVE(lif, entry); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif); free(lif);
ldp_reload(vty_conf); ldp_reload(vty_conf);
return (CMD_SUCCESS); return (CMD_SUCCESS);
@ -1392,7 +1392,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
} }
lif = l2vpn_if_new(l2vpn, &kif); lif = l2vpn_if_new(l2vpn, &kif);
LIST_INSERT_HEAD(&l2vpn->if_list, lif, entry); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
ldp_reload_ref(vty_conf, (void **)&l2vpn); ldp_reload_ref(vty_conf, (void **)&l2vpn);
@ -1425,14 +1425,14 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
if (pw == NULL) if (pw == NULL)
goto cancel; goto cancel;
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
free(pw); free(pw);
ldp_reload(vty_conf); ldp_reload(vty_conf);
return (CMD_SUCCESS); return (CMD_SUCCESS);
} }
if (pw) { if (pw) {
VTY_PUSH_CONTEXT(LDP_PSEUDOWIRE_NODE, pw); VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw);
goto cancel; goto cancel;
} }
@ -1451,10 +1451,10 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
pw = l2vpn_pw_new(l2vpn, &kif); pw = l2vpn_pw_new(l2vpn, &kif);
pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, pw, entry); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
ldp_reload_ref(vty_conf, (void **)&pw); ldp_reload_ref(vty_conf, (void **)&pw);
VTY_PUSH_CONTEXT(LDP_PSEUDOWIRE_NODE, pw); VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw);
return (CMD_SUCCESS); return (CMD_SUCCESS);
@ -1474,7 +1474,7 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[])
disable = (vty_get_arg_value(args, "no")) ? 1 : 0; disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
preference_str = vty_get_arg_value(args, "preference"); preference_str = vty_get_arg_value(args, "preference");
pw = VTY_GET_CONTEXT(l2vpn_pw); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw);
vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw);
if (disable) if (disable)
@ -1510,7 +1510,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[])
return (CMD_WARNING); return (CMD_WARNING);
} }
pw = VTY_GET_CONTEXT(l2vpn_pw); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw);
vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw);
if (disable) { if (disable) {
@ -1546,7 +1546,7 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[])
return (CMD_WARNING); return (CMD_WARNING);
} }
pw = VTY_GET_CONTEXT(l2vpn_pw); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw);
vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw);
if (disable) if (disable)
@ -1578,7 +1578,7 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[])
return (CMD_WARNING); return (CMD_WARNING);
} }
pw = VTY_GET_CONTEXT(l2vpn_pw); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw);
vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw);
if (disable) if (disable)
@ -1600,7 +1600,7 @@ ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[])
disable = (vty_get_arg_value(args, "no")) ? 1 : 0; disable = (vty_get_arg_value(args, "no")) ? 1 : 0;
pw = VTY_GET_CONTEXT(l2vpn_pw); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw);
vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw);
if (disable) if (disable)
@ -1641,14 +1641,14 @@ iface_new_api(struct ldpd_conf *conf, const char *name)
} }
iface = if_new(&kif); iface = if_new(&kif);
LIST_INSERT_HEAD(&conf->iface_list, iface, entry); RB_INSERT(iface_head, &conf->iface_tree, iface);
return (iface); return (iface);
} }
void void
iface_del_api(struct iface *iface) iface_del_api(struct ldpd_conf *conf, struct iface *iface)
{ {
LIST_REMOVE(iface, entry); RB_REMOVE(iface_head, &conf->iface_tree, iface);
free(iface); free(iface);
} }
@ -1665,14 +1665,14 @@ tnbr_new_api(struct ldpd_conf *conf, int af, union ldpd_addr *addr)
tnbr = tnbr_new(af, addr); tnbr = tnbr_new(af, addr);
tnbr->flags |= F_TNBR_CONFIGURED; tnbr->flags |= F_TNBR_CONFIGURED;
LIST_INSERT_HEAD(&conf->tnbr_list, tnbr, entry); RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr);
return (tnbr); return (tnbr);
} }
void void
tnbr_del_api(struct tnbr *tnbr) tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr)
{ {
LIST_REMOVE(tnbr, entry); RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
free(tnbr); free(tnbr);
} }
@ -1685,14 +1685,14 @@ nbrp_new_api(struct ldpd_conf *conf, struct in_addr lsr_id)
return (NULL); return (NULL);
nbrp = nbr_params_new(lsr_id); nbrp = nbr_params_new(lsr_id);
LIST_INSERT_HEAD(&conf->nbrp_list, nbrp, entry); RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp);
return (nbrp); return (nbrp);
} }
void void
nbrp_del_api(struct nbr_params *nbrp) nbrp_del_api(struct ldpd_conf *conf, struct nbr_params *nbrp)
{ {
LIST_REMOVE(nbrp, entry); RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
free(nbrp); free(nbrp);
} }
@ -1706,29 +1706,29 @@ l2vpn_new_api(struct ldpd_conf *conf, const char *name)
l2vpn = l2vpn_new(name); l2vpn = l2vpn_new(name);
l2vpn->type = L2VPN_TYPE_VPLS; l2vpn->type = L2VPN_TYPE_VPLS;
LIST_INSERT_HEAD(&conf->l2vpn_list, l2vpn, entry); RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn);
return (l2vpn); return (l2vpn);
} }
void void
l2vpn_del_api(struct l2vpn *l2vpn) l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn)
{ {
struct l2vpn_if *lif; struct l2vpn_if *lif;
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) { while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) {
LIST_REMOVE(lif, entry); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif); free(lif);
} }
while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) { while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) {
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
free(pw); free(pw);
} }
while ((pw = LIST_FIRST(&l2vpn->pw_inactive_list)) != NULL) { while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) {
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
free(pw); free(pw);
} }
LIST_REMOVE(l2vpn, entry); RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
free(l2vpn); free(l2vpn);
} }
@ -1752,14 +1752,14 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
} }
lif = l2vpn_if_new(l2vpn, &kif); lif = l2vpn_if_new(l2vpn, &kif);
LIST_INSERT_HEAD(&l2vpn->if_list, lif, entry); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif);
return (lif); return (lif);
} }
void void
l2vpn_if_del_api(struct l2vpn_if *lif) l2vpn_if_del_api(struct l2vpn *l2vpn, struct l2vpn_if *lif)
{ {
LIST_REMOVE(lif, entry); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif); free(lif);
} }
@ -1784,13 +1784,13 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
pw = l2vpn_pw_new(l2vpn, &kif); pw = l2vpn_pw_new(l2vpn, &kif);
pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF;
LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, pw, entry); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
return (pw); return (pw);
} }
void void
l2vpn_pw_del_api(struct l2vpn_pw *pw) l2vpn_pw_del_api(struct l2vpn *l2vpn, struct l2vpn_pw *pw)
{ {
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
free(pw); free(pw);
} }

View File

@ -850,40 +850,40 @@ main_imsg_send_config(struct ldpd_conf *xconf)
sizeof(*xconf)) == -1) sizeof(*xconf)) == -1)
return (-1); return (-1);
LIST_FOREACH(iface, &xconf->iface_list, entry) { RB_FOREACH(iface, iface_head, &xconf->iface_tree) {
if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface, if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface,
sizeof(*iface)) == -1) sizeof(*iface)) == -1)
return (-1); return (-1);
} }
LIST_FOREACH(tnbr, &xconf->tnbr_list, entry) { RB_FOREACH(tnbr, tnbr_head, &xconf->tnbr_tree) {
if (main_imsg_compose_both(IMSG_RECONF_TNBR, tnbr, if (main_imsg_compose_both(IMSG_RECONF_TNBR, tnbr,
sizeof(*tnbr)) == -1) sizeof(*tnbr)) == -1)
return (-1); return (-1);
} }
LIST_FOREACH(nbrp, &xconf->nbrp_list, entry) { RB_FOREACH(nbrp, nbrp_head, &xconf->nbrp_tree) {
if (main_imsg_compose_both(IMSG_RECONF_NBRP, nbrp, if (main_imsg_compose_both(IMSG_RECONF_NBRP, nbrp,
sizeof(*nbrp)) == -1) sizeof(*nbrp)) == -1)
return (-1); return (-1);
} }
LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) { RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
if (main_imsg_compose_both(IMSG_RECONF_L2VPN, l2vpn, if (main_imsg_compose_both(IMSG_RECONF_L2VPN, l2vpn,
sizeof(*l2vpn)) == -1) sizeof(*l2vpn)) == -1)
return (-1); return (-1);
LIST_FOREACH(lif, &l2vpn->if_list, entry) { RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) {
if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IF, lif, if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IF, lif,
sizeof(*lif)) == -1) sizeof(*lif)) == -1)
return (-1); return (-1);
} }
LIST_FOREACH(pw, &l2vpn->pw_list, entry) { RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
if (main_imsg_compose_both(IMSG_RECONF_L2VPN_PW, pw, if (main_imsg_compose_both(IMSG_RECONF_L2VPN_PW, pw,
sizeof(*pw)) == -1) sizeof(*pw)) == -1)
return (-1); return (-1);
} }
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) { RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IPW, pw, if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IPW, pw,
sizeof(*pw)) == -1) sizeof(*pw)) == -1)
return (-1); return (-1);
@ -930,15 +930,15 @@ ldp_config_normalize(struct ldpd_conf *xconf, void **ref)
ldp_config_reset_af(xconf, AF_INET6, ref); ldp_config_reset_af(xconf, AF_INET6, ref);
} }
LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) { RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
LIST_FOREACH(pw, &l2vpn->pw_list, entry) { RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
if (pw->flags & F_PW_STATIC_NBR_ADDR) if (pw->flags & F_PW_STATIC_NBR_ADDR)
continue; continue;
pw->af = AF_INET; pw->af = AF_INET;
pw->addr.v4 = pw->lsr_id; pw->addr.v4 = pw->lsr_id;
} }
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) { RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
if (pw->flags & F_PW_STATIC_NBR_ADDR) if (pw->flags & F_PW_STATIC_NBR_ADDR)
continue; continue;
@ -954,17 +954,17 @@ ldp_config_reset_main(struct ldpd_conf *conf, void **ref)
struct iface *iface; struct iface *iface;
struct nbr_params *nbrp; struct nbr_params *nbrp;
while ((iface = LIST_FIRST(&conf->iface_list)) != NULL) { while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) {
if (ref && *ref == iface) if (ref && *ref == iface)
*ref = NULL; *ref = NULL;
LIST_REMOVE(iface, entry); RB_REMOVE(iface_head, &conf->iface_tree, iface);
free(iface); free(iface);
} }
while ((nbrp = LIST_FIRST(&conf->nbrp_list)) != NULL) { while ((nbrp = RB_ROOT(&conf->nbrp_tree)) != NULL) {
if (ref && *ref == nbrp) if (ref && *ref == nbrp)
*ref = NULL; *ref = NULL;
LIST_REMOVE(nbrp, entry); RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
free(nbrp); free(nbrp);
} }
@ -987,18 +987,18 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af, void **ref)
struct iface_af *ia; struct iface_af *ia;
struct tnbr *tnbr, *ttmp; struct tnbr *tnbr, *ttmp;
LIST_FOREACH(iface, &conf->iface_list, entry) { RB_FOREACH(iface, iface_head, &conf->iface_tree) {
ia = iface_af_get(iface, af); ia = iface_af_get(iface, af);
ia->enabled = 0; ia->enabled = 0;
} }
LIST_FOREACH_SAFE(tnbr, &conf->tnbr_list, entry, ttmp) { RB_FOREACH_SAFE(tnbr, tnbr_head, &conf->tnbr_tree, ttmp) {
if (tnbr->af != af) if (tnbr->af != af)
continue; continue;
if (ref && *ref == tnbr) if (ref && *ref == tnbr)
*ref = NULL; *ref = NULL;
LIST_REMOVE(tnbr, entry); RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
free(tnbr); free(tnbr);
} }
@ -1032,46 +1032,46 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref)
} while (0) } while (0)
COPY(xconf, conf); COPY(xconf, conf);
LIST_INIT(&xconf->iface_list); RB_INIT(&xconf->iface_tree);
LIST_INIT(&xconf->tnbr_list); RB_INIT(&xconf->tnbr_tree);
LIST_INIT(&xconf->nbrp_list); RB_INIT(&xconf->nbrp_tree);
LIST_INIT(&xconf->l2vpn_list); RB_INIT(&xconf->l2vpn_tree);
LIST_FOREACH(iface, &conf->iface_list, entry) { RB_FOREACH(iface, iface_head, &conf->iface_tree) {
COPY(xi, iface); COPY(xi, iface);
xi->ipv4.iface = xi; xi->ipv4.iface = xi;
xi->ipv6.iface = xi; xi->ipv6.iface = xi;
LIST_INSERT_HEAD(&xconf->iface_list, xi, entry); RB_INSERT(iface_head, &xconf->iface_tree, xi);
} }
LIST_FOREACH(tnbr, &conf->tnbr_list, entry) { RB_FOREACH(tnbr, tnbr_head, &conf->tnbr_tree) {
COPY(xt, tnbr); COPY(xt, tnbr);
LIST_INSERT_HEAD(&xconf->tnbr_list, xt, entry); RB_INSERT(tnbr_head, &xconf->tnbr_tree, xt);
} }
LIST_FOREACH(nbrp, &conf->nbrp_list, entry) { RB_FOREACH(nbrp, nbrp_head, &conf->nbrp_tree) {
COPY(xn, nbrp); COPY(xn, nbrp);
LIST_INSERT_HEAD(&xconf->nbrp_list, xn, entry); RB_INSERT(nbrp_head, &xconf->nbrp_tree, xn);
} }
LIST_FOREACH(l2vpn, &conf->l2vpn_list, entry) { RB_FOREACH(l2vpn, l2vpn_head, &conf->l2vpn_tree) {
COPY(xl, l2vpn); COPY(xl, l2vpn);
LIST_INIT(&xl->if_list); RB_INIT(&xl->if_tree);
LIST_INIT(&xl->pw_list); RB_INIT(&xl->pw_tree);
LIST_INIT(&xl->pw_inactive_list); RB_INIT(&xl->pw_inactive_tree);
LIST_INSERT_HEAD(&xconf->l2vpn_list, xl, entry); RB_INSERT(l2vpn_head, &xconf->l2vpn_tree, xl);
LIST_FOREACH(lif, &l2vpn->if_list, entry) { RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) {
COPY(xf, lif); COPY(xf, lif);
xf->l2vpn = xl; xf->l2vpn = xl;
LIST_INSERT_HEAD(&xl->if_list, xf, entry); RB_INSERT(l2vpn_if_head, &xl->if_tree, xf);
} }
LIST_FOREACH(pw, &l2vpn->pw_list, entry) { RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
COPY(xp, pw); COPY(xp, pw);
xp->l2vpn = xl; xp->l2vpn = xl;
LIST_INSERT_HEAD(&xl->pw_list, xp, entry); RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp);
} }
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) { RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) {
COPY(xp, pw); COPY(xp, pw);
xp->l2vpn = xl; xp->l2vpn = xl;
LIST_INSERT_HEAD(&xl->pw_inactive_list, xp, entry); RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
} }
} }
#undef COPY #undef COPY
@ -1093,20 +1093,20 @@ ldp_clear_config(struct ldpd_conf *xconf)
struct nbr_params *nbrp; struct nbr_params *nbrp;
struct l2vpn *l2vpn; struct l2vpn *l2vpn;
while ((iface = LIST_FIRST(&xconf->iface_list)) != NULL) { while ((iface = RB_ROOT(&xconf->iface_tree)) != NULL) {
LIST_REMOVE(iface, entry); RB_REMOVE(iface_head, &xconf->iface_tree, iface);
free(iface); free(iface);
} }
while ((tnbr = LIST_FIRST(&xconf->tnbr_list)) != NULL) { while ((tnbr = RB_ROOT(&xconf->tnbr_tree)) != NULL) {
LIST_REMOVE(tnbr, entry); RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr);
free(tnbr); free(tnbr);
} }
while ((nbrp = LIST_FIRST(&xconf->nbrp_list)) != NULL) { while ((nbrp = RB_ROOT(&xconf->nbrp_tree)) != NULL) {
LIST_REMOVE(nbrp, entry); RB_REMOVE(nbrp_head, &xconf->nbrp_tree, nbrp);
free(nbrp); free(nbrp);
} }
while ((l2vpn = LIST_FIRST(&xconf->l2vpn_list)) != NULL) { while ((l2vpn = RB_ROOT(&xconf->l2vpn_tree)) != NULL) {
LIST_REMOVE(l2vpn, entry); RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, l2vpn);
l2vpn_del(l2vpn); l2vpn_del(l2vpn);
} }
@ -1236,10 +1236,10 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
{ {
struct iface *iface, *itmp, *xi; struct iface *iface, *itmp, *xi;
LIST_FOREACH_SAFE(iface, &conf->iface_list, entry, itmp) { RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
/* find deleted interfaces */ /* find deleted interfaces */
if ((xi = if_lookup_name(xconf, iface->name)) == NULL) { if ((xi = if_lookup_name(xconf, iface->name)) == NULL) {
LIST_REMOVE(iface, entry); RB_REMOVE(iface_head, &conf->iface_tree, iface);
switch (ldpd_process) { switch (ldpd_process) {
case PROC_LDE_ENGINE: case PROC_LDE_ENGINE:
@ -1254,11 +1254,11 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
free(iface); free(iface);
} }
} }
LIST_FOREACH_SAFE(xi, &xconf->iface_list, entry, itmp) { RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) {
/* find new interfaces */ /* find new interfaces */
if ((iface = if_lookup_name(conf, xi->name)) == NULL) { if ((iface = if_lookup_name(conf, xi->name)) == NULL) {
LIST_REMOVE(xi, entry); RB_REMOVE(iface_head, &xconf->iface_tree, xi);
LIST_INSERT_HEAD(&conf->iface_list, xi, entry); RB_INSERT(iface_head, &conf->iface_tree, xi);
if (ldpd_process == PROC_MAIN) { if (ldpd_process == PROC_MAIN) {
QOBJ_REG (xi, iface); QOBJ_REG (xi, iface);
@ -1271,7 +1271,7 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
/* update existing interfaces */ /* update existing interfaces */
merge_iface_af(&iface->ipv4, &xi->ipv4); merge_iface_af(&iface->ipv4, &xi->ipv4);
merge_iface_af(&iface->ipv6, &xi->ipv6); merge_iface_af(&iface->ipv6, &xi->ipv6);
LIST_REMOVE(xi, entry); RB_REMOVE(iface_head, &xconf->iface_tree, xi);
if (ref && *ref == xi) if (ref && *ref == xi)
*ref = iface; *ref = iface;
free(xi); free(xi);
@ -1295,7 +1295,7 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
{ {
struct tnbr *tnbr, *ttmp, *xt; struct tnbr *tnbr, *ttmp, *xt;
LIST_FOREACH_SAFE(tnbr, &conf->tnbr_list, entry, ttmp) { RB_FOREACH_SAFE(tnbr, tnbr_head, &conf->tnbr_tree, ttmp) {
if (!(tnbr->flags & F_TNBR_CONFIGURED)) if (!(tnbr->flags & F_TNBR_CONFIGURED))
continue; continue;
@ -1303,26 +1303,26 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) { if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) {
switch (ldpd_process) { switch (ldpd_process) {
case PROC_LDE_ENGINE: case PROC_LDE_ENGINE:
LIST_REMOVE(tnbr, entry); RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
free(tnbr); free(tnbr);
break; break;
case PROC_LDP_ENGINE: case PROC_LDP_ENGINE:
tnbr->flags &= ~F_TNBR_CONFIGURED; tnbr->flags &= ~F_TNBR_CONFIGURED;
tnbr_check(tnbr); tnbr_check(conf, tnbr);
break; break;
case PROC_MAIN: case PROC_MAIN:
LIST_REMOVE(tnbr, entry); RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
QOBJ_UNREG (tnbr); QOBJ_UNREG (tnbr);
free(tnbr); free(tnbr);
break; break;
} }
} }
} }
LIST_FOREACH_SAFE(xt, &xconf->tnbr_list, entry, ttmp) { RB_FOREACH_SAFE(xt, tnbr_head, &xconf->tnbr_tree, ttmp) {
/* find new tnbrs */ /* find new tnbrs */
if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) { if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) {
LIST_REMOVE(xt, entry); RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt);
LIST_INSERT_HEAD(&conf->tnbr_list, xt, entry); RB_INSERT(tnbr_head, &conf->tnbr_tree, xt);
switch (ldpd_process) { switch (ldpd_process) {
case PROC_LDE_ENGINE: case PROC_LDE_ENGINE:
@ -1340,7 +1340,7 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
/* update existing tnbrs */ /* update existing tnbrs */
if (!(tnbr->flags & F_TNBR_CONFIGURED)) if (!(tnbr->flags & F_TNBR_CONFIGURED))
tnbr->flags |= F_TNBR_CONFIGURED; tnbr->flags |= F_TNBR_CONFIGURED;
LIST_REMOVE(xt, entry); RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt);
if (ref && *ref == xt) if (ref && *ref == xt)
*ref = tnbr; *ref = tnbr;
free(xt); free(xt);
@ -1354,7 +1354,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
struct nbr *nbr; struct nbr *nbr;
int nbrp_changed; int nbrp_changed;
LIST_FOREACH_SAFE(nbrp, &conf->nbrp_list, entry, ntmp) { RB_FOREACH_SAFE(nbrp, nbrp_head, &conf->nbrp_tree, ntmp) {
/* find deleted nbrps */ /* find deleted nbrps */
if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) { if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) {
switch (ldpd_process) { switch (ldpd_process) {
@ -1380,15 +1380,15 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
QOBJ_UNREG (nbrp); QOBJ_UNREG (nbrp);
break; break;
} }
LIST_REMOVE(nbrp, entry); RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
free(nbrp); free(nbrp);
} }
} }
LIST_FOREACH_SAFE(xn, &xconf->nbrp_list, entry, ntmp) { RB_FOREACH_SAFE(xn, nbrp_head, &xconf->nbrp_tree, ntmp) {
/* find new nbrps */ /* find new nbrps */
if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) { if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) {
LIST_REMOVE(xn, entry); RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn);
LIST_INSERT_HEAD(&conf->nbrp_list, xn, entry); RB_INSERT(nbrp_head, &conf->nbrp_tree, xn);
switch (ldpd_process) { switch (ldpd_process) {
case PROC_LDE_ENGINE: case PROC_LDE_ENGINE:
@ -1455,7 +1455,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
nbr_establish_connection(nbr); nbr_establish_connection(nbr);
} }
} }
LIST_REMOVE(xn, entry); RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn);
if (ref && *ref == xn) if (ref && *ref == xn)
*ref = nbrp; *ref = nbrp;
free(xn); free(xn);
@ -1469,10 +1469,10 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
struct l2vpn_if *lif; struct l2vpn_if *lif;
struct l2vpn_pw *pw; struct l2vpn_pw *pw;
LIST_FOREACH_SAFE(l2vpn, &conf->l2vpn_list, entry, ltmp) { RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) {
/* find deleted l2vpns */ /* find deleted l2vpns */
if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) { if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) {
LIST_REMOVE(l2vpn, entry); RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
switch (ldpd_process) { switch (ldpd_process) {
case PROC_LDE_ENGINE: case PROC_LDE_ENGINE:
@ -1482,11 +1482,11 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
ldpe_l2vpn_exit(l2vpn); ldpe_l2vpn_exit(l2vpn);
break; break;
case PROC_MAIN: case PROC_MAIN:
LIST_FOREACH(lif, &l2vpn->if_list, entry) RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
QOBJ_UNREG (lif); QOBJ_UNREG (lif);
LIST_FOREACH(pw, &l2vpn->pw_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
QOBJ_UNREG (pw); QOBJ_UNREG (pw);
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
QOBJ_UNREG (pw); QOBJ_UNREG (pw);
QOBJ_UNREG (l2vpn); QOBJ_UNREG (l2vpn);
break; break;
@ -1494,11 +1494,11 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
l2vpn_del(l2vpn); l2vpn_del(l2vpn);
} }
} }
LIST_FOREACH_SAFE(xl, &xconf->l2vpn_list, entry, ltmp) { RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) {
/* find new l2vpns */ /* find new l2vpns */
if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) { if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) {
LIST_REMOVE(xl, entry); RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
LIST_INSERT_HEAD(&conf->l2vpn_list, xl, entry); RB_INSERT(l2vpn_head, &conf->l2vpn_tree, xl);
switch (ldpd_process) { switch (ldpd_process) {
case PROC_LDE_ENGINE: case PROC_LDE_ENGINE:
@ -1516,7 +1516,7 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
/* update existing l2vpns */ /* update existing l2vpns */
merge_l2vpn(conf, l2vpn, xl, ref); merge_l2vpn(conf, l2vpn, xl, ref);
LIST_REMOVE(xl, entry); RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
if (ref && *ref == xl) if (ref && *ref == xl)
*ref = l2vpn; *ref = l2vpn;
free(xl); free(xl);
@ -1530,42 +1530,42 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
struct l2vpn_pw *pw, *ptmp, *xp; struct l2vpn_pw *pw, *ptmp, *xp;
struct nbr *nbr; struct nbr *nbr;
int reset_nbr, reinstall_pwfec, reinstall_tnbr; int reset_nbr, reinstall_pwfec, reinstall_tnbr;
LIST_HEAD(, l2vpn_pw) pw_aux_list; struct l2vpn_pw_head pw_aux_list;
int previous_pw_type, previous_mtu; int previous_pw_type, previous_mtu;
previous_pw_type = l2vpn->pw_type; previous_pw_type = l2vpn->pw_type;
previous_mtu = l2vpn->mtu; previous_mtu = l2vpn->mtu;
/* merge intefaces */ /* merge intefaces */
LIST_FOREACH_SAFE(lif, &l2vpn->if_list, entry, ftmp) { RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) {
/* find deleted interfaces */ /* find deleted interfaces */
if ((xf = l2vpn_if_find_name(xl, lif->ifname)) == NULL) { if ((xf = l2vpn_if_find_name(xl, lif->ifname)) == NULL) {
if (ldpd_process == PROC_MAIN) if (ldpd_process == PROC_MAIN)
QOBJ_UNREG (lif); QOBJ_UNREG (lif);
LIST_REMOVE(lif, entry); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif); free(lif);
} }
} }
LIST_FOREACH_SAFE(xf, &xl->if_list, entry, ftmp) { RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) {
/* find new interfaces */ /* find new interfaces */
if ((lif = l2vpn_if_find_name(l2vpn, xf->ifname)) == NULL) { if ((lif = l2vpn_if_find_name(l2vpn, xf->ifname)) == NULL) {
LIST_REMOVE(xf, entry); RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
LIST_INSERT_HEAD(&l2vpn->if_list, xf, entry); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf);
xf->l2vpn = l2vpn; xf->l2vpn = l2vpn;
if (ldpd_process == PROC_MAIN) if (ldpd_process == PROC_MAIN)
QOBJ_REG (xf, l2vpn_if); QOBJ_REG (xf, l2vpn_if);
continue; continue;
} }
LIST_REMOVE(xf, entry); RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
if (ref && *ref == xf) if (ref && *ref == xf)
*ref = lif; *ref = lif;
free(xf); free(xf);
} }
/* merge active pseudowires */ /* merge active pseudowires */
LIST_INIT(&pw_aux_list); RB_INIT(&pw_aux_list);
LIST_FOREACH_SAFE(pw, &l2vpn->pw_list, entry, ptmp) { RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) {
/* find deleted active pseudowires */ /* find deleted active pseudowires */
if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) { if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) {
switch (ldpd_process) { switch (ldpd_process) {
@ -1580,15 +1580,15 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
break; break;
} }
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
free(pw); free(pw);
} }
} }
LIST_FOREACH_SAFE(xp, &xl->pw_list, entry, ptmp) { RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) {
/* find new active pseudowires */ /* find new active pseudowires */
if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) { if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) {
LIST_REMOVE(xp, entry); RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
LIST_INSERT_HEAD(&l2vpn->pw_list, xp, entry); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp);
xp->l2vpn = l2vpn; xp->l2vpn = l2vpn;
switch (ldpd_process) { switch (ldpd_process) {
@ -1644,8 +1644,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
} }
/* remove from active list */ /* remove from active list */
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
LIST_INSERT_HEAD(&pw_aux_list, pw, entry); RB_INSERT(l2vpn_pw_head, &pw_aux_list, pw);
} }
if (ldpd_process == PROC_LDP_ENGINE) { if (ldpd_process == PROC_LDP_ENGINE) {
@ -1689,27 +1689,27 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
l2vpn->mtu = previous_mtu; l2vpn->mtu = previous_mtu;
} }
LIST_REMOVE(xp, entry); RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
if (ref && *ref == xp) if (ref && *ref == xp)
*ref = pw; *ref = pw;
free(xp); free(xp);
} }
/* merge inactive pseudowires */ /* merge inactive pseudowires */
LIST_FOREACH_SAFE(pw, &l2vpn->pw_inactive_list, entry, ptmp) { RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, ptmp) {
/* find deleted inactive pseudowires */ /* find deleted inactive pseudowires */
if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) { if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) {
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
if (ldpd_process == PROC_MAIN) if (ldpd_process == PROC_MAIN)
QOBJ_UNREG (pw); QOBJ_UNREG (pw);
free(pw); free(pw);
} }
} }
LIST_FOREACH_SAFE(xp, &xl->pw_inactive_list, entry, ptmp) { RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) {
/* find new inactive pseudowires */ /* find new inactive pseudowires */
if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) { if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) {
LIST_REMOVE(xp, entry); RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, xp, entry); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp);
xp->l2vpn = l2vpn; xp->l2vpn = l2vpn;
if (ldpd_process == PROC_MAIN) if (ldpd_process == PROC_MAIN)
QOBJ_REG (xp, l2vpn_pw); QOBJ_REG (xp, l2vpn_pw);
@ -1728,8 +1728,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
/* check if the pseudowire should be activated */ /* check if the pseudowire should be activated */
if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) { if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) {
/* remove from inactive list */ /* remove from inactive list */
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
LIST_INSERT_HEAD(&l2vpn->pw_list, pw, entry); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw);
switch (ldpd_process) { switch (ldpd_process) {
case PROC_LDE_ENGINE: case PROC_LDE_ENGINE:
@ -1743,16 +1743,16 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
} }
} }
LIST_REMOVE(xp, entry); RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
if (ref && *ref == xp) if (ref && *ref == xp)
*ref = pw; *ref = pw;
free(xp); free(xp);
} }
/* insert pseudowires that were disabled in the inactive list */ /* insert pseudowires that were disabled in the inactive list */
LIST_FOREACH_SAFE(pw, &pw_aux_list, entry, ptmp) { RB_FOREACH_SAFE(pw, l2vpn_pw_head, &pw_aux_list, ptmp) {
LIST_REMOVE(pw, entry); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, pw, entry); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
} }
l2vpn->pw_type = xl->pw_type; l2vpn->pw_type = xl->pw_type;
@ -1770,10 +1770,10 @@ config_new_empty(void)
if (xconf == NULL) if (xconf == NULL)
fatal(NULL); fatal(NULL);
LIST_INIT(&xconf->iface_list); RB_INIT(&xconf->iface_tree);
LIST_INIT(&xconf->tnbr_list); RB_INIT(&xconf->tnbr_tree);
LIST_INIT(&xconf->nbrp_list); RB_INIT(&xconf->nbrp_tree);
LIST_INIT(&xconf->l2vpn_list); RB_INIT(&xconf->l2vpn_tree);
return (xconf); return (xconf);
} }

View File

@ -196,7 +196,10 @@ enum nbr_action {
NBR_ACT_CLOSE_SESSION NBR_ACT_CLOSE_SESSION
}; };
TAILQ_HEAD(mapping_head, mapping_entry); /* forward declarations */
RB_HEAD(global_adj_head, adj);
RB_HEAD(nbr_adj_head, adj);
RB_HEAD(ia_adj_head, adj);
struct map { struct map {
uint8_t type; uint8_t type;
@ -256,7 +259,7 @@ struct iface_af {
int af; int af;
int enabled; int enabled;
int state; int state;
LIST_HEAD(, adj) adj_list; struct ia_adj_head adj_tree;
time_t uptime; time_t uptime;
struct thread *hello_timer; struct thread *hello_timer;
uint16_t hello_holdtime; uint16_t hello_holdtime;
@ -264,7 +267,7 @@ struct iface_af {
}; };
struct iface { struct iface {
LIST_ENTRY(iface) entry; RB_ENTRY(iface) entry;
char name[IF_NAMESIZE]; char name[IF_NAMESIZE];
unsigned int ifindex; unsigned int ifindex;
struct if_addr_head addr_list; struct if_addr_head addr_list;
@ -275,11 +278,13 @@ struct iface {
struct iface_af ipv6; struct iface_af ipv6;
QOBJ_FIELDS QOBJ_FIELDS
}; };
RB_HEAD(iface_head, iface);
RB_PROTOTYPE(iface_head, iface, entry, iface_compare);
DECLARE_QOBJ_TYPE(iface) DECLARE_QOBJ_TYPE(iface)
/* source of targeted hellos */ /* source of targeted hellos */
struct tnbr { struct tnbr {
LIST_ENTRY(tnbr) entry; RB_ENTRY(tnbr) entry;
struct thread *hello_timer; struct thread *hello_timer;
struct adj *adj; struct adj *adj;
int af; int af;
@ -289,6 +294,8 @@ struct tnbr {
uint8_t flags; uint8_t flags;
QOBJ_FIELDS QOBJ_FIELDS
}; };
RB_HEAD(tnbr_head, tnbr);
RB_PROTOTYPE(tnbr_head, tnbr, entry, tnbr_compare);
DECLARE_QOBJ_TYPE(tnbr) DECLARE_QOBJ_TYPE(tnbr)
#define F_TNBR_CONFIGURED 0x01 #define F_TNBR_CONFIGURED 0x01
#define F_TNBR_DYNAMIC 0x02 #define F_TNBR_DYNAMIC 0x02
@ -300,7 +307,7 @@ enum auth_method {
/* neighbor specific parameters */ /* neighbor specific parameters */
struct nbr_params { struct nbr_params {
LIST_ENTRY(nbr_params) entry; RB_ENTRY(nbr_params) entry;
struct in_addr lsr_id; struct in_addr lsr_id;
uint16_t keepalive; uint16_t keepalive;
int gtsm_enabled; int gtsm_enabled;
@ -313,23 +320,27 @@ struct nbr_params {
uint8_t flags; uint8_t flags;
QOBJ_FIELDS QOBJ_FIELDS
}; };
RB_HEAD(nbrp_head, nbr_params);
RB_PROTOTYPE(nbrp_head, nbr_params, entry, nbr_params_compare);
DECLARE_QOBJ_TYPE(nbr_params) DECLARE_QOBJ_TYPE(nbr_params)
#define F_NBRP_KEEPALIVE 0x01 #define F_NBRP_KEEPALIVE 0x01
#define F_NBRP_GTSM 0x02 #define F_NBRP_GTSM 0x02
#define F_NBRP_GTSM_HOPS 0x04 #define F_NBRP_GTSM_HOPS 0x04
struct l2vpn_if { struct l2vpn_if {
LIST_ENTRY(l2vpn_if) entry; RB_ENTRY(l2vpn_if) entry;
struct l2vpn *l2vpn; struct l2vpn *l2vpn;
char ifname[IF_NAMESIZE]; char ifname[IF_NAMESIZE];
unsigned int ifindex; unsigned int ifindex;
uint16_t flags; uint16_t flags;
QOBJ_FIELDS QOBJ_FIELDS
}; };
RB_HEAD(l2vpn_if_head, l2vpn_if);
RB_PROTOTYPE(l2vpn_if_head, l2vpn_if, entry, l2vpn_if_compare);
DECLARE_QOBJ_TYPE(l2vpn_if) DECLARE_QOBJ_TYPE(l2vpn_if)
struct l2vpn_pw { struct l2vpn_pw {
LIST_ENTRY(l2vpn_pw) entry; RB_ENTRY(l2vpn_pw) entry;
struct l2vpn *l2vpn; struct l2vpn *l2vpn;
struct in_addr lsr_id; struct in_addr lsr_id;
int af; int af;
@ -343,6 +354,8 @@ struct l2vpn_pw {
uint8_t flags; uint8_t flags;
QOBJ_FIELDS QOBJ_FIELDS
}; };
RB_HEAD(l2vpn_pw_head, l2vpn_pw);
RB_PROTOTYPE(l2vpn_pw_head, l2vpn_pw, entry, l2vpn_pw_compare);
DECLARE_QOBJ_TYPE(l2vpn_pw) DECLARE_QOBJ_TYPE(l2vpn_pw)
#define F_PW_STATUSTLV_CONF 0x01 /* status tlv configured */ #define F_PW_STATUSTLV_CONF 0x01 /* status tlv configured */
#define F_PW_STATUSTLV 0x02 /* status tlv negotiated */ #define F_PW_STATUSTLV 0x02 /* status tlv negotiated */
@ -352,18 +365,20 @@ DECLARE_QOBJ_TYPE(l2vpn_pw)
#define F_PW_STATIC_NBR_ADDR 0x20 /* static neighbor address configured */ #define F_PW_STATIC_NBR_ADDR 0x20 /* static neighbor address configured */
struct l2vpn { struct l2vpn {
LIST_ENTRY(l2vpn) entry; RB_ENTRY(l2vpn) entry;
char name[L2VPN_NAME_LEN]; char name[L2VPN_NAME_LEN];
int type; int type;
int pw_type; int pw_type;
int mtu; int mtu;
char br_ifname[IF_NAMESIZE]; char br_ifname[IF_NAMESIZE];
unsigned int br_ifindex; unsigned int br_ifindex;
LIST_HEAD(, l2vpn_if) if_list; struct l2vpn_if_head if_tree;
LIST_HEAD(, l2vpn_pw) pw_list; struct l2vpn_pw_head pw_tree;
LIST_HEAD(, l2vpn_pw) pw_inactive_list; struct l2vpn_pw_head pw_inactive_tree;
QOBJ_FIELDS QOBJ_FIELDS
}; };
RB_HEAD(l2vpn_head, l2vpn);
RB_PROTOTYPE(l2vpn_head, l2vpn, entry, l2vpn_compare);
DECLARE_QOBJ_TYPE(l2vpn) DECLARE_QOBJ_TYPE(l2vpn)
#define L2VPN_TYPE_VPWS 1 #define L2VPN_TYPE_VPWS 1
#define L2VPN_TYPE_VPLS 2 #define L2VPN_TYPE_VPLS 2
@ -404,10 +419,10 @@ struct ldpd_conf {
struct in_addr rtr_id; struct in_addr rtr_id;
struct ldpd_af_conf ipv4; struct ldpd_af_conf ipv4;
struct ldpd_af_conf ipv6; struct ldpd_af_conf ipv6;
LIST_HEAD(, iface) iface_list; struct iface_head iface_tree;
LIST_HEAD(, tnbr) tnbr_list; struct tnbr_head tnbr_tree;
LIST_HEAD(, nbr_params) nbrp_list; struct nbrp_head nbrp_tree;
LIST_HEAD(, l2vpn) l2vpn_list; struct l2vpn_head l2vpn_tree;
uint16_t lhello_holdtime; uint16_t lhello_holdtime;
uint16_t lhello_interval; uint16_t lhello_interval;
uint16_t thello_holdtime; uint16_t thello_holdtime;
@ -438,7 +453,7 @@ struct ldpd_global {
uint32_t conf_seqnum; uint32_t conf_seqnum;
int pfkeysock; int pfkeysock;
struct if_addr_head addr_list; struct if_addr_head addr_list;
LIST_HEAD(, adj) adj_list; struct global_adj_head adj_tree;
struct in_addr mcast_addr_v4; struct in_addr mcast_addr_v4;
struct in6_addr mcast_addr_v6; struct in6_addr mcast_addr_v6;
TAILQ_HEAD(, pending_conn) pending_conns; TAILQ_HEAD(, pending_conn) pending_conns;
@ -627,23 +642,28 @@ void config_clear(struct ldpd_conf *);
/* ldp_vty_conf.c */ /* ldp_vty_conf.c */
/* NOTE: the parameters' names should be preserved because of codegen */ /* NOTE: the parameters' names should be preserved because of codegen */
struct iface *iface_new_api(struct ldpd_conf *cfg, struct iface *iface_new_api(struct ldpd_conf *conf,
const char *name); const char *name);
void iface_del_api(struct iface *iface); void iface_del_api(struct ldpd_conf *conf,
struct tnbr *tnbr_new_api(struct ldpd_conf *cfg, int af, struct iface *iface);
struct tnbr *tnbr_new_api(struct ldpd_conf *conf, int af,
union ldpd_addr *addr); union ldpd_addr *addr);
void tnbr_del_api(struct tnbr *tnbr); void tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr);
struct nbr_params *nbrp_new_api(struct ldpd_conf *cfg, struct nbr_params *nbrp_new_api(struct ldpd_conf *conf,
struct in_addr lsr_id); struct in_addr lsr_id);
void nbrp_del_api(struct nbr_params *nbrp); void nbrp_del_api(struct ldpd_conf *conf,
struct l2vpn *l2vpn_new_api(struct ldpd_conf *cfg, const char *name); struct nbr_params *nbrp);
void l2vpn_del_api(struct l2vpn *l2vpn); struct l2vpn *l2vpn_new_api(struct ldpd_conf *conf, const char *name);
void l2vpn_del_api(struct ldpd_conf *conf,
struct l2vpn *l2vpn);
struct l2vpn_if *l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn_if *l2vpn_if_new_api(struct ldpd_conf *conf,
struct l2vpn *l2vpn, const char *ifname); struct l2vpn *l2vpn, const char *ifname);
void l2vpn_if_del_api(struct l2vpn_if *lif); void l2vpn_if_del_api(struct l2vpn *l2vpn,
struct l2vpn_if *lif);
struct l2vpn_pw *l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn_pw *l2vpn_pw_new_api(struct ldpd_conf *conf,
struct l2vpn *l2vpn, const char *ifname); struct l2vpn *l2vpn, const char *ifname);
void l2vpn_pw_del_api(struct l2vpn_pw *pw); void l2vpn_pw_del_api(struct l2vpn *l2vpn,
struct l2vpn_pw *pw);
/* socket.c */ /* socket.c */
int ldp_create_socket(int, enum socket_type); int ldp_create_socket(int, enum socket_type);

View File

@ -111,7 +111,7 @@ ldpe(const char *user, const char *group)
ldpd_process = PROC_LDP_ENGINE; ldpd_process = PROC_LDP_ENGINE;
LIST_INIT(&global.addr_list); LIST_INIT(&global.addr_list);
LIST_INIT(&global.adj_list); RB_INIT(&global.adj_tree);
TAILQ_INIT(&global.pending_conns); TAILQ_INIT(&global.pending_conns);
if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1) if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
fatal("inet_pton"); fatal("inet_pton");
@ -209,7 +209,7 @@ ldpe_shutdown(void)
LIST_REMOVE(if_addr, entry); LIST_REMOVE(if_addr, entry);
free(if_addr); free(if_addr);
} }
while ((adj = LIST_FIRST(&global.adj_list)) != NULL) while ((adj = RB_ROOT(&global.adj_tree)) != NULL)
adj_del(adj, S_SHUTDOWN); adj_del(adj, S_SHUTDOWN);
/* clean up */ /* clean up */
@ -414,10 +414,10 @@ ldpe_dispatch_main(struct thread *thread)
fatal(NULL); fatal(NULL);
memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
LIST_INIT(&nconf->iface_list); RB_INIT(&nconf->iface_tree);
LIST_INIT(&nconf->tnbr_list); RB_INIT(&nconf->tnbr_tree);
LIST_INIT(&nconf->nbrp_list); RB_INIT(&nconf->nbrp_tree);
LIST_INIT(&nconf->l2vpn_list); RB_INIT(&nconf->l2vpn_tree);
break; break;
case IMSG_RECONF_IFACE: case IMSG_RECONF_IFACE:
if ((niface = malloc(sizeof(struct iface))) == NULL) if ((niface = malloc(sizeof(struct iface))) == NULL)
@ -425,37 +425,37 @@ ldpe_dispatch_main(struct thread *thread)
memcpy(niface, imsg.data, sizeof(struct iface)); memcpy(niface, imsg.data, sizeof(struct iface));
LIST_INIT(&niface->addr_list); LIST_INIT(&niface->addr_list);
LIST_INIT(&niface->ipv4.adj_list); RB_INIT(&niface->ipv4.adj_tree);
LIST_INIT(&niface->ipv6.adj_list); RB_INIT(&niface->ipv6.adj_tree);
niface->ipv4.iface = niface; niface->ipv4.iface = niface;
niface->ipv6.iface = niface; niface->ipv6.iface = niface;
LIST_INSERT_HEAD(&nconf->iface_list, niface, entry); RB_INSERT(iface_head, &nconf->iface_tree, niface);
break; break;
case IMSG_RECONF_TNBR: case IMSG_RECONF_TNBR:
if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL) if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
fatal(NULL); fatal(NULL);
memcpy(ntnbr, imsg.data, sizeof(struct tnbr)); memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry); RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
break; break;
case IMSG_RECONF_NBRP: case IMSG_RECONF_NBRP:
if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL) if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
fatal(NULL); fatal(NULL);
memcpy(nnbrp, imsg.data, sizeof(struct nbr_params)); memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry); RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp);
break; break;
case IMSG_RECONF_L2VPN: case IMSG_RECONF_L2VPN:
if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL) if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
fatal(NULL); fatal(NULL);
memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn)); memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
LIST_INIT(&nl2vpn->if_list); RB_INIT(&nl2vpn->if_tree);
LIST_INIT(&nl2vpn->pw_list); RB_INIT(&nl2vpn->pw_tree);
LIST_INIT(&nl2vpn->pw_inactive_list); RB_INIT(&nl2vpn->pw_inactive_tree);
LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry); RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
break; break;
case IMSG_RECONF_L2VPN_IF: case IMSG_RECONF_L2VPN_IF:
if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL) if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL)
@ -463,7 +463,7 @@ ldpe_dispatch_main(struct thread *thread)
memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
nlif->l2vpn = nl2vpn; nlif->l2vpn = nl2vpn;
LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry); RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
break; break;
case IMSG_RECONF_L2VPN_PW: case IMSG_RECONF_L2VPN_PW:
if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
@ -471,7 +471,7 @@ ldpe_dispatch_main(struct thread *thread)
memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
npw->l2vpn = nl2vpn; npw->l2vpn = nl2vpn;
LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
break; break;
case IMSG_RECONF_L2VPN_IPW: case IMSG_RECONF_L2VPN_IPW:
if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL)
@ -479,7 +479,7 @@ ldpe_dispatch_main(struct thread *thread)
memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
npw->l2vpn = nl2vpn; npw->l2vpn = nl2vpn;
LIST_INSERT_HEAD(&nl2vpn->pw_inactive_list, npw, entry); RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
break; break;
case IMSG_RECONF_END: case IMSG_RECONF_END:
merge_config(leconf, nconf); merge_config(leconf, nconf);
@ -743,12 +743,12 @@ ldpe_remove_dynamic_tnbrs(int af)
{ {
struct tnbr *tnbr, *safe; struct tnbr *tnbr, *safe;
LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) { RB_FOREACH_SAFE(tnbr, tnbr_head, &leconf->tnbr_tree, safe) {
if (tnbr->af != af) if (tnbr->af != af)
continue; continue;
tnbr->flags &= ~F_TNBR_DYNAMIC; tnbr->flags &= ~F_TNBR_DYNAMIC;
tnbr_check(tnbr); tnbr_check(leconf, tnbr);
} }
} }
@ -772,7 +772,7 @@ ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
struct iface_af *ia; struct iface_af *ia;
struct ctl_iface *ictl; struct ctl_iface *ictl;
LIST_FOREACH(iface, &leconf->iface_list, entry) { RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
if (idx == 0 || idx == iface->ifindex) { if (idx == 0 || idx == iface->ifindex) {
ia = iface_af_get(iface, af); ia = iface_af_get(iface, af);
if (!ia->enabled) if (!ia->enabled)
@ -805,7 +805,7 @@ ldpe_adj_ctl(struct ctl_conn *c)
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0); imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0);
LIST_FOREACH(iface, &leconf->iface_list, entry) { RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
memset(&ictl, 0, sizeof(ictl)); memset(&ictl, 0, sizeof(ictl));
ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE); ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE);
ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE); ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE);
@ -814,25 +814,25 @@ ldpe_adj_ctl(struct ctl_conn *c)
continue; continue;
strlcpy(ictl.name, iface->name, sizeof(ictl.name)); strlcpy(ictl.name, iface->name, sizeof(ictl.name));
if (LIST_EMPTY(&iface->ipv4.adj_list) && if (RB_EMPTY(&iface->ipv4.adj_tree) &&
LIST_EMPTY(&iface->ipv6.adj_list)) RB_EMPTY(&iface->ipv6.adj_tree))
ictl.no_adj = 1; ictl.no_adj = 1;
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0, imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0,
-1, &ictl, sizeof(ictl)); -1, &ictl, sizeof(ictl));
LIST_FOREACH(adj, &iface->ipv4.adj_list, ia_entry) { RB_FOREACH(adj, ia_adj_head, &iface->ipv4.adj_tree) {
actl = adj_to_ctl(adj); actl = adj_to_ctl(adj);
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
0, 0, -1, actl, sizeof(struct ctl_adj)); 0, 0, -1, actl, sizeof(struct ctl_adj));
} }
LIST_FOREACH(adj, &iface->ipv6.adj_list, ia_entry) { RB_FOREACH(adj, ia_adj_head, &iface->ipv6.adj_tree) {
actl = adj_to_ctl(adj); actl = adj_to_ctl(adj);
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ,
0, 0, -1, actl, sizeof(struct ctl_adj)); 0, 0, -1, actl, sizeof(struct ctl_adj));
} }
} }
LIST_FOREACH(tnbr, &leconf->tnbr_list, entry) { RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree) {
memset(&tctl, 0, sizeof(tctl)); memset(&tctl, 0, sizeof(tctl));
tctl.af = tnbr->af; tctl.af = tnbr->af;
tctl.addr = tnbr->addr; tctl.addr = tnbr->addr;
@ -869,7 +869,7 @@ ldpe_nbr_ctl(struct ctl_conn *c)
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
sizeof(struct ctl_nbr)); sizeof(struct ctl_nbr));
LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) { RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) {
actl = adj_to_ctl(adj); actl = adj_to_ctl(adj);
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC, imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC,
0, 0, -1, actl, sizeof(struct ctl_adj)); 0, 0, -1, actl, sizeof(struct ctl_adj));

View File

@ -32,6 +32,9 @@
#define min(x,y) ((x) <= (y) ? (x) : (y)) #define min(x,y) ((x) <= (y) ? (x) : (y))
#define max(x,y) ((x) > (y) ? (x) : (y)) #define max(x,y) ((x) > (y) ? (x) : (y))
/* forward declarations */
TAILQ_HEAD(mapping_head, mapping_entry);
struct hello_source { struct hello_source {
enum hello_type type; enum hello_type type;
struct { struct {
@ -42,9 +45,7 @@ struct hello_source {
}; };
struct adj { struct adj {
LIST_ENTRY(adj) global_entry; RB_ENTRY(adj) global_entry, nbr_entry, ia_entry;
LIST_ENTRY(adj) nbr_entry;
LIST_ENTRY(adj) ia_entry;
struct in_addr lsr_id; struct in_addr lsr_id;
struct nbr *nbr; struct nbr *nbr;
int ds_tlv; int ds_tlv;
@ -53,6 +54,9 @@ struct adj {
uint16_t holdtime; uint16_t holdtime;
union ldpd_addr trans_addr; union ldpd_addr trans_addr;
}; };
RB_PROTOTYPE(global_adj_head, adj, global_entry, adj_compare)
RB_PROTOTYPE(nbr_adj_head, adj, nbr_entry, adj_compare)
RB_PROTOTYPE(ia_adj_head, adj, ia_entry, adj_compare)
struct tcp_conn { struct tcp_conn {
struct nbr *nbr; struct nbr *nbr;
@ -67,7 +71,7 @@ struct tcp_conn {
struct nbr { struct nbr {
RB_ENTRY(nbr) id_tree, addr_tree, pid_tree; RB_ENTRY(nbr) id_tree, addr_tree, pid_tree;
struct tcp_conn *tcp; struct tcp_conn *tcp;
LIST_HEAD(, adj) adj_list; /* adjacencies */ struct nbr_adj_head adj_tree; /* adjacencies */
struct thread *ev_connect; struct thread *ev_connect;
struct thread *keepalive_timer; struct thread *keepalive_timer;
struct thread *keepalive_timeout; struct thread *keepalive_timeout;
@ -225,7 +229,7 @@ void adj_start_itimer(struct adj *);
void adj_stop_itimer(struct adj *); void adj_stop_itimer(struct adj *);
struct tnbr *tnbr_new(int, union ldpd_addr *); struct tnbr *tnbr_new(int, union ldpd_addr *);
struct tnbr *tnbr_find(struct ldpd_conf *, int, union ldpd_addr *); struct tnbr *tnbr_find(struct ldpd_conf *, int, union ldpd_addr *);
struct tnbr *tnbr_check(struct tnbr *); struct tnbr *tnbr_check(struct ldpd_conf *, struct tnbr *);
void tnbr_update(struct tnbr *); void tnbr_update(struct tnbr *);
void tnbr_update_all(int); void tnbr_update_all(int);
uint16_t tnbr_get_hello_holdtime(struct tnbr *); uint16_t tnbr_get_hello_holdtime(struct tnbr *);

View File

@ -39,10 +39,13 @@ static void nbr_start_itimeout(struct nbr *);
static int nbr_idtimer(struct thread *); static int nbr_idtimer(struct thread *);
static int nbr_act_session_operational(struct nbr *); static int nbr_act_session_operational(struct nbr *);
static void nbr_send_labelmappings(struct nbr *); static void nbr_send_labelmappings(struct nbr *);
static __inline int nbr_params_compare(struct nbr_params *,
struct nbr_params *);
RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare) RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare)
RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare) RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare)
RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare) RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
RB_GENERATE(nbrp_head, nbr_params, entry, nbr_params_compare)
struct { struct {
int state; int state;
@ -226,7 +229,7 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr,
if ((nbr = calloc(1, sizeof(*nbr))) == NULL) if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
fatal(__func__); fatal(__func__);
LIST_INIT(&nbr->adj_list); RB_INIT(&nbr->adj_tree);
nbr->state = NBR_STA_PRESENT; nbr->state = NBR_STA_PRESENT;
nbr->peerid = 0; nbr->peerid = 0;
nbr->af = af; nbr->af = af;
@ -241,10 +244,10 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr,
nbr->raddr_scope = scope_id; nbr->raddr_scope = scope_id;
nbr->conf_seqnum = 0; nbr->conf_seqnum = 0;
LIST_FOREACH(adj, &global.adj_list, global_entry) { RB_FOREACH(adj, global_adj_head, &global.adj_tree) {
if (adj->lsr_id.s_addr == nbr->id.s_addr) { if (adj->lsr_id.s_addr == nbr->id.s_addr) {
adj->nbr = nbr; adj->nbr = nbr;
LIST_INSERT_HEAD(&nbr->adj_list, adj, nbr_entry); RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj);
} }
} }
@ -363,7 +366,7 @@ nbr_adj_count(struct nbr *nbr, int af)
struct adj *adj; struct adj *adj;
int total = 0; int total = 0;
LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree)
if (adj_get_af(adj) == af) if (adj_get_af(adj) == af)
total++; total++;
@ -621,7 +624,7 @@ nbr_establish_connection(struct nbr *nbr)
* Send an extra hello to guarantee that the remote peer has formed * Send an extra hello to guarantee that the remote peer has formed
* an adjacency as well. * an adjacency as well.
*/ */
LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree)
send_hello(adj->source.type, adj->source.link.ia, send_hello(adj->source.type, adj->source.link.ia,
adj->source.target); adj->source.target);
@ -752,6 +755,12 @@ nbr_send_labelmappings(struct nbr *nbr)
NULL, 0); NULL, 0);
} }
static __inline int
nbr_params_compare(struct nbr_params *a, struct nbr_params *b)
{
return (ntohl(a->lsr_id.s_addr) - ntohl(b->lsr_id.s_addr));
}
struct nbr_params * struct nbr_params *
nbr_params_new(struct in_addr lsr_id) nbr_params_new(struct in_addr lsr_id)
{ {
@ -769,13 +778,9 @@ nbr_params_new(struct in_addr lsr_id)
struct nbr_params * struct nbr_params *
nbr_params_find(struct ldpd_conf *xconf, struct in_addr lsr_id) nbr_params_find(struct ldpd_conf *xconf, struct in_addr lsr_id)
{ {
struct nbr_params *nbrp; struct nbr_params nbrp;
nbrp.lsr_id = lsr_id;
LIST_FOREACH(nbrp, &xconf->nbrp_list, entry) return (RB_FIND(nbrp_head, &xconf->nbrp_tree, &nbrp));
if (nbrp->lsr_id.s_addr == lsr_id.s_addr)
return (nbrp);
return (NULL);
} }
uint16_t uint16_t

View File

@ -85,6 +85,8 @@ ldp_create_socket(int af, enum socket_type type)
if (ldpd_privs.change(ZPRIVS_RAISE)) if (ldpd_privs.change(ZPRIVS_RAISE))
log_warn("%s: could not raise privs", __func__); log_warn("%s: could not raise privs", __func__);
if (sock_set_reuse(fd, 1) == -1) { if (sock_set_reuse(fd, 1) == -1) {
if (ldpd_privs.change(ZPRIVS_LOWER))
log_warn("%s: could not lower privs", __func__);
close(fd); close(fd);
return (-1); return (-1);
} }

View File

@ -381,7 +381,7 @@ vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id)
u_char group = VRF_BITMAP_GROUP (vrf_id); u_char group = VRF_BITMAP_GROUP (vrf_id);
u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
if (bmap == VRF_BITMAP_NULL) if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN)
return; return;
if (bm->groups[group] == NULL) if (bm->groups[group] == NULL)
@ -399,7 +399,8 @@ vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id)
u_char group = VRF_BITMAP_GROUP (vrf_id); u_char group = VRF_BITMAP_GROUP (vrf_id);
u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL) if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN ||
bm->groups[group] == NULL)
return; return;
UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
@ -413,7 +414,8 @@ vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id)
u_char group = VRF_BITMAP_GROUP (vrf_id); u_char group = VRF_BITMAP_GROUP (vrf_id);
u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL) if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN ||
bm->groups[group] == NULL)
return 0; return 0;
return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],

View File

@ -508,18 +508,6 @@ vty_write (struct vty *vty, const char *buf, size_t nbytes)
buffer_put (vty->obuf, buf, nbytes); buffer_put (vty->obuf, buf, nbytes);
} }
/* Ensure length of input buffer. Is buffer is short, double it. */
static void
vty_ensure (struct vty *vty, int length)
{
if (vty->max <= length)
{
vty->max *= 2;
vty->buf = XREALLOC (MTYPE_VTY, vty->buf, vty->max);
vty->error_buf = XREALLOC (MTYPE_VTY, vty->error_buf, vty->max);
}
}
/* Basic function to insert character into vty. */ /* Basic function to insert character into vty. */
static void static void
vty_self_insert (struct vty *vty, char c) vty_self_insert (struct vty *vty, char c)
@ -527,7 +515,9 @@ vty_self_insert (struct vty *vty, char c)
int i; int i;
int length; int length;
vty_ensure (vty, vty->length + 1); if (vty->length + 1 > VTY_BUFSIZ)
return;
length = vty->length - vty->cp; length = vty->length - vty->cp;
memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length); memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);
vty->buf[vty->cp] = c; vty->buf[vty->cp] = c;
@ -544,26 +534,29 @@ vty_self_insert (struct vty *vty, char c)
static void static void
vty_self_insert_overwrite (struct vty *vty, char c) vty_self_insert_overwrite (struct vty *vty, char c)
{ {
vty_ensure (vty, vty->length + 1); if (vty->cp == vty->length)
{
vty_self_insert (vty, c);
return;
}
vty->buf[vty->cp++] = c; vty->buf[vty->cp++] = c;
if (vty->cp > vty->length)
vty->length++;
if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
return;
vty_write (vty, &c, 1); vty_write (vty, &c, 1);
} }
/* Insert a word into vty interface with overwrite mode. */ /**
* Insert a string into vty->buf at the current cursor position.
*
* If the resultant string would be larger than VTY_BUFSIZ it is
* truncated to fit.
*/
static void static void
vty_insert_word_overwrite (struct vty *vty, char *str) vty_insert_word_overwrite (struct vty *vty, char *str)
{ {
int len = strlen (str); size_t nwrite = MIN ((int) strlen (str), VTY_BUFSIZ - vty->cp);
vty_write (vty, str, len); vty_write (vty, str, nwrite);
strcpy (&vty->buf[vty->cp], str); strncpy (&vty->buf[vty->cp], str, nwrite);
vty->cp += len; vty->cp += nwrite;
vty->length = vty->cp; vty->length = vty->cp;
} }
@ -2148,36 +2141,45 @@ vtysh_read (struct thread *thread)
printf ("line: %.*s\n", nbytes, buf); printf ("line: %.*s\n", nbytes, buf);
#endif /* VTYSH_DEBUG */ #endif /* VTYSH_DEBUG */
for (p = buf; p < buf+nbytes; p++) if (vty->length + nbytes > VTY_BUFSIZ)
{ {
vty_ensure(vty, vty->length+1); /* Clear command line buffer. */
vty->buf[vty->length++] = *p; vty->cp = vty->length = 0;
if (*p == '\0') vty_clear_buf (vty);
vty_out (vty, "%% Command is too long.%s", VTY_NEWLINE);
}
else
{
for (p = buf; p < buf+nbytes; p++)
{ {
/* Pass this line to parser. */ vty->buf[vty->length++] = *p;
ret = vty_execute (vty); if (*p == '\0')
/* Note that vty_execute clears the command buffer and resets {
vty->length to 0. */ /* Pass this line to parser. */
ret = vty_execute (vty);
/* Note that vty_execute clears the command buffer and resets
vty->length to 0. */
/* Return result. */ /* Return result. */
#ifdef VTYSH_DEBUG #ifdef VTYSH_DEBUG
printf ("result: %d\n", ret); printf ("result: %d\n", ret);
printf ("vtysh node: %d\n", vty->node); printf ("vtysh node: %d\n", vty->node);
#endif /* VTYSH_DEBUG */ #endif /* VTYSH_DEBUG */
/* hack for asynchronous "write integrated" /* hack for asynchronous "write integrated"
* - other commands in "buf" will be ditched * - other commands in "buf" will be ditched
* - input during pending config-write is "unsupported" */ * - input during pending config-write is "unsupported" */
if (ret == CMD_SUSPEND) if (ret == CMD_SUSPEND)
break; break;
/* warning: watchfrr hardcodes this result write */ /* warning: watchquagga hardcodes this result write */
header[3] = ret; header[3] = ret;
buffer_put(vty->obuf, header, 4); buffer_put(vty->obuf, header, 4);
if (!vty->t_write && (vtysh_flush(vty) < 0)) if (!vty->t_write && (vtysh_flush(vty) < 0))
/* Try to flush results; exit if a write error occurs. */ /* Try to flush results; exit if a write error occurs. */
return 0; return 0;
}
} }
} }

View File

@ -26,7 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "sockunion.h" #include "sockunion.h"
#include "qobj.h" #include "qobj.h"
#define VTY_BUFSIZ 512 #define VTY_BUFSIZ 4096
#define VTY_MAXHIST 20 #define VTY_MAXHIST 20
/* VTY struct. */ /* VTY struct. */

View File

@ -473,9 +473,28 @@ typedef enum {
#define SAFI_MULTICAST 2 #define SAFI_MULTICAST 2
#define SAFI_MPLS_VPN 3 #define SAFI_MPLS_VPN 3
#define SAFI_RESERVED_4 4 #define SAFI_RESERVED_4 4
#define SAFI_ENCAP 7 /* per IANA */ #define SAFI_ENCAP 5
#define SAFI_RESERVED_5 5 #define SAFI_RESERVED_5 5
#define SAFI_MAX 8 #define SAFI_MAX 6
/*
* The above AFI and SAFI definitions are for internal use. The protocol
* definitions (IANA values) as for example used in BGP protocol packets
* are defined below and these will get mapped to/from the internal values
* in the appropriate places.
* The rationale is that the protocol (IANA) values may be sparse and are
* not optimal for use in data-structure sizing.
* Note: Only useful (i.e., supported) values are defined below.
*/
#define IANA_AFI_RESERVED 0
#define IANA_AFI_IPV4 1
#define IANA_AFI_IPV6 2
#define IANA_SAFI_RESERVED 0
#define IANA_SAFI_UNICAST 1
#define IANA_SAFI_MULTICAST 2
#define IANA_SAFI_ENCAP 7
#define IANA_SAFI_MPLS_VPN 128
/* Default Administrative Distance of each protocol. */ /* Default Administrative Distance of each protocol. */
#define ZEBRA_KERNEL_DISTANCE_DEFAULT 0 #define ZEBRA_KERNEL_DISTANCE_DEFAULT 0
@ -509,4 +528,48 @@ typedef uint32_t route_tag_t;
#define ROUTE_TAG_MAX UINT32_MAX #define ROUTE_TAG_MAX UINT32_MAX
#define ROUTE_TAG_PRI PRIu32 #define ROUTE_TAG_PRI PRIu32
static inline afi_t afi_iana2int (afi_t afi)
{
if (afi == IANA_AFI_IPV4)
return AFI_IP;
if (afi == IANA_AFI_IPV6)
return AFI_IP6;
return AFI_MAX;
}
static inline afi_t afi_int2iana (afi_t afi)
{
if (afi == AFI_IP)
return IANA_AFI_IPV4;
if (afi == AFI_IP6)
return IANA_AFI_IPV6;
return IANA_AFI_RESERVED;
}
static inline safi_t safi_iana2int (safi_t safi)
{
if (safi == IANA_SAFI_UNICAST)
return SAFI_UNICAST;
if (safi == IANA_SAFI_MULTICAST)
return SAFI_MULTICAST;
if (safi == IANA_SAFI_MPLS_VPN)
return SAFI_MPLS_VPN;
if (safi == IANA_SAFI_ENCAP)
return SAFI_ENCAP;
return SAFI_MAX;
}
static inline safi_t safi_int2iana (safi_t safi)
{
if (safi == SAFI_UNICAST)
return IANA_SAFI_UNICAST;
if (safi == SAFI_MULTICAST)
return IANA_SAFI_MULTICAST;
if (safi == SAFI_MPLS_VPN)
return IANA_SAFI_MPLS_VPN;
if (safi == SAFI_ENCAP)
return IANA_SAFI_ENCAP;
return IANA_SAFI_RESERVED;
}
#endif /* _ZEBRA_H */ #endif /* _ZEBRA_H */

View File

@ -0,0 +1,77 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_prog_perl_modules.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_PERL_MODULES([MODULES], [ACTION-IF-TRUE], [ACTION-IF-FALSE])
#
# DESCRIPTION
#
# Checks to see if the given perl modules are available. If true the shell
# commands in ACTION-IF-TRUE are executed. If not the shell commands in
# ACTION-IF-FALSE are run. Note if $PERL is not set (for example by
# calling AC_CHECK_PROG, or AC_PATH_PROG), AC_CHECK_PROG(PERL, perl, perl)
# will be run.
#
# MODULES is a space separated list of module names. To check for a
# minimum version of a module, append the version number to the module
# name, separated by an equals sign.
#
# Example:
#
# AX_PROG_PERL_MODULES( Text::Wrap Net::LDAP=1.0.3, ,
# AC_MSG_WARN(Need some Perl modules)
#
# LICENSE
#
# Copyright (c) 2009 Dean Povey <povey@wedgetail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 7
AU_ALIAS([AC_PROG_PERL_MODULES], [AX_PROG_PERL_MODULES])
AC_DEFUN([AX_PROG_PERL_MODULES],[dnl
m4_define([ax_perl_modules])
m4_foreach([ax_perl_module], m4_split(m4_normalize([$1])),
[
m4_append([ax_perl_modules],
[']m4_bpatsubst(ax_perl_module,=,[ ])[' ])
])
# Make sure we have perl
if test -z "$PERL"; then
AC_CHECK_PROG(PERL,perl,perl)
fi
if test "x$PERL" != x; then
ax_perl_modules_failed=0
for ax_perl_module in ax_perl_modules; do
AC_MSG_CHECKING(for perl module $ax_perl_module)
# Would be nice to log result here, but can't rely on autoconf internals
$PERL -e "use $ax_perl_module; exit" > /dev/null 2>&1
if test $? -ne 0; then
AC_MSG_RESULT(no);
ax_perl_modules_failed=1
else
AC_MSG_RESULT(ok);
fi
done
# Run optional shell commands
if test "$ax_perl_modules_failed" = 0; then
:
$2
else
:
$3
fi
else
AC_MSG_WARN(could not find perl)
fi])dnl

View File

@ -424,12 +424,9 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
else else
{ {
summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
if (route->type == OSPF6_DEST_TYPE_RANGE) summary->path.origin.id =
summary->path.origin.id = route->linkstate_id; ospf6_new_ls_id (summary->path.origin.type,
else summary->path.origin.adv_router, area->lsdb);
summary->path.origin.id =
ospf6_new_ls_id (summary->path.origin.type,
summary->path.origin.adv_router, area->lsdb);
} }
summary = ospf6_route_add (summary, summary_table); summary = ospf6_route_add (summary, summary_table);
} }

View File

@ -472,8 +472,6 @@ DEFUN (area_range,
range->prefix = prefix; range->prefix = prefix;
range->path.area_id = oa->area_id; range->path.area_id = oa->area_id;
range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
range->linkstate_id =
(u_int32_t) htonl(ospf6_new_range_ls_id (oa->range_table));
} }
if (argc > idx_type) if (argc > idx_type)
@ -559,8 +557,6 @@ DEFUN (no_area_range,
/* purge the old aggregated summary LSA */ /* purge the old aggregated summary LSA */
ospf6_abr_originate_summary(range); ospf6_abr_originate_summary(range);
} }
ospf6_release_range_ls_id(oa->range_table,
(u_int32_t) ntohl(range->linkstate_id));
ospf6_route_remove (range, oa->range_table); ospf6_route_remove (range, oa->range_table);
return CMD_SUCCESS; return CMD_SUCCESS;

View File

@ -547,24 +547,6 @@ ospf6_lsdb_show (struct vty *vty, enum ospf_lsdb_show_level level,
} }
} }
/* Decide new Link State ID to originate for the range. */
u_int32_t
ospf6_new_range_ls_id (struct ospf6_route_table *range_table)
{
u_int32_t id;
bf_assign_index(range_table->idspace, id);
return (id);
}
/* Release the LS ID back to the ID pool */
void
ospf6_release_range_ls_id (struct ospf6_route_table *range_table,
u_int32_t id)
{
bf_release_index(range_table->idspace, id);
}
u_int32_t u_int32_t
ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router, ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
struct ospf6_lsdb *lsdb) struct ospf6_lsdb *lsdb)

View File

@ -81,9 +81,6 @@ extern void ospf6_lsdb_show (struct vty *vty,
extern u_int32_t ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router, extern u_int32_t ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
struct ospf6_lsdb *lsdb); struct ospf6_lsdb *lsdb);
extern u_int32_t ospf6_new_range_ls_id (struct ospf6_route_table *range_table);
extern void ospf6_release_range_ls_id (struct ospf6_route_table *range_table,
u_int32_t id);
extern u_int32_t ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, extern u_int32_t ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id,
u_int32_t adv_router, u_int32_t adv_router,
struct ospf6_lsdb *lsdb); struct ospf6_lsdb *lsdb);

View File

@ -682,7 +682,7 @@ ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *on)
"I/F", "State", VNL); "I/F", "State", VNL);
*/ */
vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]%s", vty_out (vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]%s",
router_id, on->priority, deadtime, router_id, on->priority, deadtime,
ospf6_neighbor_state_str[on->state], nstate, duration, ospf6_neighbor_state_str[on->state], nstate, duration,
on->ospf6_if->interface->name, on->ospf6_if->interface->name,
@ -711,7 +711,7 @@ ospf6_neighbor_show_drchoice (struct vty *vty, struct ospf6_neighbor *on)
timersub (&now, &on->last_changed, &res); timersub (&now, &on->last_changed, &res);
timerstring (&res, duration, sizeof (duration)); timerstring (&res, duration, sizeof (duration));
vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]%s", vty_out (vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]%s",
router_id, ospf6_neighbor_state_str[on->state], router_id, ospf6_neighbor_state_str[on->state],
duration, drouter, bdrouter, on->ospf6_if->interface->name, duration, drouter, bdrouter, on->ospf6_if->interface->name,
ospf6_interface_state_str[on->ospf6_if->state], ospf6_interface_state_str[on->ospf6_if->state],
@ -856,11 +856,11 @@ DEFUN (show_ipv6_ospf6_neighbor,
} }
if (showfunc == ospf6_neighbor_show) if (showfunc == ospf6_neighbor_show)
vty_out (vty, "%-15s %3s %11s %6s/%-12s %11s %s[%s]%s", vty_out (vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]%s",
"Neighbor ID", "Pri", "DeadTime", "State", "IfState", "Duration", "Neighbor ID", "Pri", "DeadTime", "State", "IfState", "Duration",
"I/F", "State", VNL); "I/F", "State", VNL);
else if (showfunc == ospf6_neighbor_show_drchoice) else if (showfunc == ospf6_neighbor_show_drchoice)
vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]%s", vty_out (vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]%s",
"RouterID", "State", "Duration", "DR", "BDR", "I/F", "RouterID", "State", "Duration", "DR", "BDR", "I/F",
"State", VNL); "State", VNL);

View File

@ -1266,10 +1266,15 @@ DEFUN (no_ospf_area_vlink,
/* message-digest-key */ /* message-digest-key */
/* Delete one key */ /* Delete one key */
i++; i++;
vl_config.crypto_key_id = strtol (argv[i]->arg, NULL, 10); if (i < argc)
if (vl_config.crypto_key_id < 0) {
vl_config.crypto_key_id = strtol (argv[i]->arg, NULL, 10);
if (vl_config.crypto_key_id < 0)
return CMD_WARNING;
vl_config.md5_key = NULL;
}
else
return CMD_WARNING; return CMD_WARNING;
vl_config.md5_key = NULL;
break; break;
} }

View File

@ -124,21 +124,21 @@ static struct test_segment mp_segments[] =
"MP IP6/MPLS-labeled VPN", "MP IP6/MPLS-labeled VPN",
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 }, { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 },
6, SHOULD_PARSE, 0, 6, SHOULD_PARSE, 0,
1, AFI_IP6, SAFI_MPLS_LABELED_VPN, VALID_AFI, 1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
/* 7 */ /* 7 */
{ "MP5", { "MP5",
"MP IP6/MPLS-VPN", "MP IP6/MPLS-VPN",
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 }, { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 },
6, SHOULD_PARSE, 0, 6, SHOULD_PARSE, 0,
1, AFI_IP6, SAFI_MPLS_VPN, VALID_AFI, 1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
/* 8 */ /* 8 */
{ "MP6", { "MP6",
"MP IP4/MPLS-laveled VPN", "MP IP4/MPLS-laveled VPN",
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 }, { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 },
6, SHOULD_PARSE, 0, 6, SHOULD_PARSE, 0,
1, AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, 1, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
/* 10 */ /* 10 */
{ "MP8", { "MP8",
@ -585,22 +585,26 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
if (!ret && t->validate_afi) if (!ret && t->validate_afi)
{ {
safi_t safi = t->safi; afi_t afi;
safi_t safi;
if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid) /* Convert AFI, SAFI to internal values, check. */
failed++; if (bgp_map_afi_safi_iana2int (t->afi, t->safi, &afi, &safi))
{
printf ("MP: %u/%u (%u): recv %u, nego %u\n", if (t->afi_valid == VALID_AFI)
t->afi, t->safi, safi, failed++;
peer->afc_recv[t->afi][safi], }
peer->afc_nego[t->afi][safi]); printf ("MP: %u(%u)/%u(%u): recv %u, nego %u\n",
t->afi, afi, t->safi, safi,
peer->afc_recv[afi][safi],
peer->afc_nego[afi][safi]);
if (t->afi_valid == VALID_AFI) if (t->afi_valid == VALID_AFI)
{ {
if (!peer->afc_recv[t->afi][safi]) if (!peer->afc_recv[afi][safi])
failed++; failed++;
if (!peer->afc_nego[t->afi][safi]) if (!peer->afc_nego[afi][safi])
failed++; failed++;
} }
} }

View File

@ -317,7 +317,7 @@ static struct test_segment {
{ "IPv4-VPNv4", { "IPv4-VPNv4",
"IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs", "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* nexthop bytes */ 12, /* nexthop bytes */ 12,
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
0, 0, 0, 0, 0, 0, 0, 0,
@ -338,12 +338,12 @@ static struct test_segment {
}, },
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
SHOULD_PARSE, SHOULD_PARSE,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
{ "IPv4-VPNv4-bogus-plen", { "IPv4-VPNv4-bogus-plen",
"IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len", "IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* nexthop bytes */ 12, /* nexthop bytes */ 12,
/* RD */ 0, 0, 1, 2, /* RD */ 0, 0, 1, 2,
0, 0xff, 3, 4, 0, 0xff, 3, 4,
@ -355,12 +355,12 @@ static struct test_segment {
}, },
(3 + 1 + 3*4 + 1 + 3 + 4 + 1), (3 + 1 + 3*4 + 1 + 3 + 4 + 1),
SHOULD_ERR, SHOULD_ERR,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
{ "IPv4-VPNv4-plen1-short", { "IPv4-VPNv4-plen1-short",
"IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short", "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* nexthop bytes */ 12, /* nexthop bytes */ 12,
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
0, 0, 0, 0, 0, 0, 0, 0,
@ -381,12 +381,12 @@ static struct test_segment {
}, },
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
SHOULD_ERR, SHOULD_ERR,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
{ "IPv4-VPNv4-plen1-long", { "IPv4-VPNv4-plen1-long",
"IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long", "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* nexthop bytes */ 12, /* nexthop bytes */ 12,
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
0, 0, 0, 0, 0, 0, 0, 0,
@ -407,12 +407,12 @@ static struct test_segment {
}, },
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
SHOULD_ERR, SHOULD_ERR,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
{ "IPv4-VPNv4-plenn-long", { "IPv4-VPNv4-plenn-long",
"IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long", "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* nexthop bytes */ 12, /* nexthop bytes */ 12,
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
0, 0, 0, 0, 0, 0, 0, 0,
@ -434,12 +434,12 @@ static struct test_segment {
}, },
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1), (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1),
SHOULD_ERR, SHOULD_ERR,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
{ "IPv4-VPNv4-plenn-short", { "IPv4-VPNv4-plenn-short",
"IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short", "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* nexthop bytes */ 12, /* nexthop bytes */ 12,
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
0, 0, 0, 0, 0, 0, 0, 0,
@ -460,12 +460,12 @@ static struct test_segment {
}, },
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
SHOULD_ERR, SHOULD_ERR,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
{ "IPv4-VPNv4-bogus-rd-type", { "IPv4-VPNv4-bogus-rd-type",
"IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)", "IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* nexthop bytes */ 12, /* nexthop bytes */ 12,
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
0, 0, 0, 0, 0, 0, 0, 0,
@ -486,12 +486,12 @@ static struct test_segment {
}, },
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
SHOULD_PARSE, SHOULD_PARSE,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
{ "IPv4-VPNv4-0-nlri", { "IPv4-VPNv4-0-nlri",
"IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus", "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* nexthop bytes */ 12, /* nexthop bytes */ 12,
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
0, 0, 0, 0, 0, 0, 0, 0,
@ -513,7 +513,7 @@ static struct test_segment {
}, },
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1), (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1),
SHOULD_ERR, SHOULD_ERR,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
/* From bug #385 */ /* From bug #385 */
@ -625,7 +625,7 @@ static struct test_segment mp_unreach_segments [] =
{ "IPv4-unreach-VPNv4", { "IPv4-unreach-VPNv4",
"IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs", "IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs",
{ {
/* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN,
/* NLRI tuples */ 88 + 16, /* NLRI tuples */ 88 + 16,
0, 1, 2, /* tag */ 0, 1, 2, /* tag */
/* rd, 8 octets */ /* rd, 8 octets */
@ -641,7 +641,7 @@ static struct test_segment mp_unreach_segments [] =
}, },
(3 + (1+3+8+2) + (1+3+8+3)), (3 + (1+3+8+2) + (1+3+8+3)),
SHOULD_PARSE, SHOULD_PARSE,
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
}, },
{ NULL, NULL, {0}, 0, 0} { NULL, NULL, {0}, 0, 0}
}; };
@ -656,19 +656,6 @@ handle_result (struct peer *peer, struct test_segment *t,
{ {
int oldfailed = failed; int oldfailed = failed;
if (!parse_ret)
{
safi_t safi = t->safi;
if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid)
failed++;
printf ("MP: %u/%u (%u): recv %u, nego %u\n",
t->afi, t->safi, safi,
peer->afc_recv[t->afi][safi],
peer->afc_nego[t->afi][safi]);
}
printf ("mp attr parsed?: %s\n", parse_ret ? "no" : "yes"); printf ("mp attr parsed?: %s\n", parse_ret ? "no" : "yes");
if (!parse_ret) if (!parse_ret)
printf ("nrli parsed?: %s\n", nlri_ret ? "no" : "yes"); printf ("nrli parsed?: %s\n", nlri_ret ? "no" : "yes");
@ -720,9 +707,20 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
parse_ret = bgp_mp_reach_parse (&attr_args, &nlri); parse_ret = bgp_mp_reach_parse (&attr_args, &nlri);
else else
parse_ret = bgp_mp_unreach_parse (&attr_args, &nlri); parse_ret = bgp_mp_unreach_parse (&attr_args, &nlri);
if (!parse_ret)
{
afi_t pkt_afi;
safi_t pkt_safi;
if (parse_ret == 0 && t->afi_valid == VALID_AFI) /* Convert AFI, SAFI to internal values, check. */
assert (nlri.afi == t->afi && nlri.safi == t->safi); if (bgp_map_afi_safi_int2iana (nlri.afi, nlri.safi, &pkt_afi, &pkt_safi))
assert (0);
printf ("MP: %u(%u)/%u(%u): recv %u, nego %u\n",
nlri.afi , pkt_afi, nlri.safi, pkt_safi,
peer->afc_recv[nlri.afi][nlri.safi],
peer->afc_nego[nlri.afi][nlri.safi]);
}
if (!parse_ret) if (!parse_ret)
{ {
@ -731,7 +729,7 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
else else
nlri_ret = bgp_nlri_parse (peer, NULL, &nlri); nlri_ret = bgp_nlri_parse (peer, NULL, &nlri);
} }
zlog_err("xxxxxxxxxxxxxxxx nlri ret %u", nlri_ret);
handle_result (peer, t, parse_ret, nlri_ret); handle_result (peer, t, parse_ret, nlri_ret);
} }

View File

@ -3,7 +3,7 @@ set testprefix "aspathtest "
set aborted 0 set aborted 0
set color 1 set color 1
spawn "./aspathtest" spawn sh -c "exec ./aspathtest 2>/dev/null"
# proc onetest { test_name note start } { # proc onetest { test_name note start } {
# proc headerline { line } { # proc headerline { line } {

View File

@ -3,7 +3,7 @@ set testprefix "ecommtest "
set aborted 0 set aborted 0
set color 0 set color 0
spawn "./ecommtest" spawn sh -c "exec ./ecommtest 2>/dev/null"
# proc simpletest { start } { # proc simpletest { start } {

View File

@ -3,7 +3,7 @@ set testprefix "testbgpcap "
set aborted 0 set aborted 0
set color 1 set color 1
spawn "./testbgpcap" spawn sh -c "exec ./testbgpcap 2>/dev/null"
# proc simpletest { start } { # proc simpletest { start } {

View File

@ -3,7 +3,7 @@ set testprefix "testbgpmpath "
set aborted 0 set aborted 0
set color 1 set color 1
spawn "./testbgpmpath" spawn sh -c "exec ./testbgpmpath 2>/dev/null"
# proc simpletest { start } { # proc simpletest { start } {

View File

@ -3,7 +3,7 @@ set testprefix "testbgpmpattr "
set aborted 0 set aborted 0
set color 1 set color 1
spawn "./testbgpmpattr" spawn sh -c "exec ./testbgpmpattr 2>/dev/null"
# proc simpletest { start } { # proc simpletest { start } {

View File

@ -2,7 +2,7 @@ set timeout 10
set testprefix "tabletest " set testprefix "tabletest "
set aborted 0 set aborted 0
spawn "./tabletest" spawn sh -c "exec ./tabletest 2>/dev/null"
for {set i 0} {$i < 6} {incr i 1} { onesimple "cmp $i" "Verifying cmp"; } for {set i 0} {$i < 6} {incr i 1} { onesimple "cmp $i" "Verifying cmp"; }
for {set i 0} {$i < 11} {incr i 1} { onesimple "succ $i" "Verifying successor"; } for {set i 0} {$i < 11} {incr i 1} { onesimple "succ $i" "Verifying successor"; }

View File

@ -2,6 +2,6 @@ set timeout 10
set testprefix "test-timer-correctness" set testprefix "test-timer-correctness"
set aborted 0 set aborted 0
spawn "./test-timer-correctness" spawn sh -c "exec ./test-timer-correctness 2>/dev/null"
onesimple "" "Expected output and actual output match." onesimple "" "Expected output and actual output match."

View File

@ -2,7 +2,7 @@ set timeout 10
set testprefix "testnexthopiter " set testprefix "testnexthopiter "
set aborted 0 set aborted 0
spawn "./testnexthopiter" spawn sh -c "exec ./testnexthopiter 2>/dev/null"
onesimple "simple" "Simple test passed." onesimple "simple" "Simple test passed."
onesimple "prng" "PRNG test passed." onesimple "prng" "PRNG test passed."

View File

@ -1,5 +1,5 @@
set timeout 10 set timeout 10
spawn "./teststream" spawn sh -c "exec ./teststream 2>/dev/null"
expect { expect {
"endp: 15, readable: 15, writeable: 1009" { } "endp: 15, readable: 15, writeable: 1009" { }

View File

@ -141,6 +141,8 @@ sub generate_arguments {
# argument is the name of the node # argument is the name of the node
if ($node{'input'} or $node{'type'} eq "select") { if ($node{'input'} or $node{'type'} eq "select") {
$arg_value = "argv[" . $argc . "]->arg"; $arg_value = "argv[" . $argc . "]->arg";
} elsif ($node{'optional'}) {
$arg_value = "(argc > " . $argc . " ? argv[" . $argc. "]->arg : NULL)";
} else { } else {
$arg_value = '"' . $node{'name'} . '"'; $arg_value = '"' . $node{'name'} . '"';
} }
@ -196,7 +198,11 @@ sub generate_code {
$helpstr .= $::options{$options_name}{'help'}; $helpstr .= $::options{$options_name}{'help'};
} else { } else {
$funcname .= $node{'name'} . " "; $funcname .= $node{'name'} . " ";
$cmdstr .= $node{'name'} . " "; if ($node{'optional'}) {
$cmdstr .= "[" . $node{'name'} . "] ";
} else {
$cmdstr .= $node{'name'} . " ";
}
$helpstr .= "\n \"" . $node{'help'} . "\\n\""; $helpstr .= "\n \"" . $node{'help'} . "\\n\"";
} }
@ -279,6 +285,7 @@ sub parse_tree {
$node{'help'} = $xml_node->findvalue('./@help'); $node{'help'} = $xml_node->findvalue('./@help');
$node{'function'} = $xml_node->findvalue('./@function'); $node{'function'} = $xml_node->findvalue('./@function');
$node{'ifdef'} = $xml_node->findvalue('./@ifdef'); $node{'ifdef'} = $xml_node->findvalue('./@ifdef');
$node{'optional'} = $xml_node->findvalue('./@optional');
# push node to stack # push node to stack
push (@nodes, \%node); push (@nodes, \%node);

File diff suppressed because it is too large Load Diff

View File

@ -26,4 +26,4 @@ extern void watchfrr_vty_init(void);
extern pid_t integrated_write_pid; extern pid_t integrated_write_pid;
extern void integrated_write_sigchld(int status); extern void integrated_write_sigchld(int status);
#endif /* FRR_WATCHFRR_H */ #endif /* FRR_WATCHFRR_H */

View File

@ -31,18 +31,18 @@
pid_t integrated_write_pid; pid_t integrated_write_pid;
static int integrated_result_fd; static int integrated_result_fd;
DEFUN (config_write_integrated, DEFUN(config_write_integrated,
config_write_integrated_cmd, config_write_integrated_cmd,
"write integrated", "write integrated",
"Write running configuration to memory, network, or terminal\n" "Write running configuration to memory, network, or terminal\n"
"Write integrated all-daemon Frr.conf file\n") "Write integrated all-daemon Frr.conf file\n")
{ {
pid_t child; pid_t child;
sigset_t oldmask, sigmask; sigset_t oldmask, sigmask;
if (integrated_write_pid != -1) { if (integrated_write_pid != -1) {
vty_out(vty, "%% configuration write already in progress.%s", vty_out(vty, "%% configuration write already in progress.%s",
VTY_NEWLINE); VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }
@ -61,20 +61,20 @@ DEFUN (config_write_integrated,
child = fork(); child = fork();
if (child == -1) { if (child == -1) {
vty_out(vty, "%% configuration write fork() failed: %s.%s", vty_out(vty, "%% configuration write fork() failed: %s.%s",
safe_strerror(errno), VTY_NEWLINE); safe_strerror(errno), VTY_NEWLINE);
sigprocmask(SIG_SETMASK, &oldmask, NULL); sigprocmask(SIG_SETMASK, &oldmask, NULL);
return CMD_WARNING; return CMD_WARNING;
} }
if (child != 0) { if (child != 0) {
/* note: the VTY won't write a command return value to vtysh; the /* note: the VTY won't write a command return value to vtysh; the
* session temporarily enters an intentional "hang" state. This is * session temporarily enters an intentional "hang" state. This is
* to make sure latency in vtysh doing the config write (several * to make sure latency in vtysh doing the config write (several
* seconds is not rare to see) does not interfere with watchfrr's * seconds is not rare to see) does not interfere with watchfrr's
* supervisor job. * supervisor job.
* *
* The fd is duplicated here so we don't need to hold a vty pointer * The fd is duplicated here so we don't need to hold a vty pointer
* (which could become invalid in the meantime). * (which could become invalid in the meantime).
*/ */
integrated_write_pid = child; integrated_write_pid = child;
integrated_result_fd = dup(vty->wfd); integrated_result_fd = dup(vty->wfd);
sigprocmask(SIG_SETMASK, &oldmask, NULL); sigprocmask(SIG_SETMASK, &oldmask, NULL);
@ -93,7 +93,7 @@ DEFUN (config_write_integrated,
/* unbuffered write; we just messed with stdout... */ /* unbuffered write; we just messed with stdout... */
char msg[512]; char msg[512];
snprintf(msg, sizeof(msg), "error executing %s: %s\n", snprintf(msg, sizeof(msg), "error executing %s: %s\n",
VTYSH_BIN_PATH, safe_strerror(errno)); VTYSH_BIN_PATH, safe_strerror(errno));
write(1, msg, strlen(msg)); write(1, msg, strlen(msg));
exit(1); exit(1);
} }
@ -104,11 +104,11 @@ void integrated_write_sigchld(int status)
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
zlog_info("configuration write completed with exit code %d", zlog_info("configuration write completed with exit code %d",
WEXITSTATUS(status)); WEXITSTATUS(status));
reply[3] = WEXITSTATUS(status); reply[3] = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) { } else if (WIFSIGNALED(status)) {
zlog_warn("configuration write terminated by signal %d", zlog_warn("configuration write terminated by signal %d",
WTERMSIG(status)); WTERMSIG(status));
} else { } else {
zlog_warn("configuration write terminated"); zlog_warn("configuration write terminated");
} }

View File

@ -104,7 +104,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd,
/* tag */ /* tag */
if (tag_str) if (tag_str)
tag = atol(tag_str); VTY_GET_INTEGER_RANGE("tag", tag, tag_str, 0, 4294967295);
/* VRF id */ /* VRF id */
zvrf = zebra_vrf_lookup_by_name (vrf_id_str); zvrf = zebra_vrf_lookup_by_name (vrf_id_str);
@ -1340,12 +1340,12 @@ DEFUN (show_ip_route_tag,
if (strmatch(argv[idx_vrf]->text, "vrf")) if (strmatch(argv[idx_vrf]->text, "vrf"))
{ {
VRF_GET_ID (vrf_id, argv[idx_name]->arg); VRF_GET_ID (vrf_id, argv[idx_name]->arg);
tag = atol(argv[idx_tag]->arg); VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_tag]->arg, 0, 4294967295);
} }
else else
{ {
idx_tag -= 2; idx_tag -= 2;
tag = atol(argv[idx_tag]->arg); VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_tag]->arg, 0, 4294967295);
} }
table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id);
@ -1918,7 +1918,7 @@ DEFUN (show_ip_route_vrf_all_tag,
route_tag_t tag = 0; route_tag_t tag = 0;
if (argv[idx_number]->arg) if (argv[idx_number]->arg)
tag = atol(argv[idx_number]->arg); VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_number]->arg, 0, 4294967295);
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
{ {
@ -2356,7 +2356,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str,
/* tag */ /* tag */
if (tag_str) if (tag_str)
tag = atol(tag_str); VTY_GET_INTEGER_RANGE("tag", tag, tag_str, 0, 4294967295);
/* When gateway is valid IPv6 addrees, then gate is treated as /* When gateway is valid IPv6 addrees, then gate is treated as
nexthop address other case gate is treated as interface name. */ nexthop address other case gate is treated as interface name. */
@ -2866,12 +2866,12 @@ DEFUN (show_ipv6_route_tag,
if (strmatch(argv[idx_vrf]->text, "vrf")) if (strmatch(argv[idx_vrf]->text, "vrf"))
{ {
VRF_GET_ID (vrf_id, argv[idx_name]->arg); VRF_GET_ID (vrf_id, argv[idx_name]->arg);
tag = atol(argv[idx_tag]->arg); VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_tag]->arg, 0, 4294967295);
} }
else else
{ {
idx_tag -= 2; idx_tag -= 2;
tag = atol(argv[idx_tag]->arg); VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_tag]->arg, 0, 4294967295);
} }
table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id);
@ -3252,7 +3252,7 @@ DEFUN (show_ipv6_route_vrf_all_tag,
route_tag_t tag = 0; route_tag_t tag = 0;
if (argv[idx_number]->arg) if (argv[idx_number]->arg)
tag = atol(argv[idx_number]->arg); VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_number]->arg, 0, 4294967295);
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
{ {