mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-29 20:04:11 +00:00
Merge branch 'master' into cleanup
This commit is contained in:
commit
9aa7f43f7e
1
.gitignore
vendored
1
.gitignore
vendored
@ -41,6 +41,7 @@ build
|
||||
m4/*.m4
|
||||
!m4/ax_sys_weak_alias.m4
|
||||
!m4/ax_compare_version.m4
|
||||
!m4/ax_prog_perl_modules.m4
|
||||
debian/autoreconf.after
|
||||
debian/autoreconf.before
|
||||
debian/files
|
||||
|
6
README
6
README
@ -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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
@ -1849,8 +1849,8 @@ int
|
||||
bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
|
||||
struct bgp_nlri *mp_update)
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t pkt_afi, afi;
|
||||
safi_t pkt_safi, safi;
|
||||
bgp_size_t nlri_len;
|
||||
size_t start;
|
||||
struct stream *s;
|
||||
@ -1874,8 +1874,20 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
|
||||
}
|
||||
|
||||
/* Load AFI, SAFI. */
|
||||
afi = stream_getw (s);
|
||||
safi = stream_getc (s);
|
||||
pkt_afi = stream_getw (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. */
|
||||
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 stream *s;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t pkt_afi, afi;
|
||||
safi_t pkt_safi, safi;
|
||||
u_int16_t withdraw_len;
|
||||
struct peer *const peer = args->peer;
|
||||
struct attr *const attr = args->attr;
|
||||
@ -2001,9 +2013,21 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
|
||||
if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE))
|
||||
return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
|
||||
|
||||
afi = stream_getw (s);
|
||||
safi = stream_getc (s);
|
||||
|
||||
pkt_afi = stream_getw (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;
|
||||
|
||||
mp_withdraw->afi = afi;
|
||||
@ -2624,6 +2648,8 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
|
||||
struct attr *attr)
|
||||
{
|
||||
size_t sizep;
|
||||
afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
|
||||
/* Set extended bit always to encode the attribute length as 2 bytes */
|
||||
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);
|
||||
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 */
|
||||
switch (nh_afi)
|
||||
@ -3249,6 +3279,8 @@ size_t
|
||||
bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
|
||||
{
|
||||
unsigned long attrlen_pnt;
|
||||
afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
|
||||
/* Set extended bit always to encode the attribute length as 2 bytes */
|
||||
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);
|
||||
stream_putw (s, 0); /* Length of this attribute. */
|
||||
|
||||
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);
|
||||
stream_putc (s, pkt_safi);
|
||||
|
||||
return attrlen_pnt;
|
||||
}
|
||||
|
||||
|
271
bgpd/bgp_open.c
271
bgpd/bgp_open.c
@ -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)
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
|
||||
bgp_map_afi_safi_iana2int (ntohs(mpc.afi), mpc.safi, &afi, &safi);
|
||||
if (use_json)
|
||||
{
|
||||
switch (ntohs (mpc.afi))
|
||||
switch (afi)
|
||||
{
|
||||
case AFI_IP:
|
||||
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));
|
||||
break;
|
||||
}
|
||||
switch (mpc.safi)
|
||||
switch (safi)
|
||||
{
|
||||
case SAFI_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:
|
||||
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast");
|
||||
break;
|
||||
case SAFI_MPLS_LABELED_VPN:
|
||||
case SAFI_MPLS_VPN:
|
||||
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN");
|
||||
break;
|
||||
case SAFI_ENCAP:
|
||||
@ -115,7 +119,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
|
||||
else
|
||||
{
|
||||
vty_out (vty, " Capability error for: Multi protocol ");
|
||||
switch (ntohs (mpc.afi))
|
||||
switch (afi)
|
||||
{
|
||||
case AFI_IP:
|
||||
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));
|
||||
break;
|
||||
}
|
||||
switch (mpc.safi)
|
||||
switch (safi)
|
||||
{
|
||||
case 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:
|
||||
vty_out (vty, "SAFI Multicast");
|
||||
break;
|
||||
case SAFI_MPLS_LABELED_VPN:
|
||||
case SAFI_MPLS_VPN:
|
||||
vty_out (vty, "SAFI MPLS-labeled VPN");
|
||||
break;
|
||||
case SAFI_ENCAP:
|
||||
@ -178,35 +182,6 @@ bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
|
||||
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. */
|
||||
static int
|
||||
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",
|
||||
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;
|
||||
|
||||
/* 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 capability_orf_entry entry;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t pkt_afi, afi;
|
||||
safi_t pkt_safi, safi;
|
||||
u_char type;
|
||||
u_char mode;
|
||||
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 */
|
||||
bgp_capability_mp_data (s, &entry.mpc);
|
||||
entry.num = stream_getc (s);
|
||||
afi = entry.mpc.afi;
|
||||
safi = entry.mpc.safi;
|
||||
pkt_afi = entry.mpc.afi;
|
||||
pkt_safi = entry.mpc.safi;
|
||||
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
|
||||
peer->host, entry.mpc.afi, entry.mpc.safi);
|
||||
|
||||
/* Check AFI and SAFI. */
|
||||
if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
|
||||
/* Convert AFI, SAFI to internal values, check. */
|
||||
if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
|
||||
{
|
||||
zlog_info ("%s Addr-family %d/%d not supported."
|
||||
" Ignoring the ORF capability",
|
||||
peer->host, entry.mpc.afi, entry.mpc.safi);
|
||||
peer->host, pkt_afi, pkt_safi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry.mpc.afi = afi;
|
||||
entry.mpc.safi = safi;
|
||||
|
||||
/* validate number field */
|
||||
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:
|
||||
break;
|
||||
default:
|
||||
bgp_capability_orf_not_support (peer, afi, safi, type, mode);
|
||||
bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
|
||||
continue;
|
||||
}
|
||||
/* 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:
|
||||
break;
|
||||
default:
|
||||
bgp_capability_orf_not_support (peer, afi, safi, type, mode);
|
||||
bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
@ -344,12 +323,12 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
|
||||
case ORF_TYPE_PREFIX_OLD:
|
||||
break;
|
||||
default:
|
||||
bgp_capability_orf_not_support (peer, afi, safi, type, mode);
|
||||
bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bgp_capability_orf_not_support (peer, afi, safi, type, mode);
|
||||
bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -358,7 +337,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
|
||||
|| (afi == AFI_IP && safi == SAFI_MULTICAST)
|
||||
|| (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;
|
||||
}
|
||||
|
||||
@ -367,7 +346,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
|
||||
" as %s for afi/safi: %d/%d",
|
||||
peer->host, LOOKUP (orf_type_str, type),
|
||||
LOOKUP (orf_mode_str, mode),
|
||||
entry.mpc.afi, safi);
|
||||
pkt_afi, pkt_safi);
|
||||
|
||||
if (hdr->code == CAPABILITY_CODE_ORF)
|
||||
{
|
||||
@ -381,7 +360,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
|
||||
}
|
||||
else
|
||||
{
|
||||
bgp_capability_orf_not_support (peer, afi, safi, type, mode);
|
||||
bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -437,23 +416,26 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
|
||||
|
||||
while (stream_get_getp (s) + 4 <= end)
|
||||
{
|
||||
afi_t afi = stream_getw (s);
|
||||
safi_t safi = stream_getc (s);
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t pkt_afi = stream_getw (s);
|
||||
safi_t pkt_safi = 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))
|
||||
zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
|
||||
" 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])
|
||||
{
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
|
||||
" Ignore the Graceful Restart capability",
|
||||
peer->host, afi, safi);
|
||||
peer->host, pkt_afi, pkt_safi);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -512,22 +494,25 @@ bgp_capability_addpath (struct peer *peer, struct capability_header *hdr)
|
||||
|
||||
while (stream_get_getp (s) + 4 <= end)
|
||||
{
|
||||
afi_t afi = stream_getw (s);
|
||||
safi_t safi = stream_getc (s);
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t pkt_afi = stream_getw (s);
|
||||
safi_t pkt_safi = stream_getc (s);
|
||||
u_char send_receive = stream_getc (s);
|
||||
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
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_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))
|
||||
zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
|
||||
" Ignore the Addpath Attribute for this AFI/SAFI",
|
||||
peer->host, afi, safi);
|
||||
peer->host, pkt_afi, pkt_safi);
|
||||
continue;
|
||||
}
|
||||
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))
|
||||
zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
|
||||
" Ignore the AddPath capability for this AFI/SAFI",
|
||||
peer->host, afi, safi);
|
||||
peer->host, pkt_afi, pkt_safi);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -565,20 +550,21 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr)
|
||||
|
||||
while (stream_get_getp (s) + 6 <= end)
|
||||
{
|
||||
afi_t afi = stream_getw (s);
|
||||
safi_t safi = stream_getw (s);
|
||||
afi_t nh_afi = stream_getw (s);
|
||||
afi_t afi, pkt_afi = stream_getw (s);
|
||||
safi_t safi, pkt_safi = stream_getw (s);
|
||||
afi_t nh_afi, pkt_nh_afi = stream_getw (s);
|
||||
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
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))
|
||||
zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
|
||||
" Ignore the ENHE Attribute for this AFI/SAFI",
|
||||
peer->host, afi, safi);
|
||||
peer->host, pkt_afi, pkt_safi);
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u "
|
||||
"in Extended Next-hop capability, ignoring",
|
||||
peer->host, afi, safi, nh_afi);
|
||||
peer->host, pkt_afi, pkt_safi, pkt_nh_afi);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1174,9 +1162,11 @@ bgp_open_capability_orf (struct stream *s, struct peer *peer,
|
||||
unsigned long orfp;
|
||||
unsigned long numberp;
|
||||
int number_of_orfs = 0;
|
||||
afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
|
||||
if (safi == SAFI_MPLS_VPN)
|
||||
safi = SAFI_MPLS_LABELED_VPN;
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
|
||||
|
||||
stream_putc (s, BGP_OPEN_OPT_CAP);
|
||||
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 */
|
||||
orfp = stream_get_endp (s); /* Set ORF Len Pointer */
|
||||
stream_putc (s, 0); /* ORF Length */
|
||||
stream_putw (s, afi);
|
||||
stream_putw (s, pkt_afi);
|
||||
stream_putc (s, 0);
|
||||
stream_putc (s, safi);
|
||||
stream_putc (s, pkt_safi);
|
||||
numberp = stream_get_endp (s); /* Set Number Pointer */
|
||||
stream_putc (s, 0); /* Number of ORFs */
|
||||
|
||||
@ -1235,8 +1225,8 @@ bgp_open_capability (struct stream *s, struct peer *peer)
|
||||
{
|
||||
u_char len;
|
||||
unsigned long cp, capp, rcapp;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t afi, pkt_afi;
|
||||
safi_t safi, pkt_safi;
|
||||
as_t local_as;
|
||||
u_int32_t restart_time;
|
||||
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))
|
||||
return;
|
||||
|
||||
/* IPv4 unicast. */
|
||||
if (peer->afc[AFI_IP][SAFI_UNICAST])
|
||||
{
|
||||
peer->afc_adv[AFI_IP][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_IP);
|
||||
stream_putc (s, 0);
|
||||
stream_putc (s, SAFI_UNICAST);
|
||||
}
|
||||
/* IPv4 multicast. */
|
||||
if (peer->afc[AFI_IP][SAFI_MULTICAST])
|
||||
{
|
||||
peer->afc_adv[AFI_IP][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_IP);
|
||||
stream_putc (s, 0);
|
||||
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 */
|
||||
/* MP capability for configured AFI, SAFI */
|
||||
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
|
||||
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
|
||||
{
|
||||
if (peer->afc[afi][safi])
|
||||
{
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
|
||||
|
||||
peer->afc_adv[afi][safi] = 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, pkt_afi);
|
||||
stream_putc (s, 0);
|
||||
stream_putc (s, pkt_safi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Extended nexthop capability - currently supporting RFC-5549 for
|
||||
* Link-Local peering only
|
||||
*/
|
||||
if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) &&
|
||||
peer->su.sa.sa_family == AF_INET6 &&
|
||||
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))
|
||||
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. */
|
||||
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++)
|
||||
if (peer->afc[afi][safi])
|
||||
{
|
||||
stream_putw (s, afi);
|
||||
stream_putc (s, safi);
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
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)
|
||||
{
|
||||
@ -1533,8 +1452,10 @@ bgp_open_capability (struct stream *s, struct peer *peer)
|
||||
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
|
||||
if (peer->afc[afi][safi])
|
||||
{
|
||||
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);
|
||||
stream_putc (s, pkt_safi);
|
||||
if (bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD))
|
||||
stream_putc (s, RESTART_F_BIT);
|
||||
else
|
||||
|
@ -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_capability_vty_out (struct vty *, struct peer *, u_char, json_object *);
|
||||
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 */
|
||||
|
@ -147,6 +147,8 @@ static struct stream *
|
||||
bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
|
||||
{
|
||||
struct stream *s;
|
||||
afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
|
||||
if (DISABLE_BGP_ANNOUNCE)
|
||||
return NULL;
|
||||
@ -169,13 +171,16 @@ bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
|
||||
|
||||
/* Total Path Attribute Length */
|
||||
stream_putw (s, 6);
|
||||
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
|
||||
stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
|
||||
stream_putc (s, 3);
|
||||
stream_putw (s, afi);
|
||||
stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
|
||||
stream_putw (s, pkt_afi);
|
||||
stream_putc (s, pkt_safi);
|
||||
}
|
||||
|
||||
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 bgp_filter *filter;
|
||||
int orf_refresh = 0;
|
||||
afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
|
||||
if (DISABLE_BGP_ANNOUNCE)
|
||||
return;
|
||||
|
||||
filter = &peer->filter[afi][safi];
|
||||
|
||||
/* Adjust safi code. */
|
||||
if (safi == SAFI_MPLS_VPN)
|
||||
safi = SAFI_MPLS_LABELED_VPN;
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
|
||||
|
||||
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);
|
||||
|
||||
/* Encode Route Refresh message. */
|
||||
stream_putw (s, afi);
|
||||
stream_putw (s, pkt_afi);
|
||||
stream_putc (s, 0);
|
||||
stream_putc (s, safi);
|
||||
stream_putc (s, pkt_safi);
|
||||
|
||||
if (orf_type == ORF_TYPE_PREFIX
|
||||
|| 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",
|
||||
peer->host, orf_type,
|
||||
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
|
||||
afi, safi);
|
||||
pkt_afi, pkt_safi);
|
||||
}
|
||||
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",
|
||||
peer->host, orf_type,
|
||||
(when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
|
||||
afi, safi);
|
||||
pkt_afi, pkt_safi);
|
||||
}
|
||||
|
||||
/* Total ORF Entry Len. */
|
||||
@ -761,7 +767,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
|
||||
{
|
||||
if (! orf_refresh)
|
||||
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. */
|
||||
@ -776,10 +782,11 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
|
||||
int capability_code, int action)
|
||||
{
|
||||
struct stream *s;
|
||||
afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
|
||||
/* Adjust safi code. */
|
||||
if (safi == SAFI_MPLS_VPN)
|
||||
safi = SAFI_MPLS_LABELED_VPN;
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi);
|
||||
|
||||
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, CAPABILITY_CODE_MP);
|
||||
stream_putc (s, CAPABILITY_CODE_MP_LEN);
|
||||
stream_putw (s, afi);
|
||||
stream_putw (s, pkt_afi);
|
||||
stream_putc (s, 0);
|
||||
stream_putc (s, safi);
|
||||
stream_putc (s, pkt_safi);
|
||||
|
||||
if (bgp_debug_neighbor_events(peer))
|
||||
zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
|
||||
peer->host, action == CAPABILITY_ACTION_SET ?
|
||||
"Advertising" : "Removing", afi, safi);
|
||||
"Advertising" : "Removing", pkt_afi, pkt_safi);
|
||||
}
|
||||
|
||||
/* Set packet size. */
|
||||
@ -1329,7 +1336,6 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet)
|
||||
case SAFI_MULTICAST:
|
||||
return bgp_nlri_parse_ip (peer, attr, packet);
|
||||
case SAFI_MPLS_VPN:
|
||||
case SAFI_MPLS_LABELED_VPN:
|
||||
return bgp_nlri_parse_vpn (peer, attr, packet);
|
||||
case SAFI_ENCAP:
|
||||
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)
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
else if (attr.flag & ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI)
|
||||
&& nlris[NLRI_MP_WITHDRAW].length == 0
|
||||
&& bgp_afi_safi_valid_indices (nlris[NLRI_MP_WITHDRAW].afi,
|
||||
&nlris[NLRI_MP_WITHDRAW].safi))
|
||||
&& nlris[NLRI_MP_WITHDRAW].length == 0)
|
||||
{
|
||||
afi = nlris[NLRI_MP_WITHDRAW].afi;
|
||||
safi = nlris[NLRI_MP_WITHDRAW].safi;
|
||||
@ -1727,8 +1711,8 @@ bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
|
||||
static void
|
||||
bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
|
||||
{
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t pkt_afi, afi;
|
||||
safi_t pkt_safi, safi;
|
||||
struct stream *s;
|
||||
struct peer_af *paf;
|
||||
struct update_group *updgrp;
|
||||
@ -1757,28 +1741,22 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
|
||||
s = peer->ibuf;
|
||||
|
||||
/* Parse packet. */
|
||||
afi = stream_getw (s);
|
||||
pkt_afi = stream_getw (s);
|
||||
(void)stream_getc (s);
|
||||
safi = stream_getc (s);
|
||||
pkt_safi = stream_getc (s);
|
||||
|
||||
if (bgp_debug_update(peer, NULL, NULL, 0))
|
||||
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. */
|
||||
if ((afi != AFI_IP && afi != AFI_IP6)
|
||||
|| (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
|
||||
&& safi != SAFI_MPLS_LABELED_VPN))
|
||||
/* Convert AFI, SAFI to internal values and check. */
|
||||
if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi))
|
||||
{
|
||||
zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
|
||||
peer->host, afi, safi);
|
||||
peer->host, pkt_afi, pkt_safi);
|
||||
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)
|
||||
{
|
||||
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_header *hdr;
|
||||
u_char action;
|
||||
afi_t afi;
|
||||
safi_t safi;
|
||||
afi_t pkt_afi, afi;
|
||||
safi_t pkt_safi, safi;
|
||||
|
||||
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. */
|
||||
if (hdr->code == CAPABILITY_CODE_MP)
|
||||
{
|
||||
afi = ntohs (mpc.afi);
|
||||
safi = mpc.safi;
|
||||
pkt_afi = ntohs (mpc.afi);
|
||||
pkt_safi = mpc.safi;
|
||||
|
||||
/* Ignore capability when override-capability is set. */
|
||||
if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
|
||||
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))
|
||||
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;
|
||||
}
|
||||
|
||||
@ -2020,7 +1999,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
|
||||
peer->host,
|
||||
action == CAPABILITY_ACTION_SET
|
||||
? "Advertising" : "Removing",
|
||||
ntohs(mpc.afi) , mpc.safi);
|
||||
pkt_afi, pkt_safi);
|
||||
|
||||
if (action == CAPABILITY_ACTION_SET)
|
||||
{
|
||||
|
@ -2113,6 +2113,9 @@ int
|
||||
bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi,
|
||||
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))
|
||||
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))
|
||||
return 0;
|
||||
|
||||
/* Convert AFI, SAFI to values for packet. */
|
||||
pkt_afi = afi_int2iana (afi);
|
||||
pkt_safi = safi_int2iana (safi);
|
||||
{
|
||||
u_int8_t ndata[7];
|
||||
|
||||
if (safi == SAFI_MPLS_VPN)
|
||||
safi = SAFI_MPLS_LABELED_VPN;
|
||||
|
||||
ndata[0] = (afi >> 8);
|
||||
ndata[1] = afi;
|
||||
ndata[2] = safi;
|
||||
ndata[0] = (pkt_afi >> 8);
|
||||
ndata[1] = pkt_afi;
|
||||
ndata[2] = pkt_safi;
|
||||
ndata[3] = (peer->pmax[afi][safi] >> 24);
|
||||
ndata[4] = (peer->pmax[afi][safi] >> 16);
|
||||
ndata[5] = (peer->pmax[afi][safi] >> 8);
|
||||
|
@ -2944,12 +2944,14 @@ DEFUN (neighbor_local_as,
|
||||
int idx_number = 3;
|
||||
struct peer *peer;
|
||||
int ret;
|
||||
as_t as;
|
||||
|
||||
peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg);
|
||||
if (! peer)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2966,12 +2968,14 @@ DEFUN (neighbor_local_as_no_prepend,
|
||||
int idx_number = 3;
|
||||
struct peer *peer;
|
||||
int ret;
|
||||
as_t as;
|
||||
|
||||
peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg);
|
||||
if (! peer)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2989,12 +2993,14 @@ DEFUN (neighbor_local_as_no_prepend_replace_as,
|
||||
int idx_number = 3;
|
||||
struct peer *peer;
|
||||
int ret;
|
||||
as_t as;
|
||||
|
||||
peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg);
|
||||
if (! peer)
|
||||
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);
|
||||
}
|
||||
|
||||
|
29
bgpd/bgpd.c
29
bgpd/bgpd.c
@ -651,6 +651,35 @@ bgp_listen_limit_unset (struct bgp *bgp)
|
||||
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 *
|
||||
peer_af_create (struct peer *peer, afi_t afi, safi_t safi)
|
||||
{
|
||||
|
11
bgpd/bgpd.h
11
bgpd/bgpd.h
@ -1078,10 +1078,6 @@ struct bgp_nlri
|
||||
#define BGP_DEFAULT_RESTART_TIME 120
|
||||
#define BGP_DEFAULT_STALEPATH_TIME 360
|
||||
|
||||
/* RFC4364 */
|
||||
#define SAFI_MPLS_LABELED_VPN 128
|
||||
#define BGP_SAFI_VPN 128
|
||||
|
||||
/* BGP uptime string length. */
|
||||
#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
|
||||
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_find (struct peer *, afi_t, safi_t);
|
||||
extern int peer_af_delete (struct peer *, afi_t, safi_t);
|
||||
|
@ -4086,7 +4086,6 @@ rfapiBgpInfoFilteredImportFunction (safi_t safi)
|
||||
switch (safi)
|
||||
{
|
||||
case SAFI_MPLS_VPN:
|
||||
case BGP_SAFI_VPN:
|
||||
return rfapiBgpInfoFilteredImportVPN;
|
||||
|
||||
case SAFI_ENCAP:
|
||||
@ -4203,7 +4202,7 @@ rfapiProcessUpdate (
|
||||
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);
|
||||
}
|
||||
@ -4332,7 +4331,7 @@ rfapiProcessWithdraw (
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
if (safi == SAFI_MPLS_VPN)
|
||||
|
@ -292,6 +292,8 @@ if test $ac_cv_lib_json_c_json_object_get = no; then
|
||||
fi
|
||||
fi
|
||||
|
||||
AX_PROG_PERL_MODULES(XML::LibXML, , AC_MSG_ERROR(XML::LibXML perl module is needed to compile))
|
||||
|
||||
AC_ARG_ENABLE([dev_build],
|
||||
AS_HELP_STRING([--enable-dev-build], [build for development]))
|
||||
|
||||
|
@ -544,6 +544,14 @@ lsp_update (struct isis_lsp *lsp, struct stream *stream,
|
||||
if (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 */
|
||||
lsp_update_data (lsp, stream, area, level);
|
||||
|
||||
|
2
ldpd/.gitignore
vendored
2
ldpd/.gitignore
vendored
@ -15,4 +15,4 @@ TAGS
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
|
||||
ldp_vty_cmds.c
|
||||
|
@ -9,6 +9,8 @@ AM_CFLAGS = $(WERROR)
|
||||
noinst_LIBRARIES = libldp.a
|
||||
sbin_PROGRAMS = ldpd
|
||||
|
||||
BUILT_SOURCES = ldp_vty_cmds.c
|
||||
|
||||
libldp_a_SOURCES = \
|
||||
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 \
|
||||
@ -19,6 +21,9 @@ libldp_a_SOURCES = \
|
||||
noinst_HEADERS = \
|
||||
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_LDADD = libldp.a ../lib/libzebra.la @LIBCAP@
|
||||
|
||||
|
116
ldpd/adjacency.c
116
ldpd/adjacency.c
@ -25,12 +25,55 @@
|
||||
#include "ldpe.h"
|
||||
#include "log.h"
|
||||
|
||||
static __inline int adj_compare(struct adj *, struct adj *);
|
||||
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 void tnbr_start_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 *
|
||||
adj_new(struct in_addr lsr_id, struct hello_source *source,
|
||||
union ldpd_addr *addr)
|
||||
@ -48,11 +91,11 @@ adj_new(struct in_addr lsr_id, struct hello_source *source,
|
||||
adj->source = *source;
|
||||
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) {
|
||||
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;
|
||||
case HELLO_TARGETED:
|
||||
source->target->adj = adj;
|
||||
@ -70,12 +113,12 @@ adj_del_single(struct adj *adj)
|
||||
|
||||
adj_stop_itimer(adj);
|
||||
|
||||
LIST_REMOVE(adj, global_entry);
|
||||
RB_REMOVE(global_adj_head, &global.adj_tree, adj);
|
||||
if (adj->nbr)
|
||||
LIST_REMOVE(adj, nbr_entry);
|
||||
RB_REMOVE(nbr_adj_head, &adj->nbr->adj_tree, adj);
|
||||
switch (adj->source.type) {
|
||||
case HELLO_LINK:
|
||||
LIST_REMOVE(adj, ia_entry);
|
||||
RB_REMOVE(ia_adj_head, &adj->source.link.ia->adj_tree, adj);
|
||||
break;
|
||||
case HELLO_TARGETED:
|
||||
adj->source.target->adj = NULL;
|
||||
@ -99,7 +142,7 @@ adj_del(struct adj *adj, uint32_t notif_status)
|
||||
* then delete it.
|
||||
*/
|
||||
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);
|
||||
session_shutdown(nbr, notif_status, 0, 0);
|
||||
nbr_del(nbr);
|
||||
@ -109,27 +152,9 @@ adj_del(struct adj *adj, uint32_t notif_status)
|
||||
struct adj *
|
||||
adj_find(struct hello_source *source)
|
||||
{
|
||||
struct adj *adj;
|
||||
|
||||
LIST_FOREACH(adj, &global.adj_list, global_entry) {
|
||||
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);
|
||||
struct adj adj;
|
||||
adj.source = *source;
|
||||
return (RB_FIND(global_adj_head, &global.adj_tree, &adj));
|
||||
}
|
||||
|
||||
int
|
||||
@ -161,7 +186,7 @@ adj_itimer(struct thread *thread)
|
||||
if (!(adj->source.target->flags & F_TNBR_CONFIGURED) &&
|
||||
adj->source.target->pw_count == 0) {
|
||||
/* remove dynamic targeted neighbor */
|
||||
tnbr_del(adj->source.target);
|
||||
tnbr_del(leconf, adj->source.target);
|
||||
return (0);
|
||||
}
|
||||
adj->source.target->adj = NULL;
|
||||
@ -188,6 +213,17 @@ adj_stop_itimer(struct adj *adj)
|
||||
|
||||
/* 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 *
|
||||
tnbr_new(int af, union ldpd_addr *addr)
|
||||
{
|
||||
@ -204,34 +240,30 @@ tnbr_new(int af, union ldpd_addr *addr)
|
||||
}
|
||||
|
||||
static void
|
||||
tnbr_del(struct tnbr *tnbr)
|
||||
tnbr_del(struct ldpd_conf *xconf, struct tnbr *tnbr)
|
||||
{
|
||||
tnbr_stop_hello_timer(tnbr);
|
||||
if (tnbr->adj)
|
||||
adj_del(tnbr->adj, S_SHUTDOWN);
|
||||
LIST_REMOVE(tnbr, entry);
|
||||
RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr);
|
||||
free(tnbr);
|
||||
}
|
||||
|
||||
struct tnbr *
|
||||
tnbr_find(struct ldpd_conf *xconf, int af, union ldpd_addr *addr)
|
||||
{
|
||||
struct tnbr *tnbr;
|
||||
|
||||
LIST_FOREACH(tnbr, &xconf->tnbr_list, entry)
|
||||
if (af == tnbr->af &&
|
||||
ldp_addrcmp(af, addr, &tnbr->addr) == 0)
|
||||
return (tnbr);
|
||||
|
||||
return (NULL);
|
||||
struct tnbr tnbr;
|
||||
tnbr.af = af;
|
||||
tnbr.addr = *addr;
|
||||
return (RB_FIND(tnbr_head, &xconf->tnbr_tree, &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)) &&
|
||||
tnbr->pw_count == 0) {
|
||||
tnbr_del(tnbr);
|
||||
tnbr_del(xconf, tnbr);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@ -276,7 +308,7 @@ tnbr_update_all(int af)
|
||||
struct tnbr *tnbr;
|
||||
|
||||
/* 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)
|
||||
tnbr_update(tnbr);
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
|
||||
if (tnbr && (tnbr->flags & F_TNBR_DYNAMIC) &&
|
||||
!((flags & F_HELLO_REQ_TARG))) {
|
||||
tnbr->flags &= ~F_TNBR_DYNAMIC;
|
||||
tnbr = tnbr_check(tnbr);
|
||||
tnbr = tnbr_check(leconf, 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->flags |= F_TNBR_DYNAMIC;
|
||||
tnbr_update(tnbr);
|
||||
LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry);
|
||||
RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr);
|
||||
}
|
||||
|
||||
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);
|
||||
if (nbr) {
|
||||
adj->nbr = nbr;
|
||||
LIST_INSERT_HEAD(&nbr->adj_list, adj, nbr_entry);
|
||||
RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#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_lookup(struct if_addr_head *, struct kaddr *);
|
||||
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_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 *
|
||||
if_new(struct kif *kif)
|
||||
{
|
||||
@ -57,30 +66,18 @@ if_new(struct kif *kif)
|
||||
iface->ipv4.iface = iface;
|
||||
iface->ipv4.enabled = 0;
|
||||
iface->ipv4.state = IF_STA_DOWN;
|
||||
LIST_INIT(&iface->ipv4.adj_list);
|
||||
RB_INIT(&iface->ipv4.adj_tree);
|
||||
|
||||
/* ipv6 */
|
||||
iface->ipv6.af = AF_INET6;
|
||||
iface->ipv6.iface = iface;
|
||||
iface->ipv6.enabled = 0;
|
||||
iface->ipv6.state = IF_STA_DOWN;
|
||||
LIST_INIT(&iface->ipv6.adj_list);
|
||||
RB_INIT(&iface->ipv6.adj_tree);
|
||||
|
||||
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
|
||||
if_exit(struct iface *iface)
|
||||
{
|
||||
@ -100,17 +97,25 @@ if_exit(struct iface *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;
|
||||
|
||||
LIST_FOREACH(iface, &xconf->iface_list, entry)
|
||||
if (strcmp(iface->name, ifname) == 0)
|
||||
RB_FOREACH(iface, iface_head, &xconf->iface_tree)
|
||||
if (iface->ifindex == ifindex)
|
||||
return (iface);
|
||||
|
||||
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
|
||||
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);
|
||||
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);
|
||||
|
||||
/* try to cleanup */
|
||||
@ -380,7 +385,7 @@ if_update_all(int af)
|
||||
{
|
||||
struct iface *iface;
|
||||
|
||||
LIST_FOREACH(iface, &leconf->iface_list, entry)
|
||||
RB_FOREACH(iface, iface_head, &leconf->iface_tree)
|
||||
if_update(iface, af);
|
||||
}
|
||||
|
||||
@ -460,7 +465,7 @@ if_to_ctl(struct iface_af *ia)
|
||||
ictl.uptime = 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++;
|
||||
|
||||
return (&ictl);
|
||||
|
108
ldpd/l2vpn.c
108
ldpd/l2vpn.c
@ -26,7 +26,20 @@
|
||||
#include "lde.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 *
|
||||
l2vpn_new(const char *name)
|
||||
@ -42,9 +55,9 @@ l2vpn_new(const char *name)
|
||||
l2vpn->mtu = DEFAULT_L2VPN_MTU;
|
||||
l2vpn->pw_type = DEFAULT_PW_TYPE;
|
||||
|
||||
LIST_INIT(&l2vpn->if_list);
|
||||
LIST_INIT(&l2vpn->pw_list);
|
||||
LIST_INIT(&l2vpn->pw_inactive_list);
|
||||
RB_INIT(&l2vpn->if_tree);
|
||||
RB_INIT(&l2vpn->pw_tree);
|
||||
RB_INIT(&l2vpn->pw_inactive_tree);
|
||||
|
||||
return (l2vpn);
|
||||
}
|
||||
@ -52,13 +65,9 @@ l2vpn_new(const char *name)
|
||||
struct l2vpn *
|
||||
l2vpn_find(struct ldpd_conf *xconf, const char *name)
|
||||
{
|
||||
struct l2vpn *l2vpn;
|
||||
|
||||
LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry)
|
||||
if (strcmp(l2vpn->name, name) == 0)
|
||||
return (l2vpn);
|
||||
|
||||
return (NULL);
|
||||
struct l2vpn l2vpn;
|
||||
strlcpy(l2vpn.name, name, sizeof(l2vpn.name));
|
||||
return (RB_FIND(l2vpn_head, &xconf->l2vpn_tree, &l2vpn));
|
||||
}
|
||||
|
||||
void
|
||||
@ -67,16 +76,16 @@ l2vpn_del(struct l2vpn *l2vpn)
|
||||
struct l2vpn_if *lif;
|
||||
struct l2vpn_pw *pw;
|
||||
|
||||
while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) {
|
||||
LIST_REMOVE(lif, entry);
|
||||
while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) {
|
||||
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
|
||||
free(lif);
|
||||
}
|
||||
while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) {
|
||||
LIST_REMOVE(pw, entry);
|
||||
while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) {
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
||||
free(pw);
|
||||
}
|
||||
while ((pw = LIST_FIRST(&l2vpn->pw_inactive_list)) != NULL) {
|
||||
LIST_REMOVE(pw, entry);
|
||||
while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) {
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
||||
free(pw);
|
||||
}
|
||||
|
||||
@ -88,7 +97,7 @@ l2vpn_init(struct l2vpn *l2vpn)
|
||||
{
|
||||
struct l2vpn_pw *pw;
|
||||
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry)
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
|
||||
l2vpn_pw_init(pw);
|
||||
}
|
||||
|
||||
@ -97,10 +106,16 @@ l2vpn_exit(struct l2vpn *l2vpn)
|
||||
{
|
||||
struct l2vpn_pw *pw;
|
||||
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry)
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
|
||||
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 *
|
||||
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;
|
||||
|
||||
LIST_FOREACH(lif, &l2vpn->if_list, entry)
|
||||
RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
|
||||
if (lif->ifindex == ifindex)
|
||||
return (lif);
|
||||
|
||||
@ -132,15 +147,16 @@ l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex)
|
||||
struct l2vpn_if *
|
||||
l2vpn_if_find_name(struct l2vpn *l2vpn, const char *ifname)
|
||||
{
|
||||
struct l2vpn_if *lif;
|
||||
|
||||
LIST_FOREACH(lif, &l2vpn->if_list, entry)
|
||||
if (strcmp(lif->ifname, ifname) == 0)
|
||||
return (lif);
|
||||
|
||||
return (NULL);
|
||||
struct l2vpn_if lif;
|
||||
strlcpy(lif.ifname, ifname, sizeof(lif.ifname));
|
||||
return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif));
|
||||
}
|
||||
|
||||
static __inline int
|
||||
l2vpn_pw_compare(struct l2vpn_pw *a, struct l2vpn_pw *b)
|
||||
{
|
||||
return (strcmp(a->ifname, b->ifname));
|
||||
}
|
||||
|
||||
struct l2vpn_pw *
|
||||
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;
|
||||
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry)
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
|
||||
if (pw->ifindex == ifindex)
|
||||
return (pw);
|
||||
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry)
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree)
|
||||
if (pw->ifindex == ifindex)
|
||||
return (pw);
|
||||
|
||||
@ -176,15 +192,13 @@ struct l2vpn_pw *
|
||||
l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname)
|
||||
{
|
||||
struct l2vpn_pw *pw;
|
||||
struct l2vpn_pw s;
|
||||
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry)
|
||||
if (strcmp(pw->ifname, ifname) == 0)
|
||||
return (pw);
|
||||
LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry)
|
||||
if (strcmp(pw->ifname, ifname) == 0)
|
||||
return (pw);
|
||||
|
||||
return (NULL);
|
||||
strlcpy(s.ifname, ifname, sizeof(s.ifname));
|
||||
pw = RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s);
|
||||
if (pw)
|
||||
return (pw);
|
||||
return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
|
||||
}
|
||||
|
||||
void
|
||||
@ -399,8 +413,8 @@ l2vpn_sync_pws(int af, union ldpd_addr *addr)
|
||||
struct fec_node *fn;
|
||||
struct fec_nh *fnh;
|
||||
|
||||
LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) {
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
|
||||
RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) {
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
|
||||
if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr))
|
||||
continue;
|
||||
|
||||
@ -428,8 +442,8 @@ l2vpn_pw_ctl(pid_t pid)
|
||||
struct l2vpn_pw *pw;
|
||||
static struct ctl_pw pwctl;
|
||||
|
||||
LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry)
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
|
||||
RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree)
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
|
||||
memset(&pwctl, 0, sizeof(pwctl));
|
||||
strlcpy(pwctl.l2vpn_name, pw->l2vpn->name,
|
||||
sizeof(pwctl.l2vpn_name));
|
||||
@ -459,7 +473,7 @@ l2vpn_binding_ctl(pid_t pid)
|
||||
|
||||
fn = (struct fec_node *)f;
|
||||
if (fn->local_label == NO_LABEL &&
|
||||
LIST_EMPTY(&fn->downstream))
|
||||
RB_EMPTY(&fn->downstream))
|
||||
continue;
|
||||
|
||||
memset(&pwctl, 0, sizeof(pwctl));
|
||||
@ -477,7 +491,7 @@ l2vpn_binding_ctl(pid_t pid)
|
||||
} else
|
||||
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)
|
||||
break;
|
||||
|
||||
@ -508,7 +522,7 @@ ldpe_l2vpn_init(struct l2vpn *l2vpn)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -517,7 +531,7 @@ ldpe_l2vpn_exit(struct l2vpn *l2vpn)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -530,7 +544,7 @@ ldpe_l2vpn_pw_init(struct l2vpn_pw *pw)
|
||||
if (tnbr == NULL) {
|
||||
tnbr = tnbr_new(pw->af, &pw->addr);
|
||||
tnbr_update(tnbr);
|
||||
LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry);
|
||||
RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr);
|
||||
}
|
||||
|
||||
tnbr->pw_count++;
|
||||
@ -544,6 +558,6 @@ ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw)
|
||||
tnbr = tnbr_find(leconf, pw->af, &pw->addr);
|
||||
if (tnbr) {
|
||||
tnbr->pw_count--;
|
||||
tnbr_check(tnbr);
|
||||
tnbr_check(leconf, tnbr);
|
||||
}
|
||||
}
|
||||
|
49
ldpd/lde.c
49
ldpd/lde.c
@ -45,12 +45,14 @@ static struct lde_nbr *lde_nbr_find(uint32_t);
|
||||
static void lde_nbr_clear(void);
|
||||
static void lde_nbr_addr_update(struct lde_nbr *,
|
||||
struct lde_addr *, int);
|
||||
static __inline int lde_map_compare(struct lde_map *, struct lde_map *);
|
||||
static void lde_map_free(void *);
|
||||
static int lde_address_add(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 *);
|
||||
|
||||
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 nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs);
|
||||
@ -471,10 +473,10 @@ lde_dispatch_parent(struct thread *thread)
|
||||
fatal(NULL);
|
||||
memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
|
||||
|
||||
LIST_INIT(&nconf->iface_list);
|
||||
LIST_INIT(&nconf->tnbr_list);
|
||||
LIST_INIT(&nconf->nbrp_list);
|
||||
LIST_INIT(&nconf->l2vpn_list);
|
||||
RB_INIT(&nconf->iface_tree);
|
||||
RB_INIT(&nconf->tnbr_tree);
|
||||
RB_INIT(&nconf->nbrp_tree);
|
||||
RB_INIT(&nconf->l2vpn_tree);
|
||||
break;
|
||||
case IMSG_RECONF_IFACE:
|
||||
if ((niface = malloc(sizeof(struct iface))) == NULL)
|
||||
@ -482,37 +484,37 @@ lde_dispatch_parent(struct thread *thread)
|
||||
memcpy(niface, imsg.data, sizeof(struct iface));
|
||||
|
||||
LIST_INIT(&niface->addr_list);
|
||||
LIST_INIT(&niface->ipv4.adj_list);
|
||||
LIST_INIT(&niface->ipv6.adj_list);
|
||||
RB_INIT(&niface->ipv4.adj_tree);
|
||||
RB_INIT(&niface->ipv6.adj_tree);
|
||||
niface->ipv4.iface = niface;
|
||||
niface->ipv6.iface = niface;
|
||||
|
||||
LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
|
||||
RB_INSERT(iface_head, &nconf->iface_tree, niface);
|
||||
break;
|
||||
case IMSG_RECONF_TNBR:
|
||||
if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
|
||||
fatal(NULL);
|
||||
memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
|
||||
|
||||
LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry);
|
||||
RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
|
||||
break;
|
||||
case IMSG_RECONF_NBRP:
|
||||
if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
|
||||
fatal(NULL);
|
||||
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;
|
||||
case IMSG_RECONF_L2VPN:
|
||||
if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
|
||||
fatal(NULL);
|
||||
memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
|
||||
|
||||
LIST_INIT(&nl2vpn->if_list);
|
||||
LIST_INIT(&nl2vpn->pw_list);
|
||||
LIST_INIT(&nl2vpn->pw_inactive_list);
|
||||
RB_INIT(&nl2vpn->if_tree);
|
||||
RB_INIT(&nl2vpn->pw_tree);
|
||||
RB_INIT(&nl2vpn->pw_inactive_tree);
|
||||
|
||||
LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
|
||||
RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
|
||||
break;
|
||||
case IMSG_RECONF_L2VPN_IF:
|
||||
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));
|
||||
|
||||
nlif->l2vpn = nl2vpn;
|
||||
LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
|
||||
RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
|
||||
break;
|
||||
case IMSG_RECONF_L2VPN_PW:
|
||||
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));
|
||||
|
||||
npw->l2vpn = nl2vpn;
|
||||
LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry);
|
||||
RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
|
||||
break;
|
||||
case IMSG_RECONF_L2VPN_IPW:
|
||||
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));
|
||||
|
||||
npw->l2vpn = nl2vpn;
|
||||
LIST_INSERT_HEAD(&nl2vpn->pw_inactive_list, npw, entry);
|
||||
RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
|
||||
break;
|
||||
case IMSG_RECONF_END:
|
||||
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 *
|
||||
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;
|
||||
|
||||
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))
|
||||
log_warnx("failed to add %s to sent map",
|
||||
log_fec(&me->fec));
|
||||
/* XXX on failure more cleanup is needed */
|
||||
} 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))
|
||||
log_warnx("failed to add %s to recv map",
|
||||
log_fec(&me->fec));
|
||||
@ -1185,7 +1196,7 @@ lde_map_free(void *ptr)
|
||||
{
|
||||
struct lde_map *map = ptr;
|
||||
|
||||
LIST_REMOVE(map, entry);
|
||||
RB_REMOVE(lde_map_head, map->head, map);
|
||||
free(map);
|
||||
}
|
||||
|
||||
|
@ -62,10 +62,13 @@ struct lde_req {
|
||||
/* mapping entries */
|
||||
struct lde_map {
|
||||
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 map map;
|
||||
};
|
||||
RB_HEAD(lde_map_head, lde_map);
|
||||
RB_PROTOTYPE(lde_map_head, lde_map, entry, lde_map_cmp);
|
||||
|
||||
/* withdraw entries */
|
||||
struct lde_wdraw {
|
||||
@ -112,8 +115,8 @@ struct fec_node {
|
||||
struct fec fec;
|
||||
|
||||
LIST_HEAD(, fec_nh) nexthops; /* fib nexthops */
|
||||
LIST_HEAD(, lde_map) downstream; /* recv mappings */
|
||||
LIST_HEAD(, lde_map) upstream; /* sent mappings */
|
||||
struct lde_map_head downstream; /* recv mappings */
|
||||
struct lde_map_head upstream; /* sent mappings */
|
||||
|
||||
uint32_t local_label;
|
||||
void *data; /* fec specific data */
|
||||
|
@ -159,7 +159,7 @@ rt_dump(pid_t pid)
|
||||
RB_FOREACH(f, fec_tree, &ft) {
|
||||
fn = (struct fec_node *)f;
|
||||
if (fn->local_label == NO_LABEL &&
|
||||
LIST_EMPTY(&fn->downstream))
|
||||
RB_EMPTY(&fn->downstream))
|
||||
continue;
|
||||
|
||||
rtctl.first = 1;
|
||||
@ -179,7 +179,7 @@ rt_dump(pid_t pid)
|
||||
}
|
||||
|
||||
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.nexthop = me->nexthop->id;
|
||||
rtctl.remote_label = me->map.label;
|
||||
@ -188,7 +188,7 @@ rt_dump(pid_t pid)
|
||||
&rtctl, sizeof(rtctl));
|
||||
rtctl.first = 0;
|
||||
}
|
||||
if (LIST_EMPTY(&fn->downstream)) {
|
||||
if (RB_EMPTY(&fn->downstream)) {
|
||||
rtctl.in_use = 0;
|
||||
rtctl.nexthop.s_addr = INADDR_ANY;
|
||||
rtctl.remote_label = NO_LABEL;
|
||||
@ -224,10 +224,10 @@ fec_free(void *arg)
|
||||
|
||||
while ((fnh = LIST_FIRST(&fn->nexthops)))
|
||||
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_fec(&fn->fec));
|
||||
if (!LIST_EMPTY(&fn->upstream))
|
||||
if (!RB_EMPTY(&fn->upstream))
|
||||
log_warnx("%s: fec %s upstream list not empty", __func__,
|
||||
log_fec(&fn->fec));
|
||||
|
||||
@ -251,8 +251,8 @@ fec_add(struct fec *fec)
|
||||
|
||||
fn->fec = *fec;
|
||||
fn->local_label = NO_LABEL;
|
||||
LIST_INIT(&fn->upstream);
|
||||
LIST_INIT(&fn->downstream);
|
||||
RB_INIT(&fn->upstream);
|
||||
RB_INIT(&fn->downstream);
|
||||
LIST_INIT(&fn->nexthops);
|
||||
|
||||
if (fec_insert(&ft, &fn->fec))
|
||||
@ -774,8 +774,8 @@ lde_gc_timer(struct thread *thread)
|
||||
fn = (struct fec_node *) fec;
|
||||
|
||||
if (!LIST_EMPTY(&fn->nexthops) ||
|
||||
!LIST_EMPTY(&fn->downstream) ||
|
||||
!LIST_EMPTY(&fn->upstream))
|
||||
!RB_EMPTY(&fn->downstream) ||
|
||||
!RB_EMPTY(&fn->upstream))
|
||||
continue;
|
||||
|
||||
fec_remove(&ft, &fn->fec);
|
||||
|
@ -74,7 +74,7 @@ ldp_vty_debug(struct vty *vty, struct vty_arg *args[])
|
||||
DEBUG_OFF(event, EVENT);
|
||||
else
|
||||
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;
|
||||
dir_str = vty_get_arg_value(args, "dir");
|
||||
if (dir_str == NULL)
|
||||
@ -99,7 +99,7 @@ ldp_vty_debug(struct vty *vty, struct vty_arg *args[])
|
||||
DEBUG_ON(msg, MSG_SEND_ALL);
|
||||
}
|
||||
}
|
||||
} else if (strcmp(type_str, "zebra") == 0) {
|
||||
} else if (strcmp(type_str, "zebra") == 0) {
|
||||
if (disable)
|
||||
DEBUG_OFF(zebra, ZEBRA);
|
||||
else
|
||||
|
1726
ldpd/ldp_vty_cmds.c
1726
ldpd/ldp_vty_cmds.c
File diff suppressed because it is too large
Load Diff
@ -142,7 +142,7 @@ ldp_af_iface_config_write(struct vty *vty, int af)
|
||||
struct iface *iface;
|
||||
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);
|
||||
if (!ia->enabled)
|
||||
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_NEWLINE);
|
||||
|
||||
LIST_FOREACH(tnbr, &ldpd_conf->tnbr_list, entry) {
|
||||
RB_FOREACH(tnbr, tnbr_head, &ldpd_conf->tnbr_tree) {
|
||||
if (tnbr->af == af) {
|
||||
vty_out(vty, " !%s", VTY_NEWLINE);
|
||||
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)
|
||||
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)
|
||||
vty_out(vty, " neighbor %s session holdtime %u%s",
|
||||
inet_ntoa(nbrp->lsr_id), nbrp->keepalive,
|
||||
@ -341,7 +341,7 @@ ldp_l2vpn_config_write(struct vty *vty)
|
||||
struct l2vpn_if *lif;
|
||||
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);
|
||||
|
||||
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_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_NEWLINE);
|
||||
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry)
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
|
||||
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);
|
||||
|
||||
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))
|
||||
return (1);
|
||||
|
||||
LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) {
|
||||
RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
|
||||
if (l2vpn_if_find_name(l2vpn, ifname))
|
||||
return (1);
|
||||
if (l2vpn_pw_find_name(l2vpn, ifname))
|
||||
@ -740,7 +740,7 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[])
|
||||
} else {
|
||||
if (nbrp == NULL) {
|
||||
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)
|
||||
goto cancel;
|
||||
|
||||
@ -857,7 +857,7 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[])
|
||||
|
||||
ia = iface_af_get(iface, af);
|
||||
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);
|
||||
} else {
|
||||
memset(&kif, 0, sizeof(kif));
|
||||
@ -955,7 +955,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[])
|
||||
if (tnbr == NULL)
|
||||
goto cancel;
|
||||
|
||||
LIST_REMOVE(tnbr, entry);
|
||||
RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr);
|
||||
free(tnbr);
|
||||
ldp_reload(vty_conf);
|
||||
return (CMD_SUCCESS);
|
||||
@ -966,7 +966,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[])
|
||||
|
||||
tnbr = tnbr_new(af, &addr);
|
||||
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);
|
||||
|
||||
@ -1129,7 +1129,7 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[])
|
||||
} else {
|
||||
if (nbrp == NULL) {
|
||||
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 &&
|
||||
strcmp(nbrp->auth.md5key, password_str) == 0)
|
||||
goto cancel;
|
||||
@ -1195,7 +1195,7 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[])
|
||||
} else {
|
||||
if (nbrp == NULL) {
|
||||
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;
|
||||
@ -1235,7 +1235,7 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
|
||||
if (l2vpn == NULL)
|
||||
goto cancel;
|
||||
|
||||
LIST_REMOVE(l2vpn, entry);
|
||||
RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn);
|
||||
l2vpn_del(l2vpn);
|
||||
ldp_reload(vty_conf);
|
||||
return (CMD_SUCCESS);
|
||||
@ -1248,9 +1248,9 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[])
|
||||
|
||||
l2vpn = l2vpn_new(name_str);
|
||||
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);
|
||||
|
||||
return (CMD_SUCCESS);
|
||||
@ -1369,7 +1369,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
|
||||
if (lif == NULL)
|
||||
goto cancel;
|
||||
|
||||
LIST_REMOVE(lif, entry);
|
||||
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
|
||||
free(lif);
|
||||
ldp_reload(vty_conf);
|
||||
return (CMD_SUCCESS);
|
||||
@ -1392,7 +1392,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[])
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -1425,14 +1425,14 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
|
||||
if (pw == NULL)
|
||||
goto cancel;
|
||||
|
||||
LIST_REMOVE(pw, entry);
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
||||
free(pw);
|
||||
ldp_reload(vty_conf);
|
||||
return (CMD_SUCCESS);
|
||||
}
|
||||
|
||||
if (pw) {
|
||||
VTY_PUSH_CONTEXT(LDP_PSEUDOWIRE_NODE, pw);
|
||||
VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw);
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
@ -1451,10 +1451,10 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[])
|
||||
|
||||
pw = l2vpn_pw_new(l2vpn, &kif);
|
||||
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);
|
||||
VTY_PUSH_CONTEXT(LDP_PSEUDOWIRE_NODE, pw);
|
||||
VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw);
|
||||
|
||||
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;
|
||||
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);
|
||||
|
||||
if (disable)
|
||||
@ -1510,7 +1510,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[])
|
||||
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);
|
||||
|
||||
if (disable) {
|
||||
@ -1546,7 +1546,7 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[])
|
||||
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);
|
||||
|
||||
if (disable)
|
||||
@ -1578,7 +1578,7 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[])
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
pw = VTY_GET_CONTEXT(l2vpn_pw);
|
||||
pw = VTY_GET_CONTEXT_SUB(l2vpn_pw);
|
||||
vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw);
|
||||
|
||||
if (disable)
|
||||
@ -1641,14 +1641,14 @@ iface_new_api(struct ldpd_conf *conf, const char *name)
|
||||
}
|
||||
|
||||
iface = if_new(&kif);
|
||||
LIST_INSERT_HEAD(&conf->iface_list, iface, entry);
|
||||
RB_INSERT(iface_head, &conf->iface_tree, iface);
|
||||
return (iface);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1665,14 +1665,14 @@ tnbr_new_api(struct ldpd_conf *conf, int af, union ldpd_addr *addr)
|
||||
|
||||
tnbr = tnbr_new(af, addr);
|
||||
tnbr->flags |= F_TNBR_CONFIGURED;
|
||||
LIST_INSERT_HEAD(&conf->tnbr_list, tnbr, entry);
|
||||
RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr);
|
||||
return (tnbr);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1685,14 +1685,14 @@ nbrp_new_api(struct ldpd_conf *conf, struct in_addr lsr_id)
|
||||
return (NULL);
|
||||
|
||||
nbrp = nbr_params_new(lsr_id);
|
||||
LIST_INSERT_HEAD(&conf->nbrp_list, nbrp, entry);
|
||||
RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp);
|
||||
return (nbrp);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1706,29 +1706,29 @@ l2vpn_new_api(struct ldpd_conf *conf, const char *name)
|
||||
|
||||
l2vpn = l2vpn_new(name);
|
||||
l2vpn->type = L2VPN_TYPE_VPLS;
|
||||
LIST_INSERT_HEAD(&conf->l2vpn_list, l2vpn, entry);
|
||||
RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn);
|
||||
return (l2vpn);
|
||||
}
|
||||
|
||||
void
|
||||
l2vpn_del_api(struct l2vpn *l2vpn)
|
||||
l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn)
|
||||
{
|
||||
struct l2vpn_if *lif;
|
||||
struct l2vpn_pw *pw;
|
||||
|
||||
while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) {
|
||||
LIST_REMOVE(lif, entry);
|
||||
while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) {
|
||||
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
|
||||
free(lif);
|
||||
}
|
||||
while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) {
|
||||
LIST_REMOVE(pw, entry);
|
||||
while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) {
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
||||
free(pw);
|
||||
}
|
||||
while ((pw = LIST_FIRST(&l2vpn->pw_inactive_list)) != NULL) {
|
||||
LIST_REMOVE(pw, entry);
|
||||
while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) {
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
||||
free(pw);
|
||||
}
|
||||
LIST_REMOVE(l2vpn, entry);
|
||||
RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
|
||||
free(l2vpn);
|
||||
}
|
||||
|
||||
@ -1752,14 +1752,14 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1784,13 +1784,13 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn,
|
||||
|
||||
pw = l2vpn_pw_new(l2vpn, &kif);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
212
ldpd/ldpd.c
212
ldpd/ldpd.c
@ -850,40 +850,40 @@ main_imsg_send_config(struct ldpd_conf *xconf)
|
||||
sizeof(*xconf)) == -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,
|
||||
sizeof(*iface)) == -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,
|
||||
sizeof(*tnbr)) == -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,
|
||||
sizeof(*nbrp)) == -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,
|
||||
sizeof(*l2vpn)) == -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,
|
||||
sizeof(*lif)) == -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,
|
||||
sizeof(*pw)) == -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,
|
||||
sizeof(*pw)) == -1)
|
||||
return (-1);
|
||||
@ -930,15 +930,15 @@ ldp_config_normalize(struct ldpd_conf *xconf, void **ref)
|
||||
ldp_config_reset_af(xconf, AF_INET6, ref);
|
||||
}
|
||||
|
||||
LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) {
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry) {
|
||||
RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) {
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) {
|
||||
if (pw->flags & F_PW_STATIC_NBR_ADDR)
|
||||
continue;
|
||||
|
||||
pw->af = AF_INET;
|
||||
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)
|
||||
continue;
|
||||
|
||||
@ -954,17 +954,17 @@ ldp_config_reset_main(struct ldpd_conf *conf, void **ref)
|
||||
struct iface *iface;
|
||||
struct nbr_params *nbrp;
|
||||
|
||||
while ((iface = LIST_FIRST(&conf->iface_list)) != NULL) {
|
||||
while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) {
|
||||
if (ref && *ref == iface)
|
||||
*ref = NULL;
|
||||
LIST_REMOVE(iface, entry);
|
||||
RB_REMOVE(iface_head, &conf->iface_tree, iface);
|
||||
free(iface);
|
||||
}
|
||||
|
||||
while ((nbrp = LIST_FIRST(&conf->nbrp_list)) != NULL) {
|
||||
while ((nbrp = RB_ROOT(&conf->nbrp_tree)) != NULL) {
|
||||
if (ref && *ref == nbrp)
|
||||
*ref = NULL;
|
||||
LIST_REMOVE(nbrp, entry);
|
||||
RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
|
||||
free(nbrp);
|
||||
}
|
||||
|
||||
@ -987,18 +987,18 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af, void **ref)
|
||||
struct iface_af *ia;
|
||||
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->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)
|
||||
continue;
|
||||
|
||||
if (ref && *ref == tnbr)
|
||||
*ref = NULL;
|
||||
LIST_REMOVE(tnbr, entry);
|
||||
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
|
||||
free(tnbr);
|
||||
}
|
||||
|
||||
@ -1032,46 +1032,46 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref)
|
||||
} while (0)
|
||||
|
||||
COPY(xconf, conf);
|
||||
LIST_INIT(&xconf->iface_list);
|
||||
LIST_INIT(&xconf->tnbr_list);
|
||||
LIST_INIT(&xconf->nbrp_list);
|
||||
LIST_INIT(&xconf->l2vpn_list);
|
||||
RB_INIT(&xconf->iface_tree);
|
||||
RB_INIT(&xconf->tnbr_tree);
|
||||
RB_INIT(&xconf->nbrp_tree);
|
||||
RB_INIT(&xconf->l2vpn_tree);
|
||||
|
||||
LIST_FOREACH(iface, &conf->iface_list, entry) {
|
||||
RB_FOREACH(iface, iface_head, &conf->iface_tree) {
|
||||
COPY(xi, iface);
|
||||
xi->ipv4.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);
|
||||
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);
|
||||
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);
|
||||
LIST_INIT(&xl->if_list);
|
||||
LIST_INIT(&xl->pw_list);
|
||||
LIST_INIT(&xl->pw_inactive_list);
|
||||
LIST_INSERT_HEAD(&xconf->l2vpn_list, xl, entry);
|
||||
RB_INIT(&xl->if_tree);
|
||||
RB_INIT(&xl->pw_tree);
|
||||
RB_INIT(&xl->pw_inactive_tree);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
xp->l2vpn = xl;
|
||||
LIST_INSERT_HEAD(&xl->pw_inactive_list, xp, entry);
|
||||
RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
|
||||
}
|
||||
}
|
||||
#undef COPY
|
||||
@ -1093,20 +1093,20 @@ ldp_clear_config(struct ldpd_conf *xconf)
|
||||
struct nbr_params *nbrp;
|
||||
struct l2vpn *l2vpn;
|
||||
|
||||
while ((iface = LIST_FIRST(&xconf->iface_list)) != NULL) {
|
||||
LIST_REMOVE(iface, entry);
|
||||
while ((iface = RB_ROOT(&xconf->iface_tree)) != NULL) {
|
||||
RB_REMOVE(iface_head, &xconf->iface_tree, iface);
|
||||
free(iface);
|
||||
}
|
||||
while ((tnbr = LIST_FIRST(&xconf->tnbr_list)) != NULL) {
|
||||
LIST_REMOVE(tnbr, entry);
|
||||
while ((tnbr = RB_ROOT(&xconf->tnbr_tree)) != NULL) {
|
||||
RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr);
|
||||
free(tnbr);
|
||||
}
|
||||
while ((nbrp = LIST_FIRST(&xconf->nbrp_list)) != NULL) {
|
||||
LIST_REMOVE(nbrp, entry);
|
||||
while ((nbrp = RB_ROOT(&xconf->nbrp_tree)) != NULL) {
|
||||
RB_REMOVE(nbrp_head, &xconf->nbrp_tree, nbrp);
|
||||
free(nbrp);
|
||||
}
|
||||
while ((l2vpn = LIST_FIRST(&xconf->l2vpn_list)) != NULL) {
|
||||
LIST_REMOVE(l2vpn, entry);
|
||||
while ((l2vpn = RB_ROOT(&xconf->l2vpn_tree)) != NULL) {
|
||||
RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, 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;
|
||||
|
||||
LIST_FOREACH_SAFE(iface, &conf->iface_list, entry, itmp) {
|
||||
RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
|
||||
/* find deleted interfaces */
|
||||
if ((xi = if_lookup_name(xconf, iface->name)) == NULL) {
|
||||
LIST_REMOVE(iface, entry);
|
||||
RB_REMOVE(iface_head, &conf->iface_tree, iface);
|
||||
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
@ -1254,11 +1254,11 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
free(iface);
|
||||
}
|
||||
}
|
||||
LIST_FOREACH_SAFE(xi, &xconf->iface_list, entry, itmp) {
|
||||
RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) {
|
||||
/* find new interfaces */
|
||||
if ((iface = if_lookup_name(conf, xi->name)) == NULL) {
|
||||
LIST_REMOVE(xi, entry);
|
||||
LIST_INSERT_HEAD(&conf->iface_list, xi, entry);
|
||||
RB_REMOVE(iface_head, &xconf->iface_tree, xi);
|
||||
RB_INSERT(iface_head, &conf->iface_tree, xi);
|
||||
|
||||
if (ldpd_process == PROC_MAIN) {
|
||||
QOBJ_REG (xi, iface);
|
||||
@ -1271,7 +1271,7 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
/* update existing interfaces */
|
||||
merge_iface_af(&iface->ipv4, &xi->ipv4);
|
||||
merge_iface_af(&iface->ipv6, &xi->ipv6);
|
||||
LIST_REMOVE(xi, entry);
|
||||
RB_REMOVE(iface_head, &xconf->iface_tree, xi);
|
||||
if (ref && *ref == xi)
|
||||
*ref = iface;
|
||||
free(xi);
|
||||
@ -1295,7 +1295,7 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
{
|
||||
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))
|
||||
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) {
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
LIST_REMOVE(tnbr, entry);
|
||||
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
|
||||
free(tnbr);
|
||||
break;
|
||||
case PROC_LDP_ENGINE:
|
||||
tnbr->flags &= ~F_TNBR_CONFIGURED;
|
||||
tnbr_check(tnbr);
|
||||
tnbr_check(conf, tnbr);
|
||||
break;
|
||||
case PROC_MAIN:
|
||||
LIST_REMOVE(tnbr, entry);
|
||||
RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr);
|
||||
QOBJ_UNREG (tnbr);
|
||||
free(tnbr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LIST_FOREACH_SAFE(xt, &xconf->tnbr_list, entry, ttmp) {
|
||||
RB_FOREACH_SAFE(xt, tnbr_head, &xconf->tnbr_tree, ttmp) {
|
||||
/* find new tnbrs */
|
||||
if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) {
|
||||
LIST_REMOVE(xt, entry);
|
||||
LIST_INSERT_HEAD(&conf->tnbr_list, xt, entry);
|
||||
RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt);
|
||||
RB_INSERT(tnbr_head, &conf->tnbr_tree, xt);
|
||||
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
@ -1340,7 +1340,7 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
/* update existing tnbrs */
|
||||
if (!(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)
|
||||
*ref = tnbr;
|
||||
free(xt);
|
||||
@ -1354,7 +1354,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
struct nbr *nbr;
|
||||
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 */
|
||||
if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) {
|
||||
switch (ldpd_process) {
|
||||
@ -1380,15 +1380,15 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
QOBJ_UNREG (nbrp);
|
||||
break;
|
||||
}
|
||||
LIST_REMOVE(nbrp, entry);
|
||||
RB_REMOVE(nbrp_head, &conf->nbrp_tree, 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 */
|
||||
if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) {
|
||||
LIST_REMOVE(xn, entry);
|
||||
LIST_INSERT_HEAD(&conf->nbrp_list, xn, entry);
|
||||
RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn);
|
||||
RB_INSERT(nbrp_head, &conf->nbrp_tree, xn);
|
||||
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
@ -1455,7 +1455,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
nbr_establish_connection(nbr);
|
||||
}
|
||||
}
|
||||
LIST_REMOVE(xn, entry);
|
||||
RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn);
|
||||
if (ref && *ref == xn)
|
||||
*ref = nbrp;
|
||||
free(xn);
|
||||
@ -1469,10 +1469,10 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
struct l2vpn_if *lif;
|
||||
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 */
|
||||
if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) {
|
||||
LIST_REMOVE(l2vpn, entry);
|
||||
RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn);
|
||||
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
@ -1482,11 +1482,11 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
ldpe_l2vpn_exit(l2vpn);
|
||||
break;
|
||||
case PROC_MAIN:
|
||||
LIST_FOREACH(lif, &l2vpn->if_list, entry)
|
||||
RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree)
|
||||
QOBJ_UNREG (lif);
|
||||
LIST_FOREACH(pw, &l2vpn->pw_list, entry)
|
||||
RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree)
|
||||
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 (l2vpn);
|
||||
break;
|
||||
@ -1494,11 +1494,11 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
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 */
|
||||
if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) {
|
||||
LIST_REMOVE(xl, entry);
|
||||
LIST_INSERT_HEAD(&conf->l2vpn_list, xl, entry);
|
||||
RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
|
||||
RB_INSERT(l2vpn_head, &conf->l2vpn_tree, xl);
|
||||
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
@ -1516,7 +1516,7 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref)
|
||||
|
||||
/* update existing l2vpns */
|
||||
merge_l2vpn(conf, l2vpn, xl, ref);
|
||||
LIST_REMOVE(xl, entry);
|
||||
RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
|
||||
if (ref && *ref == xl)
|
||||
*ref = l2vpn;
|
||||
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 nbr *nbr;
|
||||
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;
|
||||
|
||||
previous_pw_type = l2vpn->pw_type;
|
||||
previous_mtu = l2vpn->mtu;
|
||||
|
||||
/* 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 */
|
||||
if ((xf = l2vpn_if_find_name(xl, lif->ifname)) == NULL) {
|
||||
if (ldpd_process == PROC_MAIN)
|
||||
QOBJ_UNREG (lif);
|
||||
LIST_REMOVE(lif, entry);
|
||||
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, 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 */
|
||||
if ((lif = l2vpn_if_find_name(l2vpn, xf->ifname)) == NULL) {
|
||||
LIST_REMOVE(xf, entry);
|
||||
LIST_INSERT_HEAD(&l2vpn->if_list, xf, entry);
|
||||
RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
|
||||
RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf);
|
||||
xf->l2vpn = l2vpn;
|
||||
if (ldpd_process == PROC_MAIN)
|
||||
QOBJ_REG (xf, l2vpn_if);
|
||||
continue;
|
||||
}
|
||||
|
||||
LIST_REMOVE(xf, entry);
|
||||
RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf);
|
||||
if (ref && *ref == xf)
|
||||
*ref = lif;
|
||||
free(xf);
|
||||
}
|
||||
|
||||
/* merge active pseudowires */
|
||||
LIST_INIT(&pw_aux_list);
|
||||
LIST_FOREACH_SAFE(pw, &l2vpn->pw_list, entry, ptmp) {
|
||||
RB_INIT(&pw_aux_list);
|
||||
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) {
|
||||
/* find deleted active pseudowires */
|
||||
if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) {
|
||||
switch (ldpd_process) {
|
||||
@ -1580,15 +1580,15 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
|
||||
break;
|
||||
}
|
||||
|
||||
LIST_REMOVE(pw, entry);
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, 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 */
|
||||
if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) {
|
||||
LIST_REMOVE(xp, entry);
|
||||
LIST_INSERT_HEAD(&l2vpn->pw_list, xp, entry);
|
||||
RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
|
||||
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp);
|
||||
xp->l2vpn = l2vpn;
|
||||
|
||||
switch (ldpd_process) {
|
||||
@ -1644,8 +1644,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void
|
||||
}
|
||||
|
||||
/* remove from active list */
|
||||
LIST_REMOVE(pw, entry);
|
||||
LIST_INSERT_HEAD(&pw_aux_list, pw, entry);
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
||||
RB_INSERT(l2vpn_pw_head, &pw_aux_list, pw);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
LIST_REMOVE(xp, entry);
|
||||
RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
|
||||
if (ref && *ref == xp)
|
||||
*ref = pw;
|
||||
free(xp);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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)
|
||||
QOBJ_UNREG (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 */
|
||||
if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) {
|
||||
LIST_REMOVE(xp, entry);
|
||||
LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, xp, entry);
|
||||
RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
|
||||
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp);
|
||||
xp->l2vpn = l2vpn;
|
||||
if (ldpd_process == PROC_MAIN)
|
||||
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 */
|
||||
if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) {
|
||||
/* remove from inactive list */
|
||||
LIST_REMOVE(pw, entry);
|
||||
LIST_INSERT_HEAD(&l2vpn->pw_list, pw, entry);
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
||||
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
||||
|
||||
switch (ldpd_process) {
|
||||
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)
|
||||
*ref = pw;
|
||||
free(xp);
|
||||
}
|
||||
|
||||
/* insert pseudowires that were disabled in the inactive list */
|
||||
LIST_FOREACH_SAFE(pw, &pw_aux_list, entry, ptmp) {
|
||||
LIST_REMOVE(pw, entry);
|
||||
LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, pw, entry);
|
||||
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &pw_aux_list, ptmp) {
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
||||
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
||||
}
|
||||
|
||||
l2vpn->pw_type = xl->pw_type;
|
||||
@ -1770,10 +1770,10 @@ config_new_empty(void)
|
||||
if (xconf == NULL)
|
||||
fatal(NULL);
|
||||
|
||||
LIST_INIT(&xconf->iface_list);
|
||||
LIST_INIT(&xconf->tnbr_list);
|
||||
LIST_INIT(&xconf->nbrp_list);
|
||||
LIST_INIT(&xconf->l2vpn_list);
|
||||
RB_INIT(&xconf->iface_tree);
|
||||
RB_INIT(&xconf->tnbr_tree);
|
||||
RB_INIT(&xconf->nbrp_tree);
|
||||
RB_INIT(&xconf->l2vpn_tree);
|
||||
|
||||
return (xconf);
|
||||
}
|
||||
|
72
ldpd/ldpd.h
72
ldpd/ldpd.h
@ -196,7 +196,10 @@ enum nbr_action {
|
||||
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 {
|
||||
uint8_t type;
|
||||
@ -256,7 +259,7 @@ struct iface_af {
|
||||
int af;
|
||||
int enabled;
|
||||
int state;
|
||||
LIST_HEAD(, adj) adj_list;
|
||||
struct ia_adj_head adj_tree;
|
||||
time_t uptime;
|
||||
struct thread *hello_timer;
|
||||
uint16_t hello_holdtime;
|
||||
@ -264,7 +267,7 @@ struct iface_af {
|
||||
};
|
||||
|
||||
struct iface {
|
||||
LIST_ENTRY(iface) entry;
|
||||
RB_ENTRY(iface) entry;
|
||||
char name[IF_NAMESIZE];
|
||||
unsigned int ifindex;
|
||||
struct if_addr_head addr_list;
|
||||
@ -275,11 +278,13 @@ struct iface {
|
||||
struct iface_af ipv6;
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
RB_HEAD(iface_head, iface);
|
||||
RB_PROTOTYPE(iface_head, iface, entry, iface_compare);
|
||||
DECLARE_QOBJ_TYPE(iface)
|
||||
|
||||
/* source of targeted hellos */
|
||||
struct tnbr {
|
||||
LIST_ENTRY(tnbr) entry;
|
||||
RB_ENTRY(tnbr) entry;
|
||||
struct thread *hello_timer;
|
||||
struct adj *adj;
|
||||
int af;
|
||||
@ -289,6 +294,8 @@ struct tnbr {
|
||||
uint8_t flags;
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
RB_HEAD(tnbr_head, tnbr);
|
||||
RB_PROTOTYPE(tnbr_head, tnbr, entry, tnbr_compare);
|
||||
DECLARE_QOBJ_TYPE(tnbr)
|
||||
#define F_TNBR_CONFIGURED 0x01
|
||||
#define F_TNBR_DYNAMIC 0x02
|
||||
@ -300,7 +307,7 @@ enum auth_method {
|
||||
|
||||
/* neighbor specific parameters */
|
||||
struct nbr_params {
|
||||
LIST_ENTRY(nbr_params) entry;
|
||||
RB_ENTRY(nbr_params) entry;
|
||||
struct in_addr lsr_id;
|
||||
uint16_t keepalive;
|
||||
int gtsm_enabled;
|
||||
@ -313,23 +320,27 @@ struct nbr_params {
|
||||
uint8_t flags;
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
RB_HEAD(nbrp_head, nbr_params);
|
||||
RB_PROTOTYPE(nbrp_head, nbr_params, entry, nbr_params_compare);
|
||||
DECLARE_QOBJ_TYPE(nbr_params)
|
||||
#define F_NBRP_KEEPALIVE 0x01
|
||||
#define F_NBRP_GTSM 0x02
|
||||
#define F_NBRP_GTSM_HOPS 0x04
|
||||
|
||||
struct l2vpn_if {
|
||||
LIST_ENTRY(l2vpn_if) entry;
|
||||
RB_ENTRY(l2vpn_if) entry;
|
||||
struct l2vpn *l2vpn;
|
||||
char ifname[IF_NAMESIZE];
|
||||
unsigned int ifindex;
|
||||
uint16_t flags;
|
||||
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)
|
||||
|
||||
struct l2vpn_pw {
|
||||
LIST_ENTRY(l2vpn_pw) entry;
|
||||
RB_ENTRY(l2vpn_pw) entry;
|
||||
struct l2vpn *l2vpn;
|
||||
struct in_addr lsr_id;
|
||||
int af;
|
||||
@ -343,6 +354,8 @@ struct l2vpn_pw {
|
||||
uint8_t flags;
|
||||
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)
|
||||
#define F_PW_STATUSTLV_CONF 0x01 /* status tlv configured */
|
||||
#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 */
|
||||
|
||||
struct l2vpn {
|
||||
LIST_ENTRY(l2vpn) entry;
|
||||
RB_ENTRY(l2vpn) entry;
|
||||
char name[L2VPN_NAME_LEN];
|
||||
int type;
|
||||
int pw_type;
|
||||
int mtu;
|
||||
char br_ifname[IF_NAMESIZE];
|
||||
unsigned int br_ifindex;
|
||||
LIST_HEAD(, l2vpn_if) if_list;
|
||||
LIST_HEAD(, l2vpn_pw) pw_list;
|
||||
LIST_HEAD(, l2vpn_pw) pw_inactive_list;
|
||||
struct l2vpn_if_head if_tree;
|
||||
struct l2vpn_pw_head pw_tree;
|
||||
struct l2vpn_pw_head pw_inactive_tree;
|
||||
QOBJ_FIELDS
|
||||
};
|
||||
RB_HEAD(l2vpn_head, l2vpn);
|
||||
RB_PROTOTYPE(l2vpn_head, l2vpn, entry, l2vpn_compare);
|
||||
DECLARE_QOBJ_TYPE(l2vpn)
|
||||
#define L2VPN_TYPE_VPWS 1
|
||||
#define L2VPN_TYPE_VPLS 2
|
||||
@ -404,10 +419,10 @@ struct ldpd_conf {
|
||||
struct in_addr rtr_id;
|
||||
struct ldpd_af_conf ipv4;
|
||||
struct ldpd_af_conf ipv6;
|
||||
LIST_HEAD(, iface) iface_list;
|
||||
LIST_HEAD(, tnbr) tnbr_list;
|
||||
LIST_HEAD(, nbr_params) nbrp_list;
|
||||
LIST_HEAD(, l2vpn) l2vpn_list;
|
||||
struct iface_head iface_tree;
|
||||
struct tnbr_head tnbr_tree;
|
||||
struct nbrp_head nbrp_tree;
|
||||
struct l2vpn_head l2vpn_tree;
|
||||
uint16_t lhello_holdtime;
|
||||
uint16_t lhello_interval;
|
||||
uint16_t thello_holdtime;
|
||||
@ -438,7 +453,7 @@ struct ldpd_global {
|
||||
uint32_t conf_seqnum;
|
||||
int pfkeysock;
|
||||
struct if_addr_head addr_list;
|
||||
LIST_HEAD(, adj) adj_list;
|
||||
struct global_adj_head adj_tree;
|
||||
struct in_addr mcast_addr_v4;
|
||||
struct in6_addr mcast_addr_v6;
|
||||
TAILQ_HEAD(, pending_conn) pending_conns;
|
||||
@ -627,23 +642,28 @@ void config_clear(struct ldpd_conf *);
|
||||
|
||||
/* ldp_vty_conf.c */
|
||||
/* 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);
|
||||
void iface_del_api(struct iface *iface);
|
||||
struct tnbr *tnbr_new_api(struct ldpd_conf *cfg, int af,
|
||||
void iface_del_api(struct ldpd_conf *conf,
|
||||
struct iface *iface);
|
||||
struct tnbr *tnbr_new_api(struct ldpd_conf *conf, int af,
|
||||
union ldpd_addr *addr);
|
||||
void tnbr_del_api(struct tnbr *tnbr);
|
||||
struct nbr_params *nbrp_new_api(struct ldpd_conf *cfg,
|
||||
void tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr);
|
||||
struct nbr_params *nbrp_new_api(struct ldpd_conf *conf,
|
||||
struct in_addr lsr_id);
|
||||
void nbrp_del_api(struct nbr_params *nbrp);
|
||||
struct l2vpn *l2vpn_new_api(struct ldpd_conf *cfg, const char *name);
|
||||
void l2vpn_del_api(struct l2vpn *l2vpn);
|
||||
void nbrp_del_api(struct ldpd_conf *conf,
|
||||
struct nbr_params *nbrp);
|
||||
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 *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 *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 */
|
||||
int ldp_create_socket(int, enum socket_type);
|
||||
|
56
ldpd/ldpe.c
56
ldpd/ldpe.c
@ -111,7 +111,7 @@ ldpe(const char *user, const char *group)
|
||||
ldpd_process = PROC_LDP_ENGINE;
|
||||
|
||||
LIST_INIT(&global.addr_list);
|
||||
LIST_INIT(&global.adj_list);
|
||||
RB_INIT(&global.adj_tree);
|
||||
TAILQ_INIT(&global.pending_conns);
|
||||
if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1)
|
||||
fatal("inet_pton");
|
||||
@ -209,7 +209,7 @@ ldpe_shutdown(void)
|
||||
LIST_REMOVE(if_addr, entry);
|
||||
free(if_addr);
|
||||
}
|
||||
while ((adj = LIST_FIRST(&global.adj_list)) != NULL)
|
||||
while ((adj = RB_ROOT(&global.adj_tree)) != NULL)
|
||||
adj_del(adj, S_SHUTDOWN);
|
||||
|
||||
/* clean up */
|
||||
@ -414,10 +414,10 @@ ldpe_dispatch_main(struct thread *thread)
|
||||
fatal(NULL);
|
||||
memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
|
||||
|
||||
LIST_INIT(&nconf->iface_list);
|
||||
LIST_INIT(&nconf->tnbr_list);
|
||||
LIST_INIT(&nconf->nbrp_list);
|
||||
LIST_INIT(&nconf->l2vpn_list);
|
||||
RB_INIT(&nconf->iface_tree);
|
||||
RB_INIT(&nconf->tnbr_tree);
|
||||
RB_INIT(&nconf->nbrp_tree);
|
||||
RB_INIT(&nconf->l2vpn_tree);
|
||||
break;
|
||||
case IMSG_RECONF_IFACE:
|
||||
if ((niface = malloc(sizeof(struct iface))) == NULL)
|
||||
@ -425,37 +425,37 @@ ldpe_dispatch_main(struct thread *thread)
|
||||
memcpy(niface, imsg.data, sizeof(struct iface));
|
||||
|
||||
LIST_INIT(&niface->addr_list);
|
||||
LIST_INIT(&niface->ipv4.adj_list);
|
||||
LIST_INIT(&niface->ipv6.adj_list);
|
||||
RB_INIT(&niface->ipv4.adj_tree);
|
||||
RB_INIT(&niface->ipv6.adj_tree);
|
||||
niface->ipv4.iface = niface;
|
||||
niface->ipv6.iface = niface;
|
||||
|
||||
LIST_INSERT_HEAD(&nconf->iface_list, niface, entry);
|
||||
RB_INSERT(iface_head, &nconf->iface_tree, niface);
|
||||
break;
|
||||
case IMSG_RECONF_TNBR:
|
||||
if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL)
|
||||
fatal(NULL);
|
||||
memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
|
||||
|
||||
LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry);
|
||||
RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr);
|
||||
break;
|
||||
case IMSG_RECONF_NBRP:
|
||||
if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL)
|
||||
fatal(NULL);
|
||||
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;
|
||||
case IMSG_RECONF_L2VPN:
|
||||
if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL)
|
||||
fatal(NULL);
|
||||
memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
|
||||
|
||||
LIST_INIT(&nl2vpn->if_list);
|
||||
LIST_INIT(&nl2vpn->pw_list);
|
||||
LIST_INIT(&nl2vpn->pw_inactive_list);
|
||||
RB_INIT(&nl2vpn->if_tree);
|
||||
RB_INIT(&nl2vpn->pw_tree);
|
||||
RB_INIT(&nl2vpn->pw_inactive_tree);
|
||||
|
||||
LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry);
|
||||
RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn);
|
||||
break;
|
||||
case IMSG_RECONF_L2VPN_IF:
|
||||
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));
|
||||
|
||||
nlif->l2vpn = nl2vpn;
|
||||
LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry);
|
||||
RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif);
|
||||
break;
|
||||
case IMSG_RECONF_L2VPN_PW:
|
||||
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));
|
||||
|
||||
npw->l2vpn = nl2vpn;
|
||||
LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry);
|
||||
RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw);
|
||||
break;
|
||||
case IMSG_RECONF_L2VPN_IPW:
|
||||
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));
|
||||
|
||||
npw->l2vpn = nl2vpn;
|
||||
LIST_INSERT_HEAD(&nl2vpn->pw_inactive_list, npw, entry);
|
||||
RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw);
|
||||
break;
|
||||
case IMSG_RECONF_END:
|
||||
merge_config(leconf, nconf);
|
||||
@ -743,12 +743,12 @@ ldpe_remove_dynamic_tnbrs(int af)
|
||||
{
|
||||
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)
|
||||
continue;
|
||||
|
||||
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 ctl_iface *ictl;
|
||||
|
||||
LIST_FOREACH(iface, &leconf->iface_list, entry) {
|
||||
RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
|
||||
if (idx == 0 || idx == iface->ifindex) {
|
||||
ia = iface_af_get(iface, af);
|
||||
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);
|
||||
|
||||
LIST_FOREACH(iface, &leconf->iface_list, entry) {
|
||||
RB_FOREACH(iface, iface_head, &leconf->iface_tree) {
|
||||
memset(&ictl, 0, sizeof(ictl));
|
||||
ictl.active_v4 = (iface->ipv4.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;
|
||||
|
||||
strlcpy(ictl.name, iface->name, sizeof(ictl.name));
|
||||
if (LIST_EMPTY(&iface->ipv4.adj_list) &&
|
||||
LIST_EMPTY(&iface->ipv6.adj_list))
|
||||
if (RB_EMPTY(&iface->ipv4.adj_tree) &&
|
||||
RB_EMPTY(&iface->ipv6.adj_tree))
|
||||
ictl.no_adj = 1;
|
||||
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0,
|
||||
-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);
|
||||
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_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);
|
||||
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_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));
|
||||
tctl.af = tnbr->af;
|
||||
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,
|
||||
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);
|
||||
imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC,
|
||||
0, 0, -1, actl, sizeof(struct ctl_adj));
|
||||
|
14
ldpd/ldpe.h
14
ldpd/ldpe.h
@ -32,6 +32,9 @@
|
||||
#define min(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 {
|
||||
enum hello_type type;
|
||||
struct {
|
||||
@ -42,9 +45,7 @@ struct hello_source {
|
||||
};
|
||||
|
||||
struct adj {
|
||||
LIST_ENTRY(adj) global_entry;
|
||||
LIST_ENTRY(adj) nbr_entry;
|
||||
LIST_ENTRY(adj) ia_entry;
|
||||
RB_ENTRY(adj) global_entry, nbr_entry, ia_entry;
|
||||
struct in_addr lsr_id;
|
||||
struct nbr *nbr;
|
||||
int ds_tlv;
|
||||
@ -53,6 +54,9 @@ struct adj {
|
||||
uint16_t holdtime;
|
||||
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 nbr *nbr;
|
||||
@ -67,7 +71,7 @@ struct tcp_conn {
|
||||
struct nbr {
|
||||
RB_ENTRY(nbr) id_tree, addr_tree, pid_tree;
|
||||
struct tcp_conn *tcp;
|
||||
LIST_HEAD(, adj) adj_list; /* adjacencies */
|
||||
struct nbr_adj_head adj_tree; /* adjacencies */
|
||||
struct thread *ev_connect;
|
||||
struct thread *keepalive_timer;
|
||||
struct thread *keepalive_timeout;
|
||||
@ -225,7 +229,7 @@ void adj_start_itimer(struct adj *);
|
||||
void adj_stop_itimer(struct adj *);
|
||||
struct tnbr *tnbr_new(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_all(int);
|
||||
uint16_t tnbr_get_hello_holdtime(struct tnbr *);
|
||||
|
@ -39,10 +39,13 @@ static void nbr_start_itimeout(struct nbr *);
|
||||
static int nbr_idtimer(struct thread *);
|
||||
static int nbr_act_session_operational(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_addr_head, nbr, addr_tree, nbr_addr_compare)
|
||||
RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare)
|
||||
RB_GENERATE(nbrp_head, nbr_params, entry, nbr_params_compare)
|
||||
|
||||
struct {
|
||||
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)
|
||||
fatal(__func__);
|
||||
|
||||
LIST_INIT(&nbr->adj_list);
|
||||
RB_INIT(&nbr->adj_tree);
|
||||
nbr->state = NBR_STA_PRESENT;
|
||||
nbr->peerid = 0;
|
||||
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->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) {
|
||||
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;
|
||||
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)
|
||||
total++;
|
||||
|
||||
@ -621,7 +624,7 @@ nbr_establish_connection(struct nbr *nbr)
|
||||
* Send an extra hello to guarantee that the remote peer has formed
|
||||
* 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,
|
||||
adj->source.target);
|
||||
|
||||
@ -752,6 +755,12 @@ nbr_send_labelmappings(struct nbr *nbr)
|
||||
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 *
|
||||
nbr_params_new(struct in_addr lsr_id)
|
||||
{
|
||||
@ -769,13 +778,9 @@ nbr_params_new(struct in_addr lsr_id)
|
||||
struct nbr_params *
|
||||
nbr_params_find(struct ldpd_conf *xconf, struct in_addr lsr_id)
|
||||
{
|
||||
struct nbr_params *nbrp;
|
||||
|
||||
LIST_FOREACH(nbrp, &xconf->nbrp_list, entry)
|
||||
if (nbrp->lsr_id.s_addr == lsr_id.s_addr)
|
||||
return (nbrp);
|
||||
|
||||
return (NULL);
|
||||
struct nbr_params nbrp;
|
||||
nbrp.lsr_id = lsr_id;
|
||||
return (RB_FIND(nbrp_head, &xconf->nbrp_tree, &nbrp));
|
||||
}
|
||||
|
||||
uint16_t
|
||||
|
@ -85,6 +85,8 @@ ldp_create_socket(int af, enum socket_type type)
|
||||
if (ldpd_privs.change(ZPRIVS_RAISE))
|
||||
log_warn("%s: could not raise privs", __func__);
|
||||
if (sock_set_reuse(fd, 1) == -1) {
|
||||
if (ldpd_privs.change(ZPRIVS_LOWER))
|
||||
log_warn("%s: could not lower privs", __func__);
|
||||
close(fd);
|
||||
return (-1);
|
||||
}
|
||||
|
@ -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 offset = VRF_BITMAP_BIT_OFFSET (vrf_id);
|
||||
|
||||
if (bmap == VRF_BITMAP_NULL)
|
||||
if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN)
|
||||
return;
|
||||
|
||||
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 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;
|
||||
|
||||
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 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 CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)],
|
||||
|
98
lib/vty.c
98
lib/vty.c
@ -508,18 +508,6 @@ vty_write (struct vty *vty, const char *buf, size_t 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. */
|
||||
static void
|
||||
vty_self_insert (struct vty *vty, char c)
|
||||
@ -527,7 +515,9 @@ vty_self_insert (struct vty *vty, char c)
|
||||
int i;
|
||||
int length;
|
||||
|
||||
vty_ensure (vty, vty->length + 1);
|
||||
if (vty->length + 1 > VTY_BUFSIZ)
|
||||
return;
|
||||
|
||||
length = vty->length - vty->cp;
|
||||
memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);
|
||||
vty->buf[vty->cp] = c;
|
||||
@ -544,26 +534,29 @@ vty_self_insert (struct vty *vty, char c)
|
||||
static void
|
||||
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;
|
||||
|
||||
if (vty->cp > vty->length)
|
||||
vty->length++;
|
||||
|
||||
if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
|
||||
return;
|
||||
|
||||
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
|
||||
vty_insert_word_overwrite (struct vty *vty, char *str)
|
||||
{
|
||||
int len = strlen (str);
|
||||
vty_write (vty, str, len);
|
||||
strcpy (&vty->buf[vty->cp], str);
|
||||
vty->cp += len;
|
||||
size_t nwrite = MIN ((int) strlen (str), VTY_BUFSIZ - vty->cp);
|
||||
vty_write (vty, str, nwrite);
|
||||
strncpy (&vty->buf[vty->cp], str, nwrite);
|
||||
vty->cp += nwrite;
|
||||
vty->length = vty->cp;
|
||||
}
|
||||
|
||||
@ -2148,36 +2141,45 @@ vtysh_read (struct thread *thread)
|
||||
printf ("line: %.*s\n", nbytes, buf);
|
||||
#endif /* VTYSH_DEBUG */
|
||||
|
||||
for (p = buf; p < buf+nbytes; p++)
|
||||
if (vty->length + nbytes > VTY_BUFSIZ)
|
||||
{
|
||||
vty_ensure(vty, vty->length+1);
|
||||
vty->buf[vty->length++] = *p;
|
||||
if (*p == '\0')
|
||||
/* Clear command line buffer. */
|
||||
vty->cp = vty->length = 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. */
|
||||
ret = vty_execute (vty);
|
||||
/* Note that vty_execute clears the command buffer and resets
|
||||
vty->length to 0. */
|
||||
vty->buf[vty->length++] = *p;
|
||||
if (*p == '\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
|
||||
printf ("result: %d\n", ret);
|
||||
printf ("vtysh node: %d\n", vty->node);
|
||||
printf ("result: %d\n", ret);
|
||||
printf ("vtysh node: %d\n", vty->node);
|
||||
#endif /* VTYSH_DEBUG */
|
||||
|
||||
/* hack for asynchronous "write integrated"
|
||||
* - other commands in "buf" will be ditched
|
||||
* - input during pending config-write is "unsupported" */
|
||||
if (ret == CMD_SUSPEND)
|
||||
break;
|
||||
/* hack for asynchronous "write integrated"
|
||||
* - other commands in "buf" will be ditched
|
||||
* - input during pending config-write is "unsupported" */
|
||||
if (ret == CMD_SUSPEND)
|
||||
break;
|
||||
|
||||
/* warning: watchfrr hardcodes this result write */
|
||||
header[3] = ret;
|
||||
buffer_put(vty->obuf, header, 4);
|
||||
/* warning: watchquagga hardcodes this result write */
|
||||
header[3] = ret;
|
||||
buffer_put(vty->obuf, header, 4);
|
||||
|
||||
if (!vty->t_write && (vtysh_flush(vty) < 0))
|
||||
/* Try to flush results; exit if a write error occurs. */
|
||||
return 0;
|
||||
if (!vty->t_write && (vtysh_flush(vty) < 0))
|
||||
/* Try to flush results; exit if a write error occurs. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "sockunion.h"
|
||||
#include "qobj.h"
|
||||
|
||||
#define VTY_BUFSIZ 512
|
||||
#define VTY_BUFSIZ 4096
|
||||
#define VTY_MAXHIST 20
|
||||
|
||||
/* VTY struct. */
|
||||
|
67
lib/zebra.h
67
lib/zebra.h
@ -473,9 +473,28 @@ typedef enum {
|
||||
#define SAFI_MULTICAST 2
|
||||
#define SAFI_MPLS_VPN 3
|
||||
#define SAFI_RESERVED_4 4
|
||||
#define SAFI_ENCAP 7 /* per IANA */
|
||||
#define SAFI_ENCAP 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. */
|
||||
#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_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 */
|
||||
|
77
m4/ax_prog_perl_modules.m4
Normal file
77
m4/ax_prog_perl_modules.m4
Normal 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
|
@ -424,12 +424,9 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
|
||||
else
|
||||
{
|
||||
summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
|
||||
if (route->type == OSPF6_DEST_TYPE_RANGE)
|
||||
summary->path.origin.id = route->linkstate_id;
|
||||
else
|
||||
summary->path.origin.id =
|
||||
ospf6_new_ls_id (summary->path.origin.type,
|
||||
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);
|
||||
}
|
||||
|
@ -472,8 +472,6 @@ DEFUN (area_range,
|
||||
range->prefix = prefix;
|
||||
range->path.area_id = oa->area_id;
|
||||
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)
|
||||
@ -559,8 +557,6 @@ DEFUN (no_area_range,
|
||||
/* purge the old aggregated summary LSA */
|
||||
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);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
@ -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
|
||||
ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb)
|
||||
|
@ -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,
|
||||
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,
|
||||
u_int32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb);
|
||||
|
@ -682,7 +682,7 @@ ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *on)
|
||||
"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,
|
||||
ospf6_neighbor_state_str[on->state], nstate, duration,
|
||||
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);
|
||||
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],
|
||||
duration, drouter, bdrouter, on->ospf6_if->interface->name,
|
||||
ospf6_interface_state_str[on->ospf6_if->state],
|
||||
@ -856,11 +856,11 @@ DEFUN (show_ipv6_ospf6_neighbor,
|
||||
}
|
||||
|
||||
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",
|
||||
"I/F", "State", VNL);
|
||||
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",
|
||||
"State", VNL);
|
||||
|
||||
|
@ -1266,10 +1266,15 @@ DEFUN (no_ospf_area_vlink,
|
||||
/* message-digest-key */
|
||||
/* Delete one key */
|
||||
i++;
|
||||
vl_config.crypto_key_id = strtol (argv[i]->arg, NULL, 10);
|
||||
if (vl_config.crypto_key_id < 0)
|
||||
if (i < argc)
|
||||
{
|
||||
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;
|
||||
vl_config.md5_key = NULL;
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -124,21 +124,21 @@ static struct test_segment mp_segments[] =
|
||||
"MP IP6/MPLS-labeled VPN",
|
||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 },
|
||||
6, SHOULD_PARSE, 0,
|
||||
1, AFI_IP6, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
/* 7 */
|
||||
{ "MP5",
|
||||
"MP IP6/MPLS-VPN",
|
||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 },
|
||||
6, SHOULD_PARSE, 0,
|
||||
1, AFI_IP6, SAFI_MPLS_VPN, VALID_AFI,
|
||||
1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
/* 8 */
|
||||
{ "MP6",
|
||||
"MP IP4/MPLS-laveled VPN",
|
||||
{ CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 },
|
||||
6, SHOULD_PARSE, 0,
|
||||
1, AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
1, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
/* 10 */
|
||||
{ "MP8",
|
||||
@ -585,22 +585,26 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
|
||||
|
||||
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)
|
||||
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]);
|
||||
/* Convert AFI, SAFI to internal values, check. */
|
||||
if (bgp_map_afi_safi_iana2int (t->afi, t->safi, &afi, &safi))
|
||||
{
|
||||
if (t->afi_valid == VALID_AFI)
|
||||
failed++;
|
||||
}
|
||||
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 (!peer->afc_recv[t->afi][safi])
|
||||
if (!peer->afc_recv[afi][safi])
|
||||
failed++;
|
||||
if (!peer->afc_nego[t->afi][safi])
|
||||
if (!peer->afc_nego[afi][safi])
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ static struct test_segment {
|
||||
{ "IPv4-VPNv4",
|
||||
"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,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
@ -338,12 +338,12 @@ static struct test_segment {
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_PARSE,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-bogus-plen",
|
||||
"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,
|
||||
/* RD */ 0, 0, 1, 2,
|
||||
0, 0xff, 3, 4,
|
||||
@ -355,12 +355,12 @@ static struct test_segment {
|
||||
},
|
||||
(3 + 1 + 3*4 + 1 + 3 + 4 + 1),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-plen1-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,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
@ -381,12 +381,12 @@ static struct test_segment {
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-plen1-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,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
@ -407,12 +407,12 @@ static struct test_segment {
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-plenn-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,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 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),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-plenn-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,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
@ -460,12 +460,12 @@ static struct test_segment {
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
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 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,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 0 */
|
||||
0, 0, 0, 0,
|
||||
@ -486,12 +486,12 @@ static struct test_segment {
|
||||
},
|
||||
(4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_PARSE,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
{ "IPv4-VPNv4-0-nlri",
|
||||
"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,
|
||||
/* RD */ 0, 0, 0, 0, /* RD defined to be 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),
|
||||
SHOULD_ERR,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
|
||||
/* From bug #385 */
|
||||
@ -625,7 +625,7 @@ static struct test_segment mp_unreach_segments [] =
|
||||
{ "IPv4-unreach-VPNv4",
|
||||
"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,
|
||||
0, 1, 2, /* tag */
|
||||
/* rd, 8 octets */
|
||||
@ -641,7 +641,7 @@ static struct test_segment mp_unreach_segments [] =
|
||||
},
|
||||
(3 + (1+3+8+2) + (1+3+8+3)),
|
||||
SHOULD_PARSE,
|
||||
AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI,
|
||||
AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI,
|
||||
},
|
||||
{ NULL, NULL, {0}, 0, 0}
|
||||
};
|
||||
@ -656,19 +656,6 @@ handle_result (struct peer *peer, struct test_segment *t,
|
||||
{
|
||||
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");
|
||||
if (!parse_ret)
|
||||
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);
|
||||
else
|
||||
parse_ret = bgp_mp_unreach_parse (&attr_args, &nlri);
|
||||
|
||||
if (parse_ret == 0 && t->afi_valid == VALID_AFI)
|
||||
assert (nlri.afi == t->afi && nlri.safi == t->safi);
|
||||
if (!parse_ret)
|
||||
{
|
||||
afi_t pkt_afi;
|
||||
safi_t pkt_safi;
|
||||
|
||||
/* Convert AFI, SAFI to internal values, check. */
|
||||
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)
|
||||
{
|
||||
@ -731,7 +729,7 @@ parse_test (struct peer *peer, struct test_segment *t, int type)
|
||||
else
|
||||
nlri_ret = bgp_nlri_parse (peer, NULL, &nlri);
|
||||
}
|
||||
|
||||
zlog_err("xxxxxxxxxxxxxxxx nlri ret %u", nlri_ret);
|
||||
handle_result (peer, t, parse_ret, nlri_ret);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ set testprefix "aspathtest "
|
||||
set aborted 0
|
||||
set color 1
|
||||
|
||||
spawn "./aspathtest"
|
||||
spawn sh -c "exec ./aspathtest 2>/dev/null"
|
||||
|
||||
# proc onetest { test_name note start } {
|
||||
# proc headerline { line } {
|
||||
|
@ -3,7 +3,7 @@ set testprefix "ecommtest "
|
||||
set aborted 0
|
||||
set color 0
|
||||
|
||||
spawn "./ecommtest"
|
||||
spawn sh -c "exec ./ecommtest 2>/dev/null"
|
||||
|
||||
# proc simpletest { start } {
|
||||
|
||||
|
@ -3,7 +3,7 @@ set testprefix "testbgpcap "
|
||||
set aborted 0
|
||||
set color 1
|
||||
|
||||
spawn "./testbgpcap"
|
||||
spawn sh -c "exec ./testbgpcap 2>/dev/null"
|
||||
|
||||
# proc simpletest { start } {
|
||||
|
||||
|
@ -3,7 +3,7 @@ set testprefix "testbgpmpath "
|
||||
set aborted 0
|
||||
set color 1
|
||||
|
||||
spawn "./testbgpmpath"
|
||||
spawn sh -c "exec ./testbgpmpath 2>/dev/null"
|
||||
|
||||
# proc simpletest { start } {
|
||||
|
||||
|
@ -3,7 +3,7 @@ set testprefix "testbgpmpattr "
|
||||
set aborted 0
|
||||
set color 1
|
||||
|
||||
spawn "./testbgpmpattr"
|
||||
spawn sh -c "exec ./testbgpmpattr 2>/dev/null"
|
||||
|
||||
# proc simpletest { start } {
|
||||
|
||||
|
@ -2,7 +2,7 @@ set timeout 10
|
||||
set testprefix "tabletest "
|
||||
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 < 11} {incr i 1} { onesimple "succ $i" "Verifying successor"; }
|
||||
|
@ -2,6 +2,6 @@ set timeout 10
|
||||
set testprefix "test-timer-correctness"
|
||||
set aborted 0
|
||||
|
||||
spawn "./test-timer-correctness"
|
||||
spawn sh -c "exec ./test-timer-correctness 2>/dev/null"
|
||||
|
||||
onesimple "" "Expected output and actual output match."
|
||||
|
@ -2,7 +2,7 @@ set timeout 10
|
||||
set testprefix "testnexthopiter "
|
||||
set aborted 0
|
||||
|
||||
spawn "./testnexthopiter"
|
||||
spawn sh -c "exec ./testnexthopiter 2>/dev/null"
|
||||
|
||||
onesimple "simple" "Simple test passed."
|
||||
onesimple "prng" "PRNG test passed."
|
||||
|
@ -1,5 +1,5 @@
|
||||
set timeout 10
|
||||
spawn "./teststream"
|
||||
spawn sh -c "exec ./teststream 2>/dev/null"
|
||||
|
||||
expect {
|
||||
"endp: 15, readable: 15, writeable: 1009" { }
|
||||
|
@ -141,6 +141,8 @@ sub generate_arguments {
|
||||
# argument is the name of the node
|
||||
if ($node{'input'} or $node{'type'} eq "select") {
|
||||
$arg_value = "argv[" . $argc . "]->arg";
|
||||
} elsif ($node{'optional'}) {
|
||||
$arg_value = "(argc > " . $argc . " ? argv[" . $argc. "]->arg : NULL)";
|
||||
} else {
|
||||
$arg_value = '"' . $node{'name'} . '"';
|
||||
}
|
||||
@ -196,7 +198,11 @@ sub generate_code {
|
||||
$helpstr .= $::options{$options_name}{'help'};
|
||||
} else {
|
||||
$funcname .= $node{'name'} . " ";
|
||||
$cmdstr .= $node{'name'} . " ";
|
||||
if ($node{'optional'}) {
|
||||
$cmdstr .= "[" . $node{'name'} . "] ";
|
||||
} else {
|
||||
$cmdstr .= $node{'name'} . " ";
|
||||
}
|
||||
$helpstr .= "\n \"" . $node{'help'} . "\\n\"";
|
||||
}
|
||||
|
||||
@ -279,6 +285,7 @@ sub parse_tree {
|
||||
$node{'help'} = $xml_node->findvalue('./@help');
|
||||
$node{'function'} = $xml_node->findvalue('./@function');
|
||||
$node{'ifdef'} = $xml_node->findvalue('./@ifdef');
|
||||
$node{'optional'} = $xml_node->findvalue('./@optional');
|
||||
|
||||
# push node to stack
|
||||
push (@nodes, \%node);
|
||||
|
2156
watchfrr/watchfrr.c
2156
watchfrr/watchfrr.c
File diff suppressed because it is too large
Load Diff
@ -26,4 +26,4 @@ extern void watchfrr_vty_init(void);
|
||||
extern pid_t integrated_write_pid;
|
||||
extern void integrated_write_sigchld(int status);
|
||||
|
||||
#endif /* FRR_WATCHFRR_H */
|
||||
#endif /* FRR_WATCHFRR_H */
|
||||
|
@ -31,18 +31,18 @@
|
||||
pid_t integrated_write_pid;
|
||||
static int integrated_result_fd;
|
||||
|
||||
DEFUN (config_write_integrated,
|
||||
config_write_integrated_cmd,
|
||||
"write integrated",
|
||||
"Write running configuration to memory, network, or terminal\n"
|
||||
"Write integrated all-daemon Frr.conf file\n")
|
||||
DEFUN(config_write_integrated,
|
||||
config_write_integrated_cmd,
|
||||
"write integrated",
|
||||
"Write running configuration to memory, network, or terminal\n"
|
||||
"Write integrated all-daemon Frr.conf file\n")
|
||||
{
|
||||
pid_t child;
|
||||
sigset_t oldmask, sigmask;
|
||||
|
||||
if (integrated_write_pid != -1) {
|
||||
vty_out(vty, "%% configuration write already in progress.%s",
|
||||
VTY_NEWLINE);
|
||||
VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
@ -61,20 +61,20 @@ DEFUN (config_write_integrated,
|
||||
child = fork();
|
||||
if (child == -1) {
|
||||
vty_out(vty, "%% configuration write fork() failed: %s.%s",
|
||||
safe_strerror(errno), VTY_NEWLINE);
|
||||
safe_strerror(errno), VTY_NEWLINE);
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
if (child != 0) {
|
||||
/* note: the VTY won't write a command return value to vtysh; the
|
||||
* session temporarily enters an intentional "hang" state. This is
|
||||
* to make sure latency in vtysh doing the config write (several
|
||||
* seconds is not rare to see) does not interfere with watchfrr's
|
||||
* supervisor job.
|
||||
*
|
||||
* The fd is duplicated here so we don't need to hold a vty pointer
|
||||
* (which could become invalid in the meantime).
|
||||
*/
|
||||
/* note: the VTY won't write a command return value to vtysh; the
|
||||
* session temporarily enters an intentional "hang" state. This is
|
||||
* to make sure latency in vtysh doing the config write (several
|
||||
* seconds is not rare to see) does not interfere with watchfrr's
|
||||
* supervisor job.
|
||||
*
|
||||
* The fd is duplicated here so we don't need to hold a vty pointer
|
||||
* (which could become invalid in the meantime).
|
||||
*/
|
||||
integrated_write_pid = child;
|
||||
integrated_result_fd = dup(vty->wfd);
|
||||
sigprocmask(SIG_SETMASK, &oldmask, NULL);
|
||||
@ -93,7 +93,7 @@ DEFUN (config_write_integrated,
|
||||
/* unbuffered write; we just messed with stdout... */
|
||||
char msg[512];
|
||||
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));
|
||||
exit(1);
|
||||
}
|
||||
@ -104,11 +104,11 @@ void integrated_write_sigchld(int status)
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
zlog_info("configuration write completed with exit code %d",
|
||||
WEXITSTATUS(status));
|
||||
WEXITSTATUS(status));
|
||||
reply[3] = WEXITSTATUS(status);
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
zlog_warn("configuration write terminated by signal %d",
|
||||
WTERMSIG(status));
|
||||
WTERMSIG(status));
|
||||
} else {
|
||||
zlog_warn("configuration write terminated");
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd,
|
||||
|
||||
/* tag */
|
||||
if (tag_str)
|
||||
tag = atol(tag_str);
|
||||
VTY_GET_INTEGER_RANGE("tag", tag, tag_str, 0, 4294967295);
|
||||
|
||||
/* VRF id */
|
||||
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"))
|
||||
{
|
||||
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
|
||||
{
|
||||
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);
|
||||
@ -1918,7 +1918,7 @@ DEFUN (show_ip_route_vrf_all_tag,
|
||||
route_tag_t tag = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
@ -2356,7 +2356,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str,
|
||||
|
||||
/* tag */
|
||||
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
|
||||
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"))
|
||||
{
|
||||
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
|
||||
{
|
||||
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);
|
||||
@ -3252,7 +3252,7 @@ DEFUN (show_ipv6_route_vrf_all_tag,
|
||||
route_tag_t tag = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user