X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Fdpif-netlink.c;h=f1eaa5124dca3d3fe959d10749e4075b8cd1065d;hb=0a2869d524fc3612b4b77a9df4991bff2aa3b465;hp=1d8abdf67a34b67bcfc88b70e85c508a7d9e4840;hpb=ec97c2df3c5ad87a266b1dc5432ee0057f182ffd;p=cascardo%2Fovs.git diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 1d8abdf67..f1eaa5124 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -1,5 +1,5 @@ /* - * 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. @@ -40,6 +40,7 @@ #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" @@ -759,15 +760,15 @@ get_vport_type(const struct dpif_netlink_vport *vport) 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; @@ -787,10 +788,10 @@ netdev_to_ovs_vport_type(const struct netdev *netdev) 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")) { @@ -849,12 +850,26 @@ dpif_netlink_port_add__(struct dpif_netlink *dpif, struct netdev *netdev, } tnl_cfg = netdev_get_tunnel_config(netdev); - if (tnl_cfg && tnl_cfg->dst_port != 0) { + if (tnl_cfg && (tnl_cfg->dst_port != 0 || tnl_cfg->exts)) { 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 = ofpbuf_data(&options); - request.options_len = ofpbuf_size(&options); + if (tnl_cfg->dst_port) { + nl_msg_put_u16(&options, OVS_TUNNEL_ATTR_DST_PORT, + ntohs(tnl_cfg->dst_port)); + } + if (tnl_cfg->exts) { + size_t ext_ofs; + int i; + + ext_ofs = nl_msg_start_nested(&options, OVS_TUNNEL_ATTR_EXTENSION); + for (i = 0; i < 32; i++) { + if (tnl_cfg->exts & (1 << i)) { + nl_msg_put_flag(&options, i); + } + } + nl_msg_end_nested(&options, ext_ofs); + } + request.options = options.data; + request.options_len = options.size; } request.port_no = *port_nop; @@ -1321,8 +1336,8 @@ dpif_netlink_init_flow_del(struct dpif_netlink *dpif, 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 { @@ -1455,7 +1470,7 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_, 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; @@ -1510,7 +1525,7 @@ dpif_netlink_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec, size_t key_ofs; ofpbuf_prealloc_tailroom(buf, (64 - + ofpbuf_size(d_exec->packet) + + dp_packet_size(d_exec->packet) + ODP_KEY_METADATA_SIZE + d_exec->actions_len)); @@ -1521,11 +1536,11 @@ dpif_netlink_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec, k_exec->dp_ifindex = dp_ifindex; nl_msg_put_unspec(buf, OVS_PACKET_ATTR_PACKET, - ofpbuf_data(d_exec->packet), - ofpbuf_size(d_exec->packet)); + dp_packet_data(d_exec->packet), + dp_packet_size(d_exec->packet)); key_ofs = nl_msg_start_nested(buf, OVS_PACKET_ATTR_KEY); - odp_key_from_pkt_metadata(buf, &d_exec->md); + odp_key_from_pkt_metadata(buf, &d_exec->packet->md); nl_msg_end_nested(buf, key_ofs); nl_msg_put_unspec(buf, OVS_PACKET_ATTR_ACTIONS, @@ -1533,6 +1548,9 @@ dpif_netlink_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec, 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'. @@ -1597,14 +1615,14 @@ dpif_netlink_operate__(struct dpif_netlink *dpif, case DPIF_OP_EXECUTE: /* Can't execute a packet that won't fit in a Netlink attribute. */ if (OVS_UNLIKELY(nl_attr_oversized( - ofpbuf_size(op->u.execute.packet)))) { + dp_packet_size(op->u.execute.packet)))) { /* Report an error immediately if this is the first operation. * Otherwise the easiest thing to do is to postpone to the next * call (when this will be the first operation). */ if (i == 0) { VLOG_ERR_RL(&error_rl, "dropping oversized %"PRIu32"-byte packet", - ofpbuf_size(op->u.execute.packet)); + dp_packet_size(op->u.execute.packet)); op->error = ENOBUFS; return 1; } @@ -1950,20 +1968,16 @@ parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf, /* 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, @@ -1971,9 +1985,9 @@ parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf, 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; } @@ -1986,16 +2000,18 @@ parse_odp_packet(const struct dpif_netlink *dpif, struct ofpbuf *buf, 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. */ - ofpbuf_use_stub(&upcall->packet, + dp_packet_use_stub(&upcall->packet, CONST_CAST(struct nlattr *, nl_attr_get(a[OVS_PACKET_ATTR_PACKET])) - 1, nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET]) + sizeof(struct nlattr)); - ofpbuf_set_data(&upcall->packet, - (char *)ofpbuf_data(&upcall->packet) + sizeof(struct nlattr)); - ofpbuf_set_size(&upcall->packet, nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET])); + dp_packet_set_data(&upcall->packet, + (char *)dp_packet_data(&upcall->packet) + sizeof(struct nlattr)); + dp_packet_set_size(&upcall->packet, nl_attr_get_size(a[OVS_PACKET_ATTR_PACKET])); *dp_ifindex = ovs_header->dp_ifindex; @@ -2258,8 +2274,72 @@ dpif_netlink_get_datapath_version(void) 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, @@ -2292,10 +2372,22 @@ const struct dpif_class dpif_netlink_class = { 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 @@ -2371,18 +2463,14 @@ dpif_netlink_vport_from_ofpbuf(struct dpif_netlink_vport *vport, [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, @@ -2539,18 +2627,14 @@ dpif_netlink_dp_from_ofpbuf(struct dpif_netlink_dp *dp, const struct ofpbuf *buf .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, @@ -2697,18 +2781,14 @@ dpif_netlink_flow_from_ofpbuf(struct dpif_netlink_flow *flow, /* 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,