/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 "netdev.h"
#include "netdev-linux.h"
#include "netdev-vport.h"
+#include "netlink-conntrack.h"
#include "netlink-notifier.h"
#include "netlink-socket.h"
#include "netlink.h"
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_STT:
+ return "stt";
+
case OVS_VPORT_TYPE_UNSPEC:
case __OVS_VPORT_TYPE_MAX:
break;
return OVS_VPORT_TYPE_NETDEV;
} else if (!strcmp(type, "internal")) {
return OVS_VPORT_TYPE_INTERNAL;
+ } else if (strstr(type, "stt")) {
+ return OVS_VPORT_TYPE_STT;
} else if (!strcmp(type, "geneve")) {
return OVS_VPORT_TYPE_GENEVE;
- } 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")) {
}
nl_msg_end_nested(&options, ext_ofs);
}
- request.options = ofpbuf_data(&options);
- request.options_len = ofpbuf_size(&options);
+ request.options = options.data;
+ request.options_len = options.size;
}
request.port_no = *port_nop;
const struct dpif_flow_del *del,
struct dpif_netlink_flow *request)
{
- return dpif_netlink_init_flow_del__(dpif, del->key, del->key_len,
- del->ufid, del->terse, request);
+ dpif_netlink_init_flow_del__(dpif, del->key, del->key_len,
+ del->ufid, del->terse, request);
}
struct dpif_netlink_flow_dump {
n_flows = 0;
while (!n_flows
- || (n_flows < max_flows && ofpbuf_size(&thread->nl_flows))) {
+ || (n_flows < max_flows && thread->nl_flows.size)) {
struct dpif_netlink_flow datapath_flow;
struct ofpbuf nl_flow;
int error;
if (d_exec->probe) {
nl_msg_put_flag(buf, OVS_PACKET_ATTR_PROBE);
}
+ if (d_exec->mtu) {
+ nl_msg_put_u16(buf, OVS_PACKET_ATTR_MRU, d_exec->mtu);
+ }
}
/* Executes, against 'dpif', up to the first 'n_ops' operations in 'ops'.
/* OVS_PACKET_CMD_ACTION only. */
[OVS_PACKET_ATTR_USERDATA] = { .type = NL_A_UNSPEC, .optional = true },
[OVS_PACKET_ATTR_EGRESS_TUN_KEY] = { .type = NL_A_NESTED, .optional = true },
+ [OVS_PACKET_ATTR_ACTIONS] = { .type = NL_A_NESTED, .optional = true },
+ [OVS_PACKET_ATTR_MRU] = { .type = NL_A_U16, .optional = true }
};
- struct ovs_header *ovs_header;
- struct nlattr *a[ARRAY_SIZE(ovs_packet_policy)];
- struct nlmsghdr *nlmsg;
- struct genlmsghdr *genl;
- struct ofpbuf b;
- int type;
-
- ofpbuf_use_const(&b, ofpbuf_data(buf), ofpbuf_size(buf));
+ struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
+ struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
+ struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
+ struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
- nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
- genl = ofpbuf_try_pull(&b, sizeof *genl);
- ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
+ struct nlattr *a[ARRAY_SIZE(ovs_packet_policy)];
if (!nlmsg || !genl || !ovs_header
|| nlmsg->nlmsg_type != ovs_packet_family
|| !nl_policy_parse(&b, 0, ovs_packet_policy, a,
return EINVAL;
}
- type = (genl->cmd == OVS_PACKET_CMD_MISS ? DPIF_UC_MISS
- : genl->cmd == OVS_PACKET_CMD_ACTION ? DPIF_UC_ACTION
- : -1);
+ int type = (genl->cmd == OVS_PACKET_CMD_MISS ? DPIF_UC_MISS
+ : genl->cmd == OVS_PACKET_CMD_ACTION ? DPIF_UC_ACTION
+ : -1);
if (type < 0) {
return EINVAL;
}
dpif_flow_hash(&dpif->dpif, upcall->key, upcall->key_len, &upcall->ufid);
upcall->userdata = a[OVS_PACKET_ATTR_USERDATA];
upcall->out_tun_key = a[OVS_PACKET_ATTR_EGRESS_TUN_KEY];
+ upcall->actions = a[OVS_PACKET_ATTR_ACTIONS];
+ upcall->mru = a[OVS_PACKET_ATTR_MRU];
/* Allow overwriting the netlink attribute header without reallocating. */
dp_packet_use_stub(&upcall->packet,
return version_str;
}
+#ifdef __linux__
+struct dpif_netlink_ct_dump_state {
+ struct ct_dpif_dump_state up;
+ struct nl_ct_dump_state *nl_ct_dump;
+};
+
+static int
+dpif_netlink_ct_dump_start(struct dpif *dpif OVS_UNUSED,
+ struct ct_dpif_dump_state **dump_,
+ const uint16_t *zone)
+{
+ struct dpif_netlink_ct_dump_state *dump;
+ int err;
+
+ dump = xzalloc(sizeof *dump);
+ err = nl_ct_dump_start(&dump->nl_ct_dump, zone);
+ if (err) {
+ free(dump);
+ return err;
+ }
+
+ *dump_ = &dump->up;
+
+ return 0;
+}
+
+static int
+dpif_netlink_ct_dump_next(struct dpif *dpif OVS_UNUSED,
+ struct ct_dpif_dump_state *dump_,
+ struct ct_dpif_entry *entry)
+{
+ struct dpif_netlink_ct_dump_state *dump;
+
+ INIT_CONTAINER(dump, dump_, up);
+
+ return nl_ct_dump_next(dump->nl_ct_dump, entry);
+}
+
+static int
+dpif_netlink_ct_dump_done(struct dpif *dpif OVS_UNUSED,
+ struct ct_dpif_dump_state *dump_)
+{
+ struct dpif_netlink_ct_dump_state *dump;
+ int err;
+
+ INIT_CONTAINER(dump, dump_, up);
+
+ err = nl_ct_dump_done(dump->nl_ct_dump);
+ free(dump);
+ return err;
+}
+
+static int
+dpif_netlink_ct_flush(struct dpif *dpif OVS_UNUSED, const uint16_t *zone)
+{
+ if (zone) {
+ return nl_ct_flush_zone(*zone);
+ } else {
+ return nl_ct_flush();
+ }
+}
+#endif
+
const struct dpif_class dpif_netlink_class = {
"system",
+ NULL, /* init */
dpif_netlink_enumerate,
NULL,
dpif_netlink_open,
dpif_netlink_recv,
dpif_netlink_recv_wait,
dpif_netlink_recv_purge,
+ NULL, /* register_dp_purge_cb */
NULL, /* register_upcall_cb */
NULL, /* enable_upcall */
NULL, /* disable_upcall */
dpif_netlink_get_datapath_version, /* get_datapath_version */
+#ifdef __linux__
+ dpif_netlink_ct_dump_start,
+ dpif_netlink_ct_dump_next,
+ dpif_netlink_ct_dump_done,
+ dpif_netlink_ct_flush,
+#else
+ NULL, /* ct_dump_start */
+ NULL, /* ct_dump_next */
+ NULL, /* ct_dump_done */
+ NULL, /* ct_flush */
+#endif
};
static int
[OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = true },
};
- struct nlattr *a[ARRAY_SIZE(ovs_vport_policy)];
- struct ovs_header *ovs_header;
- struct nlmsghdr *nlmsg;
- struct genlmsghdr *genl;
- struct ofpbuf b;
-
dpif_netlink_vport_init(vport);
- ofpbuf_use_const(&b, ofpbuf_data(buf), ofpbuf_size(buf));
- nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
- genl = ofpbuf_try_pull(&b, sizeof *genl);
- ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
+ struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
+ struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
+ struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
+ struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
+
+ struct nlattr *a[ARRAY_SIZE(ovs_vport_policy)];
if (!nlmsg || !genl || !ovs_header
|| nlmsg->nlmsg_type != ovs_vport_family
|| !nl_policy_parse(&b, 0, ovs_vport_policy, a,
.optional = true },
};
- struct nlattr *a[ARRAY_SIZE(ovs_datapath_policy)];
- struct ovs_header *ovs_header;
- struct nlmsghdr *nlmsg;
- struct genlmsghdr *genl;
- struct ofpbuf b;
-
dpif_netlink_dp_init(dp);
- ofpbuf_use_const(&b, ofpbuf_data(buf), ofpbuf_size(buf));
- nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
- genl = ofpbuf_try_pull(&b, sizeof *genl);
- ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
+ struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
+ struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
+ struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
+ struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
+
+ struct nlattr *a[ARRAY_SIZE(ovs_datapath_policy)];
if (!nlmsg || !genl || !ovs_header
|| nlmsg->nlmsg_type != ovs_datapath_family
|| !nl_policy_parse(&b, 0, ovs_datapath_policy, a,
/* The kernel never uses OVS_FLOW_ATTR_UFID_FLAGS. */
};
- struct nlattr *a[ARRAY_SIZE(ovs_flow_policy)];
- struct ovs_header *ovs_header;
- struct nlmsghdr *nlmsg;
- struct genlmsghdr *genl;
- struct ofpbuf b;
-
dpif_netlink_flow_init(flow);
- ofpbuf_use_const(&b, ofpbuf_data(buf), ofpbuf_size(buf));
- nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
- genl = ofpbuf_try_pull(&b, sizeof *genl);
- ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
+ struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size);
+ struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg);
+ struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl);
+ struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header);
+
+ struct nlattr *a[ARRAY_SIZE(ovs_flow_policy)];
if (!nlmsg || !genl || !ovs_header
|| nlmsg->nlmsg_type != ovs_flow_family
|| !nl_policy_parse(&b, 0, ovs_flow_policy, a,