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