#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"
* the Netlink version of the command, even if actions_len is zero. */
const struct nlattr *key; /* OVS_FLOW_ATTR_KEY. */
size_t key_len;
+ const struct nlattr *mask; /* OVS_FLOW_ATTR_MASK. */
+ size_t mask_len;
const struct nlattr *actions; /* OVS_FLOW_ATTR_ACTIONS. */
size_t actions_len;
const struct ovs_flow_stats *stats; /* OVS_FLOW_ATTR_STATS. */
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;
case OVS_VPORT_TYPE_GRE64:
return "gre64";
- case OVS_VPORT_TYPE_CAPWAP:
- return "capwap";
-
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;
return OVS_VPORT_TYPE_GRE64;
} else if (strstr(type, "gre")) {
return OVS_VPORT_TYPE_GRE;
- } else if (!strcmp(type, "capwap")) {
- return OVS_VPORT_TYPE_CAPWAP;
} 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;
}
{
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
const struct netdev_tunnel_config *tnl_cfg;
- const char *name = netdev_vport_get_dpif_port(netdev);
+ char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
+ const char *name = netdev_vport_get_dpif_port(netdev,
+ namebuf, sizeof namebuf);
const char *type = netdev_get_type(netdev);
struct dpif_linux_vport request, reply;
struct nl_sock *sock = NULL;
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,
- htons(tnl_cfg->dst_port));
+ ntohs(tnl_cfg->dst_port));
request.options = options.data;
request.options_len = options.size;
}
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->dp_ifindex = dpif->dp_ifindex;
request->key = put->key;
request->key_len = put->key_len;
+ request->mask = put->mask;
+ request->mask_len = put->mask_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;
static int
dpif_linux_flow_dump_next(const struct dpif *dpif_ OVS_UNUSED, void *state_,
const struct nlattr **key, size_t *key_len,
+ const struct nlattr **mask, size_t *mask_len,
const struct nlattr **actions, size_t *actions_len,
const struct dpif_flow_stats **stats)
{
*key = state->flow.key;
*key_len = state->flow.key_len;
}
+ if (mask) {
+ *mask = state->flow.mask;
+ *mask_len = state->flow.mask ? state->flow.mask_len : 0;
+ }
if (stats) {
dpif_linux_flow_get_stats(&state->flow, &state->stats);
*stats = &state->stats;
[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;
{
static const struct nl_policy ovs_flow_policy[] = {
[OVS_FLOW_ATTR_KEY] = { .type = NL_A_NESTED },
+ [OVS_FLOW_ATTR_MASK] = { .type = NL_A_NESTED, .optional = true },
[OVS_FLOW_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
[OVS_FLOW_ATTR_STATS] = { NL_POLICY_FOR(struct ovs_flow_stats),
.optional = true },
flow->dp_ifindex = ovs_header->dp_ifindex;
flow->key = nl_attr_get(a[OVS_FLOW_ATTR_KEY]);
flow->key_len = nl_attr_get_size(a[OVS_FLOW_ATTR_KEY]);
+
+ if (a[OVS_FLOW_ATTR_MASK]) {
+ flow->mask = nl_attr_get(a[OVS_FLOW_ATTR_MASK]);
+ flow->mask_len = nl_attr_get_size(a[OVS_FLOW_ATTR_MASK]);
+ }
if (a[OVS_FLOW_ATTR_ACTIONS]) {
flow->actions = nl_attr_get(a[OVS_FLOW_ATTR_ACTIONS]);
flow->actions_len = nl_attr_get_size(a[OVS_FLOW_ATTR_ACTIONS]);
nl_msg_put_unspec(buf, OVS_FLOW_ATTR_KEY, flow->key, flow->key_len);
}
+ if (flow->mask_len) {
+ nl_msg_put_unspec(buf, OVS_FLOW_ATTR_MASK, flow->mask, flow->mask_len);
+ }
+
if (flow->actions || flow->actions_len) {
nl_msg_put_unspec(buf, OVS_FLOW_ATTR_ACTIONS,
flow->actions, flow->actions_len);