diff options
author | zsdc <taras@vyos.io> | 2022-10-18 12:25:54 +0300 |
---|---|---|
committer | zsdc <taras@vyos.io> | 2022-10-18 12:25:54 +0300 |
commit | f78ad4c4c4cb94fe6bf321d9a6b8f54328b4cb79 (patch) | |
tree | 0115c871bf76cb11516c0968340fad12e76097ad | |
parent | d4097690c40f619bc0e78a0d674985f7880a19a3 (diff) | |
download | vyatta-cfg-quagga-f78ad4c4c4cb94fe6bf321d9a6b8f54328b4cb79.tar.gz vyatta-cfg-quagga-f78ad4c4c4cb94fe6bf321d9a6b8f54328b4cb79.zip |
bgp listen: T1875: added BGP listen range feature
This change provides the same CLI structure as in 1.4 for the
`protocols bgp listen` and must be fully compatible with future releases
(no additional migration is required).
5 files changed, 127 insertions, 6 deletions
diff --git a/scripts/bgp/vyatta-bgp.pl b/scripts/bgp/vyatta-bgp.pl index 3e49e1d1..9b8d0a3a 100755 --- a/scripts/bgp/vyatta-bgp.pl +++ b/scripts/bgp/vyatta-bgp.pl @@ -687,6 +687,26 @@ my %qcom = ( set => 'router bgp #3 ; neighbor #5 weight #7', del => 'router bgp #3 ; no neighbor #5 weight', }, + 'protocols bgp var listen' => { + set => undef, + del => undef, + }, + 'protocols bgp var listen limit' => { + set => 'router bgp #3 ; bgp listen limit #6', + del => 'router bgp #3 ; no bgp listen limit #6', + }, + 'protocols bgp var listen range' => { + set => undef, + del => undef, + }, + 'protocols bgp var listen range var' => { + set => undef, + del => undef, + }, + 'protocols bgp var listen range var peer-group' => { + set => 'router bgp #3 ; bgp listen range #6 peer-group #8', + del => 'router bgp #3 ; no bgp listen range #6 peer-group #8', + }, 'protocols bgp var parameters' => { set => undef, del => undef, @@ -1219,7 +1239,8 @@ if ( ! -e "/usr/sbin/zebra" ) { my ( $pg, $as, $neighbor ); my ( $main, $peername, $isneighbor, $checkpeergroups, $checkpeergroups6, $checksource, - $isiBGPpeer, $wasiBGPpeer, $confedibgpasn, $listpeergroups, $checkremoteas, $checkbfdpeer, $checkbfdgroup); + $isiBGPpeer, $wasiBGPpeer, $confedibgpasn, $listpeergroups, $checkremoteas, $checkbfdpeer, $checkbfdgroup, + $checkbgplisten); GetOptions( "peergroup=s" => \$pg, @@ -1237,6 +1258,7 @@ GetOptions( "check-remote-as=s" => \$checkremoteas, "check-bfd-peer=s" => \$checkbfdpeer, "check-peer-group-bfd=s" => \$checkbfdgroup, + "check-bgp-listen" => \$checkbgplisten, "main" => \$main, ); @@ -1253,6 +1275,7 @@ list_peer_groups($as) if ($listpeergroups); check_remote_as($checkremoteas) if ($checkremoteas); check_bfd_peer($checkbfdpeer) if ($checkbfdpeer); check_bfd_group($checkbfdgroup, $as) if ($checkbfdgroup); +check_bgp_listen($as) if ($checkbgplisten); exit 0; @@ -1359,15 +1382,15 @@ sub check_for_peer_groups { my @peers; # get the list of neighbors and see if they have a peer-group set - $config->setLevel("protocols bgp $as neighbor"); - my @neighbors = $config->listNodes(); + $config->setLevel("protocols bgp $as"); + my @neighbors = $config->listNodes("neighbor"); foreach my $node (@neighbors) { - my $peergroup = $config->returnValue("$node peer-group"); + my $peergroup = $config->returnValue("neighbor $node peer-group"); if ((defined $peergroup) && ($peergroup eq $pg)) { push @peers, $node; } - $peergroup = $config->returnValue("$node interface peer-group"); + $peergroup = $config->returnValue("neighbor $node interface peer-group"); if ((defined $peergroup) && ($peergroup eq $pg)) { push @peers, $node; } - $peergroup = $config->returnValue("$node interface v6only peer-group"); + $peergroup = $config->returnValue("neighbor $node interface v6only peer-group"); if ((defined $peergroup) && ($peergroup eq $pg)) { push @peers, $node; } } @@ -1380,6 +1403,17 @@ sub check_for_peer_groups { die "please delete these peers before removing the peer-group\n"; } + + # check BGP listen ranges + if ($config->exists("listen range")) { + my @listen_ranges = $config->listNodes("listen range"); + foreach my $range (@listen_ranges) { + my $peer_group = $config->returnValue("listen range $range peer-group"); + if ($pg eq $peer_group) { + die "BGP peer-group $peer_group is used for BGP listen range $range and cannot be deleted\n"; + } + } + } } # function to verify changing remote-as from/to i/eBGP @@ -1805,6 +1839,74 @@ sub check_bfd_group { } } +# check if ranges are overlapped +sub ranges_overlapped { + my @ranges = @_; + + foreach my $range (@ranges) { + foreach my $range_other (@ranges) { + if ($range_other != $range) { + my $first_address = $range->network(); + my $last_address = $range->broadcast(); + my $first_address_other = $range_other->network(); + my $last_address_other = $range_other->broadcast(); + + if (($first_address >= $first_address_other and $first_address <= $last_address_other) or + ($last_address >= $first_address_other and $last_address <= $last_address_other)) { + # ranges are overlapped + print "Listen ranges cannot overlap: $range and $range_other\n"; + return 1; + } + } + } + } + # return undef if ranges are not overlapped + return undef; +} + +# check BGP listen options +sub check_bgp_listen { + my $as = shift; + die "AS not defined\n" unless $as; + my @listen_ranges; + my @ranges_v4; + my @ranges_v6; + + # get a list of ranges + my $config = new Vyatta::Config; + $config->setLevel("protocols bgp $as"); + if ($config->exists("listen range")) { + @listen_ranges = $config->listNodes("listen range"); + } + + foreach my $range (@listen_ranges) { + # check if a peer-group is changed - this is not supported by FRR, + # a listen range must be removed and added with a new peer-group in two commits + if ($config->isChanged("listen range $range peer-group") and not $config->isAdded("listen range $range") ) { + die "A peer-group cannot be changed. A listen range $range needs to be removed and added again with the new peer-group\n"; + } + + # check if a peer-group is defined + if (not $config->exists("listen range $range peer-group")) { + die "A peer-group must be configured for range $range\n"; + } + + # sort IPv4 and IPv6 ranges + my $range_netaddr = new NetAddr::IP::Lite($range); + if ($range_netaddr->version() == 4) { + push(@ranges_v4, $range_netaddr); + } + if ($range_netaddr->version() == 6) { + push(@ranges_v6, $range_netaddr); + } + } + + # check if listen ranges are not overlapped + if (ranges_overlapped(@ranges_v4) or ranges_overlapped(@ranges_v6)) { + die "Configuration error\n"; + } +} + sub main { # initialize the Quagga Config object with data from Vyatta config tree @@ -1834,6 +1936,7 @@ sub main # notice the extra space in the level string. keeps the parent from being deleted. $qconfig->deleteConfigTreeRecursive('protocols bgp var neighbor var', undef, \@ordered) || die "exiting $?\n"; + $qconfig->deleteConfigTreeRecursive('protocols bgp var listen') || die "exiting $?\n"; $qconfig->deleteConfigTreeRecursive('protocols bgp var peer-group var', undef, \@ordered) || die "exiting $?\n"; $qconfig->deleteConfigTreeRecursive('protocols bgp') || die "exiting $?\n"; @@ -1848,5 +1951,6 @@ sub main $qconfig->setConfigTreeRecursive('protocols bgp var neighbor var address-family ipv6-unicast' , undef, \@ordered) || die "exiting $?\n"; $qconfig->setConfigTreeRecursive('protocols bgp var neighbor var ', undef, \@ordered) || die "exiting $?\n"; + $qconfig->setConfigTreeRecursive('protocols bgp var listen') || die "exiting $?\n"; $qconfig->setConfigTreeRecursive('protocols bgp') || die "exiting $?\n"; } diff --git a/templates/protocols/bgp/node.tag/listen/limit/node.def b/templates/protocols/bgp/node.tag/listen/limit/node.def new file mode 100644 index 00000000..dd249458 --- /dev/null +++ b/templates/protocols/bgp/node.tag/listen/limit/node.def @@ -0,0 +1,4 @@ +type: txt +help: Maximum number of dynamic neighbors that can be created +val_help: u32:1-5000; BGP neighbor limit +syntax:expression: exec "${vyos_libexec_dir}/validate-value --exec \"${vyos_validators_dir}/numeric --range 1-5000\" --value \'$VAR(@)\'"; "Invalid value" diff --git a/templates/protocols/bgp/node.tag/listen/node.def b/templates/protocols/bgp/node.tag/listen/node.def new file mode 100644 index 00000000..5e42f6f5 --- /dev/null +++ b/templates/protocols/bgp/node.tag/listen/node.def @@ -0,0 +1 @@ +help: Listen for and accept BGP dynamic neighbors from range diff --git a/templates/protocols/bgp/node.tag/listen/range/node.def b/templates/protocols/bgp/node.tag/listen/range/node.def new file mode 100644 index 00000000..262cb77b --- /dev/null +++ b/templates/protocols/bgp/node.tag/listen/range/node.def @@ -0,0 +1,7 @@ +tag: +type: txt +help: BGP dynamic neighbors listen range +val_help: ipv4net; IPv4 dynamic neighbors listen range +val_help: ipv6net; IPv6 dynamic neighbors listen range +syntax:expression: exec "${vyos_libexec_dir}/validate-value --exec \"${vyos_validators_dir}/ipv4-prefix \" --exec \"${vyos_validators_dir}/ipv6-prefix \" --value \'$VAR(@)\'"; "Invalid value" +commit:expression: exec "/opt/vyatta/sbin/vyatta-bgp.pl --check-bgp-listen --as $VAR(../../@)" diff --git a/templates/protocols/bgp/node.tag/listen/range/node.tag/peer-group/node.def b/templates/protocols/bgp/node.tag/listen/range/node.tag/peer-group/node.def new file mode 100644 index 00000000..b58d9263 --- /dev/null +++ b/templates/protocols/bgp/node.tag/listen/range/node.tag/peer-group/node.def @@ -0,0 +1,5 @@ +type: txt +help: Peer group for this peer +val_help: txt; Peer-group name +allowed: /bin/cli-shell-api listNodes protocols bgp $VAR(../../../@) peer-group +commit:expression: exec "/opt/vyatta/sbin/vyatta_quagga_utils.pl --exists \"protocols bgp $VAR(../../../@) peer-group $VAR(@)\" "; "protocols bgp $VAR(../../../@) peer-group $VAR(@) doesn't exist" |