]> git.proxmox.com Git - mirror_ovs.git/blob - lib/netdev-native-tnl.c
ofp-actions: Fix userspace support for mpls_ttl.
[mirror_ovs.git] / lib / netdev-native-tnl.c
1 /*
2 * Copyright (c) 2016 Nicira, Inc.
3 * Copyright (c) 2016 Red Hat, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <config.h>
19
20 #include "netdev-native-tnl.h"
21
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <sys/socket.h>
25 #include <net/if.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include <netinet/ip.h>
29 #include <netinet/ip6.h>
30 #include <sys/ioctl.h>
31
32 #include <stdlib.h>
33 #include <sys/time.h>
34
35 #include "byte-order.h"
36 #include "csum.h"
37 #include "dp-packet.h"
38 #include "netdev.h"
39 #include "netdev-vport.h"
40 #include "netdev-vport-private.h"
41 #include "odp-netlink.h"
42 #include "packets.h"
43 #include "seq.h"
44 #include "unaligned.h"
45 #include "unixctl.h"
46 #include "openvswitch/vlog.h"
47
48 VLOG_DEFINE_THIS_MODULE(native_tnl);
49 static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(60, 5);
50
51 #define VXLAN_HLEN (sizeof(struct udp_header) + \
52 sizeof(struct vxlanhdr))
53
54 #define GENEVE_BASE_HLEN (sizeof(struct udp_header) + \
55 sizeof(struct genevehdr))
56
57 #define GTPU_HLEN (sizeof(struct udp_header) + \
58 sizeof(struct gtpuhdr))
59
60 uint16_t tnl_udp_port_min = 32768;
61 uint16_t tnl_udp_port_max = 61000;
62
63 void *
64 netdev_tnl_ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl,
65 unsigned int *hlen)
66 {
67 void *nh;
68 struct ip_header *ip;
69 struct ovs_16aligned_ip6_hdr *ip6;
70 void *l4;
71 int l3_size;
72
73 nh = dp_packet_l3(packet);
74 ip = nh;
75 ip6 = nh;
76 l4 = dp_packet_l4(packet);
77
78 if (!nh || !l4) {
79 return NULL;
80 }
81
82 *hlen = sizeof(struct eth_header);
83
84 l3_size = dp_packet_size(packet) -
85 ((char *)nh - (char *)dp_packet_data(packet));
86
87 if (IP_VER(ip->ip_ihl_ver) == 4) {
88
89 ovs_be32 ip_src, ip_dst;
90
91 if (OVS_UNLIKELY(!dp_packet_ip_checksum_valid(packet))) {
92 if (csum(ip, IP_IHL(ip->ip_ihl_ver) * 4)) {
93 VLOG_WARN_RL(&err_rl, "ip packet has invalid checksum");
94 return NULL;
95 }
96 }
97
98 if (ntohs(ip->ip_tot_len) > l3_size) {
99 VLOG_WARN_RL(&err_rl, "ip packet is truncated (IP length %d, actual %d)",
100 ntohs(ip->ip_tot_len), l3_size);
101 return NULL;
102 }
103 if (IP_IHL(ip->ip_ihl_ver) * 4 > sizeof(struct ip_header)) {
104 VLOG_WARN_RL(&err_rl, "ip options not supported on tunnel packets "
105 "(%d bytes)", IP_IHL(ip->ip_ihl_ver) * 4);
106 return NULL;
107 }
108
109 ip_src = get_16aligned_be32(&ip->ip_src);
110 ip_dst = get_16aligned_be32(&ip->ip_dst);
111
112 tnl->ip_src = ip_src;
113 tnl->ip_dst = ip_dst;
114 tnl->ip_tos = ip->ip_tos;
115 tnl->ip_ttl = ip->ip_ttl;
116
117 *hlen += IP_HEADER_LEN;
118
119 } else if (IP_VER(ip->ip_ihl_ver) == 6) {
120 ovs_be32 tc_flow = get_16aligned_be32(&ip6->ip6_flow);
121
122 memcpy(tnl->ipv6_src.s6_addr, ip6->ip6_src.be16, sizeof ip6->ip6_src);
123 memcpy(tnl->ipv6_dst.s6_addr, ip6->ip6_dst.be16, sizeof ip6->ip6_dst);
124
125 tnl->ip_tos = ntohl(tc_flow) >> 20;
126 tnl->ip_ttl = ip6->ip6_hlim;
127
128 *hlen += packet->l4_ofs - packet->l3_ofs;
129
130 } else {
131 VLOG_WARN_RL(&err_rl, "ipv4 packet has invalid version (%d)",
132 IP_VER(ip->ip_ihl_ver));
133 return NULL;
134 }
135
136 return l4;
137 }
138
139 /* Pushes the 'size' bytes of 'header' into the headroom of 'packet',
140 * reallocating the packet if necessary. 'header' should contain an Ethernet
141 * header, followed by an IPv4 header (without options), and an L4 header.
142 *
143 * This function sets the IP header's ip_tot_len field (which should be zeroed
144 * as part of 'header') and puts its value into '*ip_tot_size' as well. Also
145 * updates IP header checksum, as well as the l3 and l4 offsets in 'packet'.
146 *
147 * Return pointer to the L4 header added to 'packet'. */
148 void *
149 netdev_tnl_push_ip_header(struct dp_packet *packet,
150 const void *header, int size, int *ip_tot_size)
151 {
152 struct eth_header *eth;
153 struct ip_header *ip;
154 struct ovs_16aligned_ip6_hdr *ip6;
155
156 eth = dp_packet_push_uninit(packet, size);
157 *ip_tot_size = dp_packet_size(packet) - sizeof (struct eth_header);
158
159 memcpy(eth, header, size);
160 /* The encapsulated packet has type Ethernet. Adjust dp_packet. */
161 packet->packet_type = htonl(PT_ETH);
162 dp_packet_reset_offsets(packet);
163 packet->l3_ofs = sizeof (struct eth_header);
164
165 if (netdev_tnl_is_header_ipv6(header)) {
166 ip6 = netdev_tnl_ipv6_hdr(eth);
167 *ip_tot_size -= IPV6_HEADER_LEN;
168 ip6->ip6_plen = htons(*ip_tot_size);
169 packet->l4_ofs = dp_packet_size(packet) - *ip_tot_size;
170 return ip6 + 1;
171 } else {
172 ip = netdev_tnl_ip_hdr(eth);
173 ip->ip_tot_len = htons(*ip_tot_size);
174 ip->ip_csum = recalc_csum16(ip->ip_csum, 0, ip->ip_tot_len);
175 *ip_tot_size -= IP_HEADER_LEN;
176 packet->l4_ofs = dp_packet_size(packet) - *ip_tot_size;
177 return ip + 1;
178 }
179 }
180
181 static void *
182 udp_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl,
183 unsigned int *hlen)
184 {
185 struct udp_header *udp;
186
187 udp = netdev_tnl_ip_extract_tnl_md(packet, tnl, hlen);
188 if (!udp) {
189 return NULL;
190 }
191
192 if (udp->udp_csum) {
193 if (OVS_UNLIKELY(!dp_packet_l4_checksum_valid(packet))) {
194 uint32_t csum;
195 if (netdev_tnl_is_header_ipv6(dp_packet_data(packet))) {
196 csum = packet_csum_pseudoheader6(dp_packet_l3(packet));
197 } else {
198 csum = packet_csum_pseudoheader(dp_packet_l3(packet));
199 }
200
201 csum = csum_continue(csum, udp, dp_packet_size(packet) -
202 ((const unsigned char *)udp -
203 (const unsigned char *)dp_packet_eth(packet)
204 ));
205 if (csum_finish(csum)) {
206 return NULL;
207 }
208 }
209 tnl->flags |= FLOW_TNL_F_CSUM;
210 }
211
212 tnl->tp_src = udp->udp_src;
213 tnl->tp_dst = udp->udp_dst;
214
215 return udp + 1;
216 }
217
218 static void
219 netdev_tnl_calc_udp_csum(struct udp_header *udp, struct dp_packet *packet,
220 int ip_tot_size)
221 {
222 uint32_t csum;
223
224 if (netdev_tnl_is_header_ipv6(dp_packet_data(packet))) {
225 csum = packet_csum_pseudoheader6(netdev_tnl_ipv6_hdr(
226 dp_packet_data(packet)));
227 } else {
228 csum = packet_csum_pseudoheader(netdev_tnl_ip_hdr(
229 dp_packet_data(packet)));
230 }
231
232 csum = csum_continue(csum, udp, ip_tot_size);
233 udp->udp_csum = csum_finish(csum);
234
235 if (!udp->udp_csum) {
236 udp->udp_csum = htons(0xffff);
237 }
238 }
239
240 void
241 netdev_tnl_push_udp_header(const struct netdev *netdev OVS_UNUSED,
242 struct dp_packet *packet,
243 const struct ovs_action_push_tnl *data)
244 {
245 struct udp_header *udp;
246 int ip_tot_size;
247
248 udp = netdev_tnl_push_ip_header(packet, data->header, data->header_len, &ip_tot_size);
249
250 /* set udp src port */
251 udp->udp_src = netdev_tnl_get_src_port(packet);
252 udp->udp_len = htons(ip_tot_size);
253
254 if (udp->udp_csum) {
255 netdev_tnl_calc_udp_csum(udp, packet, ip_tot_size);
256 }
257 }
258
259 static void *
260 eth_build_header(struct ovs_action_push_tnl *data,
261 const struct netdev_tnl_build_header_params *params)
262 {
263 uint16_t eth_proto = params->is_ipv6 ? ETH_TYPE_IPV6 : ETH_TYPE_IP;
264 struct eth_header *eth;
265
266 memset(data->header, 0, sizeof data->header);
267
268 eth = (struct eth_header *)data->header;
269 eth->eth_dst = params->dmac;
270 eth->eth_src = params->smac;
271 eth->eth_type = htons(eth_proto);
272 data->header_len = sizeof(struct eth_header);
273 return eth + 1;
274 }
275
276 void *
277 netdev_tnl_ip_build_header(struct ovs_action_push_tnl *data,
278 const struct netdev_tnl_build_header_params *params,
279 uint8_t next_proto)
280 {
281 void *l3;
282
283 l3 = eth_build_header(data, params);
284 if (!params->is_ipv6) {
285 ovs_be32 ip_src = in6_addr_get_mapped_ipv4(params->s_ip);
286 struct ip_header *ip;
287
288 ip = (struct ip_header *) l3;
289
290 ip->ip_ihl_ver = IP_IHL_VER(5, 4);
291 ip->ip_tos = params->flow->tunnel.ip_tos;
292 ip->ip_ttl = params->flow->tunnel.ip_ttl;
293 ip->ip_proto = next_proto;
294 put_16aligned_be32(&ip->ip_src, ip_src);
295 put_16aligned_be32(&ip->ip_dst, params->flow->tunnel.ip_dst);
296
297 ip->ip_frag_off = (params->flow->tunnel.flags & FLOW_TNL_F_DONT_FRAGMENT) ?
298 htons(IP_DF) : 0;
299
300 /* Checksum has already been zeroed by eth_build_header. */
301 ip->ip_csum = csum(ip, sizeof *ip);
302
303 data->header_len += IP_HEADER_LEN;
304 return ip + 1;
305 } else {
306 struct ovs_16aligned_ip6_hdr *ip6;
307
308 ip6 = (struct ovs_16aligned_ip6_hdr *) l3;
309
310 put_16aligned_be32(&ip6->ip6_flow, htonl(6 << 28) |
311 htonl(params->flow->tunnel.ip_tos << 20));
312 ip6->ip6_hlim = params->flow->tunnel.ip_ttl;
313 ip6->ip6_nxt = next_proto;
314 memcpy(&ip6->ip6_src, params->s_ip, sizeof(ovs_be32[4]));
315 memcpy(&ip6->ip6_dst, &params->flow->tunnel.ipv6_dst, sizeof(ovs_be32[4]));
316
317 data->header_len += IPV6_HEADER_LEN;
318 return ip6 + 1;
319 }
320 }
321
322 static void *
323 udp_build_header(struct netdev_tunnel_config *tnl_cfg,
324 struct ovs_action_push_tnl *data,
325 const struct netdev_tnl_build_header_params *params)
326 {
327 struct udp_header *udp;
328
329 udp = netdev_tnl_ip_build_header(data, params, IPPROTO_UDP);
330 udp->udp_dst = tnl_cfg->dst_port;
331
332 if (params->is_ipv6 || params->flow->tunnel.flags & FLOW_TNL_F_CSUM) {
333 /* Write a value in now to mark that we should compute the checksum
334 * later. 0xffff is handy because it is transparent to the
335 * calculation. */
336 udp->udp_csum = htons(0xffff);
337 }
338 data->header_len += sizeof *udp;
339 return udp + 1;
340 }
341
342 static int
343 gre_header_len(ovs_be16 flags)
344 {
345 int hlen = 4;
346
347 if (flags & htons(GRE_CSUM)) {
348 hlen += 4;
349 }
350 if (flags & htons(GRE_KEY)) {
351 hlen += 4;
352 }
353 if (flags & htons(GRE_SEQ)) {
354 hlen += 4;
355 }
356 return hlen;
357 }
358
359 static int
360 parse_gre_header(struct dp_packet *packet,
361 struct flow_tnl *tnl)
362 {
363 const struct gre_base_hdr *greh;
364 ovs_16aligned_be32 *options;
365 int hlen;
366 unsigned int ulen;
367 uint16_t greh_protocol;
368
369 greh = netdev_tnl_ip_extract_tnl_md(packet, tnl, &ulen);
370 if (!greh) {
371 return -EINVAL;
372 }
373
374 if (greh->flags & ~(htons(GRE_CSUM | GRE_KEY | GRE_SEQ))) {
375 return -EINVAL;
376 }
377
378 hlen = ulen + gre_header_len(greh->flags);
379 if (hlen > dp_packet_size(packet)) {
380 return -EINVAL;
381 }
382
383 options = (ovs_16aligned_be32 *)(greh + 1);
384 if (greh->flags & htons(GRE_CSUM)) {
385 ovs_be16 pkt_csum;
386
387 pkt_csum = csum(greh, dp_packet_size(packet) -
388 ((const unsigned char *)greh -
389 (const unsigned char *)dp_packet_eth(packet)));
390 if (pkt_csum) {
391 return -EINVAL;
392 }
393 tnl->flags = FLOW_TNL_F_CSUM;
394 options++;
395 }
396
397 if (greh->flags & htons(GRE_KEY)) {
398 tnl->tun_id = be32_to_be64(get_16aligned_be32(options));
399 tnl->flags |= FLOW_TNL_F_KEY;
400 options++;
401 }
402
403 if (greh->flags & htons(GRE_SEQ)) {
404 options++;
405 }
406
407 /* Set the new packet type depending on the GRE protocol field. */
408 greh_protocol = ntohs(greh->protocol);
409 if (greh_protocol == ETH_TYPE_TEB) {
410 packet->packet_type = htonl(PT_ETH);
411 } else if (greh_protocol >= ETH_TYPE_MIN) {
412 /* Allow all GRE protocol values above 0x5ff as Ethertypes. */
413 packet->packet_type = PACKET_TYPE_BE(OFPHTN_ETHERTYPE, greh_protocol);
414 } else {
415 return -EINVAL;
416 }
417
418 return hlen;
419 }
420
421 struct dp_packet *
422 netdev_gre_pop_header(struct dp_packet *packet)
423 {
424 struct pkt_metadata *md = &packet->md;
425 struct flow_tnl *tnl = &md->tunnel;
426 int hlen = sizeof(struct eth_header) + 4;
427
428 hlen += netdev_tnl_is_header_ipv6(dp_packet_data(packet)) ?
429 IPV6_HEADER_LEN : IP_HEADER_LEN;
430
431 pkt_metadata_init_tnl(md);
432 if (hlen > dp_packet_size(packet)) {
433 goto err;
434 }
435
436 hlen = parse_gre_header(packet, tnl);
437 if (hlen < 0) {
438 goto err;
439 }
440
441 dp_packet_reset_packet(packet, hlen);
442
443 return packet;
444 err:
445 dp_packet_delete(packet);
446 return NULL;
447 }
448
449 void
450 netdev_gre_push_header(const struct netdev *netdev,
451 struct dp_packet *packet,
452 const struct ovs_action_push_tnl *data)
453 {
454 struct netdev_vport *dev = netdev_vport_cast(netdev);
455 struct netdev_tunnel_config *tnl_cfg;
456 struct gre_base_hdr *greh;
457 int ip_tot_size;
458
459 greh = netdev_tnl_push_ip_header(packet, data->header, data->header_len, &ip_tot_size);
460
461 if (greh->flags & htons(GRE_CSUM)) {
462 ovs_be16 *csum_opt = (ovs_be16 *) (greh + 1);
463 *csum_opt = csum(greh, ip_tot_size);
464 }
465
466 if (greh->flags & htons(GRE_SEQ)) {
467 /* Last 4 byte is GRE seqno */
468 int seq_ofs = gre_header_len(greh->flags) - 4;
469 ovs_16aligned_be32 *seq_opt =
470 ALIGNED_CAST(ovs_16aligned_be32 *, (char *)greh + seq_ofs);
471 tnl_cfg = &dev->tnl_cfg;
472 put_16aligned_be32(seq_opt, htonl(tnl_cfg->seqno++));
473 }
474 }
475
476 int
477 netdev_gre_build_header(const struct netdev *netdev,
478 struct ovs_action_push_tnl *data,
479 const struct netdev_tnl_build_header_params *params)
480 {
481 struct netdev_vport *dev = netdev_vport_cast(netdev);
482 struct netdev_tunnel_config *tnl_cfg;
483 struct gre_base_hdr *greh;
484 ovs_16aligned_be32 *options;
485 unsigned int hlen;
486
487 /* XXX: RCUfy tnl_cfg. */
488 ovs_mutex_lock(&dev->mutex);
489 tnl_cfg = &dev->tnl_cfg;
490
491 greh = netdev_tnl_ip_build_header(data, params, IPPROTO_GRE);
492
493 if (params->flow->packet_type == htonl(PT_ETH)) {
494 greh->protocol = htons(ETH_TYPE_TEB);
495 } else if (pt_ns(params->flow->packet_type) == OFPHTN_ETHERTYPE) {
496 greh->protocol = pt_ns_type_be(params->flow->packet_type);
497 } else {
498 ovs_mutex_unlock(&dev->mutex);
499 return 1;
500 }
501 greh->flags = 0;
502
503 options = (ovs_16aligned_be32 *) (greh + 1);
504 if (params->flow->tunnel.flags & FLOW_TNL_F_CSUM) {
505 greh->flags |= htons(GRE_CSUM);
506 put_16aligned_be32(options, 0);
507 options++;
508 }
509
510 if (tnl_cfg->out_key_present) {
511 greh->flags |= htons(GRE_KEY);
512 put_16aligned_be32(options, be64_to_be32(params->flow->tunnel.tun_id));
513 options++;
514 }
515
516 if (tnl_cfg->set_seq) {
517 greh->flags |= htons(GRE_SEQ);
518 /* seqno is updated at push header */
519 options++;
520 }
521
522 ovs_mutex_unlock(&dev->mutex);
523
524 hlen = (uint8_t *) options - (uint8_t *) greh;
525
526 data->header_len += hlen;
527 if (!params->is_ipv6) {
528 data->tnl_type = OVS_VPORT_TYPE_GRE;
529 } else {
530 data->tnl_type = OVS_VPORT_TYPE_IP6GRE;
531 }
532 return 0;
533 }
534
535 struct dp_packet *
536 netdev_erspan_pop_header(struct dp_packet *packet)
537 {
538 const struct gre_base_hdr *greh;
539 const struct erspan_base_hdr *ersh;
540 struct pkt_metadata *md = &packet->md;
541 struct flow_tnl *tnl = &md->tunnel;
542 int hlen = sizeof(struct eth_header);
543 unsigned int ulen;
544 uint16_t greh_protocol;
545
546 hlen += netdev_tnl_is_header_ipv6(dp_packet_data(packet)) ?
547 IPV6_HEADER_LEN : IP_HEADER_LEN;
548
549 pkt_metadata_init_tnl(md);
550 if (hlen > dp_packet_size(packet)) {
551 goto err;
552 }
553
554 greh = netdev_tnl_ip_extract_tnl_md(packet, tnl, &ulen);
555 if (!greh) {
556 goto err;
557 }
558
559 greh_protocol = ntohs(greh->protocol);
560 if (greh_protocol != ETH_TYPE_ERSPAN1 &&
561 greh_protocol != ETH_TYPE_ERSPAN2) {
562 goto err;
563 }
564
565 if (greh->flags & ~htons(GRE_SEQ)) {
566 goto err;
567 }
568
569 ersh = ERSPAN_HDR(greh);
570 tnl->tun_id = be16_to_be64(htons(get_sid(ersh)));
571 tnl->erspan_ver = ersh->ver;
572
573 if (ersh->ver == 1) {
574 ovs_16aligned_be32 *index = ALIGNED_CAST(ovs_16aligned_be32 *,
575 ersh + 1);
576 tnl->erspan_idx = ntohl(get_16aligned_be32(index));
577 tnl->flags |= FLOW_TNL_F_KEY;
578 hlen = ulen + ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE;
579 } else if (ersh->ver == 2) {
580 struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
581 tnl->erspan_dir = md2->dir;
582 tnl->erspan_hwid = get_hwid(md2);
583 tnl->flags |= FLOW_TNL_F_KEY;
584 hlen = ulen + ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V2_MDSIZE;
585 } else {
586 VLOG_WARN_RL(&err_rl, "ERSPAN version error %d", ersh->ver);
587 goto err;
588 }
589
590 if (hlen > dp_packet_size(packet)) {
591 goto err;
592 }
593
594 dp_packet_reset_packet(packet, hlen);
595
596 return packet;
597 err:
598 dp_packet_delete(packet);
599 return NULL;
600 }
601
602 void
603 netdev_erspan_push_header(const struct netdev *netdev,
604 struct dp_packet *packet,
605 const struct ovs_action_push_tnl *data)
606 {
607 struct netdev_vport *dev = netdev_vport_cast(netdev);
608 struct netdev_tunnel_config *tnl_cfg;
609 struct erspan_base_hdr *ersh;
610 struct gre_base_hdr *greh;
611 struct erspan_md2 *md2;
612 int ip_tot_size;
613
614 greh = netdev_tnl_push_ip_header(packet, data->header,
615 data->header_len, &ip_tot_size);
616
617 /* update GRE seqno */
618 tnl_cfg = &dev->tnl_cfg;
619 ovs_16aligned_be32 *seqno = (ovs_16aligned_be32 *) (greh + 1);
620 put_16aligned_be32(seqno, htonl(tnl_cfg->seqno++));
621
622 /* update v2 timestamp */
623 if (greh->protocol == htons(ETH_TYPE_ERSPAN2)) {
624 ersh = ERSPAN_HDR(greh);
625 md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
626 put_16aligned_be32(&md2->timestamp, get_erspan_ts(ERSPAN_100US));
627 }
628 }
629
630 int
631 netdev_erspan_build_header(const struct netdev *netdev,
632 struct ovs_action_push_tnl *data,
633 const struct netdev_tnl_build_header_params *params)
634 {
635 struct netdev_vport *dev = netdev_vport_cast(netdev);
636 struct netdev_tunnel_config *tnl_cfg;
637 struct gre_base_hdr *greh;
638 struct erspan_base_hdr *ersh;
639 unsigned int hlen;
640 uint32_t tun_id;
641 int erspan_ver;
642 uint16_t sid;
643
644 /* XXX: RCUfy tnl_cfg. */
645 ovs_mutex_lock(&dev->mutex);
646 tnl_cfg = &dev->tnl_cfg;
647 greh = netdev_tnl_ip_build_header(data, params, IPPROTO_GRE);
648 ersh = ERSPAN_HDR(greh);
649
650 tun_id = ntohl(be64_to_be32(params->flow->tunnel.tun_id));
651 /* ERSPAN only has 10-bit session ID */
652 if (tun_id & ~ERSPAN_SID_MASK) {
653 ovs_mutex_unlock(&dev->mutex);
654 return 1;
655 } else {
656 sid = (uint16_t) tun_id;
657 }
658
659 if (tnl_cfg->erspan_ver_flow) {
660 erspan_ver = params->flow->tunnel.erspan_ver;
661 } else {
662 erspan_ver = tnl_cfg->erspan_ver;
663 }
664
665 if (erspan_ver == 1) {
666 greh->protocol = htons(ETH_TYPE_ERSPAN1);
667 greh->flags = htons(GRE_SEQ);
668 ersh->ver = 1;
669 set_sid(ersh, sid);
670
671 uint32_t erspan_idx = (tnl_cfg->erspan_idx_flow
672 ? params->flow->tunnel.erspan_idx
673 : tnl_cfg->erspan_idx);
674 put_16aligned_be32(ALIGNED_CAST(ovs_16aligned_be32 *, ersh + 1),
675 htonl(erspan_idx));
676
677 hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE;
678 } else if (erspan_ver == 2) {
679 struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
680
681 greh->protocol = htons(ETH_TYPE_ERSPAN2);
682 greh->flags = htons(GRE_SEQ);
683 ersh->ver = 2;
684 set_sid(ersh, sid);
685
686 md2->sgt = 0; /* security group tag */
687 md2->gra = 0;
688 put_16aligned_be32(&md2->timestamp, 0);
689
690 if (tnl_cfg->erspan_hwid_flow) {
691 set_hwid(md2, params->flow->tunnel.erspan_hwid);
692 } else {
693 set_hwid(md2, tnl_cfg->erspan_hwid);
694 }
695
696 if (tnl_cfg->erspan_dir_flow) {
697 md2->dir = params->flow->tunnel.erspan_dir;
698 } else {
699 md2->dir = tnl_cfg->erspan_dir;
700 }
701
702 hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V2_MDSIZE;
703 } else {
704 VLOG_WARN_RL(&err_rl, "ERSPAN version error %d", tnl_cfg->erspan_ver);
705 ovs_mutex_unlock(&dev->mutex);
706 return 1;
707 }
708
709 ovs_mutex_unlock(&dev->mutex);
710
711 data->header_len += hlen;
712
713 if (params->is_ipv6) {
714 data->tnl_type = OVS_VPORT_TYPE_IP6ERSPAN;
715 } else {
716 data->tnl_type = OVS_VPORT_TYPE_ERSPAN;
717 }
718 return 0;
719 }
720
721 struct dp_packet *
722 netdev_gtpu_pop_header(struct dp_packet *packet)
723 {
724 struct pkt_metadata *md = &packet->md;
725 struct flow_tnl *tnl = &md->tunnel;
726 struct gtpuhdr *gtph;
727 unsigned int gtpu_hlen;
728 unsigned int hlen;
729
730 ovs_assert(packet->l3_ofs > 0);
731 ovs_assert(packet->l4_ofs > 0);
732
733 pkt_metadata_init_tnl(md);
734 if (GTPU_HLEN > dp_packet_l4_size(packet)) {
735 goto err;
736 }
737
738 gtph = udp_extract_tnl_md(packet, tnl, &hlen);
739 if (!gtph) {
740 goto err;
741 }
742
743 tnl->gtpu_flags = gtph->md.flags;
744 tnl->gtpu_msgtype = gtph->md.msgtype;
745 tnl->tun_id = be32_to_be64(get_16aligned_be32(&gtph->teid));
746
747 if (tnl->gtpu_msgtype == GTPU_MSGTYPE_GPDU) {
748 struct ip_header *ip;
749
750 if (gtph->md.flags & GTPU_S_MASK) {
751 gtpu_hlen = GTPU_HLEN + sizeof(struct gtpuhdr_opt);
752 } else {
753 gtpu_hlen = GTPU_HLEN;
754 }
755 ip = ALIGNED_CAST(struct ip_header *, (char *)gtph + gtpu_hlen);
756
757 if (IP_VER(ip->ip_ihl_ver) == 4) {
758 packet->packet_type = htonl(PT_IPV4);
759 } else if (IP_VER(ip->ip_ihl_ver) == 6) {
760 packet->packet_type = htonl(PT_IPV6);
761 } else {
762 VLOG_WARN_RL(&err_rl, "GTP-U: Receive non-IP packet.");
763 }
764 dp_packet_reset_packet(packet, hlen + gtpu_hlen);
765 } else {
766 /* non-GPDU GTP-U messages, ex: echo request, end marker.
767 * Users should redirect these packets to controller, or.
768 * any application that handles GTP-U messages, so keep
769 * the original packet.
770 */
771 packet->packet_type = htonl(PT_ETH);
772 VLOG_WARN_ONCE("Receive non-GPDU msgtype: %"PRIu8,
773 gtph->md.msgtype);
774 }
775
776 return packet;
777
778 err:
779 dp_packet_delete(packet);
780 return NULL;
781 }
782
783 void
784 netdev_gtpu_push_header(const struct netdev *netdev,
785 struct dp_packet *packet,
786 const struct ovs_action_push_tnl *data)
787 {
788 struct netdev_vport *dev = netdev_vport_cast(netdev);
789 struct netdev_tunnel_config *tnl_cfg;
790 struct udp_header *udp;
791 struct gtpuhdr *gtpuh;
792 int ip_tot_size;
793 unsigned int payload_len;
794
795 payload_len = dp_packet_size(packet);
796 udp = netdev_tnl_push_ip_header(packet, data->header,
797 data->header_len, &ip_tot_size);
798 udp->udp_src = netdev_tnl_get_src_port(packet);
799 udp->udp_len = htons(ip_tot_size);
800 netdev_tnl_calc_udp_csum(udp, packet, ip_tot_size);
801
802 gtpuh = ALIGNED_CAST(struct gtpuhdr *, udp + 1);
803
804 tnl_cfg = &dev->tnl_cfg;
805 if (tnl_cfg->set_seq) {
806 ovs_be16 *seqno = ALIGNED_CAST(ovs_be16 *, gtpuh + 1);
807 *seqno = htons(tnl_cfg->seqno++);
808 payload_len += sizeof(struct gtpuhdr_opt);
809 }
810 gtpuh->len = htons(payload_len);
811 }
812
813 int
814 netdev_gtpu_build_header(const struct netdev *netdev,
815 struct ovs_action_push_tnl *data,
816 const struct netdev_tnl_build_header_params *params)
817 {
818 struct netdev_vport *dev = netdev_vport_cast(netdev);
819 struct netdev_tunnel_config *tnl_cfg;
820 struct gtpuhdr *gtph;
821 unsigned int gtpu_hlen;
822
823 ovs_mutex_lock(&dev->mutex);
824 tnl_cfg = &dev->tnl_cfg;
825 gtph = udp_build_header(tnl_cfg, data, params);
826
827 /* Set to default if not set in flow. */
828 gtph->md.flags = params->flow->tunnel.gtpu_flags ?
829 params->flow->tunnel.gtpu_flags : GTPU_FLAGS_DEFAULT;
830 gtph->md.msgtype = params->flow->tunnel.gtpu_msgtype ?
831 params->flow->tunnel.gtpu_msgtype : GTPU_MSGTYPE_GPDU;
832 put_16aligned_be32(&gtph->teid,
833 be64_to_be32(params->flow->tunnel.tun_id));
834
835 gtpu_hlen = sizeof *gtph;
836 if (tnl_cfg->set_seq) {
837 gtph->md.flags |= GTPU_S_MASK;
838 gtpu_hlen += sizeof(struct gtpuhdr_opt);
839 }
840 ovs_mutex_unlock(&dev->mutex);
841
842 data->header_len += gtpu_hlen;
843 data->tnl_type = OVS_VPORT_TYPE_GTPU;
844
845 return 0;
846 }
847
848 struct dp_packet *
849 netdev_vxlan_pop_header(struct dp_packet *packet)
850 {
851 struct pkt_metadata *md = &packet->md;
852 struct flow_tnl *tnl = &md->tunnel;
853 struct vxlanhdr *vxh;
854 unsigned int hlen;
855 ovs_be32 vx_flags;
856 enum packet_type next_pt = PT_ETH;
857
858 ovs_assert(packet->l3_ofs > 0);
859 ovs_assert(packet->l4_ofs > 0);
860
861 pkt_metadata_init_tnl(md);
862 if (VXLAN_HLEN > dp_packet_l4_size(packet)) {
863 goto err;
864 }
865
866 vxh = udp_extract_tnl_md(packet, tnl, &hlen);
867 if (!vxh) {
868 goto err;
869 }
870
871 vx_flags = get_16aligned_be32(&vxh->vx_flags);
872 if (vx_flags & htonl(VXLAN_HF_GPE)) {
873 vx_flags &= htonl(~VXLAN_GPE_USED_BITS);
874 /* Drop the OAM packets */
875 if (vxh->vx_gpe.flags & VXLAN_GPE_FLAGS_O) {
876 goto err;
877 }
878 switch (vxh->vx_gpe.next_protocol) {
879 case VXLAN_GPE_NP_IPV4:
880 next_pt = PT_IPV4;
881 break;
882 case VXLAN_GPE_NP_IPV6:
883 next_pt = PT_IPV6;
884 break;
885 case VXLAN_GPE_NP_NSH:
886 next_pt = PT_NSH;
887 break;
888 case VXLAN_GPE_NP_ETHERNET:
889 next_pt = PT_ETH;
890 break;
891 default:
892 goto err;
893 }
894 }
895
896 if (vx_flags != htonl(VXLAN_FLAGS) ||
897 (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
898 VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
899 ntohl(vx_flags),
900 ntohl(get_16aligned_be32(&vxh->vx_vni)));
901 goto err;
902 }
903 tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
904 tnl->flags |= FLOW_TNL_F_KEY;
905
906 packet->packet_type = htonl(next_pt);
907 dp_packet_reset_packet(packet, hlen + VXLAN_HLEN);
908 if (next_pt != PT_ETH) {
909 packet->l3_ofs = 0;
910 }
911
912 return packet;
913 err:
914 dp_packet_delete(packet);
915 return NULL;
916 }
917
918 int
919 netdev_vxlan_build_header(const struct netdev *netdev,
920 struct ovs_action_push_tnl *data,
921 const struct netdev_tnl_build_header_params *params)
922 {
923 struct netdev_vport *dev = netdev_vport_cast(netdev);
924 struct netdev_tunnel_config *tnl_cfg;
925 struct vxlanhdr *vxh;
926
927 /* XXX: RCUfy tnl_cfg. */
928 ovs_mutex_lock(&dev->mutex);
929 tnl_cfg = &dev->tnl_cfg;
930
931 vxh = udp_build_header(tnl_cfg, data, params);
932
933 if (tnl_cfg->exts & (1 << OVS_VXLAN_EXT_GPE)) {
934 put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS | VXLAN_HF_GPE));
935 put_16aligned_be32(&vxh->vx_vni,
936 htonl(ntohll(params->flow->tunnel.tun_id) << 8));
937 if (params->flow->packet_type == htonl(PT_ETH)) {
938 vxh->vx_gpe.next_protocol = VXLAN_GPE_NP_ETHERNET;
939 } else if (pt_ns(params->flow->packet_type) == OFPHTN_ETHERTYPE) {
940 switch (pt_ns_type(params->flow->packet_type)) {
941 case ETH_TYPE_IP:
942 vxh->vx_gpe.next_protocol = VXLAN_GPE_NP_IPV4;
943 break;
944 case ETH_TYPE_IPV6:
945 vxh->vx_gpe.next_protocol = VXLAN_GPE_NP_IPV6;
946 break;
947 case ETH_TYPE_NSH:
948 vxh->vx_gpe.next_protocol = VXLAN_GPE_NP_NSH;
949 break;
950 case ETH_TYPE_TEB:
951 vxh->vx_gpe.next_protocol = VXLAN_GPE_NP_ETHERNET;
952 break;
953 default:
954 goto drop;
955 }
956 } else {
957 goto drop;
958 }
959 } else {
960 put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
961 put_16aligned_be32(&vxh->vx_vni,
962 htonl(ntohll(params->flow->tunnel.tun_id) << 8));
963 }
964
965 ovs_mutex_unlock(&dev->mutex);
966 data->header_len += sizeof *vxh;
967 data->tnl_type = OVS_VPORT_TYPE_VXLAN;
968 return 0;
969
970 drop:
971 ovs_mutex_unlock(&dev->mutex);
972 return 1;
973 }
974
975 struct dp_packet *
976 netdev_geneve_pop_header(struct dp_packet *packet)
977 {
978 struct pkt_metadata *md = &packet->md;
979 struct flow_tnl *tnl = &md->tunnel;
980 struct genevehdr *gnh;
981 unsigned int hlen, opts_len, ulen;
982
983 pkt_metadata_init_tnl(md);
984 if (GENEVE_BASE_HLEN > dp_packet_l4_size(packet)) {
985 VLOG_WARN_RL(&err_rl, "geneve packet too small: min header=%u packet size=%"PRIuSIZE"\n",
986 (unsigned int)GENEVE_BASE_HLEN, dp_packet_l4_size(packet));
987 goto err;
988 }
989
990 gnh = udp_extract_tnl_md(packet, tnl, &ulen);
991 if (!gnh) {
992 goto err;
993 }
994
995 opts_len = gnh->opt_len * 4;
996 hlen = ulen + GENEVE_BASE_HLEN + opts_len;
997 if (hlen > dp_packet_size(packet)) {
998 VLOG_WARN_RL(&err_rl, "geneve packet too small: header len=%u packet size=%u\n",
999 hlen, dp_packet_size(packet));
1000 goto err;
1001 }
1002
1003 if (gnh->ver != 0) {
1004 VLOG_WARN_RL(&err_rl, "unknown geneve version: %"PRIu8"\n", gnh->ver);
1005 goto err;
1006 }
1007
1008 if (gnh->proto_type != htons(ETH_TYPE_TEB)) {
1009 VLOG_WARN_RL(&err_rl, "unknown geneve encapsulated protocol: %#x\n",
1010 ntohs(gnh->proto_type));
1011 goto err;
1012 }
1013
1014 tnl->flags |= gnh->oam ? FLOW_TNL_F_OAM : 0;
1015 tnl->tun_id = htonll(ntohl(get_16aligned_be32(&gnh->vni)) >> 8);
1016 tnl->flags |= FLOW_TNL_F_KEY;
1017
1018 memcpy(tnl->metadata.opts.gnv, gnh->options, opts_len);
1019 tnl->metadata.present.len = opts_len;
1020 tnl->flags |= FLOW_TNL_F_UDPIF;
1021
1022 packet->packet_type = htonl(PT_ETH);
1023 dp_packet_reset_packet(packet, hlen);
1024
1025 return packet;
1026 err:
1027 dp_packet_delete(packet);
1028 return NULL;
1029 }
1030
1031 int
1032 netdev_geneve_build_header(const struct netdev *netdev,
1033 struct ovs_action_push_tnl *data,
1034 const struct netdev_tnl_build_header_params *params)
1035 {
1036 struct netdev_vport *dev = netdev_vport_cast(netdev);
1037 struct netdev_tunnel_config *tnl_cfg;
1038 struct genevehdr *gnh;
1039 int opt_len;
1040 bool crit_opt;
1041
1042 /* XXX: RCUfy tnl_cfg. */
1043 ovs_mutex_lock(&dev->mutex);
1044 tnl_cfg = &dev->tnl_cfg;
1045
1046 gnh = udp_build_header(tnl_cfg, data, params);
1047
1048 put_16aligned_be32(&gnh->vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
1049
1050 ovs_mutex_unlock(&dev->mutex);
1051
1052 opt_len = tun_metadata_to_geneve_header(&params->flow->tunnel,
1053 gnh->options, &crit_opt);
1054
1055 gnh->opt_len = opt_len / 4;
1056 gnh->oam = !!(params->flow->tunnel.flags & FLOW_TNL_F_OAM);
1057 gnh->critical = crit_opt ? 1 : 0;
1058 gnh->proto_type = htons(ETH_TYPE_TEB);
1059
1060 data->header_len += sizeof *gnh + opt_len;
1061 data->tnl_type = OVS_VPORT_TYPE_GENEVE;
1062 return 0;
1063 }
1064
1065 \f
1066 void
1067 netdev_tnl_egress_port_range(struct unixctl_conn *conn, int argc,
1068 const char *argv[], void *aux OVS_UNUSED)
1069 {
1070 int val1, val2;
1071
1072 if (argc < 3) {
1073 struct ds ds = DS_EMPTY_INITIALIZER;
1074
1075 ds_put_format(&ds, "Tunnel UDP source port range: %"PRIu16"-%"PRIu16"\n",
1076 tnl_udp_port_min, tnl_udp_port_max);
1077
1078 unixctl_command_reply(conn, ds_cstr(&ds));
1079 ds_destroy(&ds);
1080 return;
1081 }
1082
1083 if (argc != 3) {
1084 return;
1085 }
1086
1087 val1 = atoi(argv[1]);
1088 if (val1 <= 0 || val1 > UINT16_MAX) {
1089 unixctl_command_reply(conn, "Invalid min.");
1090 return;
1091 }
1092 val2 = atoi(argv[2]);
1093 if (val2 <= 0 || val2 > UINT16_MAX) {
1094 unixctl_command_reply(conn, "Invalid max.");
1095 return;
1096 }
1097
1098 if (val1 > val2) {
1099 tnl_udp_port_min = val2;
1100 tnl_udp_port_max = val1;
1101 } else {
1102 tnl_udp_port_min = val1;
1103 tnl_udp_port_max = val2;
1104 }
1105 seq_change(tnl_conf_seq);
1106
1107 unixctl_command_reply(conn, "OK");
1108 }