1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2016 6WIND
4 * This file is part of FRRouting.
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
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.
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
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"
39 bgp_nlri_parse_evpn(struct peer
*peer
, struct attr
*attr
,
40 struct bgp_nlri
*packet
, int withdraw
)
46 struct evpn_addr
*p_evpn_p
;
47 struct bgp_route_evpn evpn
;
48 uint8_t route_type
, route_length
;
50 u_int32_t addpath_id
= 0;
52 /* Check peer status. */
53 if (peer
->status
!= Established
)
57 prd
.family
= AF_UNSPEC
;
60 p_evpn_p
= &p
.u
.prefix_evpn
;
62 lim
= pnt
+ packet
->length
;
64 /* clear evpn structure */
65 memset(&evpn
, 0, sizeof(evpn
));
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
));
72 /* Fetch Route Type */
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
) {
79 ("not enough bytes for New Route Type left in NLRI?");
88 zlog_err("not enough bytes for RD left in NLRI?");
92 /* Copy routing distinguisher to rd. */
93 memcpy(&prd
.val
, pnt
, 8);
98 zlog_err("not enough bytes for ESI left in NLRI?");
101 memcpy(&evpn
.eth_s_id
.val
, pnt
, 10);
104 /* Fetch Ethernet Tag */
106 zlog_err("not enough bytes for Eth Tag left in NLRI?");
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
);
116 /* Fetch IP prefix length. */
117 p_evpn_p
->ip_prefix_length
= *pnt
++;
119 if (p_evpn_p
->ip_prefix_length
> 128) {
120 zlog_err("invalid prefixlen %d in EVPN NLRI?",
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
;
128 memcpy(&(p_evpn_p
->ip
.v6_addr
), pnt
, 16);
130 memcpy(&evpn
.gw_ip
.ipv6
, pnt
, 16);
133 p_evpn_p
->flags
= IP_PREFIX_V4
;
134 memcpy(&(p_evpn_p
->ip
.v4_addr
), pnt
, 4);
136 memcpy(&evpn
.gw_ip
.ipv4
, pnt
, 4);
139 p
.family
= AFI_L2VPN
;
140 if (p_evpn_p
->flags
== IP_PREFIX_V4
)
142 (u_char
) PREFIX_LEN_ROUTE_TYPE_5_IPV4
;
144 p
.prefixlen
= PREFIX_LEN_ROUTE_TYPE_5_IPV6
;
145 p
.family
= AF_ETHERNET
;
150 zlog_err("not enough bytes for Label left in NLRI?");
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
);
162 bgp_withdraw(peer
, &p
, addpath_id
, attr
, AFI_L2VPN
,
163 SAFI_EVPN
, ZEBRA_ROUTE_BGP
,
164 BGP_ROUTE_NORMAL
, &prd
, pnt_label
, &evpn
);
168 /* Packet length consistency check. */
175 bgp_packet_mpattr_route_type_5(struct stream
*s
,
176 struct prefix
*p
, struct prefix_rd
*prd
,
177 u_char
* label
, struct attr
*attr
)
181 struct evpn_addr
*p_evpn_p
;
183 memset(&temp
, 0, 16);
184 if (p
->family
!= AF_ETHERNET
)
186 p_evpn_p
= &(p
->u
.prefix_evpn
);
187 if (p_evpn_p
->flags
& IP_PREFIX_V4
)
191 stream_putc(s
, EVPN_IP_PREFIX
);
193 8 /* RD */ + 10 /* ESI */ + 4 /* EthTag */ + 1 + len
+
195 stream_put(s
, prd
->val
, 8);
196 if (attr
&& attr
->extra
)
197 stream_put(s
, &(attr
->extra
->evpn_overlay
.eth_s_id
), 10);
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
);
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
)
209 attr
->extra
->evpn_overlay
.gw_ip
.ipv4
.
212 stream_put(s
, &(attr
->extra
->evpn_overlay
.gw_ip
.ipv6
),
215 if (p_evpn_p
->flags
& IP_PREFIX_V4
)
216 stream_put_ipv4(s
, 0);
218 stream_put(s
, &temp
, 16);
221 stream_put(s
, label
, 3);