1 /* Ethernet-VPN Attribute handling file
2 * Copyright (C) 2016 6WIND
4 * This file is part of FRRouting.
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 #include "bgpd/bgpd.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_attr_evpn.h"
34 #include "bgpd/bgp_ecommunity.h"
35 #include "bgpd/bgp_evpn.h"
36 #include "bgpd/bgp_evpn_private.h"
38 void bgp_add_routermac_ecom(struct attr
*attr
, struct ethaddr
*routermac
)
40 struct ecommunity_val routermac_ecom
;
42 memset(&routermac_ecom
, 0, sizeof(struct ecommunity_val
));
43 routermac_ecom
.val
[0] = ECOMMUNITY_ENCODE_EVPN
;
44 routermac_ecom
.val
[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
;
45 memcpy(&routermac_ecom
.val
[2], routermac
->octet
, ETH_ALEN
);
46 if (!attr
->ecommunity
)
47 attr
->ecommunity
= ecommunity_new();
48 ecommunity_add_val(attr
->ecommunity
, &routermac_ecom
);
49 ecommunity_str(attr
->ecommunity
);
53 * returns 1 on success, 0 otherwise
54 * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
55 * if id is null, check only is done
57 int str2esi(const char *str
, struct eth_segment_id
*id
)
59 unsigned int a
[ESI_LEN
];
64 if (sscanf(str
, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a
+ 0, a
+ 1,
65 a
+ 2, a
+ 3, a
+ 4, a
+ 5, a
+ 6, a
+ 7, a
+ 8, a
+ 9)
67 /* error in incoming str length */
70 /* valid mac address */
73 for (i
= 0; i
< ESI_LEN
; ++i
)
74 id
->val
[i
] = a
[i
] & 0xff;
78 char *esi2str(struct eth_segment_id
*id
)
87 ptr
= (char *)XMALLOC(MTYPE_TMP
,
88 (ESI_LEN
* 2 + ESI_LEN
- 1 + 1) * sizeof(char));
90 snprintf(ptr
, (ESI_LEN
* 2 + ESI_LEN
- 1 + 1),
91 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", val
[0],
92 val
[1], val
[2], val
[3], val
[4], val
[5], val
[6], val
[7], val
[8],
98 char *ecom_mac2str(char *ecom_mac
)
105 return prefix_mac2str((struct ethaddr
*)en
, NULL
, 0);
109 * Fetch and return the sequence number from MAC Mobility extended
110 * community, if present, else 0.
112 u_int32_t
bgp_attr_mac_mobility_seqnum(struct attr
*attr
, u_char
*sticky
)
114 struct ecommunity
*ecom
;
118 ecom
= attr
->ecommunity
;
119 if (!ecom
|| !ecom
->size
)
122 /* If there is a MAC Mobility extended community, return its
124 * TODO: RFC is silent on handling of multiple MAC mobility extended
125 * communities for the same route. We will bail out upon the first
128 for (i
= 0; i
< ecom
->size
; i
++) {
130 u_char type
, sub_type
;
133 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
136 if (!(type
== ECOMMUNITY_ENCODE_EVPN
137 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY
))
141 if (flags
& ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY
)
147 seq_num
= (*pnt
++ << 24);
148 seq_num
|= (*pnt
++ << 16);
149 seq_num
|= (*pnt
++ << 8);
158 /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
159 extern int bgp_build_evpn_prefix(int evpn_type
, uint32_t eth_tag
,
162 struct evpn_addr
*p_evpn_p
;
164 struct prefix
*src
= &p2
;
166 if (!dst
|| dst
->family
== 0)
168 /* store initial prefix in src */
169 prefix_copy(src
, dst
);
170 memset(dst
, 0, sizeof(struct prefix
));
171 p_evpn_p
= &(dst
->u
.prefix_evpn
);
172 dst
->family
= AF_ETHERNET
;
173 p_evpn_p
->route_type
= evpn_type
;
174 if (evpn_type
== BGP_EVPN_IP_PREFIX_ROUTE
) {
175 p_evpn_p
->eth_tag
= eth_tag
;
176 p_evpn_p
->ip_prefix_length
= p2
.prefixlen
;
177 if (src
->family
== AF_INET
) {
178 SET_IPADDR_V4(&p_evpn_p
->ip
);
179 memcpy(&p_evpn_p
->ip
.ipaddr_v4
, &src
->u
.prefix4
,
180 sizeof(struct in_addr
));
181 dst
->prefixlen
= (u_char
)PREFIX_LEN_ROUTE_TYPE_5_IPV4
;
183 SET_IPADDR_V6(&p_evpn_p
->ip
);
184 memcpy(&p_evpn_p
->ip
.ipaddr_v6
, &src
->u
.prefix6
,
185 sizeof(struct in6_addr
));
186 dst
->prefixlen
= (u_char
)PREFIX_LEN_ROUTE_TYPE_5_IPV6
;