2002-12-13 21:15:29 +01:00
|
|
|
/* Route map function of bgpd.
|
2017-05-13 10:25:29 +02:00
|
|
|
* Copyright (C) 1998, 1999 Kunihiro Ishiguro
|
|
|
|
*
|
|
|
|
* This file is part of GNU Zebra.
|
|
|
|
*
|
|
|
|
* GNU Zebra is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
|
|
* later version.
|
|
|
|
*
|
|
|
|
* GNU Zebra 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; see the file COPYING; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "filter.h"
|
|
|
|
#include "routemap.h"
|
|
|
|
#include "command.h"
|
|
|
|
#include "linklist.h"
|
|
|
|
#include "plist.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "log.h"
|
2019-05-09 22:08:40 +02:00
|
|
|
#include "frrlua.h"
|
2009-01-12 22:06:12 +01:00
|
|
|
#ifdef HAVE_LIBPCREPOSIX
|
2017-07-17 14:03:14 +02:00
|
|
|
#include <pcreposix.h>
|
2002-12-13 21:15:29 +01:00
|
|
|
#else
|
2017-07-17 14:03:14 +02:00
|
|
|
#include <regex.h>
|
2009-01-12 22:06:12 +01:00
|
|
|
#endif /* HAVE_LIBPCREPOSIX */
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "buffer.h"
|
|
|
|
#include "sockunion.h"
|
2015-05-20 02:40:45 +02:00
|
|
|
#include "hash.h"
|
2015-05-20 03:03:47 +02:00
|
|
|
#include "queue.h"
|
2018-06-19 17:59:53 +02:00
|
|
|
#include "frrstr.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include "bgpd/bgpd.h"
|
|
|
|
#include "bgpd/bgp_table.h"
|
|
|
|
#include "bgpd/bgp_attr.h"
|
|
|
|
#include "bgpd/bgp_aspath.h"
|
2015-05-20 02:40:45 +02:00
|
|
|
#include "bgpd/bgp_packet.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "bgpd/bgp_route.h"
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
#include "bgpd/bgp_zebra.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "bgpd/bgp_regex.h"
|
|
|
|
#include "bgpd/bgp_community.h"
|
|
|
|
#include "bgpd/bgp_clist.h"
|
|
|
|
#include "bgpd/bgp_filter.h"
|
|
|
|
#include "bgpd/bgp_mplsvpn.h"
|
|
|
|
#include "bgpd/bgp_ecommunity.h"
|
2016-11-15 11:00:39 +01:00
|
|
|
#include "bgpd/bgp_lcommunity.h"
|
2008-07-02 15:40:33 +02:00
|
|
|
#include "bgpd/bgp_vty.h"
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
#include "bgpd/bgp_debug.h"
|
2017-06-21 10:02:46 +02:00
|
|
|
#include "bgpd/bgp_evpn.h"
|
|
|
|
#include "bgpd/bgp_evpn_private.h"
|
2017-06-21 17:14:24 +02:00
|
|
|
#include "bgpd/bgp_evpn_vty.h"
|
2018-03-09 21:52:55 +01:00
|
|
|
#include "bgpd/bgp_mplsvpn.h"
|
2019-06-14 12:05:18 +02:00
|
|
|
#include "bgpd/bgp_pbr.h"
|
|
|
|
#include "bgpd/bgp_flowspec_util.h"
|
2019-06-19 23:29:34 +02:00
|
|
|
#include "bgpd/bgp_encap_types.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
bgpd: add L3/L2VPN Virtual Network Control feature
This feature adds an L3 & L2 VPN application that makes use of the VPN
and Encap SAFIs. This code is currently used to support IETF NVO3 style
operation. In NVO3 terminology it provides the Network Virtualization
Authority (NVA) and the ability to import/export IP prefixes and MAC
addresses from Network Virtualization Edges (NVEs). The code supports
per-NVE tables.
The NVE-NVA protocol used to communicate routing and Ethernet / Layer 2
(L2) forwarding information between NVAs and NVEs is referred to as the
Remote Forwarder Protocol (RFP). OpenFlow is an example RFP. For
general background on NVO3 and RFP concepts see [1]. For information on
Openflow see [2].
RFPs are integrated with BGP via the RF API contained in the new "rfapi"
BGP sub-directory. Currently, only a simple example RFP is included in
Quagga. Developers may use this example as a starting point to integrate
Quagga with an RFP of their choosing, e.g., OpenFlow. The RFAPI code
also supports the ability import/export of routing information between
VNC and customer edge routers (CEs) operating within a virtual
network. Import/export may take place between BGP views or to the
default zebera VRF.
BGP, with IP VPNs and Tunnel Encapsulation, is used to distribute VPN
information between NVAs. BGP based IP VPN support is defined in
RFC4364, BGP/MPLS IP Virtual Private Networks (VPNs), and RFC4659,
BGP-MPLS IP Virtual Private Network (VPN) Extension for IPv6 VPN . Use
of both the Encapsulation Subsequent Address Family Identifier (SAFI)
and the Tunnel Encapsulation Attribute, RFC5512, The BGP Encapsulation
Subsequent Address Family Identifier (SAFI) and the BGP Tunnel
Encapsulation Attribute, are supported. MAC address distribution does
not follow any standard BGB encoding, although it was inspired by the
early IETF EVPN concepts.
The feature is conditionally compiled and disabled by default.
Use the --enable-bgp-vnc configure option to enable.
The majority of this code was authored by G. Paul Ziemba
<paulz@labn.net>.
[1] http://tools.ietf.org/html/draft-ietf-nvo3-nve-nva-cp-req
[2] https://www.opennetworking.org/sdn-resources/technical-library
Now includes changes needed to merge with cmaster-next.
2016-05-07 20:18:56 +02:00
|
|
|
#if ENABLE_BGP_VNC
|
2017-07-17 14:03:14 +02:00
|
|
|
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
|
bgpd: add L3/L2VPN Virtual Network Control feature
This feature adds an L3 & L2 VPN application that makes use of the VPN
and Encap SAFIs. This code is currently used to support IETF NVO3 style
operation. In NVO3 terminology it provides the Network Virtualization
Authority (NVA) and the ability to import/export IP prefixes and MAC
addresses from Network Virtualization Edges (NVEs). The code supports
per-NVE tables.
The NVE-NVA protocol used to communicate routing and Ethernet / Layer 2
(L2) forwarding information between NVAs and NVEs is referred to as the
Remote Forwarder Protocol (RFP). OpenFlow is an example RFP. For
general background on NVO3 and RFP concepts see [1]. For information on
Openflow see [2].
RFPs are integrated with BGP via the RF API contained in the new "rfapi"
BGP sub-directory. Currently, only a simple example RFP is included in
Quagga. Developers may use this example as a starting point to integrate
Quagga with an RFP of their choosing, e.g., OpenFlow. The RFAPI code
also supports the ability import/export of routing information between
VNC and customer edge routers (CEs) operating within a virtual
network. Import/export may take place between BGP views or to the
default zebera VRF.
BGP, with IP VPNs and Tunnel Encapsulation, is used to distribute VPN
information between NVAs. BGP based IP VPN support is defined in
RFC4364, BGP/MPLS IP Virtual Private Networks (VPNs), and RFC4659,
BGP-MPLS IP Virtual Private Network (VPN) Extension for IPv6 VPN . Use
of both the Encapsulation Subsequent Address Family Identifier (SAFI)
and the Tunnel Encapsulation Attribute, RFC5512, The BGP Encapsulation
Subsequent Address Family Identifier (SAFI) and the BGP Tunnel
Encapsulation Attribute, are supported. MAC address distribution does
not follow any standard BGB encoding, although it was inspired by the
early IETF EVPN concepts.
The feature is conditionally compiled and disabled by default.
Use the --enable-bgp-vnc configure option to enable.
The majority of this code was authored by G. Paul Ziemba
<paulz@labn.net>.
[1] http://tools.ietf.org/html/draft-ietf-nvo3-nve-nva-cp-req
[2] https://www.opennetworking.org/sdn-resources/technical-library
Now includes changes needed to merge with cmaster-next.
2016-05-07 20:18:56 +02:00
|
|
|
#endif
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2019-02-15 03:07:27 +01:00
|
|
|
#ifndef VTYSH_EXTRACT_PL
|
|
|
|
#include "bgpd/bgp_routemap_clippy.c"
|
|
|
|
#endif
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Memo of route-map commands.
|
|
|
|
|
|
|
|
o Cisco route-map
|
|
|
|
|
|
|
|
match as-path : Done
|
|
|
|
community : Done
|
2015-05-20 02:40:47 +02:00
|
|
|
interface : Done
|
2002-12-13 21:15:29 +01:00
|
|
|
ip address : Done
|
|
|
|
ip next-hop : Done
|
2005-02-02 17:43:17 +01:00
|
|
|
ip route-source : Done
|
2002-12-13 21:15:29 +01:00
|
|
|
ip prefix-list : Done
|
|
|
|
ipv6 address : Done
|
|
|
|
ipv6 next-hop : Done
|
|
|
|
ipv6 route-source: (This will not be implemented by bgpd)
|
|
|
|
ipv6 prefix-list : Done
|
|
|
|
length : (This will not be implemented by bgpd)
|
|
|
|
metric : Done
|
|
|
|
route-type : (This will not be implemented by bgpd)
|
2015-05-20 02:46:33 +02:00
|
|
|
tag : Done
|
2015-05-20 02:40:40 +02:00
|
|
|
local-preference : Done
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
set as-path prepend : Done
|
|
|
|
as-path tag : Not yet
|
|
|
|
automatic-tag : (This will not be implemented by bgpd)
|
|
|
|
community : Done
|
2016-11-15 11:00:39 +01:00
|
|
|
large-community : Done
|
|
|
|
large-comm-list : Done
|
2002-12-13 21:15:29 +01:00
|
|
|
comm-list : Not yet
|
|
|
|
dampning : Not yet
|
|
|
|
default : (This will not be implemented by bgpd)
|
|
|
|
interface : (This will not be implemented by bgpd)
|
|
|
|
ip default : (This will not be implemented by bgpd)
|
|
|
|
ip next-hop : Done
|
|
|
|
ip precedence : (This will not be implemented by bgpd)
|
|
|
|
ip tos : (This will not be implemented by bgpd)
|
|
|
|
level : (This will not be implemented by bgpd)
|
|
|
|
local-preference : Done
|
|
|
|
metric : Done
|
|
|
|
metric-type : Not yet
|
|
|
|
origin : Done
|
2015-05-20 02:46:33 +02:00
|
|
|
tag : Done
|
2002-12-13 21:15:29 +01:00
|
|
|
weight : Done
|
|
|
|
|
2014-05-20 07:57:26 +02:00
|
|
|
o Local extensions
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
set ipv6 next-hop global: Done
|
2016-08-03 15:49:09 +02:00
|
|
|
set ipv6 next-hop prefer-global: Done
|
2002-12-13 21:15:29 +01:00
|
|
|
set ipv6 next-hop local : Done
|
2008-04-10 13:47:45 +02:00
|
|
|
set as-path exclude : Done
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2016-10-18 01:36:21 +02:00
|
|
|
*/
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* generic value manipulation to be shared in multiple rules */
|
2015-04-29 08:43:02 +02:00
|
|
|
|
|
|
|
#define RMAP_VALUE_SET 0
|
|
|
|
#define RMAP_VALUE_ADD 1
|
|
|
|
#define RMAP_VALUE_SUB 2
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_value {
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t action;
|
|
|
|
uint8_t variable;
|
|
|
|
uint32_t value;
|
2015-04-29 08:43:02 +02:00
|
|
|
};
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
static int route_value_match(struct rmap_value *rv, uint32_t value)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
if (rv->variable == 0 && value == rv->value)
|
|
|
|
return RMAP_MATCH;
|
2015-04-29 08:43:02 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
2015-04-29 08:43:02 +02:00
|
|
|
}
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
|
|
|
|
struct peer *peer)
|
2015-04-29 08:43:02 +02:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t value;
|
2015-04-29 08:43:04 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
switch (rv->variable) {
|
|
|
|
case 1:
|
|
|
|
value = peer->rtt;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
value = rv->value;
|
|
|
|
break;
|
|
|
|
}
|
2015-04-29 08:43:02 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
switch (rv->action) {
|
|
|
|
case RMAP_VALUE_ADD:
|
|
|
|
if (current > UINT32_MAX - value)
|
|
|
|
return UINT32_MAX;
|
|
|
|
return current + value;
|
|
|
|
case RMAP_VALUE_SUB:
|
|
|
|
if (current <= value)
|
|
|
|
return 0;
|
|
|
|
return current - value;
|
|
|
|
default:
|
|
|
|
return value;
|
|
|
|
}
|
2015-04-29 08:43:02 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_value_compile(const char *arg)
|
2015-04-29 08:43:02 +02:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t action = RMAP_VALUE_SET, var = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
unsigned long larg = 0;
|
|
|
|
char *endptr = NULL;
|
|
|
|
struct rmap_value *rv;
|
2015-04-29 08:43:02 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (arg[0] == '+') {
|
|
|
|
action = RMAP_VALUE_ADD;
|
|
|
|
arg++;
|
|
|
|
} else if (arg[0] == '-') {
|
|
|
|
action = RMAP_VALUE_SUB;
|
|
|
|
arg++;
|
|
|
|
}
|
2015-04-29 08:43:02 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (all_digit(arg)) {
|
|
|
|
errno = 0;
|
|
|
|
larg = strtoul(arg, &endptr, 10);
|
|
|
|
if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
|
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
if (strcmp(arg, "rtt") == 0)
|
|
|
|
var = 1;
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-04-29 08:43:02 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
|
2015-04-29 08:43:02 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
rv->action = action;
|
|
|
|
rv->variable = var;
|
|
|
|
rv->value = larg;
|
|
|
|
return rv;
|
2015-04-29 08:43:02 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_value_free(void *rule)
|
2015-04-29 08:43:02 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2015-04-29 08:43:02 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* generic as path object to be shared in multiple rules */
|
2014-05-20 08:04:49 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_aspath_compile(const char *arg)
|
2014-05-20 08:04:49 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct aspath *aspath;
|
2014-05-20 08:04:49 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
aspath = aspath_str2aspath(arg);
|
|
|
|
if (!aspath)
|
|
|
|
return NULL;
|
|
|
|
return aspath;
|
2014-05-20 08:04:49 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_aspath_free(void *rule)
|
2014-05-20 08:04:49 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct aspath *aspath = rule;
|
|
|
|
aspath_free(aspath);
|
2014-05-20 08:04:49 +02:00
|
|
|
}
|
|
|
|
|
2017-10-18 15:34:57 +02:00
|
|
|
struct bgp_match_peer_compiled {
|
|
|
|
char *interface;
|
|
|
|
union sockunion su;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* 'match peer (A.B.C.D|X:X::X:X|WORD)' */
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
|
|
|
|
/* Compares the peer specified in the 'match peer' clause with the peer
|
2018-10-03 00:15:34 +02:00
|
|
|
received in bgp_path_info->peer. If it is the same, or if the peer structure
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
received is a peer_group containing it, returns RMAP_MATCH. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_peer(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
2017-10-18 15:34:57 +02:00
|
|
|
struct bgp_match_peer_compiled *pc;
|
2017-07-17 14:03:14 +02:00
|
|
|
union sockunion *su;
|
|
|
|
union sockunion su_def = {
|
|
|
|
.sin = {.sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY}};
|
|
|
|
struct peer_group *group;
|
|
|
|
struct peer *peer;
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
2017-10-18 15:34:57 +02:00
|
|
|
pc = rule;
|
|
|
|
su = &pc->su;
|
2018-10-02 22:41:30 +02:00
|
|
|
peer = ((struct bgp_path_info *)object)->peer;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-10-18 15:34:57 +02:00
|
|
|
if (pc->interface) {
|
|
|
|
if (!peer->conf_if)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
if (strcmp(peer->conf_if, pc->interface) == 0)
|
|
|
|
return RMAP_MATCH;
|
|
|
|
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* If su='0.0.0.0' (command 'match peer local'), and it's a
|
|
|
|
NETWORK,
|
2019-08-21 17:16:05 +02:00
|
|
|
REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
|
|
|
|
=> return RMAP_MATCH
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
|
|
|
if (sockunion_same(su, &su_def)) {
|
|
|
|
int ret;
|
|
|
|
if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
|
|
|
|
|| CHECK_FLAG(peer->rmap_type,
|
|
|
|
PEER_RMAP_TYPE_REDISTRIBUTE)
|
2019-08-21 17:16:05 +02:00
|
|
|
|| CHECK_FLAG(peer->rmap_type,
|
|
|
|
PEER_RMAP_TYPE_AGGREGATE)
|
2017-07-17 14:03:14 +02:00
|
|
|
|| CHECK_FLAG(peer->rmap_type,
|
|
|
|
PEER_RMAP_TYPE_DEFAULT))
|
|
|
|
ret = RMAP_MATCH;
|
|
|
|
else
|
|
|
|
ret = RMAP_NOMATCH;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
|
|
|
|
if (sockunion_same(su, &peer->su))
|
|
|
|
return RMAP_MATCH;
|
|
|
|
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
} else {
|
|
|
|
group = peer->group;
|
|
|
|
for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
|
|
|
|
peer)) {
|
|
|
|
if (sockunion_same(su, &peer->su))
|
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *route_match_peer_compile(const char *arg)
|
|
|
|
{
|
2017-10-18 15:34:57 +02:00
|
|
|
struct bgp_match_peer_compiled *pc;
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
|
|
|
|
2017-11-15 01:44:29 +01:00
|
|
|
pc = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
2017-10-18 15:34:57 +02:00
|
|
|
sizeof(struct bgp_match_peer_compiled));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-10-18 15:34:57 +02:00
|
|
|
ret = str2sockunion(strcmp(arg, "local") ? arg : "0.0.0.0", &pc->su);
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret < 0) {
|
2017-10-18 15:34:57 +02:00
|
|
|
pc->interface = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
|
|
|
return pc;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2017-10-18 15:34:57 +02:00
|
|
|
return pc;
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip address' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_peer_free(void *rule)
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
{
|
2017-10-18 15:34:57 +02:00
|
|
|
struct bgp_match_peer_compiled *pc = rule;
|
|
|
|
|
2019-02-25 21:18:13 +01:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
|
2017-10-18 15:34:57 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip address matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_peer_cmd = {"peer", route_match_peer,
|
|
|
|
route_match_peer_compile,
|
|
|
|
route_match_peer_free};
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
|
2017-11-07 15:14:32 +01:00
|
|
|
#if defined(HAVE_LUA)
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_command(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-11-07 15:14:32 +01:00
|
|
|
{
|
|
|
|
int status = RMAP_NOMATCH;
|
|
|
|
u_int32_t locpref = 0;
|
|
|
|
u_int32_t newlocpref = 0;
|
|
|
|
enum lua_rm_status lrm_status;
|
2018-10-03 02:43:07 +02:00
|
|
|
struct bgp_path_info *path = (struct bgp_path_info *)object;
|
2017-11-07 15:14:32 +01:00
|
|
|
lua_State *L = lua_initialize("/etc/frr/lua.scr");
|
|
|
|
|
|
|
|
if (L == NULL)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup the prefix information to pass in
|
|
|
|
*/
|
|
|
|
lua_setup_prefix_table(L, prefix);
|
|
|
|
|
|
|
|
zlog_debug("Set up prefix table");
|
|
|
|
/*
|
2018-10-03 00:15:34 +02:00
|
|
|
* Setup the bgp_path_info information
|
2017-11-07 15:14:32 +01:00
|
|
|
*/
|
|
|
|
lua_newtable(L);
|
2018-10-03 02:43:07 +02:00
|
|
|
lua_pushinteger(L, path->attr->med);
|
2017-11-07 15:14:32 +01:00
|
|
|
lua_setfield(L, -2, "metric");
|
2018-10-03 02:43:07 +02:00
|
|
|
lua_pushinteger(L, path->attr->nh_ifindex);
|
2017-11-07 15:14:32 +01:00
|
|
|
lua_setfield(L, -2, "ifindex");
|
2018-10-03 02:43:07 +02:00
|
|
|
lua_pushstring(L, path->attr->aspath->str);
|
2017-11-07 15:14:32 +01:00
|
|
|
lua_setfield(L, -2, "aspath");
|
2018-10-03 02:43:07 +02:00
|
|
|
lua_pushinteger(L, path->attr->local_pref);
|
2017-11-07 15:14:32 +01:00
|
|
|
lua_setfield(L, -2, "localpref");
|
2018-10-03 02:43:07 +02:00
|
|
|
zlog_debug("%s %d", path->attr->aspath->str, path->attr->nh_ifindex);
|
2017-11-07 15:14:32 +01:00
|
|
|
lua_setglobal(L, "nexthop");
|
|
|
|
|
|
|
|
zlog_debug("Set up nexthop information");
|
|
|
|
/*
|
|
|
|
* Run the rule
|
|
|
|
*/
|
|
|
|
lrm_status = lua_run_rm_rule(L, rule);
|
|
|
|
switch (lrm_status) {
|
|
|
|
case LUA_RM_FAILURE:
|
|
|
|
zlog_debug("RM_FAILURE");
|
|
|
|
break;
|
|
|
|
case LUA_RM_NOMATCH:
|
|
|
|
zlog_debug("RM_NOMATCH");
|
|
|
|
break;
|
|
|
|
case LUA_RM_MATCH_AND_CHANGE:
|
|
|
|
zlog_debug("MATCH AND CHANGE");
|
|
|
|
lua_getglobal(L, "nexthop");
|
2018-10-03 02:43:07 +02:00
|
|
|
path->attr->med = get_integer(L, "metric");
|
2017-11-07 15:14:32 +01:00
|
|
|
/*
|
|
|
|
* This needs to be abstraced with the set function
|
|
|
|
*/
|
2018-10-03 02:43:07 +02:00
|
|
|
if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
|
|
|
|
locpref = path->attr->local_pref;
|
2017-11-07 15:14:32 +01:00
|
|
|
newlocpref = get_integer(L, "localpref");
|
|
|
|
if (newlocpref != locpref) {
|
2018-10-03 02:43:07 +02:00
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
|
|
|
path->attr->local_pref = newlocpref;
|
2017-11-07 15:14:32 +01:00
|
|
|
}
|
|
|
|
status = RMAP_MATCH;
|
|
|
|
break;
|
|
|
|
case LUA_RM_MATCH:
|
|
|
|
zlog_debug("MATCH ONLY");
|
|
|
|
status = RMAP_MATCH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lua_close(L);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *route_match_command_compile(const char *arg)
|
|
|
|
{
|
|
|
|
char *command;
|
|
|
|
|
|
|
|
command = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
|
|
|
return command;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
route_match_command_free(void *rule)
|
|
|
|
{
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct route_map_rule_cmd route_match_command_cmd = {
|
|
|
|
"command",
|
|
|
|
route_match_command,
|
|
|
|
route_match_command_compile,
|
|
|
|
route_match_command_free
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match ip address IP_ACCESS_LIST' */
|
|
|
|
|
|
|
|
/* Match function should return 1 if match is success else return
|
|
|
|
zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_ip_address(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct access_list *alist;
|
|
|
|
|
2018-05-15 19:22:25 +02:00
|
|
|
if (type == RMAP_BGP && prefix->family == AF_INET) {
|
2017-07-17 14:03:14 +02:00
|
|
|
alist = access_list_lookup(AFI_IP, (char *)rule);
|
|
|
|
if (alist == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
return (access_list_apply(alist, prefix) == FILTER_DENY
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `ip address' match statement. `arg' should be
|
|
|
|
access-list name. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ip_address_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip address' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ip_address_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip address matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ip_address_cmd = {
|
|
|
|
"ip address", route_match_ip_address, route_match_ip_address_compile,
|
|
|
|
route_match_ip_address_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match ip next-hop IP_ADDRESS' */
|
|
|
|
|
|
|
|
/* Match function return 1 if match is success else return zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_ip_next_hop(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct access_list *alist;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct prefix_ipv4 p;
|
|
|
|
|
2018-05-15 19:22:25 +02:00
|
|
|
if (type == RMAP_BGP && prefix->family == AF_INET) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
p.family = AF_INET;
|
2018-10-03 00:34:03 +02:00
|
|
|
p.prefix = path->attr->nexthop;
|
2017-07-17 14:03:14 +02:00
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
|
|
|
|
|
|
|
alist = access_list_lookup(AFI_IP, (char *)rule);
|
|
|
|
if (alist == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
return (access_list_apply(alist, &p) == FILTER_DENY
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `ip next-hop' match statement. `arg' is
|
|
|
|
access-list name. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ip_next_hop_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip address' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ip_next_hop_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip next-hop matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
|
|
|
|
"ip next-hop", route_match_ip_next_hop, route_match_ip_next_hop_compile,
|
|
|
|
route_match_ip_next_hop_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2005-02-02 17:43:17 +01:00
|
|
|
/* `match ip route-source ACCESS-LIST' */
|
|
|
|
|
|
|
|
/* Match function return 1 if match is success else return zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_ip_route_source(void *rule, const struct prefix *pfx,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct access_list *alist;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct peer *peer;
|
|
|
|
struct prefix_ipv4 p;
|
|
|
|
|
2018-07-12 22:05:19 +02:00
|
|
|
if (type == RMAP_BGP && pfx->family == AF_INET) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
peer = path->peer;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (!peer || sockunion_family(&peer->su) != AF_INET)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
p.family = AF_INET;
|
|
|
|
p.prefix = peer->su.sin.sin_addr;
|
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
|
|
|
|
|
|
|
alist = access_list_lookup(AFI_IP, (char *)rule);
|
|
|
|
if (alist == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
return (access_list_apply(alist, &p) == FILTER_DENY
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
2005-02-02 17:43:17 +01:00
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `ip route-source' match statement. `arg' is
|
|
|
|
access-list name. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ip_route_source_compile(const char *arg)
|
2005-02-02 17:43:17 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip address' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ip_route_source_free(void *rule)
|
2005-02-02 17:43:17 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip route-source matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ip_route_source_cmd = {
|
|
|
|
"ip route-source", route_match_ip_route_source,
|
|
|
|
route_match_ip_route_source_compile, route_match_ip_route_source_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
|
|
|
|
const struct prefix *p)
|
2019-06-14 12:05:18 +02:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct bgp_pbr_entry_main api;
|
|
|
|
|
|
|
|
memset(&api, 0, sizeof(api));
|
|
|
|
|
|
|
|
/* extract match from flowspec entries */
|
|
|
|
ret = bgp_flowspec_match_rules_fill(
|
|
|
|
(uint8_t *)p->u.prefix_flowspec.ptr,
|
|
|
|
p->u.prefix_flowspec.prefixlen, &api);
|
|
|
|
if (ret < 0)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
if (api.match_bitmask & PREFIX_DST_PRESENT ||
|
|
|
|
api.match_bitmask_iprule & PREFIX_DST_PRESENT) {
|
|
|
|
if (family2afi((&api.dst_prefix)->family) != afi)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
return prefix_list_apply(plist, &api.dst_prefix) == PREFIX_DENY
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH;
|
|
|
|
} else if (api.match_bitmask & PREFIX_SRC_PRESENT ||
|
|
|
|
api.match_bitmask_iprule & PREFIX_SRC_PRESENT) {
|
|
|
|
if (family2afi((&api.src_prefix)->family) != afi)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
return (prefix_list_apply(plist, &api.src_prefix) == PREFIX_DENY
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2019-06-14 12:05:18 +02:00
|
|
|
route_match_address_prefix_list(void *rule, afi_t afi,
|
|
|
|
const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct prefix_list *plist;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2019-06-14 12:05:18 +02:00
|
|
|
if (type != RMAP_BGP)
|
|
|
|
return RMAP_NOMATCH;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2019-06-14 12:05:18 +02:00
|
|
|
plist = prefix_list_lookup(afi, (char *)rule);
|
|
|
|
if (plist == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
if (prefix->family == AF_FLOWSPEC)
|
|
|
|
return route_match_prefix_list_flowspec(afi, plist,
|
|
|
|
prefix);
|
|
|
|
return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2019-06-14 12:05:18 +02:00
|
|
|
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
|
|
|
{
|
|
|
|
return route_match_address_prefix_list(rule, AFI_IP, prefix, type,
|
|
|
|
object);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ip_address_prefix_list_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ip_address_prefix_list_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
|
|
|
|
"ip address prefix-list", route_match_ip_address_prefix_list,
|
|
|
|
route_match_ip_address_prefix_list_compile,
|
|
|
|
route_match_ip_address_prefix_list_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match ip next-hop prefix-list PREFIX_LIST' */
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2018-07-12 22:05:19 +02:00
|
|
|
route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct prefix_list *plist;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct prefix_ipv4 p;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-05-15 19:22:25 +02:00
|
|
|
if (type == RMAP_BGP && prefix->family == AF_INET) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
p.family = AF_INET;
|
2018-10-03 00:34:03 +02:00
|
|
|
p.prefix = path->attr->nexthop;
|
2017-07-17 14:03:14 +02:00
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
plist = prefix_list_lookup(AFI_IP, (char *)rule);
|
|
|
|
if (plist == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return (prefix_list_apply(plist, &p) == PREFIX_DENY
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ip_next_hop_prefix_list_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ip_next_hop_prefix_list_cmd = {
|
|
|
|
"ip next-hop prefix-list", route_match_ip_next_hop_prefix_list,
|
|
|
|
route_match_ip_next_hop_prefix_list_compile,
|
|
|
|
route_match_ip_next_hop_prefix_list_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2018-09-28 10:51:50 +02:00
|
|
|
/* `match ip next-hop type <blackhole>' */
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2018-09-28 10:51:50 +02:00
|
|
|
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
|
|
|
{
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-09-28 10:51:50 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP && prefix->family == AF_INET) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = (struct bgp_path_info *)object;
|
|
|
|
if (!path || !path->attr)
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
return RMAP_NOMATCH;
|
2018-09-28 10:51:50 +02:00
|
|
|
|
|
|
|
/* If nexthop interface's index can't be resolved and nexthop is
|
|
|
|
set to any address then mark it as type `blackhole`.
|
|
|
|
This logic works for matching kernel/static routes like:
|
|
|
|
`ip route add blackhole 10.0.0.1`. */
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->nexthop.s_addr == INADDR_ANY
|
|
|
|
&& !path->attr->nh_ifindex)
|
2018-09-28 10:51:50 +02:00
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *route_match_ip_next_hop_type_compile(const char *arg)
|
|
|
|
{
|
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void route_match_ip_next_hop_type_free(void *rule)
|
|
|
|
{
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct route_map_rule_cmd route_match_ip_next_hop_type_cmd = {
|
|
|
|
"ip next-hop type", route_match_ip_next_hop_type,
|
|
|
|
route_match_ip_next_hop_type_compile,
|
|
|
|
route_match_ip_next_hop_type_free};
|
|
|
|
|
2005-02-02 17:43:17 +01:00
|
|
|
/* `match ip route-source prefix-list PREFIX_LIST' */
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2018-07-12 22:05:19 +02:00
|
|
|
route_match_ip_route_source_prefix_list(void *rule,
|
|
|
|
const struct prefix *prefix,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_object_t type, void *object)
|
2005-02-02 17:43:17 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct prefix_list *plist;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct peer *peer;
|
|
|
|
struct prefix_ipv4 p;
|
2005-02-02 17:43:17 +01:00
|
|
|
|
2018-05-15 19:22:25 +02:00
|
|
|
if (type == RMAP_BGP && prefix->family == AF_INET) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
peer = path->peer;
|
2005-02-02 17:43:17 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (!peer || sockunion_family(&peer->su) != AF_INET)
|
|
|
|
return RMAP_NOMATCH;
|
2005-02-02 17:43:17 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
p.family = AF_INET;
|
|
|
|
p.prefix = peer->su.sin.sin_addr;
|
|
|
|
p.prefixlen = IPV4_MAX_BITLEN;
|
2005-02-02 17:43:17 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
plist = prefix_list_lookup(AFI_IP, (char *)rule);
|
|
|
|
if (plist == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
2005-02-02 17:43:17 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return (prefix_list_apply(plist, &p) == PREFIX_DENY
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ip_route_source_prefix_list_compile(const char *arg)
|
2005-02-02 17:43:17 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ip_route_source_prefix_list_free(void *rule)
|
2005-02-02 17:43:17 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = {
|
|
|
|
"ip route-source prefix-list", route_match_ip_route_source_prefix_list,
|
|
|
|
route_match_ip_route_source_prefix_list_compile,
|
|
|
|
route_match_ip_route_source_prefix_list_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2018-02-22 07:02:07 +01:00
|
|
|
/* `match evpn default-route' */
|
|
|
|
|
|
|
|
/* Match function should return 1 if match is success else 0 */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_evpn_default_route(void *rule, const struct prefix *p,
|
|
|
|
route_map_object_t type, void *object)
|
2018-02-22 07:02:07 +01:00
|
|
|
{
|
|
|
|
if (type == RMAP_BGP && is_evpn_prefix_default(p))
|
|
|
|
return RMAP_MATCH;
|
|
|
|
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for default-route matching. */
|
|
|
|
struct route_map_rule_cmd route_match_evpn_default_route_cmd = {
|
|
|
|
"evpn default-route", route_match_evpn_default_route, NULL, NULL};
|
|
|
|
|
2017-06-21 10:02:46 +02:00
|
|
|
/* `match mac address MAC_ACCESS_LIST' */
|
|
|
|
|
|
|
|
/* Match function should return 1 if match is success else return
|
|
|
|
zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_mac_address(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-06-21 10:02:46 +02:00
|
|
|
{
|
|
|
|
struct access_list *alist;
|
2017-08-04 21:55:44 +02:00
|
|
|
struct prefix p;
|
2017-06-21 10:02:46 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
alist = access_list_lookup(AFI_L2VPN, (char *)rule);
|
|
|
|
if (alist == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
2017-08-04 21:55:44 +02:00
|
|
|
p.family = AF_ETHERNET;
|
|
|
|
p.prefixlen = ETH_ALEN * 8;
|
2018-04-14 00:37:30 +02:00
|
|
|
p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
|
2017-08-04 21:55:44 +02:00
|
|
|
|
2018-02-09 19:22:50 +01:00
|
|
|
return (access_list_apply(alist, &p) == FILTER_DENY
|
2017-06-21 10:02:46 +02:00
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
|
|
|
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `mac address' match statement. `arg' should be
|
|
|
|
access-list name. */
|
|
|
|
static void *route_match_mac_address_compile(const char *arg)
|
|
|
|
{
|
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip address' value. */
|
|
|
|
static void route_match_mac_address_free(void *rule)
|
|
|
|
{
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for mac address matching. */
|
|
|
|
struct route_map_rule_cmd route_match_mac_address_cmd = {
|
|
|
|
"mac address", route_match_mac_address, route_match_mac_address_compile,
|
|
|
|
route_match_mac_address_free};
|
|
|
|
|
2019-06-19 23:29:34 +02:00
|
|
|
/*
|
|
|
|
* Match function returns:
|
|
|
|
* ...RMAP_MATCH if match is found.
|
|
|
|
* ...RMAP_NOMATCH if match is not found.
|
|
|
|
* ...RMAP_NOOP to ignore this match check.
|
|
|
|
*/
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_vni(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-06-21 11:00:24 +02:00
|
|
|
{
|
|
|
|
vni_t vni = 0;
|
2019-06-19 23:29:34 +02:00
|
|
|
unsigned int label_cnt = 0;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path = NULL;
|
2019-06-19 23:29:34 +02:00
|
|
|
struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
|
2017-06-21 11:00:24 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
vni = *((vni_t *)rule);
|
2018-10-03 00:34:03 +02:00
|
|
|
path = (struct bgp_path_info *)object;
|
2017-06-21 11:00:24 +02:00
|
|
|
|
2019-06-19 23:29:34 +02:00
|
|
|
/*
|
|
|
|
* This rmap filter is valid for vxlan tunnel type only.
|
|
|
|
* For any other tunnel type, return noop to ignore
|
|
|
|
* this check.
|
|
|
|
*/
|
|
|
|
if (path->attr && path->attr->encap_tunneltype !=
|
|
|
|
BGP_ENCAP_TYPE_VXLAN)
|
|
|
|
return RMAP_NOOP;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Apply filter to type 1, 2, 5 routes only.
|
|
|
|
* Other route types do not have vni label.
|
|
|
|
*/
|
|
|
|
if (evp && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE &&
|
|
|
|
evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE &&
|
|
|
|
evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
|
|
|
|
return RMAP_NOOP;
|
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->extra == NULL)
|
2018-06-13 07:13:05 +02:00
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
2019-06-19 23:29:34 +02:00
|
|
|
for ( ; label_cnt < BGP_MAX_LABELS &&
|
|
|
|
label_cnt < path->extra->num_labels; label_cnt++) {
|
|
|
|
if (vni == label2vni(&path->extra->label[label_cnt]))
|
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
2017-06-21 11:00:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `vni' match statement. */
|
|
|
|
static void *route_match_vni_compile(const char *arg)
|
|
|
|
{
|
|
|
|
vni_t *vni = NULL;
|
|
|
|
char *end = NULL;
|
|
|
|
|
|
|
|
vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
|
|
|
|
|
|
|
|
*vni = strtoul(arg, &end, 10);
|
2017-08-25 02:43:29 +02:00
|
|
|
if (*end != '\0') {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, vni);
|
2017-06-21 11:00:24 +02:00
|
|
|
return NULL;
|
2017-08-25 02:43:29 +02:00
|
|
|
}
|
2017-06-21 11:00:24 +02:00
|
|
|
|
|
|
|
return vni;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `vni' value. */
|
|
|
|
static void route_match_vni_free(void *rule)
|
|
|
|
{
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for vni matching. */
|
|
|
|
struct route_map_rule_cmd route_match_evpn_vni_cmd = {
|
2017-07-12 23:55:22 +02:00
|
|
|
"evpn vni", route_match_vni, route_match_vni_compile,
|
|
|
|
route_match_vni_free};
|
2017-06-21 11:00:24 +02:00
|
|
|
|
2018-01-27 02:16:48 +01:00
|
|
|
/* `match evpn route-type' */
|
|
|
|
|
|
|
|
/* Match function should return 1 if match is success else return
|
|
|
|
zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_evpn_route_type(void *rule, const struct prefix *pfx,
|
|
|
|
route_map_object_t type, void *object)
|
2018-01-27 02:16:48 +01:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t route_type = 0;
|
2018-01-27 02:16:48 +01:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
2018-03-27 21:13:34 +02:00
|
|
|
route_type = *((uint8_t *)rule);
|
2018-01-27 02:16:48 +01:00
|
|
|
|
2018-07-12 22:05:19 +02:00
|
|
|
if (route_type == pfx->u.prefix_evpn.route_type)
|
2018-01-27 02:16:48 +01:00
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `route-type' match statement. */
|
|
|
|
static void *route_match_evpn_route_type_compile(const char *arg)
|
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *route_type = NULL;
|
2018-01-27 02:16:48 +01:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
route_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
|
2018-01-27 02:16:48 +01:00
|
|
|
|
|
|
|
if (strncmp(arg, "ma", 2) == 0)
|
|
|
|
*route_type = BGP_EVPN_MAC_IP_ROUTE;
|
|
|
|
else if (strncmp(arg, "mu", 2) == 0)
|
|
|
|
*route_type = BGP_EVPN_IMET_ROUTE;
|
|
|
|
else
|
|
|
|
*route_type = BGP_EVPN_IP_PREFIX_ROUTE;
|
|
|
|
|
|
|
|
return route_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `route-type' value. */
|
|
|
|
static void route_match_evpn_route_type_free(void *rule)
|
|
|
|
{
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for evpn route-type matching. */
|
|
|
|
struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
|
|
|
|
"evpn route-type", route_match_evpn_route_type,
|
2018-03-06 20:02:52 +01:00
|
|
|
route_match_evpn_route_type_compile, route_match_evpn_route_type_free};
|
2018-01-27 02:16:48 +01:00
|
|
|
|
2019-02-15 03:07:27 +01:00
|
|
|
/* Route map commands for VRF route leak with source vrf matching */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2019-02-22 16:50:14 +01:00
|
|
|
route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2019-02-15 03:07:27 +01:00
|
|
|
{
|
|
|
|
struct bgp_path_info *path;
|
|
|
|
char *vrf_name;
|
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
vrf_name = rule;
|
|
|
|
path = (struct bgp_path_info *)object;
|
|
|
|
|
|
|
|
if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
if (path->extra == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
if (strncmp(vrf_name, vrf_id_to_name(
|
|
|
|
path->extra->bgp_orig->vrf_id), VRF_NAMSIZ)
|
|
|
|
== 0)
|
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *route_match_vrl_source_vrf_compile(const char *arg)
|
|
|
|
{
|
|
|
|
uint8_t *vrf_name = NULL;
|
|
|
|
|
|
|
|
vrf_name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
|
|
|
|
|
|
|
return vrf_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `route-type' value. */
|
|
|
|
static void route_match_vrl_source_vrf_free(void *rule)
|
|
|
|
{
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
|
|
|
|
"source-vrf", route_match_vrl_source_vrf,
|
|
|
|
route_match_vrl_source_vrf_compile,
|
|
|
|
route_match_vrl_source_vrf_free};
|
|
|
|
|
2015-05-20 02:40:40 +02:00
|
|
|
/* `match local-preference LOCAL-PREF' */
|
|
|
|
|
|
|
|
/* Match function return 1 if match is success else return zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_local_pref(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t *local_pref;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
local_pref = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->local_pref == *local_pref)
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_MATCH;
|
|
|
|
else
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
2015-05-20 02:40:40 +02:00
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `match local-preference' match statement.
|
|
|
|
`arg' is local-pref value */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_local_pref_compile(const char *arg)
|
2015-05-20 02:40:40 +02:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t *local_pref;
|
2017-07-17 14:03:14 +02:00
|
|
|
char *endptr = NULL;
|
|
|
|
unsigned long tmpval;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Locpref value shoud be integer. */
|
|
|
|
if (!all_digit(arg))
|
|
|
|
return NULL;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
errno = 0;
|
|
|
|
tmpval = strtoul(arg, &endptr, 10);
|
|
|
|
if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
|
|
|
|
return NULL;
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
*local_pref = tmpval;
|
|
|
|
return local_pref;
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `match local-preference' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_local_pref_free(void *rule)
|
2015-05-20 02:40:40 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for metric matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_local_pref_cmd = {
|
|
|
|
"local-preference", route_match_local_pref,
|
|
|
|
route_match_local_pref_compile, route_match_local_pref_free};
|
2015-05-20 02:40:40 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match metric METRIC' */
|
|
|
|
|
|
|
|
/* Match function return 1 if match is success else return zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_metric(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_value *rv;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
rv = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
return route_value_match(rv, path->attr->med);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for metric matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_metric_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"metric", route_match_metric, route_value_compile, route_value_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match as-path ASPATH' */
|
|
|
|
|
|
|
|
/* Match function for as-path match. I assume given object is */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_aspath(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct as_list *as_list;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
as_list = as_list_lookup((char *)rule);
|
|
|
|
if (as_list == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Perform match. */
|
2018-10-03 00:34:03 +02:00
|
|
|
return ((as_list_apply(as_list, path->attr->aspath)
|
2017-07-17 14:03:14 +02:00
|
|
|
== AS_FILTER_DENY)
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for as-path match. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_aspath_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for as-path match. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_aspath_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for aspath matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_aspath_cmd = {
|
|
|
|
"as-path", route_match_aspath, route_match_aspath_compile,
|
|
|
|
route_match_aspath_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match community COMMUNIY' */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_community {
|
|
|
|
char *name;
|
2019-01-09 02:23:11 +01:00
|
|
|
uint32_t name_hash;
|
2017-07-17 14:03:14 +02:00
|
|
|
int exact;
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Match function for community match. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_community(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct community_list *list;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom = rule;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
rcom = rule;
|
|
|
|
|
|
|
|
list = community_list_lookup(bgp_clist, rcom->name,
|
2019-01-09 02:23:11 +01:00
|
|
|
rcom->name_hash,
|
2017-07-17 14:03:14 +02:00
|
|
|
COMMUNITY_LIST_MASTER);
|
|
|
|
if (!list)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
|
|
|
if (rcom->exact) {
|
2018-10-03 00:34:03 +02:00
|
|
|
if (community_list_exact_match(path->attr->community,
|
|
|
|
list))
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_MATCH;
|
|
|
|
} else {
|
2018-10-03 00:34:03 +02:00
|
|
|
if (community_list_match(path->attr->community, list))
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for community match. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_community_compile(const char *arg)
|
|
|
|
{
|
|
|
|
struct rmap_community *rcom;
|
|
|
|
int len;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
|
|
|
|
|
|
|
|
p = strchr(arg, ' ');
|
|
|
|
if (p) {
|
|
|
|
len = p - arg;
|
|
|
|
rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
|
|
|
|
memcpy(rcom->name, arg, len);
|
|
|
|
rcom->exact = 1;
|
|
|
|
} else {
|
|
|
|
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
|
|
|
rcom->exact = 0;
|
|
|
|
}
|
2019-01-09 02:23:11 +01:00
|
|
|
|
|
|
|
rcom->name_hash = bgp_clist_hash_key(rcom->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
return rcom;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for community match. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_community_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_community *rcom = rule;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for community matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_community_cmd = {
|
|
|
|
"community", route_match_community, route_match_community_compile,
|
|
|
|
route_match_community_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2016-11-15 11:00:39 +01:00
|
|
|
/* Match function for lcommunity match. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_lcommunity(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct community_list *list;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom = rule;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
list = community_list_lookup(bgp_clist, rcom->name,
|
2019-01-09 02:23:11 +01:00
|
|
|
rcom->name_hash,
|
2017-07-17 14:03:14 +02:00
|
|
|
LARGE_COMMUNITY_LIST_MASTER);
|
|
|
|
if (!list)
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
|
2019-05-06 11:45:32 +02:00
|
|
|
if (rcom->exact) {
|
|
|
|
if (lcommunity_list_exact_match(
|
|
|
|
path->attr->lcommunity,
|
|
|
|
list))
|
|
|
|
return RMAP_MATCH;
|
|
|
|
} else {
|
|
|
|
if (lcommunity_list_match(
|
|
|
|
path->attr->lcommunity,
|
|
|
|
list))
|
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for community match. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_lcommunity_compile(const char *arg)
|
|
|
|
{
|
|
|
|
struct rmap_community *rcom;
|
|
|
|
int len;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
|
|
|
|
|
|
|
|
p = strchr(arg, ' ');
|
|
|
|
if (p) {
|
|
|
|
len = p - arg;
|
|
|
|
rcom->name = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
|
|
|
|
memcpy(rcom->name, arg, len);
|
2019-05-06 11:45:32 +02:00
|
|
|
rcom->exact = 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
|
|
|
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
|
|
|
rcom->exact = 0;
|
|
|
|
}
|
2019-01-09 02:23:11 +01:00
|
|
|
|
|
|
|
rcom->name_hash = bgp_clist_hash_key(rcom->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
return rcom;
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for community match. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_lcommunity_free(void *rule)
|
2016-11-15 11:00:39 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_community *rcom = rule;
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for community matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_lcommunity_cmd = {
|
|
|
|
"large-community", route_match_lcommunity,
|
|
|
|
route_match_lcommunity_compile, route_match_lcommunity_free};
|
2016-11-15 11:00:39 +01:00
|
|
|
|
|
|
|
|
2003-04-19 17:49:49 +02:00
|
|
|
/* Match function for extcommunity match. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_ecommunity(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2003-04-19 17:49:49 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct community_list *list;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom = rule;
|
2003-04-19 17:49:49 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2018-12-26 19:01:06 +01:00
|
|
|
list = community_list_lookup(bgp_clist, rcom->name,
|
2019-01-09 02:23:11 +01:00
|
|
|
rcom->name_hash,
|
2017-07-17 14:03:14 +02:00
|
|
|
EXTCOMMUNITY_LIST_MASTER);
|
|
|
|
if (!list)
|
|
|
|
return RMAP_NOMATCH;
|
2003-04-19 17:49:49 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (ecommunity_list_match(path->attr->ecommunity, list))
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
2003-04-19 17:49:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for extcommunity match. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ecommunity_compile(const char *arg)
|
2003-04-19 17:49:49 +02:00
|
|
|
{
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom;
|
|
|
|
|
|
|
|
rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
|
|
|
|
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2019-01-09 02:23:11 +01:00
|
|
|
rcom->name_hash = bgp_clist_hash_key(rcom->name);
|
2018-12-26 19:01:06 +01:00
|
|
|
|
|
|
|
return rcom;
|
2003-04-19 17:49:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for extcommunity match. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ecommunity_free(void *rule)
|
2003-04-19 17:49:49 +02:00
|
|
|
{
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom = rule;
|
|
|
|
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
|
2003-04-19 17:49:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for community matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ecommunity_cmd = {
|
|
|
|
"extcommunity", route_match_ecommunity, route_match_ecommunity_compile,
|
|
|
|
route_match_ecommunity_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match nlri` and `set nlri` are replaced by `address-family ipv4`
|
|
|
|
and `address-family vpnv4'. */
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match origin' */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_origin(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *origin;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
origin = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->origin == *origin)
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_origin_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *origin;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (strcmp(arg, "igp") == 0)
|
|
|
|
*origin = 0;
|
|
|
|
else if (strcmp(arg, "egp") == 0)
|
|
|
|
*origin = 1;
|
|
|
|
else
|
|
|
|
*origin = 2;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return origin;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip address' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_origin_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for origin matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_origin_cmd = {
|
|
|
|
"origin", route_match_origin, route_match_origin_compile,
|
|
|
|
route_match_origin_free};
|
2011-11-22 17:15:10 +01:00
|
|
|
|
|
|
|
/* match probability { */
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_probability(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
long r = random();
|
|
|
|
|
|
|
|
switch (*(long *)rule) {
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case RAND_MAX:
|
|
|
|
return RMAP_MATCH;
|
|
|
|
default:
|
|
|
|
if (r < *(long *)rule) {
|
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
|
|
|
}
|
2011-11-22 17:15:10 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
2011-11-22 17:15:10 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_probability_compile(const char *arg)
|
2011-11-22 17:15:10 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
long *lobule;
|
|
|
|
unsigned perc;
|
2011-11-22 17:15:10 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
perc = atoi(arg);
|
|
|
|
lobule = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(long));
|
2011-11-22 17:15:10 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
switch (perc) {
|
|
|
|
case 0:
|
|
|
|
*lobule = 0;
|
|
|
|
break;
|
|
|
|
case 100:
|
|
|
|
*lobule = RAND_MAX;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*lobule = RAND_MAX / 100 * perc;
|
|
|
|
}
|
2011-11-22 17:15:10 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return lobule;
|
2011-11-22 17:15:10 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_probability_free(void *rule)
|
2011-11-22 17:15:10 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2011-11-22 17:15:10 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_probability_cmd = {
|
|
|
|
"probability", route_match_probability, route_match_probability_compile,
|
|
|
|
route_match_probability_free};
|
2011-11-22 17:15:10 +01:00
|
|
|
|
2015-05-20 02:40:47 +02:00
|
|
|
/* `match interface IFNAME' */
|
|
|
|
/* Match function should return 1 if match is success else return
|
|
|
|
zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_interface(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2015-05-20 02:40:47 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct interface *ifp;
|
2018-10-03 02:43:07 +02:00
|
|
|
struct bgp_path_info *path;
|
2015-05-20 02:40:47 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
2018-10-03 02:43:07 +02:00
|
|
|
path = object;
|
2015-05-20 02:40:47 +02:00
|
|
|
|
2018-10-03 02:43:07 +02:00
|
|
|
if (!path || !path->attr)
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
2015-05-20 02:40:47 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ifp = if_lookup_by_name_all_vrf((char *)rule);
|
2015-05-20 02:40:47 +02:00
|
|
|
|
2018-10-03 02:43:07 +02:00
|
|
|
if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
2015-05-20 02:40:47 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
2015-05-20 02:40:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `interface' match statement. `arg' should be
|
|
|
|
interface name. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_interface_compile(const char *arg)
|
2015-05-20 02:40:47 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2015-05-20 02:40:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `interface' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_interface_free(void *rule)
|
2015-05-20 02:40:47 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2015-05-20 02:40:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip address matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_interface_cmd = {
|
|
|
|
"interface", route_match_interface, route_match_interface_compile,
|
|
|
|
route_match_interface_free};
|
2015-05-20 02:40:47 +02:00
|
|
|
|
2011-11-22 17:15:10 +01:00
|
|
|
/* } */
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set ip next-hop IP_ADDRESS' */
|
|
|
|
|
2015-05-20 02:46:33 +02:00
|
|
|
/* Match function return 1 if match is success else return zero. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_tag(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2015-05-20 02:46:33 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
route_tag_t *tag;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
tag = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
2015-05-20 02:46:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Route map commands for tag matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static struct route_map_rule_cmd route_match_tag_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"tag", route_match_tag, route_map_rule_tag_compile,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_rule_tag_free,
|
2015-05-20 02:46:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Set nexthop to object. ojbect must be pointer to struct attr. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_ip_nexthop_set {
|
|
|
|
struct in_addr *address;
|
|
|
|
int peer_address;
|
|
|
|
int unchanged;
|
2003-08-12 07:32:27 +02:00
|
|
|
};
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_ip_nexthop(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct rmap_ip_nexthop_set *rins = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct peer *peer;
|
|
|
|
|
2018-10-20 02:38:03 +02:00
|
|
|
if (type != RMAP_BGP)
|
|
|
|
return RMAP_OKAY;
|
|
|
|
|
2018-10-20 02:43:47 +02:00
|
|
|
if (prefix->family == AF_INET6)
|
|
|
|
return RMAP_OKAY;
|
|
|
|
|
2018-10-20 02:38:03 +02:00
|
|
|
path = object;
|
|
|
|
peer = path->peer;
|
|
|
|
|
|
|
|
if (rins->unchanged) {
|
|
|
|
SET_FLAG(path->attr->rmap_change_flags,
|
|
|
|
BATTR_RMAP_NEXTHOP_UNCHANGED);
|
|
|
|
} else if (rins->peer_address) {
|
|
|
|
if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
|
|
|
|
|| CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
|
|
|
|
&& peer->su_remote
|
|
|
|
&& sockunion_family(peer->su_remote) == AF_INET) {
|
|
|
|
path->attr->nexthop.s_addr =
|
|
|
|
sockunion2ip(peer->su_remote);
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
2018-10-20 02:38:03 +02:00
|
|
|
} else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
|
|
|
|
/* The next hop value will be set as part of
|
|
|
|
* packet rewrite. Set the flags here to indicate
|
|
|
|
* that rewrite needs to be done.
|
|
|
|
* Also, clear the value.
|
|
|
|
*/
|
2018-10-03 00:34:03 +02:00
|
|
|
SET_FLAG(path->attr->rmap_change_flags,
|
2018-10-20 02:38:03 +02:00
|
|
|
BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
|
|
|
|
path->attr->nexthop.s_addr = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2018-10-20 02:38:03 +02:00
|
|
|
} else {
|
|
|
|
/* Set next hop value. */
|
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
|
|
|
|
path->attr->nexthop = *rins->address;
|
|
|
|
SET_FLAG(path->attr->rmap_change_flags,
|
|
|
|
BATTR_RMAP_IPV4_NHOP_CHANGED);
|
|
|
|
/* case for MP-BGP : MPLS VPN */
|
|
|
|
path->attr->mp_nexthop_global_in = *rins->address;
|
|
|
|
path->attr->mp_nexthop_len = sizeof(*rins->address);
|
2003-08-12 07:32:27 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `ip nexthop' compile function. Given string is converted
|
|
|
|
to struct in_addr structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_ip_nexthop_compile(const char *arg)
|
|
|
|
{
|
|
|
|
struct rmap_ip_nexthop_set *rins;
|
|
|
|
struct in_addr *address = NULL;
|
|
|
|
int peer_address = 0;
|
|
|
|
int unchanged = 0;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (strcmp(arg, "peer-address") == 0)
|
|
|
|
peer_address = 1;
|
|
|
|
else if (strcmp(arg, "unchanged") == 0)
|
|
|
|
unchanged = 1;
|
|
|
|
else {
|
|
|
|
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
|
|
|
sizeof(struct in_addr));
|
|
|
|
ret = inet_aton(arg, address);
|
|
|
|
|
|
|
|
if (ret == 0) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-08-12 07:32:27 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
|
|
|
sizeof(struct rmap_ip_nexthop_set));
|
2003-08-12 07:32:27 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
rins->address = address;
|
|
|
|
rins->peer_address = peer_address;
|
|
|
|
rins->unchanged = unchanged;
|
2003-08-12 07:32:27 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return rins;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip nexthop' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_ip_nexthop_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_ip_nexthop_set *rins = rule;
|
2003-08-12 07:32:27 +02:00
|
|
|
|
2019-02-25 21:18:13 +01:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip nexthop set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
|
|
|
|
"ip next-hop", route_set_ip_nexthop, route_set_ip_nexthop_compile,
|
|
|
|
route_set_ip_nexthop_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set local-preference LOCAL_PREF' */
|
|
|
|
|
|
|
|
/* Set local preference. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_local_pref(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct rmap_value *rv;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t locpref = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
|
|
|
rv = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Set local preference value. */
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
|
|
|
|
locpref = path->attr->local_pref;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
|
|
|
|
path->attr->local_pref =
|
|
|
|
route_value_adjust(rv, locpref, path->peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set local preference rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_local_pref_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"local-preference", route_set_local_pref, route_value_compile,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_value_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set weight WEIGHT' */
|
|
|
|
|
|
|
|
/* Set weight. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_weight(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_value *rv;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
|
|
|
rv = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Set weight value. */
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->weight = route_value_adjust(rv, 0, path->peer);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set local preference rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_weight_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"weight", route_set_weight, route_value_compile, route_value_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set metric METRIC' */
|
|
|
|
|
|
|
|
/* Set metric to attribute. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_metric(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct rmap_value *rv;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t med = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
|
|
|
rv = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
|
|
|
|
med = path->attr->med;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->med = route_value_adjust(rv, med, path->peer);
|
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set metric rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_metric_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"metric", route_set_metric, route_value_compile, route_value_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set as-path prepend ASPATH' */
|
|
|
|
|
|
|
|
/* For AS path prepend mechanism. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_aspath_prepend(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct aspath *aspath;
|
|
|
|
struct aspath *new;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->aspath->refcnt)
|
|
|
|
new = aspath_dup(path->attr->aspath);
|
2017-07-17 14:03:14 +02:00
|
|
|
else
|
2018-10-03 00:34:03 +02:00
|
|
|
new = path->attr->aspath;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if ((uintptr_t)rule > 10) {
|
|
|
|
aspath = rule;
|
|
|
|
aspath_prepend(aspath, new);
|
|
|
|
} else {
|
|
|
|
as_t as = aspath_leftmost(new);
|
|
|
|
if (!as)
|
2018-10-03 00:34:03 +02:00
|
|
|
as = path->peer->as;
|
2017-07-17 14:03:14 +02:00
|
|
|
new = aspath_add_seq_n(new, as, (uintptr_t)rule);
|
|
|
|
}
|
2016-05-26 03:49:34 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->aspath = new;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_aspath_prepend_compile(const char *arg)
|
2016-05-26 03:49:34 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
unsigned int num;
|
2016-05-26 03:49:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (sscanf(arg, "last-as %u", &num) == 1 && num > 0 && num <= 10)
|
|
|
|
return (void *)(uintptr_t)num;
|
2016-05-26 03:49:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return route_aspath_compile(arg);
|
2016-05-26 03:49:34 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_aspath_prepend_free(void *rule)
|
2016-05-26 03:49:34 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
if ((uintptr_t)rule > 10)
|
|
|
|
route_aspath_free(rule);
|
2016-05-26 03:49:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-20 07:57:26 +02:00
|
|
|
/* Set as-path prepend rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"as-path prepend", route_set_aspath_prepend,
|
|
|
|
route_set_aspath_prepend_compile, route_set_aspath_prepend_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2008-04-10 13:47:45 +02:00
|
|
|
/* `set as-path exclude ASn' */
|
|
|
|
|
|
|
|
/* For ASN exclude mechanism.
|
2017-07-17 14:03:14 +02:00
|
|
|
* Iterate over ASns requested and filter them from the given AS_PATH one by
|
|
|
|
* one.
|
2008-04-10 13:47:45 +02:00
|
|
|
* Make a deep copy of existing AS_PATH, but for the first ASn only.
|
|
|
|
*/
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_aspath_exclude(void *rule, const struct prefix *dummy,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct aspath *new_path, *exclude_path;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
exclude_path = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
if (path->attr->aspath->refcnt)
|
|
|
|
new_path = aspath_dup(path->attr->aspath);
|
2017-07-17 14:03:14 +02:00
|
|
|
else
|
2018-10-03 00:34:03 +02:00
|
|
|
new_path = path->attr->aspath;
|
|
|
|
path->attr->aspath =
|
2017-07-17 14:03:14 +02:00
|
|
|
aspath_filter_exclude(new_path, exclude_path);
|
|
|
|
}
|
|
|
|
return RMAP_OKAY;
|
2008-04-10 13:47:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set ASn exlude rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_aspath_exclude_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"as-path exclude", route_set_aspath_exclude, route_aspath_compile,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_aspath_free,
|
2008-04-10 13:47:45 +02:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set community COMMUNITY' */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_com_set {
|
|
|
|
struct community *com;
|
|
|
|
int additive;
|
|
|
|
int none;
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* For community set mechanism. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_community(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct rmap_com_set *rcs;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct attr *attr;
|
|
|
|
struct community *new = NULL;
|
|
|
|
struct community *old;
|
|
|
|
struct community *merge;
|
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
rcs = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
attr = path->attr;
|
2017-07-17 14:03:14 +02:00
|
|
|
old = attr->community;
|
|
|
|
|
|
|
|
/* "none" case. */
|
|
|
|
if (rcs->none) {
|
|
|
|
attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
|
|
|
|
attr->community = NULL;
|
|
|
|
/* See the longer comment down below. */
|
|
|
|
if (old && old->refcnt == 0)
|
2018-10-22 21:58:39 +02:00
|
|
|
community_free(&old);
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* "additive" case. */
|
|
|
|
if (rcs->additive && old) {
|
|
|
|
merge = community_merge(community_dup(old), rcs->com);
|
|
|
|
|
|
|
|
new = community_uniq_sort(merge);
|
2018-10-22 21:58:39 +02:00
|
|
|
community_free(&merge);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else
|
|
|
|
new = community_dup(rcs->com);
|
|
|
|
|
2017-08-30 10:27:15 +02:00
|
|
|
/* HACK: if the old community is not intern'd,
|
|
|
|
* we should free it here, or all reference to it may be
|
|
|
|
* lost.
|
|
|
|
* Really need to cleanup attribute caching sometime.
|
|
|
|
*/
|
|
|
|
if (old && old->refcnt == 0)
|
2018-10-22 21:58:39 +02:00
|
|
|
community_free(&old);
|
2017-08-30 10:27:15 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* will be interned by caller if required */
|
|
|
|
attr->community = new;
|
|
|
|
|
|
|
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for set community. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_community_compile(const char *arg)
|
|
|
|
{
|
|
|
|
struct rmap_com_set *rcs;
|
|
|
|
struct community *com = NULL;
|
|
|
|
char *sp;
|
|
|
|
int additive = 0;
|
|
|
|
int none = 0;
|
|
|
|
|
|
|
|
if (strcmp(arg, "none") == 0)
|
|
|
|
none = 1;
|
|
|
|
else {
|
|
|
|
sp = strstr(arg, "additive");
|
|
|
|
|
|
|
|
if (sp && sp > arg) {
|
2017-08-30 10:31:45 +02:00
|
|
|
/* "additive" keyword is included. */
|
2017-07-17 14:03:14 +02:00
|
|
|
additive = 1;
|
|
|
|
*(sp - 1) = '\0';
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
com = community_str2com(arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (additive)
|
|
|
|
*(sp - 1) = ' ';
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (!com)
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
|
|
|
|
rcs->com = com;
|
|
|
|
rcs->additive = additive;
|
|
|
|
rcs->none = none;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return rcs;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free function for set community. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_community_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_com_set *rcs = rule;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (rcs->com)
|
2018-10-22 21:58:39 +02:00
|
|
|
community_free(&rcs->com);
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set community rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_community_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"community", route_set_community, route_set_community_compile,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_set_community_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2016-11-15 11:00:39 +01:00
|
|
|
/* `set community COMMUNITY' */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_lcom_set {
|
|
|
|
struct lcommunity *lcom;
|
|
|
|
int additive;
|
|
|
|
int none;
|
2016-11-15 11:00:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* For lcommunity set mechanism. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_lcommunity(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct rmap_lcom_set *rcs;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct attr *attr;
|
|
|
|
struct lcommunity *new = NULL;
|
|
|
|
struct lcommunity *old;
|
|
|
|
struct lcommunity *merge;
|
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
rcs = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
attr = path->attr;
|
2017-07-17 14:03:14 +02:00
|
|
|
old = attr->lcommunity;
|
|
|
|
|
|
|
|
/* "none" case. */
|
|
|
|
if (rcs->none) {
|
|
|
|
attr->flag &=
|
|
|
|
~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
|
|
|
|
attr->lcommunity = NULL;
|
|
|
|
|
|
|
|
/* See the longer comment down below. */
|
|
|
|
if (old && old->refcnt == 0)
|
|
|
|
lcommunity_free(&old);
|
|
|
|
return RMAP_OKAY;
|
|
|
|
}
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (rcs->additive && old) {
|
|
|
|
merge = lcommunity_merge(lcommunity_dup(old),
|
|
|
|
rcs->lcom);
|
|
|
|
|
|
|
|
new = lcommunity_uniq_sort(merge);
|
|
|
|
lcommunity_free(&merge);
|
|
|
|
} else
|
|
|
|
new = lcommunity_dup(rcs->lcom);
|
|
|
|
|
2017-08-30 09:37:19 +02:00
|
|
|
/* HACK: if the old large-community is not intern'd,
|
|
|
|
* we should free it here, or all reference to it may be
|
|
|
|
* lost.
|
|
|
|
* Really need to cleanup attribute caching sometime.
|
|
|
|
*/
|
|
|
|
if (old && old->refcnt == 0)
|
|
|
|
lcommunity_free(&old);
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* will be intern()'d or attr_flush()'d by bgp_update_main() */
|
|
|
|
attr->lcommunity = new;
|
|
|
|
|
|
|
|
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
|
|
|
|
}
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
|
|
|
}
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Compile function for set community. */
|
|
|
|
static void *route_set_lcommunity_compile(const char *arg)
|
|
|
|
{
|
|
|
|
struct rmap_lcom_set *rcs;
|
|
|
|
struct lcommunity *lcom = NULL;
|
|
|
|
char *sp;
|
|
|
|
int additive = 0;
|
|
|
|
int none = 0;
|
|
|
|
|
|
|
|
if (strcmp(arg, "none") == 0)
|
|
|
|
none = 1;
|
|
|
|
else {
|
|
|
|
sp = strstr(arg, "additive");
|
|
|
|
|
|
|
|
if (sp && sp > arg) {
|
|
|
|
/* "additive" keyworkd is included. */
|
|
|
|
additive = 1;
|
|
|
|
*(sp - 1) = '\0';
|
|
|
|
}
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
lcom = lcommunity_str2com(arg);
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (additive)
|
|
|
|
*(sp - 1) = ' ';
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (!lcom)
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
rcs = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_com_set));
|
|
|
|
rcs->lcom = lcom;
|
|
|
|
rcs->additive = additive;
|
|
|
|
rcs->none = none;
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return rcs;
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free function for set lcommunity. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_lcommunity_free(void *rule)
|
2016-11-15 11:00:39 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct rmap_lcom_set *rcs = rule;
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (rcs->lcom) {
|
|
|
|
lcommunity_free(&rcs->lcom);
|
|
|
|
}
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs);
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set community rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_lcommunity_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"large-community", route_set_lcommunity, route_set_lcommunity_compile,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_set_lcommunity_free,
|
2016-11-15 11:00:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* `set large-comm-list (<1-99>|<100-500>|WORD) delete' */
|
|
|
|
|
|
|
|
/* For large community set mechanism. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_lcommunity_delete(void *rule, const struct prefix *pfx,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct community_list *list;
|
|
|
|
struct lcommunity *merge;
|
|
|
|
struct lcommunity *new;
|
|
|
|
struct lcommunity *old;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom = rule;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
2018-12-26 19:01:06 +01:00
|
|
|
if (!rcom)
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2018-12-26 19:01:06 +01:00
|
|
|
list = community_list_lookup(bgp_clist, rcom->name,
|
2019-01-09 02:23:11 +01:00
|
|
|
rcom->name_hash,
|
2017-07-17 14:03:14 +02:00
|
|
|
LARGE_COMMUNITY_LIST_MASTER);
|
2018-10-03 00:34:03 +02:00
|
|
|
old = path->attr->lcommunity;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (list && old) {
|
|
|
|
merge = lcommunity_list_match_delete(
|
|
|
|
lcommunity_dup(old), list);
|
|
|
|
new = lcommunity_uniq_sort(merge);
|
|
|
|
lcommunity_free(&merge);
|
|
|
|
|
|
|
|
/* HACK: if the old community is not intern'd,
|
|
|
|
* we should free it here, or all reference to it may be
|
|
|
|
* lost.
|
|
|
|
* Really need to cleanup attribute caching sometime.
|
|
|
|
*/
|
|
|
|
if (old->refcnt == 0)
|
|
|
|
lcommunity_free(&old);
|
|
|
|
|
|
|
|
if (new->size == 0) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->lcommunity = NULL;
|
|
|
|
path->attr->flag &= ~ATTR_FLAG_BIT(
|
2017-07-17 14:03:14 +02:00
|
|
|
BGP_ATTR_LARGE_COMMUNITIES);
|
|
|
|
lcommunity_free(&new);
|
|
|
|
} else {
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->lcommunity = new;
|
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(
|
2017-07-17 14:03:14 +02:00
|
|
|
BGP_ATTR_LARGE_COMMUNITIES);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return RMAP_OKAY;
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for set lcommunity. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_lcommunity_delete_compile(const char *arg)
|
2016-11-15 11:00:39 +01:00
|
|
|
{
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom;
|
2019-07-18 14:29:20 +02:00
|
|
|
char **splits;
|
|
|
|
int num;
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2019-07-18 14:29:20 +02:00
|
|
|
frrstr_split(arg, " ", &splits, &num);
|
2018-12-26 19:01:06 +01:00
|
|
|
|
2019-07-18 14:29:20 +02:00
|
|
|
rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
|
|
|
|
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
|
2019-01-09 02:23:11 +01:00
|
|
|
rcom->name_hash = bgp_clist_hash_key(rcom->name);
|
2019-02-24 01:27:09 +01:00
|
|
|
|
2019-07-18 14:29:20 +02:00
|
|
|
for (int i = 0; i < num; i++)
|
|
|
|
XFREE(MTYPE_TMP, splits[i]);
|
|
|
|
XFREE(MTYPE_TMP, splits);
|
|
|
|
|
2018-12-26 19:01:06 +01:00
|
|
|
return rcom;
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free function for set lcommunity. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_lcommunity_delete_free(void *rule)
|
2016-11-15 11:00:39 +01:00
|
|
|
{
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom = rule;
|
|
|
|
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set lcommunity rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"large-comm-list", route_set_lcommunity_delete,
|
|
|
|
route_set_lcommunity_delete_compile, route_set_lcommunity_delete_free,
|
2016-11-15 11:00:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-02-02 17:29:31 +01:00
|
|
|
/* `set comm-list (<1-99>|<100-500>|WORD) delete' */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
/* For community set mechanism. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_community_delete(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct community_list *list;
|
|
|
|
struct community *merge;
|
|
|
|
struct community *new;
|
|
|
|
struct community *old;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom = rule;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
2018-12-26 19:01:06 +01:00
|
|
|
if (!rcom)
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2018-12-26 19:01:06 +01:00
|
|
|
list = community_list_lookup(bgp_clist, rcom->name,
|
2019-01-09 02:23:11 +01:00
|
|
|
rcom->name_hash,
|
2017-07-17 14:03:14 +02:00
|
|
|
COMMUNITY_LIST_MASTER);
|
2018-10-03 00:34:03 +02:00
|
|
|
old = path->attr->community;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (list && old) {
|
|
|
|
merge = community_list_match_delete(community_dup(old),
|
|
|
|
list);
|
|
|
|
new = community_uniq_sort(merge);
|
2018-10-22 21:58:39 +02:00
|
|
|
community_free(&merge);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* HACK: if the old community is not intern'd,
|
|
|
|
* we should free it here, or all reference to it may be
|
|
|
|
* lost.
|
|
|
|
* Really need to cleanup attribute caching sometime.
|
|
|
|
*/
|
|
|
|
if (old->refcnt == 0)
|
2018-10-22 21:58:39 +02:00
|
|
|
community_free(&old);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (new->size == 0) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->community = NULL;
|
|
|
|
path->attr->flag &=
|
2017-07-17 14:03:14 +02:00
|
|
|
~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
|
2018-10-22 21:58:39 +02:00
|
|
|
community_free(&new);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->community = new;
|
|
|
|
path->attr->flag |=
|
2017-07-17 14:03:14 +02:00
|
|
|
ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
|
|
|
|
}
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for set community. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_community_delete_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom;
|
2019-07-19 14:56:58 +02:00
|
|
|
char **splits;
|
|
|
|
int num;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2019-07-19 14:56:58 +02:00
|
|
|
frrstr_split(arg, " ", &splits, &num);
|
2018-12-26 19:01:06 +01:00
|
|
|
|
2019-07-19 14:56:58 +02:00
|
|
|
rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
|
|
|
|
rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, splits[0]);
|
2019-01-09 02:23:11 +01:00
|
|
|
rcom->name_hash = bgp_clist_hash_key(rcom->name);
|
2019-02-24 01:27:09 +01:00
|
|
|
|
2019-07-19 14:56:58 +02:00
|
|
|
for (int i = 0; i < num; i++)
|
|
|
|
XFREE(MTYPE_TMP, splits[i]);
|
|
|
|
XFREE(MTYPE_TMP, splits);
|
|
|
|
|
2018-12-26 19:01:06 +01:00
|
|
|
return rcom;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free function for set community. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_community_delete_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-12-26 19:01:06 +01:00
|
|
|
struct rmap_community *rcom = rule;
|
|
|
|
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name);
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set community rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_community_delete_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"comm-list", route_set_community_delete,
|
|
|
|
route_set_community_delete_compile, route_set_community_delete_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set extcommunity rt COMMUNITY' */
|
|
|
|
|
2014-06-04 00:58:47 +02:00
|
|
|
/* For community set mechanism. Used by _rt and _soo. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_ecommunity(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct ecommunity *ecom;
|
|
|
|
struct ecommunity *new_ecom;
|
|
|
|
struct ecommunity *old_ecom;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
ecom = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (!ecom)
|
|
|
|
return RMAP_OKAY;
|
|
|
|
|
|
|
|
/* We assume additive for Extended Community. */
|
2018-10-03 00:34:03 +02:00
|
|
|
old_ecom = path->attr->ecommunity;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (old_ecom) {
|
|
|
|
new_ecom = ecommunity_merge(ecommunity_dup(old_ecom),
|
|
|
|
ecom);
|
|
|
|
|
|
|
|
/* old_ecom->refcnt = 1 => owned elsewhere, e.g.
|
|
|
|
* bgp_update_receive()
|
|
|
|
* ->refcnt = 0 => set by a previous route-map
|
|
|
|
* statement */
|
|
|
|
if (!old_ecom->refcnt)
|
|
|
|
ecommunity_free(&old_ecom);
|
|
|
|
} else
|
|
|
|
new_ecom = ecommunity_dup(ecom);
|
|
|
|
|
|
|
|
/* will be intern()'d or attr_flush()'d by bgp_update_main() */
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->ecommunity = new_ecom;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
|
2014-06-04 00:59:01 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for set community. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_ecommunity_rt_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct ecommunity *ecom;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ecom = ecommunity_str2com(arg, ECOMMUNITY_ROUTE_TARGET, 0);
|
|
|
|
if (!ecom)
|
|
|
|
return NULL;
|
|
|
|
return ecommunity_intern(ecom);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2014-06-04 00:58:47 +02:00
|
|
|
/* Free function for set community. Used by _rt and _soo */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_ecommunity_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct ecommunity *ecom = rule;
|
|
|
|
ecommunity_unintern(&ecom);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set community rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_ecommunity_rt_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"extcommunity rt", route_set_ecommunity,
|
|
|
|
route_set_ecommunity_rt_compile, route_set_ecommunity_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/* `set extcommunity soo COMMUNITY' */
|
|
|
|
|
|
|
|
/* Compile function for set community. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_ecommunity_soo_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct ecommunity *ecom;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ecom = ecommunity_str2com(arg, ECOMMUNITY_SITE_ORIGIN, 0);
|
|
|
|
if (!ecom)
|
|
|
|
return NULL;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return ecommunity_intern(ecom);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set community rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_ecommunity_soo_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"extcommunity soo", route_set_ecommunity,
|
|
|
|
route_set_ecommunity_soo_compile, route_set_ecommunity_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set origin ORIGIN' */
|
|
|
|
|
|
|
|
/* For origin set. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_origin(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *origin;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
origin = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->origin = *origin;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for origin set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_origin_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *origin;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
origin = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (strcmp(arg, "igp") == 0)
|
|
|
|
*origin = 0;
|
|
|
|
else if (strcmp(arg, "egp") == 0)
|
|
|
|
*origin = 1;
|
|
|
|
else
|
|
|
|
*origin = 2;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return origin;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for origin set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_origin_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2014-05-20 07:57:26 +02:00
|
|
|
/* Set origin rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_origin_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"origin", route_set_origin, route_set_origin_compile,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_set_origin_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set atomic-aggregate' */
|
|
|
|
|
|
|
|
/* For atomic aggregate set. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_atomic_aggregate(void *rule, const struct prefix *pfx,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for atomic aggregate. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_atomic_aggregate_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return (void *)1;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for atomic aggregate. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_atomic_aggregate_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set atomic aggregate rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_atomic_aggregate_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"atomic-aggregate", route_set_atomic_aggregate,
|
|
|
|
route_set_atomic_aggregate_compile, route_set_atomic_aggregate_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set aggregator as AS A.B.C.D' */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct aggregator {
|
|
|
|
as_t as;
|
|
|
|
struct in_addr address;
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_aggregator_as(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct aggregator *aggregator;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
aggregator = rule;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->aggregator_as = aggregator->as;
|
|
|
|
path->attr->aggregator_addr = aggregator->address;
|
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_aggregator_as_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct aggregator *aggregator;
|
|
|
|
char as[10];
|
|
|
|
char address[20];
|
|
|
|
int ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
aggregator =
|
|
|
|
XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct aggregator));
|
2017-12-05 02:51:34 +01:00
|
|
|
if (sscanf(arg, "%s %s", as, address) != 2) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
aggregator->as = strtoul(as, NULL, 10);
|
|
|
|
ret = inet_aton(address, &aggregator->address);
|
|
|
|
if (ret == 0) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, aggregator);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return aggregator;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_aggregator_as_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_aggregator_as_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"aggregator as", route_set_aggregator_as,
|
|
|
|
route_set_aggregator_as_compile, route_set_aggregator_as_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2018-10-02 22:41:30 +02:00
|
|
|
/* Set tag to object. object must be pointer to struct bgp_path_info */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_tag(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2015-05-20 02:46:33 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
route_tag_t *tag;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
tag = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Set tag value */
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->tag = *tag;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2015-05-20 02:46:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for tag set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static struct route_map_rule_cmd route_set_tag_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"tag", route_set_tag, route_map_rule_tag_compile,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_rule_tag_free,
|
2015-05-20 02:46:33 +02:00
|
|
|
};
|
|
|
|
|
2018-10-02 22:41:30 +02:00
|
|
|
/* Set label-index to object. object must be pointer to struct bgp_path_info */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_label_index(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct rmap_value *rv;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint32_t label_index;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
|
|
|
rv = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Set label-index value. */
|
|
|
|
label_index = rv->value;
|
|
|
|
if (label_index) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->label_index = label_index;
|
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
2017-06-02 21:22:53 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2017-06-02 21:22:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for label-index set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static struct route_map_rule_cmd route_set_label_index_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"label-index", route_set_label_index, route_value_compile,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_value_free,
|
2017-06-02 21:22:53 +02:00
|
|
|
};
|
2015-05-20 02:46:33 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match ipv6 address IP_ACCESS_LIST' */
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_ipv6_address(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct access_list *alist;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-05-15 19:22:25 +02:00
|
|
|
if (type == RMAP_BGP && prefix->family == AF_INET6) {
|
2017-07-17 14:03:14 +02:00
|
|
|
alist = access_list_lookup(AFI_IP6, (char *)rule);
|
|
|
|
if (alist == NULL)
|
|
|
|
return RMAP_NOMATCH;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return (access_list_apply(alist, prefix) == FILTER_DENY
|
|
|
|
? RMAP_NOMATCH
|
|
|
|
: RMAP_MATCH);
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ipv6_address_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ipv6_address_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip address matching. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ipv6_address_cmd = {
|
|
|
|
"ipv6 address", route_match_ipv6_address,
|
|
|
|
route_match_ipv6_address_compile, route_match_ipv6_address_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match ipv6 next-hop IP_ADDRESS' */
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_match_ipv6_next_hop(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct in6_addr *addr = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_MATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->mp_nexthop_len
|
2017-07-17 14:03:14 +02:00
|
|
|
== BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
|
2018-10-03 00:34:03 +02:00
|
|
|
&& IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_MATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_NOMATCH;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ipv6_next_hop_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct in6_addr *address;
|
|
|
|
int ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = inet_pton(AF_INET6, arg, address);
|
|
|
|
if (!ret) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return address;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ipv6_next_hop_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
|
|
|
|
"ipv6 next-hop", route_match_ipv6_next_hop,
|
|
|
|
route_match_ipv6_next_hop_compile, route_match_ipv6_next_hop_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `match ipv6 address prefix-list PREFIX_LIST' */
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2018-07-12 22:05:19 +02:00
|
|
|
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2019-06-14 12:05:18 +02:00
|
|
|
return route_match_address_prefix_list(rule, AFI_IP6, prefix, type,
|
|
|
|
object);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_match_ipv6_address_prefix_list_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
|
|
|
|
"ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
|
|
|
|
route_match_ipv6_address_prefix_list_compile,
|
|
|
|
route_match_ipv6_address_prefix_list_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2018-09-28 10:51:50 +02:00
|
|
|
/* `match ipv6 next-hop type <TYPE>' */
|
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2018-09-28 10:51:50 +02:00
|
|
|
route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
route_map_object_t type, void *object)
|
2018-09-28 10:51:50 +02:00
|
|
|
{
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2018-09-28 10:51:50 +02:00
|
|
|
struct in6_addr *addr = rule;
|
|
|
|
|
|
|
|
if (type == RMAP_BGP && prefix->family == AF_INET6) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path = (struct bgp_path_info *)object;
|
|
|
|
if (!path || !path->attr)
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
return RMAP_NOMATCH;
|
2018-09-28 10:51:50 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)
|
|
|
|
&& !path->attr->nh_ifindex)
|
2018-09-28 10:51:50 +02:00
|
|
|
return RMAP_MATCH;
|
|
|
|
}
|
|
|
|
return RMAP_NOMATCH;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *route_match_ipv6_next_hop_type_compile(const char *arg)
|
|
|
|
{
|
|
|
|
struct in6_addr *address;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
|
|
|
|
|
|
|
|
ret = inet_pton(AF_INET6, "::0", address);
|
|
|
|
if (!ret) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void route_match_ipv6_next_hop_type_free(void *rule)
|
|
|
|
{
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct route_map_rule_cmd route_match_ipv6_next_hop_type_cmd = {
|
|
|
|
"ipv6 next-hop type", route_match_ipv6_next_hop_type,
|
|
|
|
route_match_ipv6_next_hop_type_compile,
|
|
|
|
route_match_ipv6_next_hop_type_free};
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set ipv6 nexthop global IP_ADDRESS' */
|
|
|
|
|
|
|
|
/* Set nexthop to object. ojbect must be pointer to struct attr. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_ipv6_nexthop_global(void *rule, const struct prefix *p,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct in6_addr *address;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
|
|
|
address = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Set next hop value. */
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->mp_nexthop_global = *address;
|
2015-05-20 03:03:47 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Set nexthop length. */
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->mp_nexthop_len == 0)
|
|
|
|
path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
|
2015-05-20 03:03:47 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
SET_FLAG(path->attr->rmap_change_flags,
|
2017-07-17 14:03:14 +02:00
|
|
|
BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `ip next-hop' compile function. Given string is converted
|
|
|
|
to struct in_addr structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_ipv6_nexthop_global_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
|
|
|
struct in6_addr *address;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = inet_pton(AF_INET6, arg, address);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret == 0) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return address;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip next-hop' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_ipv6_nexthop_global_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip nexthop set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_ipv6_nexthop_global_cmd = {
|
|
|
|
"ipv6 next-hop global", route_set_ipv6_nexthop_global,
|
|
|
|
route_set_ipv6_nexthop_global_compile,
|
|
|
|
route_set_ipv6_nexthop_global_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2016-08-03 15:49:09 +02:00
|
|
|
/* Set next-hop preference value. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
2018-07-12 22:05:19 +02:00
|
|
|
route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_object_t type, void *object)
|
|
|
|
{
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct peer *peer;
|
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
peer = path->peer;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
|
|
|
|
|| CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
|
|
|
|
&& peer->su_remote
|
|
|
|
&& sockunion_family(peer->su_remote) == AF_INET6) {
|
|
|
|
/* Set next hop preference to global */
|
2019-07-01 19:26:05 +02:00
|
|
|
path->attr->mp_nexthop_prefer_global = true;
|
2018-10-03 00:34:03 +02:00
|
|
|
SET_FLAG(path->attr->rmap_change_flags,
|
2017-07-17 14:03:14 +02:00
|
|
|
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
|
|
|
|
} else {
|
2019-07-01 19:26:05 +02:00
|
|
|
path->attr->mp_nexthop_prefer_global = false;
|
2018-10-03 00:34:03 +02:00
|
|
|
SET_FLAG(path->attr->rmap_change_flags,
|
2017-07-17 14:03:14 +02:00
|
|
|
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
|
|
|
|
}
|
2016-08-03 15:49:09 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2016-08-03 15:49:09 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_ipv6_nexthop_prefer_global_compile(const char *arg)
|
2016-08-03 15:49:09 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int *rins = NULL;
|
2016-08-03 15:49:09 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
|
|
|
|
*rins = 1;
|
2016-08-03 15:49:09 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return rins;
|
2016-08-03 15:49:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip next-hop' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_ipv6_nexthop_prefer_global_free(void *rule)
|
2016-08-03 15:49:09 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2016-08-03 15:49:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip nexthop set preferred. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_ipv6_nexthop_prefer_global_cmd = {
|
|
|
|
"ipv6 next-hop prefer-global", route_set_ipv6_nexthop_prefer_global,
|
|
|
|
route_set_ipv6_nexthop_prefer_global_compile,
|
|
|
|
route_set_ipv6_nexthop_prefer_global_free};
|
2016-08-03 15:49:09 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set ipv6 nexthop local IP_ADDRESS' */
|
|
|
|
|
|
|
|
/* Set nexthop to object. ojbect must be pointer to struct attr. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_ipv6_nexthop_local(void *rule, const struct prefix *p,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct in6_addr *address;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
|
|
|
address = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Set next hop value. */
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->mp_nexthop_local = *address;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* Set nexthop length. */
|
2018-10-03 00:34:03 +02:00
|
|
|
if (path->attr->mp_nexthop_len
|
2017-07-17 14:03:14 +02:00
|
|
|
!= BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->mp_nexthop_len =
|
2017-07-17 14:03:14 +02:00
|
|
|
BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
|
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
SET_FLAG(path->attr->rmap_change_flags,
|
2017-07-17 14:03:14 +02:00
|
|
|
BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `ip nexthop' compile function. Given string is converted
|
|
|
|
to struct in_addr structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_ipv6_nexthop_local_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
|
|
|
struct in6_addr *address;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = inet_pton(AF_INET6, arg, address);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret == 0) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return address;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip nexthop' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_ipv6_nexthop_local_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip nexthop set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_ipv6_nexthop_local_cmd = {
|
|
|
|
"ipv6 next-hop local", route_set_ipv6_nexthop_local,
|
|
|
|
route_set_ipv6_nexthop_local_compile,
|
|
|
|
route_set_ipv6_nexthop_local_free};
|
2015-05-20 02:24:45 +02:00
|
|
|
|
|
|
|
/* `set ipv6 nexthop peer-address' */
|
|
|
|
|
|
|
|
/* Set nexthop to object. ojbect must be pointer to struct attr. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx,
|
|
|
|
route_map_object_t type, void *object)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct in6_addr peer_address;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct peer *peer;
|
|
|
|
|
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
|
|
|
peer = path->peer;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
|
|
|
|
|| CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
|
|
|
|
&& peer->su_remote
|
|
|
|
&& sockunion_family(peer->su_remote) == AF_INET6) {
|
|
|
|
peer_address = peer->su_remote->sin6.sin6_addr;
|
|
|
|
/* Set next hop value and length in attribute. */
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->mp_nexthop_local = peer_address;
|
2019-09-13 10:43:44 +02:00
|
|
|
if (path->attr->mp_nexthop_len
|
|
|
|
!= BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
|
|
|
|
path->attr->mp_nexthop_len =
|
|
|
|
BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->mp_nexthop_global = peer_address;
|
|
|
|
if (path->attr->mp_nexthop_len == 0)
|
2019-09-13 10:43:44 +02:00
|
|
|
path->attr->mp_nexthop_len =
|
|
|
|
BGP_ATTR_NHLEN_IPV6_GLOBAL;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
|
|
|
|
/* The next hop value will be set as part of packet
|
|
|
|
* rewrite.
|
|
|
|
* Set the flags here to indicate that rewrite needs to
|
|
|
|
* be done.
|
|
|
|
* Also, clear the value - we clear both global and
|
|
|
|
* link-local
|
|
|
|
* nexthops, whether we send one or both is determined
|
|
|
|
* elsewhere.
|
|
|
|
*/
|
2018-10-03 00:34:03 +02:00
|
|
|
SET_FLAG(path->attr->rmap_change_flags,
|
2017-07-17 14:03:14 +02:00
|
|
|
BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
|
|
|
|
/* clear next hop value. */
|
2018-10-03 00:34:03 +02:00
|
|
|
memset(&(path->attr->mp_nexthop_global), 0,
|
2017-07-17 14:03:14 +02:00
|
|
|
sizeof(struct in6_addr));
|
2018-10-03 00:34:03 +02:00
|
|
|
memset(&(path->attr->mp_nexthop_local), 0,
|
2017-07-17 14:03:14 +02:00
|
|
|
sizeof(struct in6_addr));
|
|
|
|
}
|
2015-05-20 02:24:45 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2015-05-20 02:24:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map `ip next-hop' compile function. Given string is converted
|
|
|
|
to struct in_addr structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_ipv6_nexthop_peer_compile(const char *arg)
|
2015-05-20 02:24:45 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int *rins = NULL;
|
2015-05-20 02:24:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
|
|
|
|
*rins = 1;
|
2015-05-20 02:24:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return rins;
|
2015-05-20 02:24:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free route map's compiled `ip next-hop' value. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_ipv6_nexthop_peer_free(void *rule)
|
2015-05-20 02:24:45 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2015-05-20 02:24:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Route map commands for ip nexthop set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
|
|
|
|
"ipv6 next-hop peer-address", route_set_ipv6_nexthop_peer,
|
|
|
|
route_set_ipv6_nexthop_peer_compile, route_set_ipv6_nexthop_peer_free};
|
2015-05-20 02:24:45 +02:00
|
|
|
|
2017-07-12 20:02:33 +02:00
|
|
|
/* `set ipv4 vpn next-hop A.B.C.D' */
|
2002-12-13 21:15:29 +01:00
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct in_addr *address;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
|
|
|
address = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Set next hop value. */
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->mp_nexthop_global_in = *address;
|
2019-09-13 10:43:44 +02:00
|
|
|
path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_vpnv4_nexthop_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
|
|
|
struct in_addr *address;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = inet_aton(arg, address);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret == 0) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return address;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-12 20:02:33 +02:00
|
|
|
/* `set ipv6 vpn next-hop A.B.C.D' */
|
2017-01-18 12:27:52 +01:00
|
|
|
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2017-01-18 12:27:52 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct in6_addr *address;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2017-01-18 12:27:52 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
/* Fetch routemap's rule information. */
|
|
|
|
address = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2017-01-18 12:27:52 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
/* Set next hop value. */
|
2018-10-03 00:34:03 +02:00
|
|
|
memcpy(&path->attr->mp_nexthop_global, address,
|
2017-07-17 14:03:14 +02:00
|
|
|
sizeof(struct in6_addr));
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-01-18 12:27:52 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2017-01-18 12:27:52 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_vpnv6_nexthop_compile(const char *arg)
|
2017-01-18 12:27:52 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
|
|
|
struct in6_addr *address;
|
2017-01-18 12:27:52 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in6_addr));
|
|
|
|
ret = inet_pton(AF_INET6, arg, address);
|
2017-01-18 12:27:52 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret == 0) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-01-18 12:27:52 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return address;
|
2017-01-18 12:27:52 +01:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_vpn_nexthop_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-07-12 20:02:33 +02:00
|
|
|
/* Route map commands for ipv4 next-hop set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_vpnv4_nexthop_cmd = {
|
|
|
|
"ipv4 vpn next-hop", route_set_vpnv4_nexthop,
|
|
|
|
route_set_vpnv4_nexthop_compile, route_set_vpn_nexthop_free};
|
2017-01-18 12:27:52 +01:00
|
|
|
|
2017-07-12 20:02:33 +02:00
|
|
|
/* Route map commands for ipv6 next-hop set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
|
|
|
|
"ipv6 vpn next-hop", route_set_vpnv6_nexthop,
|
|
|
|
route_set_vpnv6_nexthop_compile, route_set_vpn_nexthop_free};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* `set originator-id' */
|
|
|
|
|
|
|
|
/* For origin set. */
|
lib: Introducing a 3rd state for route-map match cmd: RMAP_NOOP
Introducing a 3rd state for route_map_apply library function: RMAP_NOOP
Traditionally route map MATCH rule apis were designed to return
a binary response, consisting of either RMAP_MATCH or RMAP_NOMATCH.
(Route-map SET rule apis return RMAP_OKAY or RMAP_ERROR).
Depending on this response, the following statemachine decided the
course of action:
State1:
If match cmd returns RMAP_MATCH then, keep existing behaviour.
If routemap type is PERMIT, execute set cmds or call cmds if applicable,
otherwise PERMIT!
Else If routemap type is DENY, we DENYMATCH right away
State2:
If match cmd returns RMAP_NOMATCH, continue on to next route-map. If there
are no other rules or if all the rules return RMAP_NOMATCH, return DENYMATCH
We require a 3rd state because of the following situation:
The issue - what if, the rule api needs to abort or ignore a rule?:
"match evpn vni xx" route-map filter can be applied to incoming routes
regardless of whether the tunnel type is vxlan or mpls.
This rule should be N/A for mpls based evpn route, but applicable to only
vxlan based evpn route.
Also, this rule should be applicable for routes with VNI label only, and
not for routes without labels. For example, type 3 and type 4 EVPN routes
do not have labels, so, this match cmd should let them through.
Today, the filter produces either a match or nomatch response regardless of
whether it is mpls/vxlan, resulting in either permitting or denying the
route.. So an mpls evpn route may get filtered out incorrectly.
Eg: "route-map RM1 permit 10 ; match evpn vni 20" or
"route-map RM2 deny 20 ; match vni 20"
With the introduction of the 3rd state, we can abort this rule check safely.
How? The rules api can now return RMAP_NOOP to indicate
that it encountered an invalid check, and needs to abort just that rule,
but continue with other rules.
As a result we have a 3rd state:
State3:
If match cmd returned RMAP_NOOP
Then, proceed to other route-map, otherwise if there are no more
rules or if all the rules return RMAP_NOOP, then, return RMAP_PERMITMATCH.
Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
2019-06-19 23:04:36 +02:00
|
|
|
static enum route_map_cmd_result_t
|
|
|
|
route_set_originator_id(void *rule, const struct prefix *prefix,
|
|
|
|
route_map_object_t type, void *object)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
struct in_addr *address;
|
2018-10-03 00:34:03 +02:00
|
|
|
struct bgp_path_info *path;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (type == RMAP_BGP) {
|
|
|
|
address = rule;
|
2018-10-03 00:34:03 +02:00
|
|
|
path = object;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2018-10-03 00:34:03 +02:00
|
|
|
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
|
|
|
|
path->attr->originator_id = *address;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return RMAP_OKAY;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for originator-id set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void *route_set_originator_id_compile(const char *arg)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
|
|
|
struct in_addr *address;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = inet_aton(arg, address);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (ret == 0) {
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
|
|
|
|
return NULL;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return address;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compile function for originator_id set. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static void route_set_originator_id_free(void *rule)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2014-05-20 07:57:26 +02:00
|
|
|
/* Set originator-id rule structure. */
|
2017-07-17 14:03:14 +02:00
|
|
|
struct route_map_rule_cmd route_set_originator_id_cmd = {
|
2017-07-22 14:52:33 +02:00
|
|
|
"originator-id", route_set_originator_id,
|
|
|
|
route_set_originator_id_compile, route_set_originator_id_free,
|
2002-12-13 21:15:29 +01:00
|
|
|
};
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Add bgp route map rule. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int bgp_route_match_add(struct vty *vty, const char *command,
|
|
|
|
const char *arg, route_map_event_t type)
|
|
|
|
{
|
|
|
|
VTY_DECLVAR_CONTEXT(route_map_index, index);
|
2017-08-25 14:31:03 +02:00
|
|
|
int retval = CMD_SUCCESS;
|
2019-08-27 14:04:43 +02:00
|
|
|
enum rmap_compile_rets ret;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-05-15 09:09:08 +02:00
|
|
|
ret = route_map_add_match(index, command, arg, type);
|
2017-08-25 14:31:03 +02:00
|
|
|
switch (ret) {
|
|
|
|
case RMAP_RULE_MISSING:
|
|
|
|
vty_out(vty, "%% BGP Can't find rule.\n");
|
|
|
|
retval = CMD_WARNING_CONFIG_FAILED;
|
|
|
|
break;
|
|
|
|
case RMAP_COMPILE_ERROR:
|
|
|
|
vty_out(vty, "%% BGP Argument is malformed.\n");
|
|
|
|
retval = CMD_WARNING_CONFIG_FAILED;
|
|
|
|
break;
|
|
|
|
case RMAP_COMPILE_SUCCESS:
|
|
|
|
if (type != RMAP_EVENT_MATCH_ADDED) {
|
|
|
|
route_map_upd8_dependency(type, arg, index->map->name);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-08-25 14:31:03 +02:00
|
|
|
break;
|
2019-08-27 14:04:43 +02:00
|
|
|
case RMAP_DUPLICATE_RULE:
|
|
|
|
/*
|
|
|
|
* Intentionally doing nothing here.
|
|
|
|
*/
|
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2017-08-25 14:31:03 +02:00
|
|
|
return retval;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete bgp route map rule. */
|
2017-07-17 14:03:14 +02:00
|
|
|
static int bgp_route_match_delete(struct vty *vty, const char *command,
|
|
|
|
const char *arg, route_map_event_t type)
|
|
|
|
{
|
|
|
|
VTY_DECLVAR_CONTEXT(route_map_index, index);
|
2019-08-27 14:04:43 +02:00
|
|
|
enum rmap_compile_rets ret;
|
2017-08-25 14:31:03 +02:00
|
|
|
int retval = CMD_SUCCESS;
|
2017-07-17 14:03:14 +02:00
|
|
|
char *dep_name = NULL;
|
|
|
|
const char *tmpstr;
|
|
|
|
char *rmap_name = NULL;
|
|
|
|
|
|
|
|
if (type != RMAP_EVENT_MATCH_DELETED) {
|
|
|
|
/* ignore the mundane, the types without any dependency */
|
|
|
|
if (arg == NULL) {
|
|
|
|
if ((tmpstr = route_map_get_match_arg(index, command))
|
|
|
|
!= NULL)
|
|
|
|
dep_name =
|
|
|
|
XSTRDUP(MTYPE_ROUTE_MAP_RULE, tmpstr);
|
|
|
|
} else {
|
|
|
|
dep_name = XSTRDUP(MTYPE_ROUTE_MAP_RULE, arg);
|
|
|
|
}
|
|
|
|
rmap_name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, index->map->name);
|
2015-05-20 03:12:17 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
ret = route_map_delete_match(index, command, dep_name);
|
2017-08-25 14:31:03 +02:00
|
|
|
switch (ret) {
|
|
|
|
case RMAP_RULE_MISSING:
|
|
|
|
vty_out(vty, "%% BGP Can't find rule.\n");
|
|
|
|
retval = CMD_WARNING_CONFIG_FAILED;
|
|
|
|
break;
|
|
|
|
case RMAP_COMPILE_ERROR:
|
|
|
|
vty_out(vty, "%% BGP Argument is malformed.\n");
|
|
|
|
retval = CMD_WARNING_CONFIG_FAILED;
|
|
|
|
break;
|
|
|
|
case RMAP_COMPILE_SUCCESS:
|
|
|
|
if (type != RMAP_EVENT_MATCH_DELETED && dep_name)
|
|
|
|
route_map_upd8_dependency(type, dep_name, rmap_name);
|
|
|
|
break;
|
2019-08-27 14:04:43 +02:00
|
|
|
case RMAP_DUPLICATE_RULE:
|
|
|
|
/*
|
|
|
|
* Nothing to do here
|
|
|
|
*/
|
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2019-02-25 21:18:13 +01:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2017-08-25 14:31:03 +02:00
|
|
|
return retval;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2015-05-20 02:40:45 +02:00
|
|
|
/*
|
2015-11-10 16:29:12 +01:00
|
|
|
* This is the workhorse routine for processing in/out routemap
|
2015-05-20 02:40:45 +02:00
|
|
|
* modifications.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
static void bgp_route_map_process_peer(const char *rmap_name,
|
|
|
|
struct route_map *map, struct peer *peer,
|
|
|
|
int afi, int safi, int route_update)
|
|
|
|
{
|
|
|
|
struct bgp_filter *filter;
|
|
|
|
|
|
|
|
if (!peer || !rmap_name)
|
|
|
|
return;
|
|
|
|
|
|
|
|
filter = &peer->filter[afi][safi];
|
|
|
|
/*
|
|
|
|
* in is for non-route-server clients,
|
|
|
|
* out is for all peers
|
|
|
|
*/
|
2019-05-17 13:29:47 +02:00
|
|
|
if (filter->map[RMAP_IN].name
|
|
|
|
&& (strcmp(rmap_name, filter->map[RMAP_IN].name) == 0)) {
|
|
|
|
filter->map[RMAP_IN].map = map;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-05-17 13:29:47 +02:00
|
|
|
if (route_update && peer->status == Established) {
|
2017-07-17 14:03:14 +02:00
|
|
|
if (CHECK_FLAG(peer->af_flags[afi][safi],
|
|
|
|
PEER_FLAG_SOFT_RECONFIG)) {
|
|
|
|
if (bgp_debug_update(peer, NULL, NULL, 1))
|
|
|
|
zlog_debug(
|
2019-05-17 13:29:47 +02:00
|
|
|
"Processing route_map %s update on peer %s (inbound, soft-reconfig)",
|
2017-07-17 14:03:14 +02:00
|
|
|
rmap_name, peer->host);
|
|
|
|
|
|
|
|
bgp_soft_reconfig_in(peer, afi, safi);
|
|
|
|
} else if (CHECK_FLAG(peer->cap,
|
|
|
|
PEER_CAP_REFRESH_OLD_RCV)
|
|
|
|
|| CHECK_FLAG(peer->cap,
|
|
|
|
PEER_CAP_REFRESH_NEW_RCV)) {
|
|
|
|
if (bgp_debug_update(peer, NULL, NULL, 1))
|
|
|
|
zlog_debug(
|
2019-05-17 13:29:47 +02:00
|
|
|
"Processing route_map %s update on peer %s (inbound, route-refresh)",
|
2017-07-17 14:03:14 +02:00
|
|
|
rmap_name, peer->host);
|
|
|
|
bgp_route_refresh_send(peer, afi, safi, 0, 0,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
2015-05-20 02:40:45 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* For outbound, unsuppress and default-originate map change (content or
|
|
|
|
* map created), merely update the "config" here, the actual route
|
|
|
|
* announcement happens at the group level.
|
|
|
|
*/
|
|
|
|
if (filter->map[RMAP_OUT].name
|
|
|
|
&& (strcmp(rmap_name, filter->map[RMAP_OUT].name) == 0))
|
|
|
|
filter->map[RMAP_OUT].map = map;
|
|
|
|
|
|
|
|
if (filter->usmap.name && (strcmp(rmap_name, filter->usmap.name) == 0))
|
|
|
|
filter->usmap.map = map;
|
|
|
|
|
|
|
|
if (peer->default_rmap[afi][safi].name
|
|
|
|
&& (strcmp(rmap_name, peer->default_rmap[afi][safi].name) == 0))
|
|
|
|
peer->default_rmap[afi][safi].map = map;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bgp_route_map_update_peer_group(const char *rmap_name,
|
|
|
|
struct route_map *map,
|
|
|
|
struct bgp *bgp)
|
|
|
|
{
|
|
|
|
struct peer_group *group;
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct bgp_filter *filter;
|
|
|
|
int afi, safi;
|
|
|
|
int direct;
|
|
|
|
|
|
|
|
if (!bgp)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* All the peers have been updated correctly already. This is
|
|
|
|
* just updating the placeholder data. No real update required.
|
|
|
|
*/
|
2017-11-21 19:02:06 +01:00
|
|
|
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
|
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
filter = &group->conf->filter[afi][safi];
|
|
|
|
|
|
|
|
for (direct = RMAP_IN; direct < RMAP_MAX; direct++) {
|
|
|
|
if ((filter->map[direct].name)
|
|
|
|
&& (strcmp(rmap_name,
|
|
|
|
filter->map[direct].name)
|
2017-07-17 14:03:14 +02:00
|
|
|
== 0))
|
2017-11-21 19:02:06 +01:00
|
|
|
filter->map[direct].map = map;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2017-11-21 19:02:06 +01:00
|
|
|
|
|
|
|
if (filter->usmap.name
|
|
|
|
&& (strcmp(rmap_name, filter->usmap.name) == 0))
|
|
|
|
filter->usmap.map = map;
|
|
|
|
}
|
|
|
|
}
|
2015-05-20 02:40:45 +02:00
|
|
|
}
|
|
|
|
|
2015-10-28 20:12:24 +01:00
|
|
|
/*
|
|
|
|
* Note that if an extreme number (tens of thousands) of route-maps are in use
|
|
|
|
* and if bgp has an extreme number of peers, network statements, etc then this
|
|
|
|
* function can consume a lot of cycles. This is due to this function being
|
|
|
|
* called for each route-map and within this function we walk the list of peers,
|
|
|
|
* network statements, etc looking to see if they use this route-map.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
|
|
|
|
int route_update)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
afi_t afi;
|
|
|
|
safi_t safi;
|
|
|
|
struct peer *peer;
|
|
|
|
struct bgp_node *bn;
|
|
|
|
struct bgp_static *bgp_static;
|
2019-08-21 17:16:05 +02:00
|
|
|
struct bgp_aggregate *aggregate;
|
2017-07-17 14:03:14 +02:00
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct route_map *map;
|
|
|
|
char buf[INET6_ADDRSTRLEN];
|
|
|
|
|
|
|
|
map = route_map_lookup_by_name(rmap_name);
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
|
|
|
|
|
|
|
|
/* Ignore dummy peer-group structure */
|
|
|
|
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
|
|
|
|
continue;
|
|
|
|
|
2017-11-21 19:02:06 +01:00
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
/* process in/out/import/export/default-orig
|
|
|
|
* route-maps */
|
|
|
|
bgp_route_map_process_peer(rmap_name, map, peer, afi,
|
|
|
|
safi, route_update);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* for outbound/default-orig route-maps, process for groups */
|
|
|
|
update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP, rmap_name,
|
|
|
|
route_update, 0);
|
|
|
|
|
|
|
|
/* update peer-group config (template) */
|
|
|
|
bgp_route_map_update_peer_group(rmap_name, map, bgp);
|
|
|
|
|
2017-11-21 19:02:06 +01:00
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
|
|
|
/* For table route-map updates. */
|
|
|
|
if (!bgp_fibupd_safi(safi))
|
|
|
|
continue;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-11-21 19:02:06 +01:00
|
|
|
if (bgp->table_map[afi][safi].name
|
|
|
|
&& (strcmp(rmap_name, bgp->table_map[afi][safi].name)
|
|
|
|
== 0)) {
|
2019-02-04 14:27:56 +01:00
|
|
|
|
|
|
|
/* bgp->table_map[afi][safi].map is NULL.
|
|
|
|
* i.e Route map creation event.
|
|
|
|
* So update applied_counter.
|
|
|
|
* If it is not NULL, i.e It may be routemap updation or
|
|
|
|
* deletion. so no need to update the counter.
|
|
|
|
*/
|
|
|
|
if (!bgp->table_map[afi][safi].map)
|
|
|
|
route_map_counter_increment(map);
|
2017-11-21 19:02:06 +01:00
|
|
|
bgp->table_map[afi][safi].map = map;
|
|
|
|
|
|
|
|
if (BGP_DEBUG(zebra, ZEBRA))
|
|
|
|
zlog_debug(
|
|
|
|
"Processing route_map %s update on "
|
|
|
|
"table map",
|
|
|
|
rmap_name);
|
|
|
|
if (route_update)
|
|
|
|
bgp_zebra_announce_table(bgp, afi, safi);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-11-21 19:02:06 +01:00
|
|
|
/* For network route-map updates. */
|
|
|
|
for (bn = bgp_table_top(bgp->route[afi][safi]); bn;
|
2018-09-26 13:51:49 +02:00
|
|
|
bn = bgp_route_next(bn)) {
|
2018-11-16 14:46:19 +01:00
|
|
|
bgp_static = bgp_node_get_bgp_static_info(bn);
|
2018-10-12 14:44:15 +02:00
|
|
|
if (!bgp_static)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!bgp_static->rmap.name
|
|
|
|
|| (strcmp(rmap_name, bgp_static->rmap.name) != 0))
|
|
|
|
continue;
|
|
|
|
|
2019-02-04 14:27:56 +01:00
|
|
|
if (!bgp_static->rmap.map)
|
|
|
|
route_map_counter_increment(map);
|
|
|
|
|
2018-10-12 14:44:15 +02:00
|
|
|
bgp_static->rmap.map = map;
|
|
|
|
|
|
|
|
if (route_update && !bgp_static->backdoor) {
|
|
|
|
if (bgp_debug_zebra(&bn->p))
|
|
|
|
zlog_debug(
|
|
|
|
"Processing route_map %s update on static route %s",
|
|
|
|
rmap_name,
|
|
|
|
inet_ntop(bn->p.family,
|
|
|
|
&bn->p.u.prefix, buf,
|
|
|
|
INET6_ADDRSTRLEN));
|
|
|
|
bgp_static_update(bgp, &bn->p, bgp_static, afi,
|
|
|
|
safi);
|
2017-11-21 19:02:06 +01:00
|
|
|
}
|
2018-09-26 13:51:49 +02:00
|
|
|
}
|
2019-08-21 17:16:05 +02:00
|
|
|
|
|
|
|
/* For aggregate-address route-map updates. */
|
|
|
|
for (bn = bgp_table_top(bgp->aggregate[afi][safi]); bn;
|
|
|
|
bn = bgp_route_next(bn)) {
|
|
|
|
aggregate = bgp_node_get_bgp_aggregate_info(bn);
|
|
|
|
if (!aggregate)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!aggregate->rmap.name
|
|
|
|
|| (strcmp(rmap_name, aggregate->rmap.name) != 0))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!aggregate->rmap.map)
|
|
|
|
route_map_counter_increment(map);
|
|
|
|
|
|
|
|
aggregate->rmap.map = map;
|
|
|
|
|
|
|
|
if (route_update) {
|
|
|
|
if (bgp_debug_zebra(&bn->p))
|
|
|
|
zlog_debug(
|
|
|
|
"Processing route_map %s update on aggregate-address route %s",
|
|
|
|
rmap_name,
|
|
|
|
inet_ntop(bn->p.family,
|
|
|
|
&bn->p.u.prefix, buf,
|
|
|
|
INET6_ADDRSTRLEN));
|
|
|
|
bgp_aggregate_route(bgp, &bn->p, afi, safi,
|
|
|
|
aggregate);
|
|
|
|
}
|
|
|
|
}
|
2017-11-21 19:02:06 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
/* For redistribute route-map updates. */
|
|
|
|
for (afi = AFI_IP; afi < AFI_MAX; afi++)
|
|
|
|
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
|
|
|
|
struct list *red_list;
|
|
|
|
struct bgp_redist *red;
|
|
|
|
|
|
|
|
red_list = bgp->redist[afi][i];
|
|
|
|
if (!red_list)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
|
2018-10-12 14:44:15 +02:00
|
|
|
if (!red->rmap.name
|
|
|
|
|| (strcmp(rmap_name, red->rmap.name) != 0))
|
|
|
|
continue;
|
|
|
|
|
2019-02-04 14:27:56 +01:00
|
|
|
if (!red->rmap.map)
|
|
|
|
route_map_counter_increment(map);
|
|
|
|
|
2018-10-12 14:44:15 +02:00
|
|
|
red->rmap.map = map;
|
|
|
|
|
|
|
|
if (!route_update)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (BGP_DEBUG(zebra, ZEBRA))
|
|
|
|
zlog_debug(
|
|
|
|
"Processing route_map %s update on redistributed routes",
|
|
|
|
rmap_name);
|
|
|
|
|
|
|
|
bgp_redistribute_resend(bgp, afi, i,
|
2017-07-17 14:03:14 +02:00
|
|
|
red->instance);
|
|
|
|
}
|
|
|
|
}
|
2018-02-09 10:09:20 +01:00
|
|
|
|
|
|
|
/* for type5 command route-maps */
|
|
|
|
FOREACH_AFI_SAFI (afi, safi) {
|
2018-10-12 14:44:15 +02:00
|
|
|
if (!bgp->adv_cmd_rmap[afi][safi].name
|
|
|
|
|| strcmp(rmap_name, bgp->adv_cmd_rmap[afi][safi].name)
|
|
|
|
!= 0)
|
|
|
|
continue;
|
|
|
|
|
2019-01-24 10:43:48 +01:00
|
|
|
/* Make sure the route-map is populated here if not already done */
|
|
|
|
bgp->adv_cmd_rmap[afi][safi].map = map;
|
|
|
|
|
2018-10-12 14:44:15 +02:00
|
|
|
if (BGP_DEBUG(zebra, ZEBRA))
|
|
|
|
zlog_debug(
|
|
|
|
"Processing route_map %s update on advertise type5 route command",
|
|
|
|
rmap_name);
|
2019-01-24 10:43:48 +01:00
|
|
|
|
2019-03-05 19:40:26 +01:00
|
|
|
if (route_update && advertise_type5_routes(bgp, afi)) {
|
2019-01-24 10:43:48 +01:00
|
|
|
bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
|
|
|
|
bgp_evpn_advertise_type5_routes(bgp, afi, safi);
|
|
|
|
}
|
2018-02-09 10:09:20 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2018-06-20 03:18:33 +02:00
|
|
|
static void bgp_route_map_process_update_cb(char *rmap_name)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct bgp *bgp;
|
|
|
|
|
2018-03-09 21:52:55 +01:00
|
|
|
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
|
2017-07-17 14:03:14 +02:00
|
|
|
bgp_route_map_process_update(bgp, rmap_name, 1);
|
2016-03-22 18:46:30 +01:00
|
|
|
|
bgpd: add L3/L2VPN Virtual Network Control feature
This feature adds an L3 & L2 VPN application that makes use of the VPN
and Encap SAFIs. This code is currently used to support IETF NVO3 style
operation. In NVO3 terminology it provides the Network Virtualization
Authority (NVA) and the ability to import/export IP prefixes and MAC
addresses from Network Virtualization Edges (NVEs). The code supports
per-NVE tables.
The NVE-NVA protocol used to communicate routing and Ethernet / Layer 2
(L2) forwarding information between NVAs and NVEs is referred to as the
Remote Forwarder Protocol (RFP). OpenFlow is an example RFP. For
general background on NVO3 and RFP concepts see [1]. For information on
Openflow see [2].
RFPs are integrated with BGP via the RF API contained in the new "rfapi"
BGP sub-directory. Currently, only a simple example RFP is included in
Quagga. Developers may use this example as a starting point to integrate
Quagga with an RFP of their choosing, e.g., OpenFlow. The RFAPI code
also supports the ability import/export of routing information between
VNC and customer edge routers (CEs) operating within a virtual
network. Import/export may take place between BGP views or to the
default zebera VRF.
BGP, with IP VPNs and Tunnel Encapsulation, is used to distribute VPN
information between NVAs. BGP based IP VPN support is defined in
RFC4364, BGP/MPLS IP Virtual Private Networks (VPNs), and RFC4659,
BGP-MPLS IP Virtual Private Network (VPN) Extension for IPv6 VPN . Use
of both the Encapsulation Subsequent Address Family Identifier (SAFI)
and the Tunnel Encapsulation Attribute, RFC5512, The BGP Encapsulation
Subsequent Address Family Identifier (SAFI) and the BGP Tunnel
Encapsulation Attribute, are supported. MAC address distribution does
not follow any standard BGB encoding, although it was inspired by the
early IETF EVPN concepts.
The feature is conditionally compiled and disabled by default.
Use the --enable-bgp-vnc configure option to enable.
The majority of this code was authored by G. Paul Ziemba
<paulz@labn.net>.
[1] http://tools.ietf.org/html/draft-ietf-nvo3-nve-nva-cp-req
[2] https://www.opennetworking.org/sdn-resources/technical-library
Now includes changes needed to merge with cmaster-next.
2016-05-07 20:18:56 +02:00
|
|
|
#if ENABLE_BGP_VNC
|
2018-03-09 21:52:55 +01:00
|
|
|
/* zlog_debug("%s: calling vnc_routemap_update", __func__); */
|
|
|
|
vnc_routemap_update(bgp, __func__);
|
bgpd: add L3/L2VPN Virtual Network Control feature
This feature adds an L3 & L2 VPN application that makes use of the VPN
and Encap SAFIs. This code is currently used to support IETF NVO3 style
operation. In NVO3 terminology it provides the Network Virtualization
Authority (NVA) and the ability to import/export IP prefixes and MAC
addresses from Network Virtualization Edges (NVEs). The code supports
per-NVE tables.
The NVE-NVA protocol used to communicate routing and Ethernet / Layer 2
(L2) forwarding information between NVAs and NVEs is referred to as the
Remote Forwarder Protocol (RFP). OpenFlow is an example RFP. For
general background on NVO3 and RFP concepts see [1]. For information on
Openflow see [2].
RFPs are integrated with BGP via the RF API contained in the new "rfapi"
BGP sub-directory. Currently, only a simple example RFP is included in
Quagga. Developers may use this example as a starting point to integrate
Quagga with an RFP of their choosing, e.g., OpenFlow. The RFAPI code
also supports the ability import/export of routing information between
VNC and customer edge routers (CEs) operating within a virtual
network. Import/export may take place between BGP views or to the
default zebera VRF.
BGP, with IP VPNs and Tunnel Encapsulation, is used to distribute VPN
information between NVAs. BGP based IP VPN support is defined in
RFC4364, BGP/MPLS IP Virtual Private Networks (VPNs), and RFC4659,
BGP-MPLS IP Virtual Private Network (VPN) Extension for IPv6 VPN . Use
of both the Encapsulation Subsequent Address Family Identifier (SAFI)
and the Tunnel Encapsulation Attribute, RFC5512, The BGP Encapsulation
Subsequent Address Family Identifier (SAFI) and the BGP Tunnel
Encapsulation Attribute, are supported. MAC address distribution does
not follow any standard BGB encoding, although it was inspired by the
early IETF EVPN concepts.
The feature is conditionally compiled and disabled by default.
Use the --enable-bgp-vnc configure option to enable.
The majority of this code was authored by G. Paul Ziemba
<paulz@labn.net>.
[1] http://tools.ietf.org/html/draft-ietf-nvo3-nve-nva-cp-req
[2] https://www.opennetworking.org/sdn-resources/technical-library
Now includes changes needed to merge with cmaster-next.
2016-05-07 20:18:56 +02:00
|
|
|
#endif
|
2018-03-09 21:52:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
vpn_policy_routemap_event(rmap_name);
|
2015-05-20 02:40:45 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
int bgp_route_map_update_timer(struct thread *thread)
|
2015-05-20 02:40:45 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
bm->t_rmap_update = NULL;
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_walk_update_list(bgp_route_map_process_update_cb);
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return (0);
|
2015-05-20 02:40:45 +02:00
|
|
|
}
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void bgp_route_map_mark_update(const char *rmap_name)
|
2015-05-20 02:40:45 +02:00
|
|
|
{
|
2019-08-11 13:24:15 +02:00
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct bgp *bgp;
|
|
|
|
|
|
|
|
/* If new update is received before the current timer timed out,
|
|
|
|
* turn it off and start a new timer.
|
|
|
|
*/
|
|
|
|
if (bm->t_rmap_update != NULL)
|
|
|
|
THREAD_OFF(bm->t_rmap_update);
|
|
|
|
|
|
|
|
/* rmap_update_timer of 0 means don't do route updates */
|
|
|
|
if (bm->rmap_update_timer) {
|
|
|
|
thread_add_timer(bm->master, bgp_route_map_update_timer,
|
|
|
|
NULL, bm->rmap_update_timer,
|
|
|
|
&bm->t_rmap_update);
|
|
|
|
|
|
|
|
/* Signal the groups that a route-map update event has
|
|
|
|
* started */
|
|
|
|
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
|
|
|
|
update_group_policy_update(bgp,
|
|
|
|
BGP_POLICY_ROUTE_MAP,
|
|
|
|
rmap_name, 1, 1);
|
|
|
|
} else {
|
|
|
|
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
|
|
|
|
bgp_route_map_process_update(bgp, rmap_name, 0);
|
2017-07-17 14:03:14 +02:00
|
|
|
#if ENABLE_BGP_VNC
|
2019-08-11 13:24:15 +02:00
|
|
|
zlog_debug("%s: calling vnc_routemap_update", __func__);
|
|
|
|
vnc_routemap_update(bgp, __func__);
|
bgpd: add L3/L2VPN Virtual Network Control feature
This feature adds an L3 & L2 VPN application that makes use of the VPN
and Encap SAFIs. This code is currently used to support IETF NVO3 style
operation. In NVO3 terminology it provides the Network Virtualization
Authority (NVA) and the ability to import/export IP prefixes and MAC
addresses from Network Virtualization Edges (NVEs). The code supports
per-NVE tables.
The NVE-NVA protocol used to communicate routing and Ethernet / Layer 2
(L2) forwarding information between NVAs and NVEs is referred to as the
Remote Forwarder Protocol (RFP). OpenFlow is an example RFP. For
general background on NVO3 and RFP concepts see [1]. For information on
Openflow see [2].
RFPs are integrated with BGP via the RF API contained in the new "rfapi"
BGP sub-directory. Currently, only a simple example RFP is included in
Quagga. Developers may use this example as a starting point to integrate
Quagga with an RFP of their choosing, e.g., OpenFlow. The RFAPI code
also supports the ability import/export of routing information between
VNC and customer edge routers (CEs) operating within a virtual
network. Import/export may take place between BGP views or to the
default zebera VRF.
BGP, with IP VPNs and Tunnel Encapsulation, is used to distribute VPN
information between NVAs. BGP based IP VPN support is defined in
RFC4364, BGP/MPLS IP Virtual Private Networks (VPNs), and RFC4659,
BGP-MPLS IP Virtual Private Network (VPN) Extension for IPv6 VPN . Use
of both the Encapsulation Subsequent Address Family Identifier (SAFI)
and the Tunnel Encapsulation Attribute, RFC5512, The BGP Encapsulation
Subsequent Address Family Identifier (SAFI) and the BGP Tunnel
Encapsulation Attribute, are supported. MAC address distribution does
not follow any standard BGB encoding, although it was inspired by the
early IETF EVPN concepts.
The feature is conditionally compiled and disabled by default.
Use the --enable-bgp-vnc configure option to enable.
The majority of this code was authored by G. Paul Ziemba
<paulz@labn.net>.
[1] http://tools.ietf.org/html/draft-ietf-nvo3-nve-nva-cp-req
[2] https://www.opennetworking.org/sdn-resources/technical-library
Now includes changes needed to merge with cmaster-next.
2016-05-07 20:18:56 +02:00
|
|
|
#endif
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void bgp_route_map_add(const char *rmap_name)
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
{
|
2018-06-20 02:44:15 +02:00
|
|
|
if (route_map_mark_updated(rmap_name) == 0)
|
2017-07-17 14:03:14 +02:00
|
|
|
bgp_route_map_mark_update(rmap_name);
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
}
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
static void bgp_route_map_delete(const char *rmap_name)
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
{
|
2018-06-20 02:44:15 +02:00
|
|
|
if (route_map_mark_updated(rmap_name) == 0)
|
2017-07-17 14:03:14 +02:00
|
|
|
bgp_route_map_mark_update(rmap_name);
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
}
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2019-05-09 05:19:55 +02:00
|
|
|
static void bgp_route_map_event(const char *rmap_name)
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
{
|
2018-06-20 02:44:15 +02:00
|
|
|
if (route_map_mark_updated(rmap_name) == 0)
|
2017-07-17 14:03:14 +02:00
|
|
|
bgp_route_map_mark_update(rmap_name);
|
2015-05-20 02:40:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
}
|
|
|
|
|
2017-06-21 10:02:46 +02:00
|
|
|
DEFUN (match_mac_address,
|
|
|
|
match_mac_address_cmd,
|
|
|
|
"match mac address WORD",
|
|
|
|
MATCH_STR
|
|
|
|
"mac address\n"
|
|
|
|
"Match address of route\n"
|
|
|
|
"MAC Access-list name\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_add(vty, "mac address", argv[3]->arg,
|
|
|
|
RMAP_EVENT_FILTER_ADDED);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_match_mac_address,
|
|
|
|
no_match_mac_address_cmd,
|
2017-07-12 23:55:22 +02:00
|
|
|
"no match mac address WORD",
|
2017-06-21 10:02:46 +02:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
"mac\n"
|
2017-07-12 23:55:22 +02:00
|
|
|
"Match address of route\n"
|
|
|
|
"MAC acess-list name\n")
|
2017-06-21 10:02:46 +02:00
|
|
|
{
|
|
|
|
return bgp_route_match_delete(vty, "mac address", argv[4]->arg,
|
|
|
|
RMAP_EVENT_FILTER_DELETED);
|
|
|
|
}
|
bgpd: bgpd-table-map.patch
COMMAND:
table-map <route-map-name>
DESCRIPTION:
This feature is used to apply a route-map on route updates from BGP to Zebra.
All the applicable match operations are allowed, such as match on prefix,
next-hop, communities, etc. Set operations for this attach-point are limited
to metric and next-hop only. Any operation of this feature does not affect
BGPs internal RIB.
Supported for ipv4 and ipv6 address families. It works on multi-paths as well,
however, metric setting is based on the best-path only.
IMPLEMENTATION NOTES:
The route-map application at this point is not supposed to modify any of BGP
route's attributes (anything in bgp_info for that matter). To achieve that,
creating a copy of the bgp_attr was inevitable. Implementation tries to keep
the memory footprint low, code comments do point out the rationale behind a
few choices made.
bgp_zebra_announce() was already a big routine, adding this feature would
extend it further. Patch has created a few smaller routines/macros whereever
possible to keep the size of the routine in check without compromising on the
readability of the code/flow inside this routine.
For updating a partially filtered route (with its nexthops), BGP to Zebra
replacement semantic of the next-hops serves the purpose well. However, with
this patch there could be some redundant withdraws each time BGP announces a
route thats (all the nexthops) gets denied by the route-map application.
Handling of this case could be optimized by keeping state with the prefix and
the nexthops in BGP. The patch doesn't optimizing that case, as even with the
redundant withdraws the total number of updates to zebra are still be capped
by the total number of routes in the table.
Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Pradosh Mohapatra <pmohapat@cumulusnetworks.com>
2015-05-20 02:40:34 +02:00
|
|
|
|
2018-01-27 02:16:48 +01:00
|
|
|
DEFUN (match_evpn_route_type,
|
|
|
|
match_evpn_route_type_cmd,
|
2018-02-05 22:56:12 +01:00
|
|
|
"match evpn route-type <macip | multicast | prefix>",
|
2018-01-27 02:16:48 +01:00
|
|
|
MATCH_STR
|
|
|
|
EVPN_HELP_STR
|
|
|
|
"Match route-type\n"
|
|
|
|
"mac-ip route\n"
|
|
|
|
"IMET route\n"
|
|
|
|
"prefix route\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_add(vty, "evpn route-type", argv[3]->arg,
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_match_evpn_route_type,
|
|
|
|
no_match_evpn_route_type_cmd,
|
2018-02-05 22:56:12 +01:00
|
|
|
"no match evpn route-type <macip | multicast | prefix>",
|
2018-01-27 02:16:48 +01:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
EVPN_HELP_STR
|
|
|
|
"Match route-type\n"
|
|
|
|
"mac-ip route\n"
|
|
|
|
"IMET route\n"
|
|
|
|
"prefix route\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_delete(vty, "evpn route-type", argv[4]->arg,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-21 11:00:24 +02:00
|
|
|
DEFUN (match_evpn_vni,
|
|
|
|
match_evpn_vni_cmd,
|
2018-10-19 02:44:52 +02:00
|
|
|
"match evpn vni " CMD_VNI_RANGE,
|
2017-06-21 11:00:24 +02:00
|
|
|
MATCH_STR
|
2017-06-21 17:14:24 +02:00
|
|
|
EVPN_HELP_STR
|
2017-06-21 11:00:24 +02:00
|
|
|
"Match VNI\n"
|
|
|
|
"VNI ID\n")
|
|
|
|
{
|
2017-07-12 23:55:22 +02:00
|
|
|
return bgp_route_match_add(vty, "evpn vni", argv[3]->arg,
|
2017-06-21 11:00:24 +02:00
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_match_evpn_vni,
|
|
|
|
no_match_evpn_vni_cmd,
|
2018-10-19 02:44:52 +02:00
|
|
|
"no match evpn vni " CMD_VNI_RANGE,
|
2017-06-21 11:00:24 +02:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
2017-06-21 17:14:24 +02:00
|
|
|
EVPN_HELP_STR
|
2017-06-21 11:00:24 +02:00
|
|
|
"Match VNI\n"
|
|
|
|
"VNI ID\n")
|
|
|
|
{
|
2017-07-12 23:55:22 +02:00
|
|
|
return bgp_route_match_delete(vty, "evpn vni", argv[4]->arg,
|
2017-06-21 11:00:24 +02:00
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
|
|
|
}
|
|
|
|
|
2018-02-22 07:02:07 +01:00
|
|
|
DEFUN (match_evpn_default_route,
|
|
|
|
match_evpn_default_route_cmd,
|
|
|
|
"match evpn default-route",
|
|
|
|
MATCH_STR
|
|
|
|
EVPN_HELP_STR
|
|
|
|
"default EVPN type-5 route\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_add(vty, "evpn default-route", NULL,
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_match_evpn_default_route,
|
|
|
|
no_match_evpn_default_route_cmd,
|
|
|
|
"no match evpn default-route",
|
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
EVPN_HELP_STR
|
|
|
|
"default EVPN type-5 route\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_delete(vty, "evpn default-route", NULL,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
|
|
|
}
|
|
|
|
|
2019-02-15 03:07:27 +01:00
|
|
|
DEFPY(match_vrl_source_vrf,
|
|
|
|
match_vrl_source_vrf_cmd,
|
|
|
|
"match source-vrf NAME$vrf_name",
|
|
|
|
MATCH_STR
|
|
|
|
"source vrf\n"
|
|
|
|
"The VRF name\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_add(vty, "source-vrf", vrf_name,
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFPY(no_match_vrl_source_vrf,
|
|
|
|
no_match_vrl_source_vrf_cmd,
|
|
|
|
"no match source-vrf NAME$vrf_name",
|
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
"source vrf\n"
|
|
|
|
"The VRF name\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_delete(vty, "source-vrf", vrf_name,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
|
|
|
}
|
|
|
|
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
DEFUN (match_peer,
|
|
|
|
match_peer_cmd,
|
2017-10-18 15:34:57 +02:00
|
|
|
"match peer <A.B.C.D|X:X::X:X|WORD>",
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
MATCH_STR
|
|
|
|
"Match peer address\n"
|
2016-05-11 14:26:39 +02:00
|
|
|
"IP address of peer\n"
|
2017-10-18 15:34:57 +02:00
|
|
|
"IPv6 address of peer\n"
|
|
|
|
"Interface name of peer\n")
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ip = 2;
|
|
|
|
return bgp_route_match_add(vty, "peer", argv[idx_ip]->arg,
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (match_peer_local,
|
2016-09-23 05:55:26 +02:00
|
|
|
match_peer_local_cmd,
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
"match peer local",
|
|
|
|
MATCH_STR
|
|
|
|
"Match peer address\n"
|
|
|
|
"Static or Redistributed routes\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return bgp_route_match_add(vty, "peer", "local",
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_match_peer,
|
|
|
|
no_match_peer_cmd,
|
2017-10-18 15:34:57 +02:00
|
|
|
"no match peer [<local|A.B.C.D|X:X::X:X|WORD>]",
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"Match peer address\n"
|
|
|
|
"Static or Redistributed routes\n"
|
|
|
|
"IP address of peer\n"
|
2017-10-18 15:34:57 +02:00
|
|
|
"IPv6 address of peer\n"
|
|
|
|
"Interface name of peer\n")
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_peer = 3;
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (argc <= idx_peer)
|
|
|
|
return bgp_route_match_delete(vty, "peer", NULL,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
|
|
|
return bgp_route_match_delete(vty, "peer", argv[idx_peer]->arg,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
}
|
|
|
|
|
2017-11-07 15:14:32 +01:00
|
|
|
#if defined(HAVE_LUA)
|
|
|
|
DEFUN (match_command,
|
|
|
|
match_command_cmd,
|
|
|
|
"match command WORD",
|
|
|
|
MATCH_STR
|
|
|
|
"Run a command to match\n"
|
|
|
|
"The command to run\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_add(vty, "command", argv[2]->arg,
|
|
|
|
RMAP_EVENT_FILTER_ADDED);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_match_command,
|
|
|
|
no_match_command_cmd,
|
|
|
|
"no match command WORD",
|
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
"Run a command to match\n"
|
|
|
|
"The command to run\n")
|
|
|
|
{
|
|
|
|
return bgp_route_match_delete(vty, "command", argv[3]->arg,
|
|
|
|
RMAP_EVENT_FILTER_DELETED);
|
|
|
|
}
|
|
|
|
#endif
|
2004-09-13 Jose Luis Rubio <jrubio@dit.upm.es>
(at Technical University of Madrid as part of Euro6ix Project)
Enhanced Route Server functionality and Route-Maps:
* bgpd/bgpd.h: Modified 'struct peer' and 'struct bgp_filter' to
support rs-clients. A 'struct bgp_table *rib' has been added to the
first (to mantain a separated RIB for each rs-client) and two new
route-maps have been added to the last (for import/export policies).
Added the following #defines: RMAP_{IN|OUT|IMPORT|EXPORT|MAX},
PEER_RMAP_TYPE_{IMPORT|EXPORT} and BGP_CLEAR_SOFT_RSCLIENT.
* bgpd/bgpd.c: Modified the functions that create/delete/etc peers in
order to consider the new fields included in 'struct peer' for
supporting rs-clients, i.e. the import/export route-maps and the
'struct bgp_table'.
* bgpd/bgp_route.{ch}: Modified several functions related with
receiving/sending announces in order to support the new Route Server
capabilities.
Function 'bgp_process' has been reorganized, creating an auxiliar
function for best path selection ('bgp_best_selection').
Modified 'bgp_show' and 'bgp_show_route' for displaying information
about any RIB (and not only the main bgp RIB).
Added commands for displaying information about RS-clients RIBs:
'show bgp rsclient (A.B.C.D|X:X::X:X)', 'show bgp rsclient
(A.B.C.D|X:X::X:X) X:X::X:X/M', etc
* bgpd/bgp_table.{ch}: The structure 'struct bgp_table' now has two
new fields: type (which can take the values BGP_TABLE_{MAIN|RSCLIENT})
and 'void *owner' which points to 'struct bgp' or 'struct peer' which
owns the table.
When creating a new bgp_table by default 'type=BGP_TABLE_MAIN' is set.
* bgpd/bgp_vty.c: The commands 'neighbor ... route-server-client' and
'no neighbor ... route-server-client' now not only set/unset the flag
PEER_FLAG_RSERVER_CLIENT, but they create/destroy the 'struct
bgp_table' of the peer. Special actions are taken for peer_groups.
Command 'neighbor ... route-map WORD (in|out)' now also supports two
new kinds of route-map: 'import' and 'export'.
Added commands 'clear bgp * rsclient', etc. These commands allow a new
kind of soft_reconfig which affects only the RIB of the specified
RS-client.
Added commands 'show bgp rsclient summary', etc which display a
summary of the rs-clients configured for the corresponding address
family.
* bgpd/bgp_routemap.c: A new match statement is available,
'match peer (A.B.C.D|X:X::X:X)'. This statement can only be used in
import/export route-maps, and it matches when the peer who announces
(when used in an import route-map) or is going to receive (when used
in an export route-map) the route is the same than the one specified
in the statement.
For peer-groups the statement matches if the specified peer is member
of the peer-group.
A special version of the command, 'match peer local', matches with
routes originated by the Route Server (defined with 'network ...',
redistributed routes and default-originate).
* lib/routemap.{ch}: Added a new clause 'call NAME' for use in
route-maps. It jumps into the specified route-map and when it returns
the first route-map ends if the called RM returns DENY_MATCH, or
continues in other case.
2004-09-13 07:12:46 +02:00
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
/* match probability */
|
2011-11-22 17:15:10 +01:00
|
|
|
DEFUN (match_probability,
|
|
|
|
match_probability_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"match probability (0-100)",
|
2011-11-22 17:15:10 +01:00
|
|
|
MATCH_STR
|
|
|
|
"Match portion of routes defined by percentage value\n"
|
|
|
|
"Percentage of routes\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_number = 2;
|
|
|
|
return bgp_route_match_add(vty, "probability", argv[idx_number]->arg,
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
2011-11-22 17:15:10 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2011-11-22 17:15:10 +01:00
|
|
|
DEFUN (no_match_probability,
|
|
|
|
no_match_probability_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no match probability [(1-99)]",
|
2011-11-22 17:15:10 +01:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"Match portion of routes defined by percentage value\n"
|
|
|
|
"Percentage of routes\n")
|
2011-11-22 17:15:10 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_number = 3;
|
|
|
|
if (argc <= idx_number)
|
|
|
|
return bgp_route_match_delete(vty, "probability", NULL,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
|
|
|
return bgp_route_match_delete(vty, "probability", argv[idx_number]->arg,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
2011-11-22 17:15:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-23 05:55:26 +02:00
|
|
|
DEFUN (match_ip_route_source,
|
2005-02-02 17:43:17 +01:00
|
|
|
match_ip_route_source_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"match ip route-source <(1-199)|(1300-2699)|WORD>",
|
2005-02-02 17:43:17 +01:00
|
|
|
MATCH_STR
|
|
|
|
IP_STR
|
|
|
|
"Match advertising source address of route\n"
|
|
|
|
"IP access-list number\n"
|
|
|
|
"IP access-list number (expanded range)\n"
|
|
|
|
"IP standard access-list name\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_acl = 3;
|
|
|
|
return bgp_route_match_add(vty, "ip route-source", argv[idx_acl]->arg,
|
|
|
|
RMAP_EVENT_FILTER_ADDED);
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2005-02-02 17:43:17 +01:00
|
|
|
DEFUN (no_match_ip_route_source,
|
|
|
|
no_match_ip_route_source_cmd,
|
2016-09-30 17:31:48 +02:00
|
|
|
"no match ip route-source [<(1-199)|(1300-2699)|WORD>]",
|
2005-02-02 17:43:17 +01:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
IP_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"Match advertising source address of route\n"
|
|
|
|
"IP access-list number\n"
|
|
|
|
"IP access-list number (expanded range)\n"
|
|
|
|
"IP standard access-list name\n")
|
2005-02-02 17:43:17 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_number = 4;
|
|
|
|
if (argc <= idx_number)
|
|
|
|
return bgp_route_match_delete(vty, "ip route-source", NULL,
|
|
|
|
RMAP_EVENT_FILTER_DELETED);
|
|
|
|
return bgp_route_match_delete(vty, "ip route-source",
|
|
|
|
argv[idx_number]->arg,
|
|
|
|
RMAP_EVENT_FILTER_DELETED);
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-23 05:55:26 +02:00
|
|
|
DEFUN (match_ip_route_source_prefix_list,
|
2005-02-02 17:43:17 +01:00
|
|
|
match_ip_route_source_prefix_list_cmd,
|
|
|
|
"match ip route-source prefix-list WORD",
|
|
|
|
MATCH_STR
|
|
|
|
IP_STR
|
|
|
|
"Match advertising source address of route\n"
|
|
|
|
"Match entries of prefix-lists\n"
|
|
|
|
"IP prefix-list name\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_word = 4;
|
|
|
|
return bgp_route_match_add(vty, "ip route-source prefix-list",
|
|
|
|
argv[idx_word]->arg, RMAP_EVENT_PLIST_ADDED);
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2005-02-02 17:43:17 +01:00
|
|
|
DEFUN (no_match_ip_route_source_prefix_list,
|
|
|
|
no_match_ip_route_source_prefix_list_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no match ip route-source prefix-list [WORD]",
|
2005-02-02 17:43:17 +01:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
IP_STR
|
|
|
|
"Match advertising source address of route\n"
|
2016-09-27 07:05:12 +02:00
|
|
|
"Match entries of prefix-lists\n"
|
|
|
|
"IP prefix-list name\n")
|
2005-02-02 17:43:17 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_word = 5;
|
|
|
|
if (argc <= idx_word)
|
|
|
|
return bgp_route_match_delete(vty,
|
|
|
|
"ip route-source prefix-list",
|
|
|
|
NULL, RMAP_EVENT_PLIST_DELETED);
|
|
|
|
return bgp_route_match_delete(vty, "ip route-source prefix-list",
|
|
|
|
argv[idx_word]->arg,
|
|
|
|
RMAP_EVENT_PLIST_DELETED);
|
2005-02-02 17:43:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-20 02:40:40 +02:00
|
|
|
DEFUN (match_local_pref,
|
|
|
|
match_local_pref_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"match local-preference (0-4294967295)",
|
2015-05-20 02:40:40 +02:00
|
|
|
MATCH_STR
|
|
|
|
"Match local-preference of route\n"
|
|
|
|
"Metric value\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_number = 2;
|
|
|
|
return bgp_route_match_add(vty, "local-preference",
|
|
|
|
argv[idx_number]->arg,
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2015-05-20 02:40:40 +02:00
|
|
|
DEFUN (no_match_local_pref,
|
|
|
|
no_match_local_pref_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no match local-preference [(0-4294967295)]",
|
2015-05-20 02:40:40 +02:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"Match local preference of route\n"
|
|
|
|
"Local preference value\n")
|
2015-05-20 02:40:40 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_localpref = 3;
|
|
|
|
if (argc <= idx_localpref)
|
|
|
|
return bgp_route_match_delete(vty, "local-preference", NULL,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
|
|
|
return bgp_route_match_delete(vty, "local-preference",
|
|
|
|
argv[idx_localpref]->arg,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
2015-05-20 02:40:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-23 05:55:26 +02:00
|
|
|
DEFUN (match_community,
|
2002-12-13 21:15:29 +01:00
|
|
|
match_community_cmd,
|
2017-01-30 20:49:24 +01:00
|
|
|
"match community <(1-99)|(100-500)|WORD> [exact-match]",
|
2002-12-13 21:15:29 +01:00
|
|
|
MATCH_STR
|
|
|
|
"Match BGP community list\n"
|
|
|
|
"Community-list number (standard)\n"
|
|
|
|
"Community-list number (expanded)\n"
|
|
|
|
"Community-list name\n"
|
|
|
|
"Do exact matching of communities\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_comm_list = 2;
|
|
|
|
int ret;
|
|
|
|
char *argstr;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (argc == 4) {
|
|
|
|
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
|
|
|
strlen(argv[idx_comm_list]->arg)
|
|
|
|
+ strlen("exact-match") + 2);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
|
|
|
|
} else
|
|
|
|
argstr = argv[idx_comm_list]->arg;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = bgp_route_match_add(vty, "community", argstr,
|
|
|
|
RMAP_EVENT_CLIST_ADDED);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (argstr != argv[idx_comm_list]->arg)
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_match_community,
|
|
|
|
no_match_community_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no match community [<(1-99)|(100-500)|WORD> [exact-match]]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"Match BGP community list\n"
|
|
|
|
"Community-list number (standard)\n"
|
|
|
|
"Community-list number (expanded)\n"
|
|
|
|
"Community-list name\n"
|
|
|
|
"Do exact matching of communities\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return bgp_route_match_delete(vty, "community", NULL,
|
|
|
|
RMAP_EVENT_CLIST_DELETED);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-11-15 11:00:39 +01:00
|
|
|
DEFUN (match_lcommunity,
|
|
|
|
match_lcommunity_cmd,
|
2019-05-06 11:45:32 +02:00
|
|
|
"match large-community <(1-99)|(100-500)|WORD> [exact-match]",
|
2016-11-15 11:00:39 +01:00
|
|
|
MATCH_STR
|
|
|
|
"Match BGP large community list\n"
|
|
|
|
"Large Community-list number (standard)\n"
|
|
|
|
"Large Community-list number (expanded)\n"
|
2019-05-06 11:45:32 +02:00
|
|
|
"Large Community-list name\n"
|
|
|
|
"Do exact matching of communities\n")
|
2016-11-15 11:00:39 +01:00
|
|
|
{
|
2019-05-06 11:45:32 +02:00
|
|
|
int idx_lcomm_list = 2;
|
|
|
|
int ret;
|
|
|
|
char *argstr;
|
|
|
|
|
|
|
|
if (argc == 4) {
|
|
|
|
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
|
|
|
strlen(argv[idx_lcomm_list]->arg)
|
|
|
|
+ strlen("exact-match") + 2);
|
|
|
|
|
|
|
|
sprintf(argstr, "%s exact-match", argv[idx_lcomm_list]->arg);
|
|
|
|
} else
|
|
|
|
argstr = argv[idx_lcomm_list]->arg;
|
|
|
|
|
|
|
|
ret = bgp_route_match_add(vty, "large-community", argstr,
|
2017-07-17 14:03:14 +02:00
|
|
|
RMAP_EVENT_LLIST_ADDED);
|
2019-05-06 11:45:32 +02:00
|
|
|
if (argstr != argv[idx_lcomm_list]->arg)
|
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
|
|
|
|
|
|
|
|
return ret;
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2016-11-15 11:00:39 +01:00
|
|
|
DEFUN (no_match_lcommunity,
|
|
|
|
no_match_lcommunity_cmd,
|
2019-05-06 11:45:32 +02:00
|
|
|
"no match large-community [<(1-99)|(100-500)|WORD> [exact-match]]",
|
2016-11-15 11:00:39 +01:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
"Match BGP large community list\n"
|
|
|
|
"Large Community-list number (standard)\n"
|
|
|
|
"Large Community-list number (expanded)\n"
|
2019-05-06 11:45:32 +02:00
|
|
|
"Large Community-list name\n"
|
|
|
|
"Do exact matching of communities\n")
|
2016-11-15 11:00:39 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return bgp_route_match_delete(vty, "large-community", NULL,
|
|
|
|
RMAP_EVENT_LLIST_DELETED);
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2016-09-23 05:55:26 +02:00
|
|
|
DEFUN (match_ecommunity,
|
2003-04-19 17:49:49 +02:00
|
|
|
match_ecommunity_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"match extcommunity <(1-99)|(100-500)|WORD>",
|
2003-04-19 17:49:49 +02:00
|
|
|
MATCH_STR
|
|
|
|
"Match BGP/VPN extended community list\n"
|
|
|
|
"Extended community-list number (standard)\n"
|
|
|
|
"Extended community-list number (expanded)\n"
|
|
|
|
"Extended community-list name\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_comm_list = 2;
|
|
|
|
return bgp_route_match_add(vty, "extcommunity",
|
|
|
|
argv[idx_comm_list]->arg,
|
|
|
|
RMAP_EVENT_ECLIST_ADDED);
|
2003-04-19 17:49:49 +02:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2003-04-19 17:49:49 +02:00
|
|
|
DEFUN (no_match_ecommunity,
|
|
|
|
no_match_ecommunity_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no match extcommunity [<(1-99)|(100-500)|WORD>]",
|
2003-04-19 17:49:49 +02:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"Match BGP/VPN extended community list\n"
|
|
|
|
"Extended community-list number (standard)\n"
|
|
|
|
"Extended community-list number (expanded)\n"
|
|
|
|
"Extended community-list name\n")
|
2003-04-19 17:49:49 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return bgp_route_match_delete(vty, "extcommunity", NULL,
|
|
|
|
RMAP_EVENT_ECLIST_DELETED);
|
2003-04-19 17:49:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (match_aspath,
|
|
|
|
match_aspath_cmd,
|
|
|
|
"match as-path WORD",
|
|
|
|
MATCH_STR
|
|
|
|
"Match BGP AS path list\n"
|
|
|
|
"AS path access-list name\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_word = 2;
|
|
|
|
return bgp_route_match_add(vty, "as-path", argv[idx_word]->arg,
|
|
|
|
RMAP_EVENT_ASLIST_ADDED);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_match_aspath,
|
|
|
|
no_match_aspath_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no match as-path [WORD]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"Match BGP AS path list\n"
|
|
|
|
"AS path access-list name\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return bgp_route_match_delete(vty, "as-path", NULL,
|
|
|
|
RMAP_EVENT_ASLIST_DELETED);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFUN (match_origin,
|
|
|
|
match_origin_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"match origin <egp|igp|incomplete>",
|
2002-12-13 21:15:29 +01:00
|
|
|
MATCH_STR
|
|
|
|
"BGP origin code\n"
|
|
|
|
"remote EGP\n"
|
|
|
|
"local IGP\n"
|
|
|
|
"unknown heritage\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_origin = 2;
|
|
|
|
if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
|
|
|
|
return bgp_route_match_add(vty, "origin", "igp",
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
|
|
|
if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
|
|
|
|
return bgp_route_match_add(vty, "origin", "egp",
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
|
|
|
if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
|
|
|
|
return bgp_route_match_add(vty, "origin", "incomplete",
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
vty_out(vty, "%% Invalid match origin type\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_match_origin,
|
|
|
|
no_match_origin_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no match origin [<egp|igp|incomplete>]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"BGP origin code\n"
|
|
|
|
"remote EGP\n"
|
|
|
|
"local IGP\n"
|
|
|
|
"unknown heritage\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return bgp_route_match_delete(vty, "origin", NULL,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2003-11-02 08:24:40 +01:00
|
|
|
DEFUN (set_ip_nexthop_peer,
|
|
|
|
set_ip_nexthop_peer_cmd,
|
2017-08-10 18:31:47 +02:00
|
|
|
"[no] set ip next-hop peer-address",
|
|
|
|
NO_STR
|
2003-11-02 08:24:40 +01:00
|
|
|
SET_STR
|
|
|
|
IP_STR
|
|
|
|
"Next hop address\n"
|
|
|
|
"Use peer address (for BGP only)\n")
|
|
|
|
{
|
2017-08-10 18:31:47 +02:00
|
|
|
int (*func)(struct vty *, struct route_map_index *, const char *,
|
2018-02-09 19:22:50 +01:00
|
|
|
const char *) = strmatch(argv[0]->text, "no")
|
|
|
|
? generic_set_delete
|
|
|
|
: generic_set_add;
|
2017-08-10 18:31:47 +02:00
|
|
|
|
|
|
|
return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
|
|
|
|
"peer-address");
|
2003-11-02 08:24:40 +01:00
|
|
|
}
|
|
|
|
|
2015-05-20 03:03:49 +02:00
|
|
|
DEFUN (set_ip_nexthop_unchanged,
|
|
|
|
set_ip_nexthop_unchanged_cmd,
|
2017-08-10 18:55:32 +02:00
|
|
|
"[no] set ip next-hop unchanged",
|
|
|
|
NO_STR
|
2015-05-20 03:03:49 +02:00
|
|
|
SET_STR
|
|
|
|
IP_STR
|
|
|
|
"Next hop address\n"
|
|
|
|
"Don't modify existing Next hop address\n")
|
|
|
|
{
|
2017-08-10 18:55:32 +02:00
|
|
|
int (*func)(struct vty *, struct route_map_index *, const char *,
|
2018-02-09 19:22:50 +01:00
|
|
|
const char *) = strmatch(argv[0]->text, "no")
|
|
|
|
? generic_set_delete
|
|
|
|
: generic_set_add;
|
2017-08-10 18:55:32 +02:00
|
|
|
|
|
|
|
return func(vty, VTY_GET_CONTEXT(route_map_index), "ip next-hop",
|
|
|
|
"unchanged");
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFUN (set_local_pref,
|
|
|
|
set_local_pref_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"set local-preference (0-4294967295)",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"BGP local preference path attribute\n"
|
|
|
|
"Preference value\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_number = 2;
|
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"local-preference", argv[idx_number]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_set_local_pref,
|
|
|
|
no_set_local_pref_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no set local-preference [(0-4294967295)]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"BGP local preference path attribute\n"
|
|
|
|
"Preference value\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_localpref = 3;
|
|
|
|
if (argc <= idx_localpref)
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"local-preference", NULL);
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"local-preference", argv[idx_localpref]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFUN (set_weight,
|
|
|
|
set_weight_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"set weight (0-4294967295)",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"BGP weight for routing table\n"
|
|
|
|
"Weight value\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_number = 2;
|
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "weight",
|
|
|
|
argv[idx_number]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_set_weight,
|
|
|
|
no_set_weight_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no set weight [(0-4294967295)]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"BGP weight for routing table\n"
|
|
|
|
"Weight value\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_weight = 3;
|
|
|
|
if (argc <= idx_weight)
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"weight", NULL);
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"weight", argv[idx_weight]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-06-02 21:22:53 +02:00
|
|
|
DEFUN (set_label_index,
|
|
|
|
set_label_index_cmd,
|
2017-06-06 18:29:30 +02:00
|
|
|
"set label-index (0-1048560)",
|
2017-06-02 21:22:53 +02:00
|
|
|
SET_STR
|
|
|
|
"Label index to associate with the prefix\n"
|
|
|
|
"Label index value\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_number = 2;
|
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"label-index", argv[idx_number]->arg);
|
2017-06-02 21:22:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_label_index,
|
|
|
|
no_set_label_index_cmd,
|
2017-06-06 18:29:30 +02:00
|
|
|
"no set label-index [(0-1048560)]",
|
2017-06-02 21:22:53 +02:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"Label index to associate with the prefix\n"
|
|
|
|
"Label index value\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_label_index = 3;
|
|
|
|
if (argc <= idx_label_index)
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"label-index", NULL);
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"label-index", argv[idx_label_index]->arg);
|
2017-06-02 21:22:53 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2016-10-04 21:21:45 +02:00
|
|
|
DEFUN (set_aspath_prepend_asn,
|
|
|
|
set_aspath_prepend_asn_cmd,
|
|
|
|
"set as-path prepend (1-4294967295)...",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
2008-04-10 13:47:45 +02:00
|
|
|
"Transform BGP AS_PATH attribute\n"
|
2002-12-13 21:15:29 +01:00
|
|
|
"Prepend to the as-path\n"
|
2016-10-04 21:21:45 +02:00
|
|
|
"AS number\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_asn = 3;
|
|
|
|
int ret;
|
|
|
|
char *str;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
str = argv_concat(argv, argc, idx_asn);
|
|
|
|
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"as-path prepend", str);
|
|
|
|
XFREE(MTYPE_TMP, str);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-10-04 21:21:45 +02:00
|
|
|
DEFUN (set_aspath_prepend_lastas,
|
|
|
|
set_aspath_prepend_lastas_cmd,
|
2017-04-15 02:13:26 +02:00
|
|
|
"set as-path prepend last-as (1-10)",
|
2016-10-04 21:21:45 +02:00
|
|
|
SET_STR
|
|
|
|
"Transform BGP AS_PATH attribute\n"
|
|
|
|
"Prepend to the as-path\n"
|
|
|
|
"Use the peer's AS-number\n"
|
2017-04-15 02:13:26 +02:00
|
|
|
"Number of times to insert\n")
|
2016-10-04 21:21:45 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return set_aspath_prepend_asn(self, vty, argc, argv);
|
2016-10-04 21:21:45 +02:00
|
|
|
}
|
2016-05-26 03:49:34 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_set_aspath_prepend,
|
|
|
|
no_set_aspath_prepend_cmd,
|
2016-09-27 15:24:19 +02:00
|
|
|
"no set as-path prepend [(1-4294967295)]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
2008-04-10 13:47:45 +02:00
|
|
|
"Transform BGP AS_PATH attribute\n"
|
2016-09-27 15:24:19 +02:00
|
|
|
"Prepend to the as-path\n"
|
|
|
|
"AS number\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_asn = 4;
|
|
|
|
int ret;
|
|
|
|
char *str;
|
2007-12-18 16:13:06 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
str = argv_concat(argv, argc, idx_asn);
|
|
|
|
ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"as-path prepend", str);
|
|
|
|
XFREE(MTYPE_TMP, str);
|
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
bgpd: Add 'no set as-path prepend last-as X' command
The `set as-path prepend last-as X` command had no, 'no' form
of the command. Add this into the cli.
Testing:
!
route-map BLARBLE permit 10
set as-path prepend last-as 3
!
!
router bgp 9999
neighbor 10.50.12.118 remote-as external
neighbor 10.50.12.118 ebgp-multihop 30
!
address-family ipv4 unicast
neighbor 10.50.12.118 route-map BLARBLE in
!
!
eva# show bgp ipv4 uni 4.4.4.4
BGP routing table entry for 4.4.4.4/32
Paths: (1 available, best #1, table default)
Advertised to non peer-group peers:
10.50.12.118
999 999 999 999
10.50.12.118 from 10.50.12.118 (10.50.12.118)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Mon Aug 26 09:47:17 2019
eva# conf
eva(config)# route-map BLARBLE permit 10
eva(config-route-map)# no set as-path prepend last-as 3
eva(config-route-map)# end
eva# clear bgp ipv4 uni *
eva# show bgp ipv4 uni 4.4.4.4
BGP routing table entry for 4.4.4.4/32
Paths: (1 available, best #1, table default)
Advertised to non peer-group peers:
10.50.12.118
999
10.50.12.118 from 10.50.12.118 (10.50.12.118)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Mon Aug 26 09:48:31 2019
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
2019-08-26 15:49:18 +02:00
|
|
|
DEFUN (no_set_aspath_prepend_lastas,
|
|
|
|
no_set_aspath_prepend_lastas_cmd,
|
|
|
|
"no set as-path prepend last-as [(1-10)]",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"Transform BGP AS_PATH attribute\n"
|
|
|
|
"Prepend to the as-path\n"
|
|
|
|
"Use the peers AS-number\n"
|
|
|
|
"Number of times to insert\n")
|
|
|
|
{
|
|
|
|
return no_set_aspath_prepend(self, vty, argc, argv);
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2008-04-10 13:47:45 +02:00
|
|
|
DEFUN (set_aspath_exclude,
|
|
|
|
set_aspath_exclude_cmd,
|
2016-09-27 15:24:19 +02:00
|
|
|
"set as-path exclude (1-4294967295)...",
|
2008-04-10 13:47:45 +02:00
|
|
|
SET_STR
|
|
|
|
"Transform BGP AS-path attribute\n"
|
|
|
|
"Exclude from the as-path\n"
|
|
|
|
"AS number\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_asn = 3;
|
|
|
|
int ret;
|
|
|
|
char *str;
|
2008-04-10 13:47:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
str = argv_concat(argv, argc, idx_asn);
|
|
|
|
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"as-path exclude", str);
|
|
|
|
XFREE(MTYPE_TMP, str);
|
|
|
|
return ret;
|
2008-04-10 13:47:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_aspath_exclude,
|
|
|
|
no_set_aspath_exclude_cmd,
|
2016-09-27 15:24:19 +02:00
|
|
|
"no set as-path exclude (1-4294967295)...",
|
2008-04-10 13:47:45 +02:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"Transform BGP AS_PATH attribute\n"
|
2016-09-27 15:24:19 +02:00
|
|
|
"Exclude from the as-path\n"
|
|
|
|
"AS number\n")
|
2008-04-10 13:47:45 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_asn = 4;
|
|
|
|
int ret;
|
|
|
|
char *str;
|
2008-04-10 13:47:45 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
str = argv_concat(argv, argc, idx_asn);
|
|
|
|
ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"as-path exclude", str);
|
|
|
|
XFREE(MTYPE_TMP, str);
|
|
|
|
return ret;
|
2008-04-10 13:47:45 +02:00
|
|
|
}
|
|
|
|
|
2018-11-15 20:57:34 +01:00
|
|
|
ALIAS(no_set_aspath_exclude, no_set_aspath_exclude_all_cmd,
|
|
|
|
"no set as-path exclude",
|
|
|
|
NO_STR SET_STR
|
|
|
|
"Transform BGP AS_PATH attribute\n"
|
|
|
|
"Exclude from the as-path\n")
|
2008-04-10 13:47:45 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (set_community,
|
|
|
|
set_community_cmd,
|
2016-09-27 02:07:46 +02:00
|
|
|
"set community AA:NN...",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"BGP community attribute\n"
|
2016-04-14 20:16:43 +02:00
|
|
|
COMMUNITY_VAL_STR)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_aa_nn = 2;
|
|
|
|
int i;
|
|
|
|
int first = 0;
|
|
|
|
int additive = 0;
|
|
|
|
struct buffer *b;
|
|
|
|
struct community *com = NULL;
|
|
|
|
char *str;
|
|
|
|
char *argstr;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
b = buffer_new(1024);
|
|
|
|
|
|
|
|
for (i = idx_aa_nn; i < argc; i++) {
|
|
|
|
if (strncmp(argv[i]->arg, "additive", strlen(argv[i]->arg))
|
|
|
|
== 0) {
|
|
|
|
additive = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (first)
|
|
|
|
buffer_putc(b, ' ');
|
|
|
|
else
|
|
|
|
first = 1;
|
|
|
|
|
|
|
|
if (strncmp(argv[i]->arg, "internet", strlen(argv[i]->arg))
|
|
|
|
== 0) {
|
|
|
|
buffer_putstr(b, "internet");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strncmp(argv[i]->arg, "local-AS", strlen(argv[i]->arg))
|
|
|
|
== 0) {
|
|
|
|
buffer_putstr(b, "local-AS");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strncmp(argv[i]->arg, "no-a", strlen("no-a")) == 0
|
|
|
|
&& strncmp(argv[i]->arg, "no-advertise",
|
|
|
|
strlen(argv[i]->arg))
|
|
|
|
== 0) {
|
|
|
|
buffer_putstr(b, "no-advertise");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (strncmp(argv[i]->arg, "no-e", strlen("no-e")) == 0
|
|
|
|
&& strncmp(argv[i]->arg, "no-export", strlen(argv[i]->arg))
|
|
|
|
== 0) {
|
|
|
|
buffer_putstr(b, "no-export");
|
|
|
|
continue;
|
|
|
|
}
|
2018-02-09 19:22:50 +01:00
|
|
|
if (strncmp(argv[i]->arg, "graceful-shutdown",
|
|
|
|
strlen(argv[i]->arg))
|
2017-08-25 20:27:49 +02:00
|
|
|
== 0) {
|
|
|
|
buffer_putstr(b, "graceful-shutdown");
|
|
|
|
continue;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
buffer_putstr(b, argv[i]->arg);
|
|
|
|
}
|
|
|
|
buffer_putc(b, '\0');
|
|
|
|
|
|
|
|
/* Fetch result string then compile it to communities attribute. */
|
|
|
|
str = buffer_getstr(b);
|
|
|
|
buffer_free(b);
|
|
|
|
|
|
|
|
if (str) {
|
|
|
|
com = community_str2com(str);
|
|
|
|
XFREE(MTYPE_TMP, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Can't compile user input into communities attribute. */
|
|
|
|
if (!com) {
|
|
|
|
vty_out(vty, "%% Malformed communities attribute\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set communites attribute string. */
|
2017-11-17 02:43:56 +01:00
|
|
|
str = community_str(com, false);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
if (additive) {
|
2019-05-06 23:05:06 +02:00
|
|
|
size_t argstr_sz = strlen(str) + strlen(" additive") + 1;
|
|
|
|
argstr = XCALLOC(MTYPE_TMP, argstr_sz);
|
|
|
|
strlcpy(argstr, str, argstr_sz);
|
|
|
|
strlcat(argstr, " additive", argstr_sz);
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"community", argstr);
|
|
|
|
XFREE(MTYPE_TMP, argstr);
|
|
|
|
} else
|
|
|
|
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"community", str);
|
|
|
|
|
2018-10-22 21:58:39 +02:00
|
|
|
community_free(&com);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (set_community_none,
|
|
|
|
set_community_none_cmd,
|
|
|
|
"set community none",
|
|
|
|
SET_STR
|
|
|
|
"BGP community attribute\n"
|
|
|
|
"No community attribute\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"community", "none");
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_community,
|
|
|
|
no_set_community_cmd,
|
2016-09-27 15:24:19 +02:00
|
|
|
"no set community AA:NN...",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
2016-11-08 02:46:04 +01:00
|
|
|
"BGP community attribute\n"
|
|
|
|
COMMUNITY_VAL_STR)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"community", NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2018-12-16 19:54:41 +01:00
|
|
|
ALIAS (no_set_community,
|
|
|
|
no_set_community_short_cmd,
|
|
|
|
"no set community",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP community attribute\n")
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
DEFUN (set_community_delete,
|
|
|
|
set_community_delete_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"set comm-list <(1-99)|(100-500)|WORD> delete",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"set BGP community list (for deletion)\n"
|
|
|
|
"Community-list number (standard)\n"
|
2015-05-20 02:47:22 +02:00
|
|
|
"Community-list number (expanded)\n"
|
2002-12-13 21:15:29 +01:00
|
|
|
"Community-list name\n"
|
|
|
|
"Delete matching communities\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_comm_list = 2;
|
2019-06-26 14:06:10 +02:00
|
|
|
char *args;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2019-06-26 14:06:10 +02:00
|
|
|
args = argv_concat(argv, argc, idx_comm_list);
|
2017-07-17 14:03:14 +02:00
|
|
|
generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
|
2019-06-26 14:06:10 +02:00
|
|
|
args);
|
|
|
|
XFREE(MTYPE_TMP, args);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_community_delete,
|
|
|
|
no_set_community_delete_cmd,
|
2016-09-27 15:24:19 +02:00
|
|
|
"no set comm-list [<(1-99)|(100-500)|WORD> delete]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
2016-11-08 02:46:04 +01:00
|
|
|
"set BGP community list (for deletion)\n"
|
|
|
|
"Community-list number (standard)\n"
|
|
|
|
"Community-list number (expanded)\n"
|
|
|
|
"Community-list name\n"
|
|
|
|
"Delete matching communities\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"comm-list", NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-11-15 11:00:39 +01:00
|
|
|
DEFUN (set_lcommunity,
|
|
|
|
set_lcommunity_cmd,
|
|
|
|
"set large-community AA:BB:CC...",
|
|
|
|
SET_STR
|
|
|
|
"BGP large community attribute\n"
|
|
|
|
"Large Community number in aa:bb:cc format or additive\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int ret;
|
|
|
|
char *str;
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
str = argv_concat(argv, argc, 2);
|
|
|
|
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"large-community", str);
|
|
|
|
XFREE(MTYPE_TMP, str);
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return ret;
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (set_lcommunity_none,
|
|
|
|
set_lcommunity_none_cmd,
|
|
|
|
"set large-community none",
|
|
|
|
SET_STR
|
|
|
|
"BGP large community attribute\n"
|
|
|
|
"No large community attribute\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"large-community", "none");
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_lcommunity,
|
|
|
|
no_set_lcommunity_cmd,
|
2017-01-20 16:43:08 +01:00
|
|
|
"no set large-community none",
|
2016-11-15 11:00:39 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP large community attribute\n"
|
2017-01-20 16:43:08 +01:00
|
|
|
"No community attribute\n")
|
2016-11-15 11:00:39 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"large-community", NULL);
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
2017-01-20 16:43:08 +01:00
|
|
|
DEFUN (no_set_lcommunity1,
|
|
|
|
no_set_lcommunity1_cmd,
|
|
|
|
"no set large-community AA:BB:CC...",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP large community attribute\n"
|
|
|
|
"Large community in AA:BB:CC... format or additive\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"large-community", NULL);
|
2017-01-20 16:43:08 +01:00
|
|
|
}
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2018-12-19 13:30:01 +01:00
|
|
|
ALIAS (no_set_lcommunity1,
|
|
|
|
no_set_lcommunity1_short_cmd,
|
|
|
|
"no set large-community",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP large community attribute\n")
|
|
|
|
|
2016-11-15 11:00:39 +01:00
|
|
|
DEFUN (set_lcommunity_delete,
|
|
|
|
set_lcommunity_delete_cmd,
|
|
|
|
"set large-comm-list <(1-99)|(100-500)|WORD> delete",
|
|
|
|
SET_STR
|
|
|
|
"set BGP large community list (for deletion)\n"
|
|
|
|
"Large Community-list number (standard)\n"
|
|
|
|
"Large Communitly-list number (expanded)\n"
|
|
|
|
"Large Community-list name\n"
|
|
|
|
"Delete matching large communities\n")
|
|
|
|
{
|
2019-06-26 14:06:10 +02:00
|
|
|
int idx_lcomm_list = 2;
|
|
|
|
char *args;
|
|
|
|
|
|
|
|
args = argv_concat(argv, argc, idx_lcomm_list);
|
2017-07-17 14:03:14 +02:00
|
|
|
generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
2019-06-26 14:06:10 +02:00
|
|
|
"large-comm-list", args);
|
|
|
|
XFREE(MTYPE_TMP, args);
|
2016-11-15 11:00:39 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return CMD_SUCCESS;
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_lcommunity_delete,
|
|
|
|
no_set_lcommunity_delete_cmd,
|
2017-01-26 03:38:58 +01:00
|
|
|
"no set large-comm-list <(1-99)|(100-500)|WORD> [delete]",
|
2016-11-15 11:00:39 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"set BGP large community list (for deletion)\n"
|
|
|
|
"Large Community-list number (standard)\n"
|
|
|
|
"Large Communitly-list number (expanded)\n"
|
|
|
|
"Large Community-list name\n"
|
|
|
|
"Delete matching large communities\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"large-comm-list", NULL);
|
2016-11-15 11:00:39 +01:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-12-19 13:30:01 +01:00
|
|
|
ALIAS (no_set_lcommunity_delete,
|
|
|
|
no_set_lcommunity_delete_short_cmd,
|
|
|
|
"no set large-comm-list",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"set BGP large community list (for deletion)\n")
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (set_ecommunity_rt,
|
|
|
|
set_ecommunity_rt_cmd,
|
2017-09-14 20:07:30 +02:00
|
|
|
"set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"BGP extended community attribute\n"
|
2009-06-01 18:20:36 +02:00
|
|
|
"Route Target extended community\n"
|
2002-12-13 21:15:29 +01:00
|
|
|
"VPN extended community\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_asn_nn = 3;
|
|
|
|
int ret;
|
|
|
|
char *str;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
str = argv_concat(argv, argc, idx_asn_nn);
|
|
|
|
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"extcommunity rt", str);
|
|
|
|
XFREE(MTYPE_TMP, str);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_ecommunity_rt,
|
|
|
|
no_set_ecommunity_rt_cmd,
|
2017-09-14 20:07:30 +02:00
|
|
|
"no set extcommunity rt ASN:NN_OR_IP-ADDRESS:NN...",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP extended community attribute\n"
|
2016-11-30 00:07:11 +01:00
|
|
|
"Route Target extended community\n"
|
|
|
|
"VPN extended community\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"extcommunity rt", NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2018-12-19 13:22:26 +01:00
|
|
|
ALIAS (no_set_ecommunity_rt,
|
|
|
|
no_set_ecommunity_rt_short_cmd,
|
|
|
|
"no set extcommunity rt",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP extended community attribute\n"
|
|
|
|
"Route Target extended community\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
DEFUN (set_ecommunity_soo,
|
|
|
|
set_ecommunity_soo_cmd,
|
2017-09-14 20:07:30 +02:00
|
|
|
"set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"BGP extended community attribute\n"
|
|
|
|
"Site-of-Origin extended community\n"
|
|
|
|
"VPN extended community\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_asn_nn = 3;
|
|
|
|
int ret;
|
|
|
|
char *str;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
str = argv_concat(argv, argc, idx_asn_nn);
|
|
|
|
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"extcommunity soo", str);
|
|
|
|
XFREE(MTYPE_TMP, str);
|
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 15:24:19 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_set_ecommunity_soo,
|
|
|
|
no_set_ecommunity_soo_cmd,
|
2017-09-14 20:07:30 +02:00
|
|
|
"no set extcommunity soo ASN:NN_OR_IP-ADDRESS:NN...",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP extended community attribute\n"
|
2016-11-30 00:07:11 +01:00
|
|
|
"Site-of-Origin extended community\n"
|
|
|
|
"VPN extended community\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"extcommunity soo", NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2018-12-19 13:22:26 +01:00
|
|
|
ALIAS (no_set_ecommunity_soo,
|
|
|
|
no_set_ecommunity_soo_short_cmd,
|
|
|
|
"no set extcommunity soo",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"GP extended community attribute\n"
|
|
|
|
"Site-of-Origin extended community\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
DEFUN (set_origin,
|
|
|
|
set_origin_cmd,
|
2016-09-23 15:47:20 +02:00
|
|
|
"set origin <egp|igp|incomplete>",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"BGP origin code\n"
|
|
|
|
"remote EGP\n"
|
|
|
|
"local IGP\n"
|
|
|
|
"unknown heritage\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_origin = 2;
|
|
|
|
if (strncmp(argv[idx_origin]->arg, "igp", 2) == 0)
|
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"origin", "igp");
|
|
|
|
if (strncmp(argv[idx_origin]->arg, "egp", 1) == 0)
|
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"origin", "egp");
|
|
|
|
if (strncmp(argv[idx_origin]->arg, "incomplete", 2) == 0)
|
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"origin", "incomplete");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
vty_out(vty, "%% Invalid set origin type\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 15:24:19 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_set_origin,
|
|
|
|
no_set_origin_cmd,
|
2016-09-27 15:24:19 +02:00
|
|
|
"no set origin [<egp|igp|incomplete>]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
2016-11-08 02:46:04 +01:00
|
|
|
"BGP origin code\n"
|
|
|
|
"remote EGP\n"
|
|
|
|
"local IGP\n"
|
|
|
|
"unknown heritage\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"origin", NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DEFUN (set_atomic_aggregate,
|
|
|
|
set_atomic_aggregate_cmd,
|
|
|
|
"set atomic-aggregate",
|
|
|
|
SET_STR
|
|
|
|
"BGP atomic aggregate attribute\n" )
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"atomic-aggregate", NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_atomic_aggregate,
|
|
|
|
no_set_atomic_aggregate_cmd,
|
|
|
|
"no set atomic-aggregate",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP atomic aggregate attribute\n" )
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"atomic-aggregate", NULL);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (set_aggregator_as,
|
|
|
|
set_aggregator_as_cmd,
|
2016-09-25 16:10:48 +02:00
|
|
|
"set aggregator as (1-4294967295) A.B.C.D",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"BGP aggregator attribute\n"
|
|
|
|
"AS number of aggregator\n"
|
|
|
|
"AS number\n"
|
|
|
|
"IP address of aggregator\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_number = 3;
|
|
|
|
int idx_ipv4 = 4;
|
|
|
|
int ret;
|
|
|
|
struct in_addr address;
|
|
|
|
char *argstr;
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = inet_aton(argv[idx_ipv4]->arg, &address);
|
|
|
|
if (ret == 0) {
|
|
|
|
vty_out(vty, "Aggregator IP address is invalid\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
|
|
|
strlen(argv[idx_number]->arg)
|
|
|
|
+ strlen(argv[idx_ipv4]->arg) + 2);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"aggregator as", argstr);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 15:24:19 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_set_aggregator_as,
|
|
|
|
no_set_aggregator_as_cmd,
|
2016-09-27 15:24:19 +02:00
|
|
|
"no set aggregator as [(1-4294967295) A.B.C.D]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"BGP aggregator attribute\n"
|
2016-09-27 15:24:19 +02:00
|
|
|
"AS number of aggregator\n"
|
|
|
|
"AS number\n"
|
|
|
|
"IP address of aggregator\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_asn = 4;
|
|
|
|
int idx_ip = 5;
|
|
|
|
int ret;
|
|
|
|
struct in_addr address;
|
|
|
|
char *argstr;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
if (argc <= idx_asn)
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"aggregator as", NULL);
|
2016-10-18 01:36:21 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = inet_aton(argv[idx_ip]->arg, &address);
|
|
|
|
if (ret == 0) {
|
|
|
|
vty_out(vty, "Aggregator IP address is invalid\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
|
|
|
|
strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
|
|
|
|
+ 2);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"aggregator as", argstr);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
XFREE(MTYPE_ROUTE_MAP_COMPILED, argstr);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return ret;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-23 05:55:26 +02:00
|
|
|
DEFUN (match_ipv6_next_hop,
|
2002-12-13 21:15:29 +01:00
|
|
|
match_ipv6_next_hop_cmd,
|
|
|
|
"match ipv6 next-hop X:X::X:X",
|
|
|
|
MATCH_STR
|
|
|
|
IPV6_STR
|
|
|
|
"Match IPv6 next-hop address of route\n"
|
|
|
|
"IPv6 address of next hop\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ipv6 = 3;
|
|
|
|
return bgp_route_match_add(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
|
|
|
|
RMAP_EVENT_MATCH_ADDED);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_match_ipv6_next_hop,
|
|
|
|
no_match_ipv6_next_hop_cmd,
|
|
|
|
"no match ipv6 next-hop X:X::X:X",
|
|
|
|
NO_STR
|
|
|
|
MATCH_STR
|
|
|
|
IPV6_STR
|
|
|
|
"Match IPv6 next-hop address of route\n"
|
|
|
|
"IPv6 address of next hop\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ipv6 = 4;
|
|
|
|
return bgp_route_match_delete(vty, "ipv6 next-hop", argv[idx_ipv6]->arg,
|
|
|
|
RMAP_EVENT_MATCH_DELETED);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-20 02:24:45 +02:00
|
|
|
DEFUN (set_ipv6_nexthop_peer,
|
|
|
|
set_ipv6_nexthop_peer_cmd,
|
|
|
|
"set ipv6 next-hop peer-address",
|
|
|
|
SET_STR
|
|
|
|
IPV6_STR
|
|
|
|
"Next hop address\n"
|
|
|
|
"Use peer address (for BGP only)\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 next-hop peer-address", NULL);
|
2015-05-20 02:24:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_ipv6_nexthop_peer,
|
|
|
|
no_set_ipv6_nexthop_peer_cmd,
|
|
|
|
"no set ipv6 next-hop peer-address",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
IPV6_STR
|
|
|
|
"IPv6 next-hop address\n"
|
2016-08-03 15:49:09 +02:00
|
|
|
"Use peer address (for BGP only)\n")
|
2015-05-20 02:24:45 +02:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 next-hop peer-address", NULL);
|
2015-05-20 02:24:45 +02:00
|
|
|
}
|
|
|
|
|
2016-08-03 15:49:09 +02:00
|
|
|
DEFUN (set_ipv6_nexthop_prefer_global,
|
|
|
|
set_ipv6_nexthop_prefer_global_cmd,
|
|
|
|
"set ipv6 next-hop prefer-global",
|
|
|
|
SET_STR
|
|
|
|
IPV6_STR
|
|
|
|
"IPv6 next-hop address\n"
|
|
|
|
"Prefer global over link-local if both exist\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 next-hop prefer-global", NULL);
|
|
|
|
;
|
2016-08-03 15:49:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN (no_set_ipv6_nexthop_prefer_global,
|
|
|
|
no_set_ipv6_nexthop_prefer_global_cmd,
|
|
|
|
"no set ipv6 next-hop prefer-global",
|
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
IPV6_STR
|
|
|
|
"IPv6 next-hop address\n"
|
|
|
|
"Prefer global over link-local if both exist\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 next-hop prefer-global", NULL);
|
2016-08-03 15:49:09 +02:00
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (set_ipv6_nexthop_global,
|
|
|
|
set_ipv6_nexthop_global_cmd,
|
|
|
|
"set ipv6 next-hop global X:X::X:X",
|
|
|
|
SET_STR
|
|
|
|
IPV6_STR
|
|
|
|
"IPv6 next-hop address\n"
|
|
|
|
"IPv6 global address\n"
|
|
|
|
"IPv6 address of next hop\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ipv6 = 4;
|
|
|
|
struct in6_addr addr;
|
|
|
|
int ret;
|
2015-06-11 18:19:59 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
ret = inet_pton(AF_INET6, argv[idx_ipv6]->arg, &addr);
|
|
|
|
if (!ret) {
|
|
|
|
vty_out(vty, "%% Malformed nexthop address\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED(&addr) || IN6_IS_ADDR_LOOPBACK(&addr)
|
|
|
|
|| IN6_IS_ADDR_MULTICAST(&addr) || IN6_IS_ADDR_LINKLOCAL(&addr)) {
|
|
|
|
vty_out(vty, "%% Invalid global nexthop address\n");
|
|
|
|
return CMD_WARNING_CONFIG_FAILED;
|
|
|
|
}
|
2015-06-11 18:19:59 +02:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 next-hop global", argv[idx_ipv6]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 15:24:19 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_set_ipv6_nexthop_global,
|
|
|
|
no_set_ipv6_nexthop_global_cmd,
|
2016-09-27 15:24:19 +02:00
|
|
|
"no set ipv6 next-hop global X:X::X:X",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
IPV6_STR
|
|
|
|
"IPv6 next-hop address\n"
|
2016-09-27 15:24:19 +02:00
|
|
|
"IPv6 global address\n"
|
|
|
|
"IPv6 address of next hop\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ipv6 = 5;
|
|
|
|
if (argc <= idx_ipv6)
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 next-hop global", NULL);
|
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 next-hop global", argv[idx_ipv6]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-01-18 12:27:52 +01:00
|
|
|
#ifdef KEEP_OLD_VPN_COMMANDS
|
|
|
|
DEFUN (set_vpn_nexthop,
|
|
|
|
set_vpn_nexthop_cmd,
|
2017-07-11 21:42:11 +02:00
|
|
|
"set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_STR
|
|
|
|
"VPNv4 information\n"
|
2017-01-18 12:27:52 +01:00
|
|
|
"VPN next-hop address\n"
|
|
|
|
"IP address of next hop\n"
|
2017-07-11 21:42:11 +02:00
|
|
|
"VPNv6 information\n"
|
|
|
|
"VPN next-hop address\n"
|
2017-01-18 12:27:52 +01:00
|
|
|
"IPv6 address of next hop\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ip = 3;
|
|
|
|
afi_t afi;
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
|
|
|
|
if (afi == AFI_IP)
|
|
|
|
return generic_set_add(
|
|
|
|
vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv4 vpn next-hop", argv[idx_ip]->arg);
|
|
|
|
else
|
|
|
|
return generic_set_add(
|
|
|
|
vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 vpn next-hop", argv[idx_ip]->arg);
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
2017-01-18 12:27:52 +01:00
|
|
|
}
|
2016-09-27 15:24:19 +02:00
|
|
|
|
2017-01-18 12:27:52 +01:00
|
|
|
DEFUN (no_set_vpn_nexthop,
|
|
|
|
no_set_vpn_nexthop_cmd,
|
2017-07-11 21:42:11 +02:00
|
|
|
"no set <vpnv4 next-hop A.B.C.D|vpnv6 next-hop X:X::X:X>",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
2017-07-11 21:42:11 +02:00
|
|
|
"VPNv4 information\n"
|
2017-01-18 12:27:52 +01:00
|
|
|
"VPN next-hop address\n"
|
|
|
|
"IP address of next hop\n"
|
2017-07-11 21:42:11 +02:00
|
|
|
"VPNv6 information\n"
|
|
|
|
"VPN next-hop address\n"
|
2017-01-18 12:27:52 +01:00
|
|
|
"IPv6 address of next hop\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ip = 4;
|
|
|
|
char *arg;
|
|
|
|
afi_t afi;
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
if (argc <= idx_ip)
|
|
|
|
arg = NULL;
|
|
|
|
else
|
|
|
|
arg = argv[idx_ip]->arg;
|
|
|
|
if (argv_find_and_parse_vpnvx(argv, argc, &idx, &afi)) {
|
|
|
|
if (afi == AFI_IP)
|
|
|
|
return generic_set_delete(
|
|
|
|
vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv4 vpn next-hop", arg);
|
|
|
|
else
|
|
|
|
return generic_set_delete(
|
|
|
|
vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 vpn next-hop", argv[idx_ip]->arg);
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
2017-01-18 12:27:52 +01:00
|
|
|
}
|
|
|
|
#endif /* KEEP_OLD_VPN_COMMANDS */
|
|
|
|
|
|
|
|
DEFUN (set_ipx_vpn_nexthop,
|
|
|
|
set_ipx_vpn_nexthop_cmd,
|
2017-01-30 20:49:24 +01:00
|
|
|
"set <ipv4|ipv6> vpn next-hop <A.B.C.D|X:X::X:X>",
|
2017-01-18 12:27:52 +01:00
|
|
|
SET_STR
|
|
|
|
"IPv4 information\n"
|
|
|
|
"IPv6 information\n"
|
|
|
|
"VPN information\n"
|
|
|
|
"VPN next-hop address\n"
|
|
|
|
"IP address of next hop\n"
|
|
|
|
"IPv6 address of next hop\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ip = 4;
|
|
|
|
afi_t afi;
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
|
|
|
|
if (afi == AFI_IP)
|
|
|
|
return generic_set_add(
|
|
|
|
vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv4 vpn next-hop", argv[idx_ip]->arg);
|
|
|
|
else
|
|
|
|
return generic_set_add(
|
|
|
|
vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 vpn next-hop", argv[idx_ip]->arg);
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2017-01-18 12:27:52 +01:00
|
|
|
DEFUN (no_set_ipx_vpn_nexthop,
|
|
|
|
no_set_ipx_vpn_nexthop_cmd,
|
2017-01-22 19:13:48 +01:00
|
|
|
"no set <ipv4|ipv6> vpn next-hop [<A.B.C.D|X:X::X:X>]",
|
2017-01-18 12:27:52 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
|
|
|
"IPv4 information\n"
|
|
|
|
"IPv6 information\n"
|
|
|
|
"VPN information\n"
|
|
|
|
"VPN next-hop address\n"
|
|
|
|
"IP address of next hop\n"
|
|
|
|
"IPv6 address of next hop\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ip = 5;
|
|
|
|
char *arg;
|
|
|
|
afi_t afi;
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
if (argc <= idx_ip)
|
|
|
|
arg = NULL;
|
|
|
|
else
|
|
|
|
arg = argv[idx_ip]->arg;
|
|
|
|
if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
|
|
|
|
if (afi == AFI_IP)
|
|
|
|
return generic_set_delete(
|
|
|
|
vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv4 vpn next-hop", arg);
|
|
|
|
else
|
|
|
|
return generic_set_delete(
|
|
|
|
vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"ipv6 vpn next-hop", arg);
|
|
|
|
}
|
|
|
|
return CMD_SUCCESS;
|
2017-01-18 12:27:52 +01:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
DEFUN (set_originator_id,
|
|
|
|
set_originator_id_cmd,
|
|
|
|
"set originator-id A.B.C.D",
|
|
|
|
SET_STR
|
|
|
|
"BGP originator ID attribute\n"
|
|
|
|
"IP address of originator\n")
|
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx_ipv4 = 2;
|
|
|
|
return generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"originator-id", argv[idx_ipv4]->arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2016-09-27 07:05:12 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
DEFUN (no_set_originator_id,
|
|
|
|
no_set_originator_id_cmd,
|
2016-09-27 07:05:12 +02:00
|
|
|
"no set originator-id [A.B.C.D]",
|
2002-12-13 21:15:29 +01:00
|
|
|
NO_STR
|
|
|
|
SET_STR
|
2016-09-27 07:05:12 +02:00
|
|
|
"BGP originator ID attribute\n"
|
|
|
|
"IP address of originator\n")
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2017-07-17 14:03:14 +02:00
|
|
|
int idx = 0;
|
|
|
|
char *arg =
|
|
|
|
argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL;
|
2017-01-30 20:49:24 +01:00
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
|
|
|
|
"originator-id", arg);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialization of route map. */
|
2017-07-17 14:03:14 +02:00
|
|
|
void bgp_route_map_init(void)
|
|
|
|
{
|
|
|
|
route_map_init();
|
|
|
|
|
|
|
|
route_map_add_hook(bgp_route_map_add);
|
|
|
|
route_map_delete_hook(bgp_route_map_delete);
|
|
|
|
route_map_event_hook(bgp_route_map_event);
|
|
|
|
|
|
|
|
route_map_match_interface_hook(generic_match_add);
|
|
|
|
route_map_no_match_interface_hook(generic_match_delete);
|
|
|
|
|
|
|
|
route_map_match_ip_address_hook(generic_match_add);
|
|
|
|
route_map_no_match_ip_address_hook(generic_match_delete);
|
|
|
|
|
|
|
|
route_map_match_ip_address_prefix_list_hook(generic_match_add);
|
|
|
|
route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
|
|
|
|
|
|
|
|
route_map_match_ip_next_hop_hook(generic_match_add);
|
|
|
|
route_map_no_match_ip_next_hop_hook(generic_match_delete);
|
|
|
|
|
|
|
|
route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
|
|
|
|
route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
|
|
|
|
|
2018-09-28 10:51:50 +02:00
|
|
|
route_map_match_ip_next_hop_type_hook(generic_match_add);
|
|
|
|
route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_match_ipv6_address_hook(generic_match_add);
|
|
|
|
route_map_no_match_ipv6_address_hook(generic_match_delete);
|
|
|
|
|
|
|
|
route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
|
|
|
|
route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
|
|
|
|
|
2018-09-28 10:51:50 +02:00
|
|
|
route_map_match_ipv6_next_hop_type_hook(generic_match_add);
|
|
|
|
route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_match_metric_hook(generic_match_add);
|
|
|
|
route_map_no_match_metric_hook(generic_match_delete);
|
|
|
|
|
|
|
|
route_map_match_tag_hook(generic_match_add);
|
|
|
|
route_map_no_match_tag_hook(generic_match_delete);
|
|
|
|
|
|
|
|
route_map_set_ip_nexthop_hook(generic_set_add);
|
|
|
|
route_map_no_set_ip_nexthop_hook(generic_set_delete);
|
|
|
|
|
|
|
|
route_map_set_ipv6_nexthop_local_hook(generic_set_add);
|
|
|
|
route_map_no_set_ipv6_nexthop_local_hook(generic_set_delete);
|
|
|
|
|
|
|
|
route_map_set_metric_hook(generic_set_add);
|
|
|
|
route_map_no_set_metric_hook(generic_set_delete);
|
|
|
|
|
|
|
|
route_map_set_tag_hook(generic_set_add);
|
|
|
|
route_map_no_set_tag_hook(generic_set_delete);
|
|
|
|
|
|
|
|
route_map_install_match(&route_match_peer_cmd);
|
|
|
|
route_map_install_match(&route_match_local_pref_cmd);
|
2017-11-07 15:14:32 +01:00
|
|
|
#if defined(HAVE_LUA)
|
|
|
|
route_map_install_match(&route_match_command_cmd);
|
|
|
|
#endif
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_install_match(&route_match_ip_address_cmd);
|
|
|
|
route_map_install_match(&route_match_ip_next_hop_cmd);
|
|
|
|
route_map_install_match(&route_match_ip_route_source_cmd);
|
|
|
|
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
|
|
|
|
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
|
2018-09-28 10:51:50 +02:00
|
|
|
route_map_install_match(&route_match_ip_next_hop_type_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_install_match(&route_match_ip_route_source_prefix_list_cmd);
|
|
|
|
route_map_install_match(&route_match_aspath_cmd);
|
|
|
|
route_map_install_match(&route_match_community_cmd);
|
|
|
|
route_map_install_match(&route_match_lcommunity_cmd);
|
|
|
|
route_map_install_match(&route_match_ecommunity_cmd);
|
|
|
|
route_map_install_match(&route_match_local_pref_cmd);
|
|
|
|
route_map_install_match(&route_match_metric_cmd);
|
|
|
|
route_map_install_match(&route_match_origin_cmd);
|
|
|
|
route_map_install_match(&route_match_probability_cmd);
|
|
|
|
route_map_install_match(&route_match_interface_cmd);
|
|
|
|
route_map_install_match(&route_match_tag_cmd);
|
2017-06-21 10:02:46 +02:00
|
|
|
route_map_install_match(&route_match_mac_address_cmd);
|
2017-06-21 11:00:24 +02:00
|
|
|
route_map_install_match(&route_match_evpn_vni_cmd);
|
2018-01-27 02:16:48 +01:00
|
|
|
route_map_install_match(&route_match_evpn_route_type_cmd);
|
2018-02-22 07:02:07 +01:00
|
|
|
route_map_install_match(&route_match_evpn_default_route_cmd);
|
2019-02-15 03:07:27 +01:00
|
|
|
route_map_install_match(&route_match_vrl_source_vrf_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
route_map_install_set(&route_set_ip_nexthop_cmd);
|
|
|
|
route_map_install_set(&route_set_local_pref_cmd);
|
|
|
|
route_map_install_set(&route_set_weight_cmd);
|
|
|
|
route_map_install_set(&route_set_label_index_cmd);
|
|
|
|
route_map_install_set(&route_set_metric_cmd);
|
|
|
|
route_map_install_set(&route_set_aspath_prepend_cmd);
|
|
|
|
route_map_install_set(&route_set_aspath_exclude_cmd);
|
|
|
|
route_map_install_set(&route_set_origin_cmd);
|
|
|
|
route_map_install_set(&route_set_atomic_aggregate_cmd);
|
|
|
|
route_map_install_set(&route_set_aggregator_as_cmd);
|
|
|
|
route_map_install_set(&route_set_community_cmd);
|
|
|
|
route_map_install_set(&route_set_community_delete_cmd);
|
|
|
|
route_map_install_set(&route_set_lcommunity_cmd);
|
|
|
|
route_map_install_set(&route_set_lcommunity_delete_cmd);
|
|
|
|
route_map_install_set(&route_set_vpnv4_nexthop_cmd);
|
|
|
|
route_map_install_set(&route_set_vpnv6_nexthop_cmd);
|
|
|
|
route_map_install_set(&route_set_originator_id_cmd);
|
|
|
|
route_map_install_set(&route_set_ecommunity_rt_cmd);
|
|
|
|
route_map_install_set(&route_set_ecommunity_soo_cmd);
|
|
|
|
route_map_install_set(&route_set_tag_cmd);
|
|
|
|
route_map_install_set(&route_set_label_index_cmd);
|
|
|
|
|
|
|
|
install_element(RMAP_NODE, &match_peer_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_peer_local_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_peer_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_ip_route_source_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_ip_route_source_prefix_list_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_ip_route_source_prefix_list_cmd);
|
2017-06-21 10:02:46 +02:00
|
|
|
install_element(RMAP_NODE, &match_mac_address_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_mac_address_cmd);
|
2017-06-21 11:00:24 +02:00
|
|
|
install_element(RMAP_NODE, &match_evpn_vni_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
|
2018-01-27 02:16:48 +01:00
|
|
|
install_element(RMAP_NODE, &match_evpn_route_type_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
|
2018-02-22 07:02:07 +01:00
|
|
|
install_element(RMAP_NODE, &match_evpn_default_route_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
|
2019-02-15 03:07:27 +01:00
|
|
|
install_element(RMAP_NODE, &match_vrl_source_vrf_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_vrl_source_vrf_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
|
|
|
install_element(RMAP_NODE, &match_aspath_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_aspath_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_local_pref_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_local_pref_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_community_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_community_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_lcommunity_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_lcommunity_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_ecommunity_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_ecommunity_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_origin_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_origin_cmd);
|
|
|
|
install_element(RMAP_NODE, &match_probability_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_probability_cmd);
|
|
|
|
|
|
|
|
install_element(RMAP_NODE, &set_ip_nexthop_peer_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_ip_nexthop_unchanged_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_local_pref_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_local_pref_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_weight_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_label_index_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_weight_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_label_index_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_aspath_prepend_asn_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_aspath_exclude_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
|
bgpd: Add 'no set as-path prepend last-as X' command
The `set as-path prepend last-as X` command had no, 'no' form
of the command. Add this into the cli.
Testing:
!
route-map BLARBLE permit 10
set as-path prepend last-as 3
!
!
router bgp 9999
neighbor 10.50.12.118 remote-as external
neighbor 10.50.12.118 ebgp-multihop 30
!
address-family ipv4 unicast
neighbor 10.50.12.118 route-map BLARBLE in
!
!
eva# show bgp ipv4 uni 4.4.4.4
BGP routing table entry for 4.4.4.4/32
Paths: (1 available, best #1, table default)
Advertised to non peer-group peers:
10.50.12.118
999 999 999 999
10.50.12.118 from 10.50.12.118 (10.50.12.118)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Mon Aug 26 09:47:17 2019
eva# conf
eva(config)# route-map BLARBLE permit 10
eva(config-route-map)# no set as-path prepend last-as 3
eva(config-route-map)# end
eva# clear bgp ipv4 uni *
eva# show bgp ipv4 uni 4.4.4.4
BGP routing table entry for 4.4.4.4/32
Paths: (1 available, best #1, table default)
Advertised to non peer-group peers:
10.50.12.118
999
10.50.12.118 from 10.50.12.118 (10.50.12.118)
Origin incomplete, metric 0, valid, external, best (First path received)
Last update: Mon Aug 26 09:48:31 2019
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
2019-08-26 15:49:18 +02:00
|
|
|
install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
|
2018-11-15 20:57:34 +01:00
|
|
|
install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(RMAP_NODE, &set_origin_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_origin_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_atomic_aggregate_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_aggregator_as_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_aggregator_as_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_community_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_community_none_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_community_cmd);
|
2018-12-16 19:54:41 +01:00
|
|
|
install_element(RMAP_NODE, &no_set_community_short_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(RMAP_NODE, &set_community_delete_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_community_delete_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_lcommunity_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_lcommunity_none_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_lcommunity_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_lcommunity1_cmd);
|
2018-12-19 13:30:01 +01:00
|
|
|
install_element(RMAP_NODE, &no_set_lcommunity1_short_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(RMAP_NODE, &set_lcommunity_delete_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_lcommunity_delete_cmd);
|
2018-12-19 13:30:01 +01:00
|
|
|
install_element(RMAP_NODE, &no_set_lcommunity_delete_short_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(RMAP_NODE, &set_ecommunity_rt_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_ecommunity_rt_cmd);
|
2018-12-19 13:22:26 +01:00
|
|
|
install_element(RMAP_NODE, &no_set_ecommunity_rt_short_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(RMAP_NODE, &set_ecommunity_soo_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_ecommunity_soo_cmd);
|
2018-12-19 13:22:26 +01:00
|
|
|
install_element(RMAP_NODE, &no_set_ecommunity_soo_short_cmd);
|
2017-01-18 12:27:52 +01:00
|
|
|
#ifdef KEEP_OLD_VPN_COMMANDS
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(RMAP_NODE, &set_vpn_nexthop_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_vpn_nexthop_cmd);
|
2017-01-18 12:27:52 +01:00
|
|
|
#endif /* KEEP_OLD_VPN_COMMANDS */
|
2017-07-17 14:03:14 +02:00
|
|
|
install_element(RMAP_NODE, &set_ipx_vpn_nexthop_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_originator_id_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_originator_id_cmd);
|
|
|
|
|
|
|
|
route_map_install_match(&route_match_ipv6_address_cmd);
|
|
|
|
route_map_install_match(&route_match_ipv6_next_hop_cmd);
|
|
|
|
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
|
2018-09-28 10:51:50 +02:00
|
|
|
route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
|
2017-07-17 14:03:14 +02:00
|
|
|
route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
|
|
|
|
route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
|
|
|
|
route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
|
|
|
|
route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
|
|
|
|
|
|
|
|
install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
|
|
|
|
install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
|
2017-11-07 15:14:32 +01:00
|
|
|
#if defined(HAVE_LUA)
|
|
|
|
install_element(RMAP_NODE, &match_command_cmd);
|
|
|
|
install_element(RMAP_NODE, &no_match_command_cmd);
|
|
|
|
#endif
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void bgp_route_map_terminate(void)
|
|
|
|
{
|
|
|
|
/* ToDo: Cleanup all the used memory */
|
|
|
|
route_map_finish();
|
2015-05-20 02:40:45 +02:00
|
|
|
}
|