]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_evpn.c
debianpkg: Add Debian 9 Package support
[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
ac4d0be5 38int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
39 struct bgp_nlri *packet, int withdraw)
7ef5a232 40{
4d0e6ece
PG
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) {
ac4d0be5 77 zlog_err(
78 "not enough bytes for New Route Type left in NLRI?");
4d0e6ece
PG
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 */
ac4d0be5 124 if (route_length - 4 - 10 - 8 - 3 /* label to be read */
125 >= 32) {
4d0e6ece 126 p_evpn_p->flags = IP_PREFIX_V6;
daf9ddbb 127 memcpy(&(p_evpn_p->ip.v6_addr), pnt, 16);
4d0e6ece
PG
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 =
ac4d0be5 141 (u_char)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
4d0e6ece
PG
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 }
7ef5a232
PG
165 }
166
4d0e6ece
PG
167 /* Packet length consistency check. */
168 if (pnt != lim)
169 return -1;
170 return 0;
7ef5a232 171}
b18825eb 172
ac4d0be5 173void bgp_packet_mpattr_route_type_5(struct stream *s, struct prefix *p,
174 struct prefix_rd *prd, u_char *label,
175 struct attr *attr)
b18825eb 176{
4d0e6ece
PG
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)
ac4d0be5 186 len = 8; /* ipv4 */
4d0e6ece 187 else
ac4d0be5 188 len = 32; /* ipv6 */
4d0e6ece
PG
189 stream_putc(s, EVPN_IP_PREFIX);
190 stream_putc(s,
ac4d0be5 191 8 /* RD */ + 10 /* ESI */ + 4 /* EthTag */ + 1 + len
192 + 3 /* label */);
4d0e6ece
PG
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)
ac4d0be5 206 stream_put_ipv4(
207 s, attr->extra->evpn_overlay.gw_ip.ipv4.s_addr);
4d0e6ece
PG
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;
b18825eb 222}