diff options
author | Christian Poessinger <christian@poessinger.com> | 2021-08-24 12:27:07 +0200 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2021-08-24 12:27:07 +0200 |
commit | 474db49afc759eeacc2208a18995452e6fe5f6fc (patch) | |
tree | 38c8c7ed731e2d5bcdae211c07a362e2a6b36c52 | |
parent | a98b0d886f522ca9620182bd0f1a2f73a905f35a (diff) | |
download | vyos-1x-474db49afc759eeacc2208a18995452e6fe5f6fc.tar.gz vyos-1x-474db49afc759eeacc2208a18995452e6fe5f6fc.zip |
bgp: T3759: "l2vpn evpn" and ipv4/ipv6 safi route-targets differ
The "l2vpn evpn" address-family route-target command only accepts a single
route-target value consisting of (A.B.C.D:MN|EF:OPQR|GHJK:MN). The
"ipv4-unicast or ipv6-unicast" address-family route-target command for VPNs
support multiple, whitespace separated route-target values.
This commit adds a new custom validator named "bgp-route-target" with a --single
and a --multi option to pass one or more route-target values.
7 files changed, 141 insertions, 62 deletions
diff --git a/interface-definitions/include/bgp/afi-l2vpn-common.xml.i b/interface-definitions/include/bgp/afi-l2vpn-common.xml.i index a9a833851..8deb189ab 100644 --- a/interface-definitions/include/bgp/afi-l2vpn-common.xml.i +++ b/interface-definitions/include/bgp/afi-l2vpn-common.xml.i @@ -17,9 +17,42 @@ <help>Route Target</help> </properties> <children> - #include <include/bgp/route-target-both.xml.i> - #include <include/bgp/route-target-export.xml.i> - #include <include/bgp/route-target-import.xml.i> + <leafNode name="both"> + <properties> + <help>Route Target both import and export</help> + <valueHelp> + <format>txt</format> + <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> + </valueHelp> + <constraint> + <validator name="bgp-route-target" argument="--single"/> + </constraint> + </properties> + </leafNode> + <leafNode name="import"> + <properties> + <help>Route Target import</help> + <valueHelp> + <format>txt</format> + <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> + </valueHelp> + <constraint> + <validator name="bgp-route-target" argument="--single"/> + </constraint> + </properties> + </leafNode> + <leafNode name="export"> + <properties> + <help>Route Target export</help> + <valueHelp> + <format>txt</format> + <description>Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> + </valueHelp> + <constraint> + <validator name="bgp-route-target" argument="--single"/> + </constraint> + </properties> + </leafNode> </children> </node> <!-- include end --> diff --git a/interface-definitions/include/bgp/afi-route-target-vpn.xml.i b/interface-definitions/include/bgp/afi-route-target-vpn.xml.i new file mode 100644 index 000000000..1dc184a02 --- /dev/null +++ b/interface-definitions/include/bgp/afi-route-target-vpn.xml.i @@ -0,0 +1,52 @@ +<!-- include start from bgp/route-target-both.xml.i --> +<node name="route-target"> + <properties> + <help>Specify route distinguisher</help> + </properties> + <children> + <node name="vpn"> + <properties> + <help>Between current address-family and VPN</help> + </properties> + <children> + <leafNode name="both"> + <properties> + <help>Route Target both import and export</help> + <valueHelp> + <format>txt</format> + <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> + </valueHelp> + <constraint> + <validator name="bgp-route-target" argument="--multi"/> + </constraint> + </properties> + </leafNode> + <leafNode name="import"> + <properties> + <help>Route Target import</help> + <valueHelp> + <format>txt</format> + <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> + </valueHelp> + <constraint> + <validator name="bgp-route-target" argument="--multi"/> + </constraint> + </properties> + </leafNode> + <leafNode name="export"> + <properties> + <help>Route Target export</help> + <valueHelp> + <format>txt</format> + <description>Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)</description> + </valueHelp> + <constraint> + <validator name="bgp-route-target" argument="--multi"/> + </constraint> + </properties> + </leafNode> + </children> + </node> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i index a971c52b8..2b22bac7d 100644 --- a/interface-definitions/include/bgp/protocol-common-config.xml.i +++ b/interface-definitions/include/bgp/protocol-common-config.xml.i @@ -119,23 +119,7 @@ </tagNode> #include <include/bgp/afi-rd.xml.i> #include <include/bgp/afi-route-map-vpn.xml.i> - <node name="route-target"> - <properties> - <help>Specify route distinguisher</help> - </properties> - <children> - <node name="vpn"> - <properties> - <help>Between current address-family and VPN</help> - </properties> - <children> - #include <include/bgp/route-target-both.xml.i> - #include <include/bgp/route-target-export.xml.i> - #include <include/bgp/route-target-import.xml.i> - </children> - </node> - </children> - </node> + #include <include/bgp/afi-route-target-vpn.xml.i> <node name="redistribute"> <properties> <help>Redistribute routes from other protocols into BGP</help> @@ -520,6 +504,7 @@ </tagNode> #include <include/bgp/afi-rd.xml.i> #include <include/bgp/afi-route-map-vpn.xml.i> + #include <include/bgp/afi-route-target-vpn.xml.i> <node name="redistribute"> <properties> <help>Redistribute routes from other protocols into BGP</help> diff --git a/interface-definitions/include/bgp/route-target-both.xml.i b/interface-definitions/include/bgp/route-target-both.xml.i deleted file mode 100644 index d77878812..000000000 --- a/interface-definitions/include/bgp/route-target-both.xml.i +++ /dev/null @@ -1,14 +0,0 @@ -<!-- include start from bgp/route-target-both.xml.i --> -<leafNode name="both"> - <properties> - <help>Route Target both import and export</help> - <valueHelp> - <format>txt</format> - <description>Route target (x.x.x.x:yyy|xxxx:yyyy)</description> - </valueHelp> - <constraint> - <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex> - </constraint> - </properties> -</leafNode> -<!-- include end --> diff --git a/interface-definitions/include/bgp/route-target-export.xml.i b/interface-definitions/include/bgp/route-target-export.xml.i deleted file mode 100644 index 0431f0fcb..000000000 --- a/interface-definitions/include/bgp/route-target-export.xml.i +++ /dev/null @@ -1,14 +0,0 @@ -<!-- include start from bgp/route-target-export.xml.i --> -<leafNode name="export"> - <properties> - <help>Route Target export</help> - <valueHelp> - <format>txt</format> - <description>Route target (x.x.x.x:yyy|xxxx:yyyy)</description> - </valueHelp> - <constraint> - <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex> - </constraint> - </properties> -</leafNode> -<!-- include end --> diff --git a/interface-definitions/include/bgp/route-target-import.xml.i b/interface-definitions/include/bgp/route-target-import.xml.i deleted file mode 100644 index aa861c428..000000000 --- a/interface-definitions/include/bgp/route-target-import.xml.i +++ /dev/null @@ -1,14 +0,0 @@ -<!-- include start from bgp/route-target-import.xml.i --> -<leafNode name="import"> - <properties> - <help>Route Target import</help> - <valueHelp> - <format>txt</format> - <description>Route target (x.x.x.x:yyy|xxxx:yyyy)</description> - </valueHelp> - <constraint> - <regex>^((25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)(\.(25[0-5]|2[0-4][0-9]|[1][0-9][0-9]|[1-9][0-9]|[0-9]?)){3}|[0-9]{1,10}):[0-9]{1,5}$</regex> - </constraint> - </properties> -</leafNode> -<!-- include end --> diff --git a/src/validators/bgp-route-target b/src/validators/bgp-route-target new file mode 100755 index 000000000..e7e4d403f --- /dev/null +++ b/src/validators/bgp-route-target @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2021 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from argparse import ArgumentParser +from vyos.template import is_ipv4 + +parser = ArgumentParser() +group = parser.add_mutually_exclusive_group() +group.add_argument('--single', action='store', help='Validate and allow only one route-target') +group.add_argument('--multi', action='store', help='Validate multiple, whitespace separated route-targets') +args = parser.parse_args() + +def is_valid_rt(rt): + # every route target needs to have a colon and must consists of two parts + value = rt.split(':') + if len(value) != 2: + return False + # A route target must either be only numbers, or the first part must be an + # IPv4 address + if (is_ipv4(value[0]) or value[0].isdigit()) and value[1].isdigit(): + return True + return False + +if __name__ == '__main__': + if args.single: + if not is_valid_rt(args.single): + exit(1) + + elif args.multi: + for rt in args.multi.split(' '): + if not is_valid_rt(rt): + exit(1) + + else: + parser.print_help() + exit(1) + + exit(0) |