]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn.c
Merge pull request #531 from qlyoung/fix-stack-ref
[mirror_frr.git] / bgpd / bgp_evpn.c
CommitLineData
7ef5a232
PG
1/* Ethernet-VPN Packet and vty Processing File
2 Copyright (C) 2016 6WIND
3
52884837 4This file is part of FRRouting.
7ef5a232 5
52884837 6FRRouting is free software; you can redistribute it and/or modify it
7ef5a232
PG
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
52884837 11FRRouting is distributed in the hope that it will be useful, but
7ef5a232
PG
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
52884837 17along with FRRouting; see the file COPYING. If not, write to the Free
7ef5a232
PG
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
7ef5a232
PG
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/bgp_attr_evpn.h"
31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_table.h"
33#include "bgpd/bgp_route.h"
34#include "bgpd/bgp_attr.h"
35#include "bgpd/bgp_mplsvpn.h"
36#include "bgpd/bgp_evpn.h"
37
38int
4d0e6ece
PG
39bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
40 struct bgp_nlri *packet, int withdraw)
7ef5a232 41{
4d0e6ece
PG
42 u_char *pnt;
43 u_char *lim;
44 struct prefix p;
45 struct prefix_rd prd;
46 struct evpn_addr *p_evpn_p;
47 struct bgp_route_evpn evpn;
48 uint8_t route_type, route_length;
49 u_char *pnt_label;
50 u_int32_t addpath_id = 0;
51
52 /* Check peer status. */
53 if (peer->status != Established)
54 return 0;
55
56 /* Make prefix_rd */
57 prd.family = AF_UNSPEC;
58 prd.prefixlen = 64;
59
60 p_evpn_p = &p.u.prefix_evpn;
61 pnt = packet->nlri;
62 lim = pnt + packet->length;
63 while (pnt < lim) {
64 /* clear evpn structure */
65 memset(&evpn, 0, sizeof(evpn));
66
67 /* Clear prefix structure. */
68 memset(&p, 0, sizeof(struct prefix));
69 memset(&evpn.gw_ip, 0, sizeof(union gw_addr));
70 memset(&evpn.eth_s_id, 0, sizeof(struct eth_segment_id));
71
72 /* Fetch Route Type */
73 route_type = *pnt++;
74 route_length = *pnt++;
75 /* simply ignore. goto next route type if any */
76 if (route_type != EVPN_IP_PREFIX) {
77 if (pnt + route_length > lim) {
78 zlog_err
79 ("not enough bytes for New Route Type left in NLRI?");
80 return -1;
81 }
82 pnt += route_length;
83 continue;
84 }
85
86 /* Fetch RD */
87 if (pnt + 8 > lim) {
88 zlog_err("not enough bytes for RD left in NLRI?");
89 return -1;
90 }
91
92 /* Copy routing distinguisher to rd. */
93 memcpy(&prd.val, pnt, 8);
94 pnt += 8;
95
96 /* Fetch ESI */
97 if (pnt + 10 > lim) {
98 zlog_err("not enough bytes for ESI left in NLRI?");
99 return -1;
100 }
101 memcpy(&evpn.eth_s_id.val, pnt, 10);
102 pnt += 10;
103
104 /* Fetch Ethernet Tag */
105 if (pnt + 4 > lim) {
106 zlog_err("not enough bytes for Eth Tag left in NLRI?");
107 return -1;
108 }
109
110 if (route_type == EVPN_IP_PREFIX) {
111 p_evpn_p->route_type = route_type;
112 memcpy(&(p_evpn_p->eth_tag), pnt, 4);
113 p_evpn_p->eth_tag = ntohl(p_evpn_p->eth_tag);
114 pnt += 4;
115
116 /* Fetch IP prefix length. */
117 p_evpn_p->ip_prefix_length = *pnt++;
118
119 if (p_evpn_p->ip_prefix_length > 128) {
120 zlog_err("invalid prefixlen %d in EVPN NLRI?",
121 p.prefixlen);
122 return -1;
123 }
124 /* determine IPv4 or IPv6 prefix */
125 if (route_length - 4 - 10 - 8 -
126 3 /* label to be read */ >= 32) {
127 p_evpn_p->flags = IP_PREFIX_V6;
daf9ddbb 128 memcpy(&(p_evpn_p->ip.v6_addr), pnt, 16);
4d0e6ece
PG
129 pnt += 16;
130 memcpy(&evpn.gw_ip.ipv6, pnt, 16);
131 pnt += 16;
132 } else {
133 p_evpn_p->flags = IP_PREFIX_V4;
134 memcpy(&(p_evpn_p->ip.v4_addr), pnt, 4);
135 pnt += 4;
136 memcpy(&evpn.gw_ip.ipv4, pnt, 4);
137 pnt += 4;
138 }
139 p.family = AFI_L2VPN;
140 if (p_evpn_p->flags == IP_PREFIX_V4)
141 p.prefixlen =
142 (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4;
143 else
144 p.prefixlen = PREFIX_LEN_ROUTE_TYPE_5_IPV6;
145 p.family = AF_ETHERNET;
146 }
147
148 /* Fetch Label */
149 if (pnt + 3 > lim) {
150 zlog_err("not enough bytes for Label left in NLRI?");
151 return -1;
152 }
153 pnt_label = pnt;
154
155 pnt += 3;
156
157 if (!withdraw) {
158 bgp_update(peer, &p, addpath_id, attr, AFI_L2VPN,
159 SAFI_EVPN, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
160 &prd, pnt_label, 0, &evpn);
161 } else {
162 bgp_withdraw(peer, &p, addpath_id, attr, AFI_L2VPN,
163 SAFI_EVPN, ZEBRA_ROUTE_BGP,
164 BGP_ROUTE_NORMAL, &prd, pnt_label, &evpn);
165 }
7ef5a232
PG
166 }
167
4d0e6ece
PG
168 /* Packet length consistency check. */
169 if (pnt != lim)
170 return -1;
171 return 0;
7ef5a232 172}
b18825eb
PG
173
174void
4d0e6ece
PG
175bgp_packet_mpattr_route_type_5(struct stream *s,
176 struct prefix *p, struct prefix_rd *prd,
177 u_char * label, struct attr *attr)
b18825eb 178{
4d0e6ece
PG
179 int len;
180 char temp[16];
181 struct evpn_addr *p_evpn_p;
182
183 memset(&temp, 0, 16);
184 if (p->family != AF_ETHERNET)
185 return;
186 p_evpn_p = &(p->u.prefix_evpn);
187 if (p_evpn_p->flags & IP_PREFIX_V4)
188 len = 8; /* ipv4 */
189 else
190 len = 32; /* ipv6 */
191 stream_putc(s, EVPN_IP_PREFIX);
192 stream_putc(s,
193 8 /* RD */ + 10 /* ESI */ + 4 /* EthTag */ + 1 + len +
194 3 /* label */ );
195 stream_put(s, prd->val, 8);
196 if (attr && attr->extra)
197 stream_put(s, &(attr->extra->evpn_overlay.eth_s_id), 10);
198 else
199 stream_put(s, &temp, 10);
200 stream_putl(s, p_evpn_p->eth_tag);
201 stream_putc(s, p_evpn_p->ip_prefix_length);
202 if (p_evpn_p->flags & IP_PREFIX_V4)
203 stream_put_ipv4(s, p_evpn_p->ip.v4_addr.s_addr);
204 else
205 stream_put(s, &p_evpn_p->ip.v6_addr, 16);
206 if (attr && attr->extra) {
207 if (p_evpn_p->flags & IP_PREFIX_V4)
208 stream_put_ipv4(s,
209 attr->extra->evpn_overlay.gw_ip.ipv4.
210 s_addr);
211 else
212 stream_put(s, &(attr->extra->evpn_overlay.gw_ip.ipv6),
213 16);
214 } else {
215 if (p_evpn_p->flags & IP_PREFIX_V4)
216 stream_put_ipv4(s, 0);
217 else
218 stream_put(s, &temp, 16);
219 }
220 if (label)
221 stream_put(s, label, 3);
222 else
223 stream_put3(s, 0);
224 return;
b18825eb 225}