2 * Copyright (c) 2010, 2011, 2012, 2013, 2014, 2017 Nicira, Inc.
3 * Copyright (c) 2016 Red Hat, Inc.
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include "netdev-vport.h"
24 #include <sys/socket.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28 #include <netinet/ip6.h>
29 #include <sys/ioctl.h>
31 #include "byte-order.h"
36 #include "netdev-native-tnl.h"
37 #include "netdev-provider.h"
38 #include "netdev-vport-private.h"
39 #include "openvswitch/dynamic-string.h"
40 #include "ovs-router.h"
42 #include "openvswitch/poll-loop.h"
43 #include "route-table.h"
46 #include "socket-util.h"
47 #include "unaligned.h"
49 #include "openvswitch/vlog.h"
51 #include "netdev-linux.h"
54 VLOG_DEFINE_THIS_MODULE(netdev_vport
);
56 #define GENEVE_DST_PORT 6081
57 #define VXLAN_DST_PORT 4789
58 #define LISP_DST_PORT 4341
59 #define STT_DST_PORT 7471
61 #define DEFAULT_TTL 64
63 /* Last read of the route-table's change number. */
64 static uint64_t rt_change_seqno
;
66 static int get_patch_config(const struct netdev
*netdev
, struct smap
*args
);
67 static int get_tunnel_config(const struct netdev
*, struct smap
*args
);
68 static bool tunnel_check_status_change__(struct netdev_vport
*);
69 static void update_vxlan_global_cfg(struct netdev
*,
70 struct netdev_tunnel_config
*,
71 struct netdev_tunnel_config
*);
74 const char *dpif_port
;
75 struct netdev_class netdev_class
;
76 struct simap global_cfg_tracker
;
80 netdev_vport_is_vport_class(const struct netdev_class
*class)
82 return is_vport_class(class);
85 static struct vport_class
*
86 vport_class_cast(const struct netdev_class
*class)
88 ovs_assert(is_vport_class(class));
89 return CONTAINER_OF(class, struct vport_class
, netdev_class
);
92 static const struct netdev_tunnel_config
*
93 get_netdev_tunnel_config(const struct netdev
*netdev
)
95 return &netdev_vport_cast(netdev
)->tnl_cfg
;
99 netdev_vport_is_patch(const struct netdev
*netdev
)
101 const struct netdev_class
*class = netdev_get_class(netdev
);
103 return class->get_config
== get_patch_config
;
107 netdev_vport_needs_dst_port(const struct netdev
*dev
)
109 const struct netdev_class
*class = netdev_get_class(dev
);
110 const char *type
= netdev_get_type(dev
);
112 return (class->get_config
== get_tunnel_config
&&
113 (!strcmp("geneve", type
) || !strcmp("vxlan", type
) ||
114 !strcmp("lisp", type
) || !strcmp("stt", type
) ||
115 !strcmp("gtpu", type
)));
119 netdev_vport_class_get_dpif_port(const struct netdev_class
*class)
121 return is_vport_class(class) ? vport_class_cast(class)->dpif_port
: NULL
;
125 netdev_vport_get_dpif_port(const struct netdev
*netdev
,
126 char namebuf
[], size_t bufsize
)
128 const struct netdev_class
*class = netdev_get_class(netdev
);
129 const char *dpif_port
= netdev_vport_class_get_dpif_port(class);
132 return netdev_get_name(netdev
);
135 if (netdev_vport_needs_dst_port(netdev
)) {
136 const struct netdev_vport
*vport
= netdev_vport_cast(netdev
);
139 * Note: IFNAMSIZ is 16 bytes long. Implementations should choose
140 * a dpif port name that is short enough to fit including any
141 * port numbers but assert just in case.
143 BUILD_ASSERT(NETDEV_VPORT_NAME_BUFSIZE
>= IFNAMSIZ
);
144 ovs_assert(strlen(dpif_port
) + 6 < IFNAMSIZ
);
145 snprintf(namebuf
, bufsize
, "%s_%d", dpif_port
,
146 ntohs(vport
->tnl_cfg
.dst_port
));
153 /* Whenever the route-table change number is incremented,
154 * netdev_vport_route_changed() should be called to update
155 * the corresponding tunnel interface status. */
157 netdev_vport_route_changed(void)
159 struct netdev
**vports
;
162 vports
= netdev_get_vports(&n_vports
);
163 for (i
= 0; i
< n_vports
; i
++) {
164 struct netdev
*netdev_
= vports
[i
];
165 struct netdev_vport
*netdev
= netdev_vport_cast(netdev_
);
167 ovs_mutex_lock(&netdev
->mutex
);
168 /* Finds all tunnel vports. */
169 if (ipv6_addr_is_set(&netdev
->tnl_cfg
.ipv6_dst
)) {
170 if (tunnel_check_status_change__(netdev
)) {
171 netdev_change_seq_changed(netdev_
);
174 ovs_mutex_unlock(&netdev
->mutex
);
176 netdev_close(netdev_
);
182 static struct netdev
*
183 netdev_vport_alloc(void)
185 struct netdev_vport
*netdev
= xzalloc(sizeof *netdev
);
190 netdev_vport_construct(struct netdev
*netdev_
)
192 const struct netdev_class
*class = netdev_get_class(netdev_
);
193 const char *dpif_port
= netdev_vport_class_get_dpif_port(class);
194 struct netdev_vport
*dev
= netdev_vport_cast(netdev_
);
195 const char *p
, *name
= netdev_get_name(netdev_
);
196 const char *type
= netdev_get_type(netdev_
);
199 ovs_mutex_init(&dev
->mutex
);
200 eth_addr_random(&dev
->etheraddr
);
202 if (name
&& dpif_port
&& (strlen(name
) > strlen(dpif_port
) + 1) &&
203 (!strncmp(name
, dpif_port
, strlen(dpif_port
)))) {
204 p
= name
+ strlen(dpif_port
) + 1;
208 /* If a destination port for tunnel ports is specified in the netdev
209 * name, use it instead of the default one. Otherwise, use the default
210 * destination port */
211 if (!strcmp(type
, "geneve")) {
212 dev
->tnl_cfg
.dst_port
= port
? htons(port
) : htons(GENEVE_DST_PORT
);
213 } else if (!strcmp(type
, "vxlan")) {
214 dev
->tnl_cfg
.dst_port
= port
? htons(port
) : htons(VXLAN_DST_PORT
);
215 update_vxlan_global_cfg(netdev_
, NULL
, &dev
->tnl_cfg
);
216 } else if (!strcmp(type
, "lisp")) {
217 dev
->tnl_cfg
.dst_port
= port
? htons(port
) : htons(LISP_DST_PORT
);
218 } else if (!strcmp(type
, "stt")) {
219 dev
->tnl_cfg
.dst_port
= port
? htons(port
) : htons(STT_DST_PORT
);
220 } else if (!strcmp(type
, "gtpu")) {
221 dev
->tnl_cfg
.dst_port
= port
? htons(port
) : htons(GTPU_DST_PORT
);
224 dev
->tnl_cfg
.dont_fragment
= true;
225 dev
->tnl_cfg
.ttl
= DEFAULT_TTL
;
230 netdev_vport_destruct(struct netdev
*netdev_
)
232 struct netdev_vport
*netdev
= netdev_vport_cast(netdev_
);
233 const char *type
= netdev_get_type(netdev_
);
235 if (!strcmp(type
, "vxlan")) {
236 update_vxlan_global_cfg(netdev_
, &netdev
->tnl_cfg
, NULL
);
240 ovs_mutex_destroy(&netdev
->mutex
);
244 netdev_vport_dealloc(struct netdev
*netdev_
)
246 struct netdev_vport
*netdev
= netdev_vport_cast(netdev_
);
251 netdev_vport_set_etheraddr(struct netdev
*netdev_
, const struct eth_addr mac
)
253 struct netdev_vport
*netdev
= netdev_vport_cast(netdev_
);
255 ovs_mutex_lock(&netdev
->mutex
);
256 netdev
->etheraddr
= mac
;
257 ovs_mutex_unlock(&netdev
->mutex
);
258 netdev_change_seq_changed(netdev_
);
264 netdev_vport_get_etheraddr(const struct netdev
*netdev_
, struct eth_addr
*mac
)
266 struct netdev_vport
*netdev
= netdev_vport_cast(netdev_
);
268 ovs_mutex_lock(&netdev
->mutex
);
269 *mac
= netdev
->etheraddr
;
270 ovs_mutex_unlock(&netdev
->mutex
);
275 /* Checks if the tunnel status has changed and returns a boolean.
276 * Updates the tunnel status if it has changed. */
278 tunnel_check_status_change__(struct netdev_vport
*netdev
)
279 OVS_REQUIRES(netdev
->mutex
)
281 char iface
[IFNAMSIZ
];
283 struct in6_addr
*route
;
288 route
= &netdev
->tnl_cfg
.ipv6_dst
;
289 mark
= netdev
->tnl_cfg
.egress_pkt_mark
;
290 if (ovs_router_lookup(mark
, route
, iface
, NULL
, &gw
)) {
291 struct netdev
*egress_netdev
;
293 if (!netdev_open(iface
, NULL
, &egress_netdev
)) {
294 status
= netdev_get_carrier(egress_netdev
);
295 netdev_close(egress_netdev
);
299 if (strcmp(netdev
->egress_iface
, iface
)
300 || netdev
->carrier_status
!= status
) {
301 ovs_strlcpy_arrays(netdev
->egress_iface
, iface
);
302 netdev
->carrier_status
= status
;
311 tunnel_get_status(const struct netdev
*netdev_
, struct smap
*smap
)
313 struct netdev_vport
*netdev
= netdev_vport_cast(netdev_
);
315 if (netdev
->egress_iface
[0]) {
316 smap_add(smap
, "tunnel_egress_iface", netdev
->egress_iface
);
318 smap_add(smap
, "tunnel_egress_iface_carrier",
319 netdev
->carrier_status
? "up" : "down");
326 netdev_vport_update_flags(struct netdev
*netdev OVS_UNUSED
,
327 enum netdev_flags off
,
328 enum netdev_flags on OVS_UNUSED
,
329 enum netdev_flags
*old_flagsp
)
331 if (off
& (NETDEV_UP
| NETDEV_PROMISC
)) {
335 *old_flagsp
= NETDEV_UP
| NETDEV_PROMISC
;
340 netdev_vport_run(const struct netdev_class
*netdev_class OVS_UNUSED
)
345 seq
= route_table_get_change_seq();
346 if (rt_change_seqno
!= seq
) {
347 rt_change_seqno
= seq
;
348 netdev_vport_route_changed();
353 netdev_vport_wait(const struct netdev_class
*netdev_class OVS_UNUSED
)
358 seq
= route_table_get_change_seq();
359 if (rt_change_seqno
!= seq
) {
360 poll_immediate_wake();
364 /* Code specific to tunnel types. */
367 parse_key(const struct smap
*args
, const char *name
,
368 bool *present
, bool *flow
)
375 s
= smap_get(args
, name
);
377 s
= smap_get(args
, "key");
385 if (!strcmp(s
, "flow")) {
389 return htonll(strtoull(s
, NULL
, 0));
394 parse_tunnel_ip(const char *value
, bool accept_mcast
, bool *flow
,
395 struct in6_addr
*ipv6
, uint16_t *protocol
)
397 if (!strcmp(value
, "flow")) {
402 if (addr_is_ipv6(value
)) {
403 if (lookup_ipv6(value
, ipv6
)) {
406 if (!accept_mcast
&& ipv6_addr_is_multicast(ipv6
)) {
409 *protocol
= ETH_TYPE_IPV6
;
412 if (lookup_ip(value
, &ip
)) {
415 if (!accept_mcast
&& ip_is_multicast(ip
.s_addr
)) {
418 in6_addr_set_mapped_ipv4(ipv6
, ip
.s_addr
);
419 *protocol
= ETH_TYPE_IP
;
425 TNL_L2
= 1 << 0, /* 1 if a tunnel type can carry Ethernet traffic. */
426 TNL_L3
= 1 << 1 /* 1 if a tunnel type can carry L3 traffic. */
428 static enum tunnel_layers
429 tunnel_supported_layers(const char *type
,
430 const struct netdev_tunnel_config
*tnl_cfg
)
432 if (!strcmp(type
, "lisp")) {
434 } else if (!strcmp(type
, "gre")) {
435 return TNL_L2
| TNL_L3
;
436 } else if (!strcmp(type
, "vxlan")
437 && tnl_cfg
->exts
& (1 << OVS_VXLAN_EXT_GPE
)) {
438 return TNL_L2
| TNL_L3
;
439 } else if (!strcmp(type
, "gtpu")) {
445 static enum netdev_pt_mode
446 default_pt_mode(enum tunnel_layers layers
)
448 return layers
== TNL_L3
? NETDEV_PT_LEGACY_L3
: NETDEV_PT_LEGACY_L2
;
452 vxlan_get_port_ext_gbp_str(uint16_t port
, bool gbp
,
453 char namebuf
[], size_t bufsize
)
455 snprintf(namebuf
, bufsize
, "dst_port_%d%s",
456 port
, gbp
? "_gbp" : "");
462 update_vxlan_global_cfg(struct netdev
*netdev
,
463 struct netdev_tunnel_config
*old_cfg
,
464 struct netdev_tunnel_config
*new_cfg
)
468 const char *type
= netdev_get_type(netdev
);
469 struct vport_class
*vclass
= vport_class_cast(netdev_get_class(netdev
));
471 if (strcmp(type
, "vxlan") ||
472 (old_cfg
!= NULL
&& new_cfg
!= NULL
&&
473 old_cfg
->dst_port
== new_cfg
->dst_port
&&
474 old_cfg
->exts
== new_cfg
->exts
)) {
478 if (old_cfg
!= NULL
) {
479 vxlan_get_port_ext_gbp_str(ntohs(old_cfg
->dst_port
),
481 (1 << OVS_VXLAN_EXT_GBP
),
482 namebuf
, sizeof(namebuf
));
484 count
= simap_get(&vclass
->global_cfg_tracker
, namebuf
);
487 simap_put(&vclass
->global_cfg_tracker
, namebuf
, count
);
489 simap_find_and_delete(&vclass
->global_cfg_tracker
, namebuf
);
494 if (new_cfg
!= NULL
) {
495 vxlan_get_port_ext_gbp_str(ntohs(new_cfg
->dst_port
),
497 (1 << OVS_VXLAN_EXT_GBP
),
498 namebuf
, sizeof(namebuf
));
500 simap_increase(&vclass
->global_cfg_tracker
, namebuf
, 1);
505 is_concomitant_vxlan_tunnel_present(struct netdev_vport
*dev
,
506 const struct netdev_tunnel_config
*tnl_cfg
)
509 const char *type
= netdev_get_type(&dev
->up
);
510 struct vport_class
*vclass
= vport_class_cast(netdev_get_class(&dev
->up
));
512 if (strcmp(type
, "vxlan")) {
516 if (dev
->tnl_cfg
.dst_port
== tnl_cfg
->dst_port
&&
517 (dev
->tnl_cfg
.exts
& (1 << OVS_VXLAN_EXT_GBP
)) ==
518 (tnl_cfg
->exts
& (1 << OVS_VXLAN_EXT_GBP
))) {
520 if (ntohs(dev
->tnl_cfg
.dst_port
) == VXLAN_DST_PORT
) {
521 /* Special case where we kept the default port/gbp, only ok if
522 the opposite of the default does not exits */
523 vxlan_get_port_ext_gbp_str(ntohs(tnl_cfg
->dst_port
),
525 (1 << OVS_VXLAN_EXT_GBP
)),
526 namebuf
, sizeof(namebuf
));
528 if (simap_get(&vclass
->global_cfg_tracker
, namebuf
) > 0) {
535 /* Same port: ok if no one is left with the previous configuration */
536 if (dev
->tnl_cfg
.dst_port
== tnl_cfg
->dst_port
) {
537 vxlan_get_port_ext_gbp_str(ntohs(dev
->tnl_cfg
.dst_port
),
539 (1 << OVS_VXLAN_EXT_GBP
),
540 namebuf
, sizeof(namebuf
));
542 if (simap_get(&vclass
->global_cfg_tracker
, namebuf
) > 1) {
549 /* Different port: ok if the opposite gbp option does not yet exists */
550 vxlan_get_port_ext_gbp_str(ntohs(tnl_cfg
->dst_port
),
552 (1 << OVS_VXLAN_EXT_GBP
)),
553 namebuf
, sizeof(namebuf
));
555 if (simap_get(&vclass
->global_cfg_tracker
, namebuf
) > 0) {
563 set_tunnel_config(struct netdev
*dev_
, const struct smap
*args
, char **errp
)
565 struct netdev_vport
*dev
= netdev_vport_cast(dev_
);
566 const char *name
= netdev_get_name(dev_
);
567 const char *type
= netdev_get_type(dev_
);
568 struct ds errors
= DS_EMPTY_INITIALIZER
;
569 bool needs_dst_port
, has_csum
, has_seq
;
570 uint16_t dst_proto
= 0, src_proto
= 0;
571 struct netdev_tunnel_config tnl_cfg
;
572 struct smap_node
*node
;
575 has_csum
= strstr(type
, "gre") || strstr(type
, "geneve") ||
576 strstr(type
, "stt") || strstr(type
, "vxlan");
577 has_seq
= strstr(type
, "gre");
578 memset(&tnl_cfg
, 0, sizeof tnl_cfg
);
580 /* Add a default destination port for tunnel ports if none specified. */
581 if (!strcmp(type
, "geneve")) {
582 tnl_cfg
.dst_port
= htons(GENEVE_DST_PORT
);
585 if (!strcmp(type
, "vxlan")) {
586 tnl_cfg
.dst_port
= htons(VXLAN_DST_PORT
);
589 if (!strcmp(type
, "lisp")) {
590 tnl_cfg
.dst_port
= htons(LISP_DST_PORT
);
593 if (!strcmp(type
, "stt")) {
594 tnl_cfg
.dst_port
= htons(STT_DST_PORT
);
597 if (!strcmp(type
, "gtpu")) {
598 tnl_cfg
.dst_port
= htons(GTPU_DST_PORT
);
601 needs_dst_port
= netdev_vport_needs_dst_port(dev_
);
602 tnl_cfg
.dont_fragment
= true;
604 SMAP_FOR_EACH (node
, args
) {
605 if (!strcmp(node
->key
, "remote_ip")) {
606 err
= parse_tunnel_ip(node
->value
, false, &tnl_cfg
.ip_dst_flow
,
607 &tnl_cfg
.ipv6_dst
, &dst_proto
);
610 ds_put_format(&errors
, "%s: bad %s 'remote_ip'\n", name
, type
);
613 ds_put_format(&errors
,
614 "%s: multicast remote_ip=%s not allowed\n",
618 } else if (!strcmp(node
->key
, "local_ip")) {
619 err
= parse_tunnel_ip(node
->value
, true, &tnl_cfg
.ip_src_flow
,
620 &tnl_cfg
.ipv6_src
, &src_proto
);
623 ds_put_format(&errors
, "%s: bad %s 'local_ip'\n", name
, type
);
626 } else if (!strcmp(node
->key
, "tos")) {
627 if (!strcmp(node
->value
, "inherit")) {
628 tnl_cfg
.tos_inherit
= true;
632 tos
= strtol(node
->value
, &endptr
, 0);
633 if (*endptr
== '\0' && tos
== (tos
& IP_DSCP_MASK
)) {
636 ds_put_format(&errors
, "%s: invalid TOS %s\n", name
,
640 } else if (!strcmp(node
->key
, "ttl")) {
641 if (!strcmp(node
->value
, "inherit")) {
642 tnl_cfg
.ttl_inherit
= true;
644 tnl_cfg
.ttl
= atoi(node
->value
);
646 } else if (!strcmp(node
->key
, "dst_port") && needs_dst_port
) {
647 tnl_cfg
.dst_port
= htons(atoi(node
->value
));
648 } else if (!strcmp(node
->key
, "csum") && has_csum
) {
649 if (!strcmp(node
->value
, "true")) {
652 } else if (!strcmp(node
->key
, "seq") && has_seq
) {
653 if (!strcmp(node
->value
, "true")) {
654 tnl_cfg
.set_seq
= true;
656 } else if (!strcmp(node
->key
, "df_default")) {
657 if (!strcmp(node
->value
, "false")) {
658 tnl_cfg
.dont_fragment
= false;
660 } else if (!strcmp(node
->key
, "key") ||
661 !strcmp(node
->key
, "in_key") ||
662 !strcmp(node
->key
, "out_key") ||
663 !strcmp(node
->key
, "packet_type")) {
664 /* Handled separately below. */
665 } else if (!strcmp(node
->key
, "exts") && !strcmp(type
, "vxlan")) {
666 char *str
= xstrdup(node
->value
);
667 char *ext
, *save_ptr
= NULL
;
671 ext
= strtok_r(str
, ",", &save_ptr
);
673 if (!strcmp(type
, "vxlan") && !strcmp(ext
, "gbp")) {
674 tnl_cfg
.exts
|= (1 << OVS_VXLAN_EXT_GBP
);
675 } else if (!strcmp(type
, "vxlan") && !strcmp(ext
, "gpe")) {
676 tnl_cfg
.exts
|= (1 << OVS_VXLAN_EXT_GPE
);
678 ds_put_format(&errors
, "%s: unknown extension '%s'\n",
682 ext
= strtok_r(NULL
, ",", &save_ptr
);
686 } else if (!strcmp(node
->key
, "egress_pkt_mark")) {
687 tnl_cfg
.egress_pkt_mark
= strtoul(node
->value
, NULL
, 10);
688 tnl_cfg
.set_egress_pkt_mark
= true;
689 } else if (!strcmp(node
->key
, "erspan_idx")) {
690 if (!strcmp(node
->value
, "flow")) {
691 tnl_cfg
.erspan_idx_flow
= true;
693 tnl_cfg
.erspan_idx_flow
= false;
694 tnl_cfg
.erspan_idx
= strtol(node
->value
, NULL
, 16);
696 if (tnl_cfg
.erspan_idx
& ~ERSPAN_IDX_MASK
) {
697 ds_put_format(&errors
, "%s: invalid erspan index: %s\n",
703 } else if (!strcmp(node
->key
, "erspan_ver")) {
704 if (!strcmp(node
->value
, "flow")) {
705 tnl_cfg
.erspan_ver_flow
= true;
706 tnl_cfg
.erspan_idx_flow
= true;
707 tnl_cfg
.erspan_dir_flow
= true;
708 tnl_cfg
.erspan_hwid_flow
= true;
710 tnl_cfg
.erspan_ver_flow
= false;
711 tnl_cfg
.erspan_ver
= atoi(node
->value
);
713 if (tnl_cfg
.erspan_ver
!= 1 && tnl_cfg
.erspan_ver
!= 2) {
714 ds_put_format(&errors
, "%s: invalid erspan version: %s\n",
720 } else if (!strcmp(node
->key
, "erspan_dir")) {
721 if (!strcmp(node
->value
, "flow")) {
722 tnl_cfg
.erspan_dir_flow
= true;
724 tnl_cfg
.erspan_dir_flow
= false;
725 tnl_cfg
.erspan_dir
= atoi(node
->value
);
727 if (tnl_cfg
.erspan_dir
!= 0 && tnl_cfg
.erspan_dir
!= 1) {
728 ds_put_format(&errors
, "%s: invalid erspan direction: %s\n",
734 } else if (!strcmp(node
->key
, "erspan_hwid")) {
735 if (!strcmp(node
->value
, "flow")) {
736 tnl_cfg
.erspan_hwid_flow
= true;
738 tnl_cfg
.erspan_hwid_flow
= false;
739 tnl_cfg
.erspan_hwid
= strtol(node
->value
, NULL
, 16);
741 if (tnl_cfg
.erspan_hwid
& ~(ERSPAN_HWID_MASK
>> 4)) {
742 ds_put_format(&errors
, "%s: invalid erspan hardware ID: %s\n",
749 ds_put_format(&errors
, "%s: unknown %s argument '%s'\n", name
,
754 enum tunnel_layers layers
= tunnel_supported_layers(type
, &tnl_cfg
);
755 const char *full_type
= (strcmp(type
, "vxlan") ? type
756 : (tnl_cfg
.exts
& (1 << OVS_VXLAN_EXT_GPE
)
757 ? "VXLAN-GPE" : "VXLAN (without GPE)"));
758 const char *packet_type
= smap_get(args
, "packet_type");
760 tnl_cfg
.pt_mode
= default_pt_mode(layers
);
761 } else if (!strcmp(packet_type
, "legacy_l2")) {
762 tnl_cfg
.pt_mode
= NETDEV_PT_LEGACY_L2
;
763 if (!(layers
& TNL_L2
)) {
764 ds_put_format(&errors
, "%s: legacy_l2 configured on %s tunnel "
765 "that cannot carry L2 traffic\n",
770 } else if (!strcmp(packet_type
, "legacy_l3")) {
771 tnl_cfg
.pt_mode
= NETDEV_PT_LEGACY_L3
;
772 if (!(layers
& TNL_L3
)) {
773 ds_put_format(&errors
, "%s: legacy_l3 configured on %s tunnel "
774 "that cannot carry L3 traffic\n",
779 } else if (!strcmp(packet_type
, "ptap")) {
780 tnl_cfg
.pt_mode
= NETDEV_PT_AWARE
;
782 ds_put_format(&errors
, "%s: unknown packet_type '%s'\n",
788 if (!ipv6_addr_is_set(&tnl_cfg
.ipv6_dst
) && !tnl_cfg
.ip_dst_flow
) {
789 ds_put_format(&errors
,
790 "%s: %s type requires valid 'remote_ip' argument\n",
795 if (tnl_cfg
.ip_src_flow
&& !tnl_cfg
.ip_dst_flow
) {
796 ds_put_format(&errors
,
797 "%s: %s type requires 'remote_ip=flow' "
798 "with 'local_ip=flow'\n",
803 if (src_proto
&& dst_proto
&& src_proto
!= dst_proto
) {
804 ds_put_format(&errors
,
805 "%s: 'remote_ip' and 'local_ip' "
806 "has to be of the same address family\n",
812 tnl_cfg
.ttl
= DEFAULT_TTL
;
815 tnl_cfg
.in_key
= parse_key(args
, "in_key",
816 &tnl_cfg
.in_key_present
,
817 &tnl_cfg
.in_key_flow
);
819 tnl_cfg
.out_key
= parse_key(args
, "out_key",
820 &tnl_cfg
.out_key_present
,
821 &tnl_cfg
.out_key_flow
);
823 if (is_concomitant_vxlan_tunnel_present(dev
, &tnl_cfg
)) {
824 ds_put_format(&errors
, "%s: VXLAN-GBP, and non-VXLAN-GBP "
825 "tunnels can't be configured on the same "
831 update_vxlan_global_cfg(dev_
, &dev
->tnl_cfg
, &tnl_cfg
);
833 ovs_mutex_lock(&dev
->mutex
);
834 if (memcmp(&dev
->tnl_cfg
, &tnl_cfg
, sizeof tnl_cfg
)) {
835 dev
->tnl_cfg
= tnl_cfg
;
836 tunnel_check_status_change__(dev
);
837 netdev_change_seq_changed(dev_
);
839 ovs_mutex_unlock(&dev
->mutex
);
845 ds_chomp(&errors
, '\n');
846 VLOG_WARN("%s", ds_cstr(&errors
));
848 *errp
= ds_steal_cstr(&errors
);
858 get_tunnel_config(const struct netdev
*dev
, struct smap
*args
)
860 struct netdev_vport
*netdev
= netdev_vport_cast(dev
);
861 const char *type
= netdev_get_type(dev
);
862 struct netdev_tunnel_config tnl_cfg
;
864 ovs_mutex_lock(&netdev
->mutex
);
865 tnl_cfg
= netdev
->tnl_cfg
;
866 ovs_mutex_unlock(&netdev
->mutex
);
868 if (ipv6_addr_is_set(&tnl_cfg
.ipv6_dst
)) {
869 smap_add_ipv6(args
, "remote_ip", &tnl_cfg
.ipv6_dst
);
870 } else if (tnl_cfg
.ip_dst_flow
) {
871 smap_add(args
, "remote_ip", "flow");
874 if (ipv6_addr_is_set(&tnl_cfg
.ipv6_src
)) {
875 smap_add_ipv6(args
, "local_ip", &tnl_cfg
.ipv6_src
);
876 } else if (tnl_cfg
.ip_src_flow
) {
877 smap_add(args
, "local_ip", "flow");
880 if (tnl_cfg
.in_key_flow
&& tnl_cfg
.out_key_flow
) {
881 smap_add(args
, "key", "flow");
882 } else if (tnl_cfg
.in_key_present
&& tnl_cfg
.out_key_present
883 && tnl_cfg
.in_key
== tnl_cfg
.out_key
) {
884 smap_add_format(args
, "key", "%"PRIu64
, ntohll(tnl_cfg
.in_key
));
886 if (tnl_cfg
.in_key_flow
) {
887 smap_add(args
, "in_key", "flow");
888 } else if (tnl_cfg
.in_key_present
) {
889 smap_add_format(args
, "in_key", "%"PRIu64
,
890 ntohll(tnl_cfg
.in_key
));
893 if (tnl_cfg
.out_key_flow
) {
894 smap_add(args
, "out_key", "flow");
895 } else if (tnl_cfg
.out_key_present
) {
896 smap_add_format(args
, "out_key", "%"PRIu64
,
897 ntohll(tnl_cfg
.out_key
));
901 if (tnl_cfg
.ttl_inherit
) {
902 smap_add(args
, "ttl", "inherit");
903 } else if (tnl_cfg
.ttl
!= DEFAULT_TTL
) {
904 smap_add_format(args
, "ttl", "%"PRIu8
, tnl_cfg
.ttl
);
907 if (tnl_cfg
.tos_inherit
) {
908 smap_add(args
, "tos", "inherit");
909 } else if (tnl_cfg
.tos
) {
910 smap_add_format(args
, "tos", "0x%x", tnl_cfg
.tos
);
913 if (tnl_cfg
.dst_port
) {
914 uint16_t dst_port
= ntohs(tnl_cfg
.dst_port
);
916 if ((!strcmp("geneve", type
) && dst_port
!= GENEVE_DST_PORT
) ||
917 (!strcmp("vxlan", type
) && dst_port
!= VXLAN_DST_PORT
) ||
918 (!strcmp("lisp", type
) && dst_port
!= LISP_DST_PORT
) ||
919 (!strcmp("stt", type
) && dst_port
!= STT_DST_PORT
) ||
920 (!strcmp("gtpu", type
) && dst_port
!= GTPU_DST_PORT
)) {
921 smap_add_format(args
, "dst_port", "%d", dst_port
);
926 smap_add(args
, "csum", "true");
929 if (tnl_cfg
.set_seq
) {
930 smap_add(args
, "seq", "true");
933 enum tunnel_layers layers
= tunnel_supported_layers(type
, &tnl_cfg
);
934 if (tnl_cfg
.pt_mode
!= default_pt_mode(layers
)) {
935 smap_add(args
, "packet_type",
936 tnl_cfg
.pt_mode
== NETDEV_PT_LEGACY_L2
? "legacy_l2"
937 : tnl_cfg
.pt_mode
== NETDEV_PT_LEGACY_L3
? "legacy_l3"
941 if (!tnl_cfg
.dont_fragment
) {
942 smap_add(args
, "df_default", "false");
945 if (tnl_cfg
.set_egress_pkt_mark
) {
946 smap_add_format(args
, "egress_pkt_mark",
947 "%"PRIu32
, tnl_cfg
.egress_pkt_mark
);
950 if (!strcmp("erspan", type
) || !strcmp("ip6erspan", type
)) {
951 if (tnl_cfg
.erspan_ver_flow
) {
952 /* since version number is not determined,
953 * assume print all other as flow
955 smap_add(args
, "erspan_ver", "flow");
956 smap_add(args
, "erspan_idx", "flow");
957 smap_add(args
, "erspan_dir", "flow");
958 smap_add(args
, "erspan_hwid", "flow");
960 smap_add_format(args
, "erspan_ver", "%d", tnl_cfg
.erspan_ver
);
962 if (tnl_cfg
.erspan_ver
== 1) {
963 if (tnl_cfg
.erspan_idx_flow
) {
964 smap_add(args
, "erspan_idx", "flow");
966 smap_add_format(args
, "erspan_idx", "0x%x",
969 } else if (tnl_cfg
.erspan_ver
== 2) {
970 if (tnl_cfg
.erspan_dir_flow
) {
971 smap_add(args
, "erspan_dir", "flow");
973 smap_add_format(args
, "erspan_dir", "%d",
976 if (tnl_cfg
.erspan_hwid_flow
) {
977 smap_add(args
, "erspan_hwid", "flow");
979 smap_add_format(args
, "erspan_hwid", "0x%x",
980 tnl_cfg
.erspan_hwid
);
989 /* Code specific to patch ports. */
991 /* If 'netdev' is a patch port, returns the name of its peer as a malloc()'d
992 * string that the caller must free.
994 * If 'netdev' is not a patch port, returns NULL. */
996 netdev_vport_patch_peer(const struct netdev
*netdev_
)
1000 if (netdev_vport_is_patch(netdev_
)) {
1001 struct netdev_vport
*netdev
= netdev_vport_cast(netdev_
);
1003 ovs_mutex_lock(&netdev
->mutex
);
1005 peer
= xstrdup(netdev
->peer
);
1007 ovs_mutex_unlock(&netdev
->mutex
);
1014 netdev_vport_inc_rx(const struct netdev
*netdev
,
1015 const struct dpif_flow_stats
*stats
)
1017 if (is_vport_class(netdev_get_class(netdev
))) {
1018 struct netdev_vport
*dev
= netdev_vport_cast(netdev
);
1020 ovs_mutex_lock(&dev
->mutex
);
1021 dev
->stats
.rx_packets
+= stats
->n_packets
;
1022 dev
->stats
.rx_bytes
+= stats
->n_bytes
;
1023 ovs_mutex_unlock(&dev
->mutex
);
1028 netdev_vport_inc_tx(const struct netdev
*netdev
,
1029 const struct dpif_flow_stats
*stats
)
1031 if (is_vport_class(netdev_get_class(netdev
))) {
1032 struct netdev_vport
*dev
= netdev_vport_cast(netdev
);
1034 ovs_mutex_lock(&dev
->mutex
);
1035 dev
->stats
.tx_packets
+= stats
->n_packets
;
1036 dev
->stats
.tx_bytes
+= stats
->n_bytes
;
1037 ovs_mutex_unlock(&dev
->mutex
);
1042 get_patch_config(const struct netdev
*dev_
, struct smap
*args
)
1044 struct netdev_vport
*dev
= netdev_vport_cast(dev_
);
1046 ovs_mutex_lock(&dev
->mutex
);
1048 smap_add(args
, "peer", dev
->peer
);
1050 ovs_mutex_unlock(&dev
->mutex
);
1056 set_patch_config(struct netdev
*dev_
, const struct smap
*args
, char **errp
)
1058 struct netdev_vport
*dev
= netdev_vport_cast(dev_
);
1059 const char *name
= netdev_get_name(dev_
);
1062 peer
= smap_get(args
, "peer");
1064 VLOG_ERR_BUF(errp
, "%s: patch type requires valid 'peer' argument",
1069 if (smap_count(args
) > 1) {
1070 VLOG_ERR_BUF(errp
, "%s: patch type takes only a 'peer' argument",
1075 if (!strcmp(name
, peer
)) {
1076 VLOG_ERR_BUF(errp
, "%s: patch peer must not be self", name
);
1080 ovs_mutex_lock(&dev
->mutex
);
1081 if (!dev
->peer
|| strcmp(dev
->peer
, peer
)) {
1083 dev
->peer
= xstrdup(peer
);
1084 netdev_change_seq_changed(dev_
);
1086 ovs_mutex_unlock(&dev
->mutex
);
1092 netdev_vport_get_stats(const struct netdev
*netdev
, struct netdev_stats
*stats
)
1094 struct netdev_vport
*dev
= netdev_vport_cast(netdev
);
1096 ovs_mutex_lock(&dev
->mutex
);
1097 /* Passing only collected counters */
1098 stats
->tx_packets
= dev
->stats
.tx_packets
;
1099 stats
->tx_bytes
= dev
->stats
.tx_bytes
;
1100 stats
->rx_packets
= dev
->stats
.rx_packets
;
1101 stats
->rx_bytes
= dev
->stats
.rx_bytes
;
1102 ovs_mutex_unlock(&dev
->mutex
);
1107 static enum netdev_pt_mode
1108 netdev_vport_get_pt_mode(const struct netdev
*netdev
)
1110 struct netdev_vport
*dev
= netdev_vport_cast(netdev
);
1112 return dev
->tnl_cfg
.pt_mode
;
1119 netdev_vport_get_ifindex(const struct netdev
*netdev_
)
1121 char buf
[NETDEV_VPORT_NAME_BUFSIZE
];
1122 const char *name
= netdev_vport_get_dpif_port(netdev_
, buf
, sizeof(buf
));
1124 return linux_get_ifindex(name
);
1127 #define NETDEV_VPORT_GET_IFINDEX netdev_vport_get_ifindex
1128 #else /* !__linux__ */
1129 #define NETDEV_VPORT_GET_IFINDEX NULL
1130 #endif /* __linux__ */
1132 #define VPORT_FUNCTIONS_COMMON \
1133 .run = netdev_vport_run, \
1134 .wait = netdev_vport_wait, \
1135 .alloc = netdev_vport_alloc, \
1136 .construct = netdev_vport_construct, \
1137 .destruct = netdev_vport_destruct, \
1138 .dealloc = netdev_vport_dealloc, \
1139 .set_etheraddr = netdev_vport_set_etheraddr, \
1140 .get_etheraddr = netdev_vport_get_etheraddr, \
1141 .get_stats = netdev_vport_get_stats, \
1142 .get_pt_mode = netdev_vport_get_pt_mode, \
1143 .update_flags = netdev_vport_update_flags
1145 #define TUNNEL_FUNCTIONS_COMMON \
1146 VPORT_FUNCTIONS_COMMON, \
1147 .get_config = get_tunnel_config, \
1148 .set_config = set_tunnel_config, \
1149 .get_tunnel_config = get_netdev_tunnel_config, \
1150 .get_status = tunnel_get_status
1153 netdev_vport_tunnel_register(void)
1155 /* The name of the dpif_port should be short enough to accomodate adding
1156 * a port number to the end if one is necessary. */
1157 static struct vport_class vport_classes
[] = {
1160 TUNNEL_FUNCTIONS_COMMON
,
1162 .build_header
= netdev_geneve_build_header
,
1163 .push_header
= netdev_tnl_push_udp_header
,
1164 .pop_header
= netdev_geneve_pop_header
,
1165 .get_ifindex
= NETDEV_VPORT_GET_IFINDEX
,
1167 {{NULL
, NULL
, 0, 0}}
1171 TUNNEL_FUNCTIONS_COMMON
,
1173 .build_header
= netdev_gre_build_header
,
1174 .push_header
= netdev_gre_push_header
,
1175 .pop_header
= netdev_gre_pop_header
,
1176 .get_ifindex
= NETDEV_VPORT_GET_IFINDEX
,
1178 {{NULL
, NULL
, 0, 0}}
1182 TUNNEL_FUNCTIONS_COMMON
,
1184 .build_header
= netdev_vxlan_build_header
,
1185 .push_header
= netdev_tnl_push_udp_header
,
1186 .pop_header
= netdev_vxlan_pop_header
,
1187 .get_ifindex
= NETDEV_VPORT_GET_IFINDEX
1189 {{NULL
, NULL
, 0, 0}}
1193 TUNNEL_FUNCTIONS_COMMON
,
1196 {{NULL
, NULL
, 0, 0}}
1200 TUNNEL_FUNCTIONS_COMMON
,
1203 {{NULL
, NULL
, 0, 0}}
1207 TUNNEL_FUNCTIONS_COMMON
,
1209 .build_header
= netdev_erspan_build_header
,
1210 .push_header
= netdev_erspan_push_header
,
1211 .pop_header
= netdev_erspan_pop_header
1213 {{NULL
, NULL
, 0, 0}}
1217 TUNNEL_FUNCTIONS_COMMON
,
1218 .type
= "ip6erspan",
1219 .build_header
= netdev_erspan_build_header
,
1220 .push_header
= netdev_erspan_push_header
,
1221 .pop_header
= netdev_erspan_pop_header
1223 {{NULL
, NULL
, 0, 0}}
1227 TUNNEL_FUNCTIONS_COMMON
,
1229 .build_header
= netdev_gre_build_header
,
1230 .push_header
= netdev_gre_push_header
,
1231 .pop_header
= netdev_gre_pop_header
,
1232 .get_ifindex
= NETDEV_VPORT_GET_IFINDEX
,
1234 {{NULL
, NULL
, 0, 0}}
1238 TUNNEL_FUNCTIONS_COMMON
,
1240 .build_header
= netdev_gtpu_build_header
,
1241 .push_header
= netdev_gtpu_push_header
,
1242 .pop_header
= netdev_gtpu_pop_header
,
1244 {{NULL
, NULL
, 0, 0}}
1248 static struct ovsthread_once once
= OVSTHREAD_ONCE_INITIALIZER
;
1250 if (ovsthread_once_start(&once
)) {
1253 for (i
= 0; i
< ARRAY_SIZE(vport_classes
); i
++) {
1254 simap_init(&vport_classes
[i
].global_cfg_tracker
);
1255 netdev_register_provider(&vport_classes
[i
].netdev_class
);
1258 unixctl_command_register("tnl/egress_port_range", "min max", 0, 2,
1259 netdev_tnl_egress_port_range
, NULL
);
1261 ovsthread_once_done(&once
);
1266 netdev_vport_patch_register(void)
1268 static struct vport_class patch_class
= {
1270 { VPORT_FUNCTIONS_COMMON
,
1272 .get_config
= get_patch_config
,
1273 .set_config
= set_patch_config
,
1275 {{NULL
, NULL
, 0, 0}}
1277 simap_init(&patch_class
.global_cfg_tracker
);
1278 netdev_register_provider(&patch_class
.netdev_class
);