]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_attr_evpn.c
bgpd: enhance structures and esi and mac functions to handle EVPN
[mirror_frr.git] / bgpd / bgp_attr_evpn.c
CommitLineData
212f5cbc
PG
1/* Ethernet-VPN Attribute handling file
2 Copyright (C) 2016 6WIND
3
4This file is part of Free Range Routing.
5
6Free Range Routing is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11Free Range Routing is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with Free Range Routing; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "command.h"
24#include "prefix.h"
25#include "log.h"
26#include "memory.h"
27#include "stream.h"
28
29#include "bgpd/bgp_attr_evpn.h"
30
31static uint8_t convertchartohexa (uint8_t *hexa, int *error)
32{
33 if( (*hexa == '0') || (*hexa == '1') || (*hexa == '2') ||
34 (*hexa == '3') || (*hexa == '4') || (*hexa == '5') ||
35 (*hexa == '6') || (*hexa == '7') || (*hexa == '8') ||
36 (*hexa == '9'))
37 return (uint8_t)(*hexa)-'0';
38 if((*hexa == 'a') || (*hexa == 'A'))
39 return 0xa;
40 if((*hexa == 'b') || (*hexa == 'B'))
41 return 0xb;
42 if((*hexa == 'c') || (*hexa == 'C'))
43 return 0xc;
44 if((*hexa == 'd') || (*hexa == 'D'))
45 return 0xd;
46 if((*hexa == 'e') || (*hexa == 'E'))
47 return 0xe;
48 if((*hexa == 'f') || (*hexa == 'F'))
49 return 0xf;
50 *error = -1;
51 return 0;
52}
53
54/* converts to internal representation of mac address
55 * returns 1 on success, 0 otherwise
56 * format accepted: AA:BB:CC:DD:EE:FF
57 * if mac parameter is null, then check only
58 */
59int
60str2mac (const char *str, char *mac)
61{
62 unsigned int k=0, i, j;
63 uint8_t *ptr, *ptr2;
64 size_t len;
65 uint8_t car;
66
67 if (!str)
68 return 0;
69
70 if (str[0] == ':' && str[1] == '\0')
71 return 1;
72
73 i = 0;
74 ptr = (uint8_t *)str;
75 while (i < 6)
76 {
77 uint8_t temp[5];
78 int error = 0;
79 ptr2 = (uint8_t *)strchr((const char *)ptr, ':');
80 if (ptr2 == NULL)
81 {
82 /* if last occurence return ok */
83 if(i != 5)
84 {
85 zlog_err("[%s]: format non recognized",mac);
86 return 0;
87 }
88 len = strlen((char *)ptr);
89 }
90 else
91 {
92 len = ptr2 - ptr;
93 }
94 if(len > 5)
95 {
96 zlog_err("[%s]: format non recognized",mac);
97 return 0;
98 }
99 memcpy(temp, ptr, len);
100 for(j=0;j< len;j++)
101 {
102 if (k >= MAC_LEN)
103 return 0;
104 if(mac)
105 mac[k] = 0;
106 car = convertchartohexa (&temp[j], &error);
107 if (error)
108 return 0;
109 if(mac)
110 mac[k] = car << 4;
111 j++;
112 if(j == len)
113 return 0;
114 car = convertchartohexa (&temp[j], &error) & 0xf;
115 if (error)
116 return 0;
117 if(mac)
118 mac[k] |= car & 0xf;
119 k++;
120 i++;
121 }
122 ptr = ptr2;
123 if(ptr == NULL)
124 break;
125 ptr++;
126 }
127 if(mac && 0)
128 {
129 zlog_err("leave correct : %02x:%02x:%02x:%02x:%02x:%02x",
130 mac[0] & 0xff, mac[1] & 0xff, mac[2] & 0xff,
131 mac[3] & 0xff, mac[4] & 0xff, mac[5] & 0xff);
132 }
133 return 1;
134}
135
136/* converts to an esi
137 * returns 1 on success, 0 otherwise
138 * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
139 * if id is null, check only is done
140 */
141int
142str2esi (const char *str, struct eth_segment_id *id)
143{
144 unsigned int k=0, i, j;
145 uint8_t *ptr, *ptr2;
146 size_t len;
147 uint8_t car;
148
149 if (!str)
150 return 0;
151 if (str[0] == ':' && str[1] == '\0')
152 return 1;
153
154 i = 0;
155 ptr = (uint8_t *)str;
156 while (i < 10)
157 {
158 uint8_t temp[5];
159 int error = 0;
160 ptr2 = (uint8_t *)strchr((const char *)ptr, ':');
161 if (ptr2 == NULL)
162 {
163 /* if last occurence return ok */
164 if(i != 9)
165 {
166 zlog_err("[%s]: format non recognized",str);
167 return 0;
168 }
169 len = strlen((char *)ptr);
170 }
171 else
172 {
173 len = ptr2 - ptr;
174 }
175 memcpy(temp, ptr, len);
176 if(len > 5)
177 {
178 zlog_err("[%s]: format non recognized",str);
179 return 0;
180 }
181 for(j=0;j< len;j++)
182 {
183 if (k >= ESI_LEN)
184 return 0;
185 if(id)
186 id->val[k] = 0;
187 car = convertchartohexa (&temp[j], &error);
188 if (error)
189 return 0;
190 if(id)
191 id->val[k] = car << 4;
192 j++;
193 if(j == len)
194 return 0;
195 car = convertchartohexa (&temp[j], &error) & 0xf;
196 if (error)
197 return 0;
198 if(id)
199 id->val[k] |= car & 0xf;
200 k++;
201 i++;
202 }
203 ptr = ptr2;
204 if(ptr == NULL)
205 break;
206 ptr++;
207 }
208 if(id && 0)
209 {
210 zlog_err("leave correct : %02x:%02x:%02x:%02x:%02x",
211 id->val[0], id->val[1], id->val[2], id->val[3], id->val[4]);
212 zlog_err("%02x:%02x:%02x:%02x:%02x",
213 id->val[5], id->val[6], id->val[7], id->val[8], id->val[9]);
214 }
215 return 1;
216}
217
218char *
219esi2str (struct eth_segment_id *id)
220{
221 char *ptr;
222 u_char *val;
223
224 if(!id)
225 return NULL;
226
227 val = id->val;
228 ptr = (char *) malloc ((ESI_LEN*2+ESI_LEN-1+1)*sizeof(char));
229
230 snprintf (ptr, (ESI_LEN*2+ESI_LEN-1+1),
231 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
232 val[0], val[1], val[2], val[3], val[4],
233 val[5], val[6], val[7], val[8], val[9]);
234
235 return ptr;
236}
237
238char *
239mac2str (char *mac)
240{
241 char *ptr;
242
243 if(!mac)
244 return NULL;
245
246 ptr = (char *) malloc ((MAC_LEN*2+MAC_LEN-1+1)*sizeof(char));
247
248 snprintf (ptr, (MAC_LEN*2+MAC_LEN-1+1), "%02x:%02x:%02x:%02x:%02x:%02x",
249 (uint8_t) mac[0], (uint8_t)mac[1], (uint8_t)mac[2], (uint8_t)mac[3],
250 (uint8_t)mac[4], (uint8_t)mac[5]);
251
252 return ptr;
253}
254
255char *ecom_mac2str(char *ecom_mac)
256{
257 char *en;
258
259 en = ecom_mac;
260 en+=2;
261 return mac2str(en);
262}