#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_ecommunity.h"
+#include "bgpd/bgp_evpn.h"
void bgp_add_routermac_ecom (struct attr* attr, char * routermac)
{
en+=2;
return mac2str(en);
}
+
+/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
+extern int bgp_build_evpn_prefix (int evpn_type, uint32_t eth_tag, struct prefix *dst)
+{
+#if defined(HAVE_EVPN)
+ struct evpn_addr *p_evpn_p;
+ struct prefix p2;
+ struct prefix *src = &p2;
+
+ if (!dst || dst->family == 0)
+ return -1;
+ /* store initial prefix in src */
+ prefix_copy (src, dst);
+ memset (dst, 0, sizeof (struct prefix));
+ p_evpn_p = &(dst->u.prefix_evpn);
+ dst->family = AF_ETHERNET;
+ p_evpn_p->route_type = evpn_type;
+ if (evpn_type == EVPN_IP_PREFIX)
+ {
+ p_evpn_p->eth_tag = eth_tag;
+ p_evpn_p->ip_prefix_length = p2.prefixlen;
+ if (src->family == AF_INET)
+ {
+ p_evpn_p->flags = IP_PREFIX_V4;
+ memcpy (&p_evpn_p->ip.v4_addr, &src->u.prefix4, sizeof(struct in_addr));
+ dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
+ }
+ else
+ {
+ p_evpn_p->flags = IP_PREFIX_V6;
+ memcpy (&p_evpn_p->ip.v6_addr, &src->u.prefix6, sizeof(struct in6_addr));
+ dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
+ }
+ }
+ else
+ return -1;
+ return 0;
+#else
+ return -1;
+#endif /* !(HAVE_EVPN) */
+}
extern char *ecom_mac2str(char *ecom_mac);
extern void bgp_add_routermac_ecom (struct attr* attr, char * routermac);
-
+extern int bgp_build_evpn_prefix (int type, uint32_t eth_tag, struct prefix *dst);
#endif /* _QUAGGA_BGP_ATTR_EVPN_H */
int idx_ipv4 = 1;
int idx_rd = 3;
int idx_word = 5;
- return bgp_static_set_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg, NULL);
+ return bgp_static_set_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg,
+ NULL, 0, NULL, NULL, NULL, NULL);
}
/* For testing purpose, static route of ENCAP. */
int idx_ipv4 = 2;
int idx_rd = 4;
int idx_word = 6;
- return bgp_static_unset_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg);
+ return bgp_static_unset_safi (SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg,
+ 0, NULL, NULL, NULL);
}
static int
#include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_vpn.h"
#include "bgpd/bgp_evpn_vty.h"
+#include "bgpd/bgp_evpn.h"
#define SHOW_DISPLAY_STANDARD 0
#define SHOW_DISPLAY_TAGS 1
SHOW_DISPLAY_OVERLAY, use_json (argc, argv));
}
+/* For testing purpose, static route of MPLS-VPN. */
+DEFUN (evpnrt5_network,
+ evpnrt5_network_cmd,
+ "network <A.B.C.D/M|X:X::X:X/M> rd ASN:nn_or_IP-address:nn ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map WORD]",
+ "Specify a network to announce via BGP\n"
+ "IP prefix\n"
+ "IPv6 prefix\n"
+ "Specify Route Distinguisher\n"
+ "VPN Route Distinguisher\n"
+ "Ethernet Tag\n"
+ "Ethernet Tag Value\n"
+ "BGP label\n"
+ "label value\n"
+ "Ethernet Segment Identifier\n"
+ "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
+ "Gateway IP\n"
+ "Gateway IP ( A.B.C.D )\n"
+ "Gateway IPv6 ( X:X::X:X )\n"
+ "Router Mac Ext Comm\n"
+ "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n")
+{
+ int idx_ipv4_prefixlen = 1;
+ int idx_ext_community = 3;
+ int idx_word = 7;
+ int idx_esi = 9;
+ int idx_gwip = 11;
+ int idx_ethtag = 5;
+ int idx_routermac = 13;
+ int idx_rmap = 15;
+ return bgp_static_set_safi (SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg,
+ argv[idx_word]->arg, argv[idx_rmap]?argv[idx_gwip]->arg:NULL,
+ EVPN_IP_PREFIX, argv[idx_esi]->arg, argv[idx_gwip]->arg,
+ argv[idx_ethtag]->arg, argv[idx_routermac]->arg);
+}
+
+/* For testing purpose, static route of MPLS-VPN. */
+DEFUN (no_evpnrt5_network,
+ no_evpnrt5_network_cmd,
+ "no network <A.B.C.D/M|X:X::X:X/M> rd ASN:nn_or_IP-address:nn ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X>",
+ NO_STR
+ "Specify a network to announce via BGP\n"
+ "IP prefix\n"
+ "IPv6 prefix\n"
+ "Specify Route Distinguisher\n"
+ "VPN Route Distinguisher\n"
+ "Ethernet Tag\n"
+ "Ethernet Tag Value\n"
+ "BGP label\n"
+ "label value\n"
+ "Ethernet Segment Identifier\n"
+ "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
+ "Gateway IP\n"
+ "Gateway IP ( A.B.C.D )\n"
+ "Gateway IPv6 ( X:X::X:X )\n")
+{
+ int idx_ipv4_prefixlen = 2;
+ int idx_ext_community = 4;
+ int idx_label = 8;
+ int idx_ethtag = 6;
+ int idx_esi = 10;
+ int idx_gwip = 12;
+ return bgp_static_unset_safi (SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg,
+ EVPN_IP_PREFIX, argv[idx_esi]->arg, argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
+}
+
void
bgp_ethernetvpn_init (void)
install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
install_element (VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
install_element (VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
+ install_element (BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
+ install_element (BGP_EVPN_NODE, &evpnrt5_network_cmd);
}
int idx_ipv4_prefixlen = 1;
int idx_ext_community = 3;
int idx_word = 5;
- return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL);
+ return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg,
+ argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL);
}
DEFUN (vpnv4_network_route_map,
int idx_ext_community = 3;
int idx_word = 5;
int idx_word_2 = 7;
- return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg);
+ return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg,
+ argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
}
/* For testing purpose, static route of MPLS-VPN. */
int idx_ipv4_prefixlen = 2;
int idx_ext_community = 4;
int idx_word = 6;
- return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg);
+ return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
+ argv[idx_ext_community]->arg, argv[idx_word]->arg,
+ 0, NULL, NULL, NULL);
}
DEFUN (vpnv6_network,
int idx_word = 5;
int idx_word_2 = 7;
if (argv[idx_word_2])
- return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg);
+ return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
else
- return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL);
+ return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL);
}
/* For testing purpose, static route of MPLS-VPN. */
int idx_ipv6_prefix = 2;
int idx_ext_community = 4;
int idx_word = 6;
- return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg);
+ return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, 0, NULL, NULL, NULL);
}
int
#include "bgpd/bgp_encap_types.h"
#include "bgpd/bgp_encap_tlv.h"
#include "bgpd/bgp_evpn.h"
+#include "bgpd/bgp_evpn_vty.h"
/* Extern from bgp_dump.c */
int
bgp_static_set_safi (safi_t safi, struct vty *vty, const char *ip_str,
const char *rd_str, const char *tag_str,
- const char *rmap_str)
+ const char *rmap_str, int evpn_type, const char *esi, const char *gwip,
+ const char *ethtag, const char *routermac)
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret;
struct bgp_static *bgp_static;
u_char tag[3];
afi_t afi;
+ struct prefix gw_ip;
+ if(safi == SAFI_EVPN)
+ afi = AFI_L2VPN;
+ else
+ afi = AFI_IP;
+
+ /* validate ip prefix */
ret = str2prefix (ip_str, &p);
if (! ret)
{
return CMD_WARNING;
}
apply_mask (&p);
+ if ( (afi == AFI_L2VPN) &&
+ (bgp_build_evpn_prefix ( evpn_type, ethtag!=NULL?atol(ethtag):0, &p)))
+ {
+ vty_out (vty, "%% L2VPN prefix could not be forged%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
ret = str2prefix_rd (rd_str, &prd);
if (! ret)
return CMD_WARNING;
}
- ret = str2tag (tag_str, tag);
- if (! ret)
+ if (tag_str)
{
- vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
- return CMD_WARNING;
+ ret = str2tag (tag_str, tag);
+ if (! ret)
+ {
+ vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
}
- if (p.family == AF_INET)
- afi = AFI_IP;
- else if (p.family == AF_INET6)
- afi = AFI_IP6;
else
{
- vty_out (vty, "%% Non Supported prefix%s", VTY_NEWLINE);
- return CMD_WARNING;
+ encode_label (0, tag);
+ }
+ if (safi == SAFI_EVPN)
+ {
+ if( esi && str2esi (esi, NULL) == 0)
+ {
+ vty_out (vty, "%% Malformed ESI%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if( routermac && str2mac (routermac, NULL) == 0)
+ {
+ vty_out (vty, "%% Malformed Router MAC%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (gwip)
+ {
+ memset (&gw_ip, 0, sizeof (struct prefix));
+ ret = str2prefix (gwip, &gw_ip);
+ if (! ret)
+ {
+ vty_out (vty, "%% Malformed GatewayIp%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if((gw_ip.family == AF_INET && (p.u.prefix_evpn.flags & IP_PREFIX_V6))
+ || (gw_ip.family == AF_INET6 && (p.u.prefix_evpn.flags & IP_PREFIX_V4)))
+ {
+ vty_out (vty, "%% GatewayIp family differs with IP prefix%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
}
prn = bgp_node_get (bgp->route[afi][safi],
(struct prefix *)&prd);
bgp_static->rmap.name = strdup (rmap_str);
bgp_static->rmap.map = route_map_lookup_by_name (rmap_str);
}
+
+ if (safi == SAFI_EVPN)
+ {
+ if(esi)
+ {
+ bgp_static->eth_s_id = XCALLOC (MTYPE_ATTR, sizeof(struct eth_segment_id));
+ str2esi (esi, bgp_static->eth_s_id);
+ }
+ if( routermac)
+ {
+ bgp_static->router_mac = XCALLOC (MTYPE_ATTR, MAC_LEN+1);
+ str2mac (routermac, bgp_static->router_mac);
+ }
+ if (gwip)
+ prefix_copy (&bgp_static->gatewayIp, &gw_ip);
+ }
rn->info = bgp_static;
bgp_static->valid = 1;
/* Configure static BGP network. */
int
bgp_static_unset_safi(safi_t safi, struct vty *vty, const char *ip_str,
- const char *rd_str, const char *tag_str)
+ const char *rd_str, const char *tag_str,
+ int evpn_type, const char *esi, const char *gwip, const char *ethtag)
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret;
struct bgp_table *table;
struct bgp_static *bgp_static;
u_char tag[3];
+ afi_t afi;
+
+ if(safi == SAFI_EVPN)
+ afi = AFI_L2VPN;
+ else
+ afi = AFI_IP;
/* Convert IP prefix string to struct prefix. */
ret = str2prefix (ip_str, &p);
return CMD_WARNING;
}
apply_mask (&p);
-
+ if ( (afi == AFI_L2VPN) &&
+ (bgp_build_evpn_prefix ( evpn_type, ethtag!=NULL?atol(ethtag):0, &p)))
+ {
+ vty_out (vty, "%% L2VPN prefix could not be forged%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
ret = str2prefix_rd (rd_str, &prd);
if (! ret)
{
return CMD_WARNING;
}
- prn = bgp_node_get (bgp->route[AFI_IP][safi],
+ prn = bgp_node_get (bgp->route[afi][safi],
(struct prefix *)&prd);
if (prn->info == NULL)
- prn->info = bgp_table_init (AFI_IP, safi);
+ prn->info = bgp_table_init (afi, safi);
else
bgp_unlock_node (prn);
table = prn->info;
if (rn)
{
- bgp_static_withdraw_safi (bgp, &p, AFI_IP, safi, &prd, tag);
+ bgp_static_withdraw_safi (bgp, &p, afi, safi, &prd, tag);
bgp_static = rn->info;
bgp_static_free (bgp_static);
return 0;
}
+static int
+bgp_config_write_network_evpn (struct vty *vty, struct bgp *bgp,
+ afi_t afi, safi_t safi, int *write)
+{
+ struct bgp_node *prn;
+ struct bgp_node *rn;
+ struct bgp_table *table;
+ struct prefix *p;
+ struct prefix_rd *prd;
+ struct bgp_static *bgp_static;
+ char buf[PREFIX_STRLEN];
+ char buf2[SU_ADDRSTRLEN];
+ char rdbuf[RD_ADDRSTRLEN];
+
+ /* Network configuration. */
+ for (prn = bgp_table_top (bgp->route[afi][safi]); prn; prn = bgp_route_next (prn))
+ if ((table = prn->info) != NULL)
+ for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+ if ((bgp_static = rn->info) != NULL)
+ {
+ char *macrouter = NULL;
+ char *esi = NULL;
+
+ if(bgp_static->router_mac)
+ macrouter = mac2str(bgp_static->router_mac);
+ if(bgp_static->eth_s_id)
+ esi = esi2str(bgp_static->eth_s_id);
+ p = &rn->p;
+ prd = (struct prefix_rd *) &prn->p;
+
+ /* "address-family" display. */
+ bgp_config_write_family_header (vty, afi, safi, write);
+
+ /* "network" configuration display. */
+ prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN);
+
+ inet_ntop (AF_INET, &bgp_static->igpnexthop, buf2, SU_ADDRSTRLEN);
+
+ prefix2str (p, buf, sizeof (buf)),
+ vty_out (vty, " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
+ buf, rdbuf, p->u.prefix_evpn.eth_tag,
+ decode_label (bgp_static->tag), esi, buf2 , macrouter);
+ vty_out (vty, "%s", VTY_NEWLINE);
+ }
+ return 0;
+}
+
/* Configuration of static route announcement and aggregate
information. */
int
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
return bgp_config_write_network_vpn (vty, bgp, afi, safi, write);
+ if (afi == AFI_L2VPN && safi == SAFI_EVPN)
+ return bgp_config_write_network_evpn (vty, bgp, afi, safi, write);
+
/* Network configuration. */
for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn))
if ((bgp_static = rn->info) != NULL)
extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t);
extern int bgp_static_set_safi (safi_t safi, struct vty *vty, const char *,
- const char *, const char *, const char *);
+ const char *, const char *, const char *,
+ int, const char *, const char *, const char *, const char *);
extern int bgp_static_unset_safi (safi_t safi, struct vty *, const char *,
- const char *, const char *);
+ const char *, const char *,
+ int, const char *, const char *, const char *);
/* this is primarily for MPLS-VPN */
extern int bgp_update (struct peer *, struct prefix *, u_int32_t, struct attr *,