/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "odp-util.h"
#include "ofpbuf.h"
#include "openvswitch/datapath-compat.h"
-#include "openvswitch/tunnel.h"
#include "packets.h"
#include "poll-loop.h"
#include "random.h"
int new_size = port_no + 1;
int i;
- if (new_size > 65535) {
+ if (new_size > MAX_PORTS) {
VLOG_WARN_RL(&error_rl, "%s: datapath port %"PRIu32" too big",
dpif_name(&dpif->dpif), port_no);
return EFBIG;
return errno;
}
+ nl_sock_destroy(dpif->channels[port_no].sock);
dpif->channels[port_no].sock = sock;
dpif->channels[port_no].last_poll = LLONG_MIN;
}
epoll_ctl(dpif->epoll_fd, EPOLL_CTL_DEL, nl_sock_fd(ch->sock), NULL);
+ dpif->event_offset = dpif->n_events = 0;
nl_sock_destroy(ch->sock);
ch->sock = NULL;
return error;
}
+static const char *
+get_vport_type(const struct dpif_linux_vport *vport)
+{
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+
+ switch (vport->type) {
+ case OVS_VPORT_TYPE_NETDEV:
+ return "system";
+
+ case OVS_VPORT_TYPE_INTERNAL:
+ return "internal";
+
+ case OVS_VPORT_TYPE_GRE:
+ return "gre";
+
+ case OVS_VPORT_TYPE_GRE64:
+ return "gre64";
+
+ case OVS_VPORT_TYPE_VXLAN:
+ return "vxlan";
+
+ case OVS_VPORT_TYPE_LISP:
+ return "lisp";
+
+ case OVS_VPORT_TYPE_UNSPEC:
+ case __OVS_VPORT_TYPE_MAX:
+ break;
+ }
+
+ VLOG_WARN_RL(&rl, "dp%d: port `%s' has unsupported type %u",
+ vport->dp_ifindex, vport->name, (unsigned int) vport->type);
+ return "unknown";
+}
+
+static enum ovs_vport_type
+netdev_to_ovs_vport_type(const struct netdev *netdev)
+{
+ const char *type = netdev_get_type(netdev);
+
+ if (!strcmp(type, "tap") || !strcmp(type, "system")) {
+ return OVS_VPORT_TYPE_NETDEV;
+ } else if (!strcmp(type, "internal")) {
+ return OVS_VPORT_TYPE_INTERNAL;
+ } else if (strstr(type, "gre64")) {
+ return OVS_VPORT_TYPE_GRE64;
+ } else if (strstr(type, "gre")) {
+ return OVS_VPORT_TYPE_GRE;
+ } else if (!strcmp(type, "vxlan")) {
+ return OVS_VPORT_TYPE_VXLAN;
+ } else if (!strcmp(type, "lisp")) {
+ return OVS_VPORT_TYPE_LISP;
+ } else {
+ return OVS_VPORT_TYPE_UNSPEC;
+ }
+}
+
static int
dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev,
uint32_t *port_nop)
{
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
- const char *name = netdev_get_name(netdev);
+ const struct netdev_tunnel_config *tnl_cfg;
+ const char *name = netdev_vport_get_dpif_port(netdev);
const char *type = netdev_get_type(netdev);
struct dpif_linux_vport request, reply;
- const struct ofpbuf *options;
struct nl_sock *sock = NULL;
uint32_t upcall_pid;
struct ofpbuf *buf;
+ uint64_t options_stub[64 / 8];
+ struct ofpbuf options;
int error;
if (dpif->epoll_fd >= 0) {
dpif_linux_vport_init(&request);
request.cmd = OVS_VPORT_CMD_NEW;
request.dp_ifindex = dpif->dp_ifindex;
- request.type = netdev_vport_get_vport_type(netdev);
+ request.type = netdev_to_ovs_vport_type(netdev);
if (request.type == OVS_VPORT_TYPE_UNSPEC) {
VLOG_WARN_RL(&error_rl, "%s: cannot create port `%s' because it has "
"unsupported type `%s'",
}
request.name = name;
- options = netdev_vport_get_options(netdev);
- if (options && options->size) {
- request.options = options->data;
- request.options_len = options->size;
- }
-
if (request.type == OVS_VPORT_TYPE_NETDEV) {
netdev_linux_ethtool_set_flag(netdev, ETH_FLAG_LRO, "LRO", false);
}
+ tnl_cfg = netdev_get_tunnel_config(netdev);
+ if (tnl_cfg && tnl_cfg->dst_port != 0) {
+ ofpbuf_use_stack(&options, options_stub, sizeof options_stub);
+ nl_msg_put_u16(&options, OVS_TUNNEL_ATTR_DST_PORT,
+ ntohs(tnl_cfg->dst_port));
+ request.options = options.data;
+ request.options_len = options.size;
+ }
+
request.port_no = *port_nop;
upcall_pid = sock ? nl_sock_pid(sock) : 0;
request.upcall_pid = &upcall_pid;
*port_nop = reply.port_no;
VLOG_DBG("%s: assigning port %"PRIu32" to netlink pid %"PRIu32,
dpif_name(dpif_), reply.port_no, upcall_pid);
- } else if (error == EBUSY && *port_nop != UINT32_MAX) {
- VLOG_INFO("%s: requested port %"PRIu32" is in use",
- dpif_name(dpif_), *port_nop);
+ } else {
+ if (error == EBUSY && *port_nop != UINT32_MAX) {
+ VLOG_INFO("%s: requested port %"PRIu32" is in use",
+ dpif_name(dpif_), *port_nop);
+ }
nl_sock_destroy(sock);
ofpbuf_delete(buf);
return error;
error = ENODEV;
} else if (dpif_port) {
dpif_port->name = xstrdup(reply.name);
- dpif_port->type = xstrdup(netdev_vport_get_netdev_type(&reply));
+ dpif_port->type = xstrdup(get_vport_type(&reply));
dpif_port->port_no = reply.port_no;
}
ofpbuf_delete(buf);
}
dpif_port->name = CONST_CAST(char *, vport.name);
- dpif_port->type = CONST_CAST(char *, netdev_vport_get_netdev_type(&vport));
+ dpif_port->type = CONST_CAST(char *, get_vport_type(&vport));
dpif_port->port_no = vport.port_no;
return 0;
}
dpif_linux_init_flow_put(struct dpif *dpif_, const struct dpif_flow_put *put,
struct dpif_linux_flow *request)
{
- static struct nlattr dummy_action;
+ static const struct nlattr dummy_action;
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
request->key = put->key;
request->key_len = put->key_len;
/* Ensure that OVS_FLOW_ATTR_ACTIONS will always be included. */
- request->actions = put->actions ? put->actions : &dummy_action;
+ request->actions = (put->actions
+ ? put->actions
+ : CONST_CAST(struct nlattr *, &dummy_action));
request->actions_len = put->actions_len;
if (put->flags & DPIF_FP_ZERO_STATS) {
request->clear = true;
[OVS_PACKET_ATTR_KEY] = { .type = NL_A_NESTED },
/* OVS_PACKET_CMD_ACTION only. */
- [OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_U64, .optional = true },
+ [OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_UNSPEC, .optional = true },
};
struct ovs_header *ovs_header;
upcall->key = CONST_CAST(struct nlattr *,
nl_attr_get(a[OVS_PACKET_ATTR_KEY]));
upcall->key_len = nl_attr_get_size(a[OVS_PACKET_ATTR_KEY]);
- upcall->userdata = (a[OVS_PACKET_ATTR_USERDATA]
- ? nl_attr_get_u64(a[OVS_PACKET_ATTR_USERDATA])
- : 0);
+ upcall->userdata = a[OVS_PACKET_ATTR_USERDATA];
*dp_ifindex = ovs_header->dp_ifindex;
return 0;
[OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_U32 },
[OVS_VPORT_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_vport_stats),
.optional = true },
- [OVS_VPORT_ATTR_ADDRESS] = { .type = NL_A_UNSPEC,
- .min_len = ETH_ADDR_LEN,
- .max_len = ETH_ADDR_LEN,
- .optional = true },
[OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = true },
};
if (a[OVS_VPORT_ATTR_STATS]) {
vport->stats = nl_attr_get(a[OVS_VPORT_ATTR_STATS]);
}
- if (a[OVS_VPORT_ATTR_ADDRESS]) {
- vport->address = nl_attr_get(a[OVS_VPORT_ATTR_ADDRESS]);
- }
if (a[OVS_VPORT_ATTR_OPTIONS]) {
vport->options = nl_attr_get(a[OVS_VPORT_ATTR_OPTIONS]);
vport->options_len = nl_attr_get_size(a[OVS_VPORT_ATTR_OPTIONS]);
vport->stats, sizeof *vport->stats);
}
- if (vport->address) {
- nl_msg_put_unspec(buf, OVS_VPORT_ATTR_ADDRESS,
- vport->address, ETH_ADDR_LEN);
- }
-
if (vport->options) {
nl_msg_put_nested(buf, OVS_VPORT_ATTR_OPTIONS,
vport->options, vport->options_len);
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
struct ds s;
- if (VLOG_DROP_ERR(&rl)) {
+ if (VLOG_DROP_WARN(&rl)) {
return;
}