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
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
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"
38 int bgp_nlri_parse_evpn(struct peer
*peer
, struct attr
*attr
,
39 struct bgp_nlri
*packet
, int withdraw
)
45 struct evpn_addr
*p_evpn_p
;
46 struct bgp_route_evpn evpn
;
47 uint8_t route_type
, route_length
;
49 u_int32_t addpath_id
= 0;
51 /* Check peer status. */
52 if (peer
->status
!= Established
)
56 prd
.family
= AF_UNSPEC
;
59 p_evpn_p
= &p
.u
.prefix_evpn
;
61 lim
= pnt
+ packet
->length
;
63 /* clear evpn structure */
64 memset(&evpn
, 0, sizeof(evpn
));
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
));
71 /* Fetch Route Type */
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
) {
78 "not enough bytes for New Route Type left in NLRI?");
87 zlog_err("not enough bytes for RD left in NLRI?");
91 /* Copy routing distinguisher to rd. */
92 memcpy(&prd
.val
, pnt
, 8);
97 zlog_err("not enough bytes for ESI left in NLRI?");
100 memcpy(&evpn
.eth_s_id
.val
, pnt
, 10);
103 /* Fetch Ethernet Tag */
105 zlog_err("not enough bytes for Eth Tag left in NLRI?");
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
);
115 /* Fetch IP prefix length. */
116 p_evpn_p
->ip_prefix_length
= *pnt
++;
118 if (p_evpn_p
->ip_prefix_length
> 128) {
119 zlog_err("invalid prefixlen %d in EVPN NLRI?",
123 /* determine IPv4 or IPv6 prefix */
124 if (route_length
- 4 - 10 - 8 - 3 /* label to be read */
126 p_evpn_p
->flags
= IP_PREFIX_V6
;
127 memcpy(&(p_evpn_p
->ip
.v6_addr
), pnt
, 16);
129 memcpy(&evpn
.gw_ip
.ipv6
, pnt
, 16);
132 p_evpn_p
->flags
= IP_PREFIX_V4
;
133 memcpy(&(p_evpn_p
->ip
.v4_addr
), pnt
, 4);
135 memcpy(&evpn
.gw_ip
.ipv4
, pnt
, 4);
138 p
.family
= AFI_L2VPN
;
139 if (p_evpn_p
->flags
== IP_PREFIX_V4
)
141 (u_char
)PREFIX_LEN_ROUTE_TYPE_5_IPV4
;
143 p
.prefixlen
= PREFIX_LEN_ROUTE_TYPE_5_IPV6
;
144 p
.family
= AF_ETHERNET
;
149 zlog_err("not enough bytes for Label left in NLRI?");
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
);
161 bgp_withdraw(peer
, &p
, addpath_id
, attr
, AFI_L2VPN
,
162 SAFI_EVPN
, ZEBRA_ROUTE_BGP
,
163 BGP_ROUTE_NORMAL
, &prd
, pnt_label
, &evpn
);
167 /* Packet length consistency check. */
173 void bgp_packet_mpattr_route_type_5(struct stream
*s
, struct prefix
*p
,
174 struct prefix_rd
*prd
, u_char
*label
,
179 struct evpn_addr
*p_evpn_p
;
181 memset(&temp
, 0, 16);
182 if (p
->family
!= AF_ETHERNET
)
184 p_evpn_p
= &(p
->u
.prefix_evpn
);
185 if (p_evpn_p
->flags
& IP_PREFIX_V4
)
189 stream_putc(s
, EVPN_IP_PREFIX
);
191 8 /* RD */ + 10 /* ESI */ + 4 /* EthTag */ + 1 + len
193 stream_put(s
, prd
->val
, 8);
194 if (attr
&& attr
->extra
)
195 stream_put(s
, &(attr
->extra
->evpn_overlay
.eth_s_id
), 10);
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
);
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
)
207 s
, attr
->extra
->evpn_overlay
.gw_ip
.ipv4
.s_addr
);
209 stream_put(s
, &(attr
->extra
->evpn_overlay
.gw_ip
.ipv6
),
212 if (p_evpn_p
->flags
& IP_PREFIX_V4
)
213 stream_put_ipv4(s
, 0);
215 stream_put(s
, &temp
, 16);
218 stream_put(s
, label
, 3);