]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_attr_evpn.c
Merge pull request #1161 from dslicenc/bgp-vrf-nexthop
[mirror_frr.git] / bgpd / bgp_attr_evpn.c
1 /* Ethernet-VPN Attribute handling file
2 * Copyright (C) 2016 6WIND
3 *
4 * This file is part of FRRouting.
5 *
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
9 * later version.
10 *
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.
15 *
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
19 */
20
21 #include <zebra.h>
22
23 #include "command.h"
24 #include "filter.h"
25 #include "prefix.h"
26 #include "log.h"
27 #include "memory.h"
28 #include "stream.h"
29
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"
37
38 void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
39 {
40 struct ecommunity_val routermac_ecom;
41
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);
50 }
51
52 /* converts to an esi
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
56 */
57 int str2esi(const char *str, struct eth_segment_id *id)
58 {
59 unsigned int a[ESI_LEN];
60 int i;
61
62 if (!str)
63 return 0;
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)
66 != ESI_LEN) {
67 /* error in incoming str length */
68 return 0;
69 }
70 /* valid mac address */
71 if (!id)
72 return 1;
73 for (i = 0; i < ESI_LEN; ++i)
74 id->val[i] = a[i] & 0xff;
75 return 1;
76 }
77
78 char *esi2str(struct eth_segment_id *id)
79 {
80 char *ptr;
81 u_char *val;
82
83 if (!id)
84 return NULL;
85
86 val = id->val;
87 ptr = (char *)XMALLOC(MTYPE_TMP,
88 (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
89
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],
93 val[9]);
94
95 return ptr;
96 }
97
98 char *ecom_mac2str(char *ecom_mac)
99 {
100 char *en;
101
102 en = ecom_mac;
103 en += 2;
104
105 return prefix_mac2str((struct ethaddr *)en, NULL, 0);
106 }
107
108 /*
109 * Fetch and return the sequence number from MAC Mobility extended
110 * community, if present, else 0.
111 */
112 u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, u_char *sticky)
113 {
114 struct ecommunity *ecom;
115 int i;
116 u_char flags = 0;
117
118 ecom = attr->ecommunity;
119 if (!ecom || !ecom->size)
120 return 0;
121
122 /* If there is a MAC Mobility extended community, return its
123 * sequence number.
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
126 * one.
127 */
128 for (i = 0; i < ecom->size; i++) {
129 u_char *pnt;
130 u_char type, sub_type;
131 u_int32_t seq_num;
132
133 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
134 type = *pnt++;
135 sub_type = *pnt++;
136 if (!(type == ECOMMUNITY_ENCODE_EVPN
137 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
138 continue;
139 flags = *pnt++;
140
141 if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
142 *sticky = 1;
143 else
144 *sticky = 0;
145
146 pnt++;
147 pnt = ptr_get_be32(pnt, &seq_num);
148 (void)pnt; /* consume value */
149 return seq_num;
150 }
151
152 return 0;
153 }
154
155 /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
156 extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
157 struct prefix *dst)
158 {
159 struct evpn_addr *p_evpn_p;
160 struct prefix p2;
161 struct prefix *src = &p2;
162
163 if (!dst || dst->family == 0)
164 return -1;
165 /* store initial prefix in src */
166 prefix_copy(src, dst);
167 memset(dst, 0, sizeof(struct prefix));
168 p_evpn_p = &(dst->u.prefix_evpn);
169 dst->family = AF_EVPN;
170 p_evpn_p->route_type = evpn_type;
171 if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
172 p_evpn_p->eth_tag = eth_tag;
173 p_evpn_p->ip_prefix_length = p2.prefixlen;
174 if (src->family == AF_INET) {
175 SET_IPADDR_V4(&p_evpn_p->ip);
176 memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
177 sizeof(struct in_addr));
178 dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
179 } else {
180 SET_IPADDR_V6(&p_evpn_p->ip);
181 memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
182 sizeof(struct in6_addr));
183 dst->prefixlen = (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
184 }
185 } else
186 return -1;
187 return 0;
188 }