aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/datapath.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r--net/openvswitch/datapath.c77
1 files changed, 49 insertions, 28 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 9db4bf6740d1..64dc864a417f 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -47,8 +47,6 @@
47#include <linux/openvswitch.h> 47#include <linux/openvswitch.h>
48#include <linux/rculist.h> 48#include <linux/rculist.h>
49#include <linux/dmi.h> 49#include <linux/dmi.h>
50#include <linux/genetlink.h>
51#include <net/genetlink.h>
52#include <net/genetlink.h> 50#include <net/genetlink.h>
53#include <net/net_namespace.h> 51#include <net/net_namespace.h>
54#include <net/netns/generic.h> 52#include <net/netns/generic.h>
@@ -66,25 +64,26 @@ static struct genl_family dp_packet_genl_family;
66static struct genl_family dp_flow_genl_family; 64static struct genl_family dp_flow_genl_family;
67static struct genl_family dp_datapath_genl_family; 65static struct genl_family dp_datapath_genl_family;
68 66
69static struct genl_multicast_group ovs_dp_flow_multicast_group = { 67static const struct genl_multicast_group ovs_dp_flow_multicast_group = {
70 .name = OVS_FLOW_MCGROUP 68 .name = OVS_FLOW_MCGROUP,
71}; 69};
72 70
73static struct genl_multicast_group ovs_dp_datapath_multicast_group = { 71static const struct genl_multicast_group ovs_dp_datapath_multicast_group = {
74 .name = OVS_DATAPATH_MCGROUP 72 .name = OVS_DATAPATH_MCGROUP,
75}; 73};
76 74
77struct genl_multicast_group ovs_dp_vport_multicast_group = { 75static const struct genl_multicast_group ovs_dp_vport_multicast_group = {
78 .name = OVS_VPORT_MCGROUP 76 .name = OVS_VPORT_MCGROUP,
79}; 77};
80 78
81/* Check if need to build a reply message. 79/* Check if need to build a reply message.
82 * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */ 80 * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
83static bool ovs_must_notify(struct genl_info *info, 81static bool ovs_must_notify(struct genl_family *family, struct genl_info *info,
84 const struct genl_multicast_group *grp) 82 unsigned int group)
85{ 83{
86 return info->nlhdr->nlmsg_flags & NLM_F_ECHO || 84 return info->nlhdr->nlmsg_flags & NLM_F_ECHO ||
87 netlink_has_listeners(genl_info_net(info)->genl_sock, 0); 85 genl_has_listeners(family, genl_info_net(info)->genl_sock,
86 group);
88} 87}
89 88
90static void ovs_notify(struct genl_family *family, 89static void ovs_notify(struct genl_family *family,
@@ -266,9 +265,12 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
266 upcall.cmd = OVS_PACKET_CMD_MISS; 265 upcall.cmd = OVS_PACKET_CMD_MISS;
267 upcall.key = &key; 266 upcall.key = &key;
268 upcall.userdata = NULL; 267 upcall.userdata = NULL;
269 upcall.portid = p->upcall_portid; 268 upcall.portid = ovs_vport_find_upcall_portid(p, skb);
270 ovs_dp_upcall(dp, skb, &upcall); 269 error = ovs_dp_upcall(dp, skb, &upcall);
271 consume_skb(skb); 270 if (unlikely(error))
271 kfree_skb(skb);
272 else
273 consume_skb(skb);
272 stats_counter = &stats->n_missed; 274 stats_counter = &stats->n_missed;
273 goto out; 275 goto out;
274 } 276 }
@@ -406,7 +408,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
406{ 408{
407 struct ovs_header *upcall; 409 struct ovs_header *upcall;
408 struct sk_buff *nskb = NULL; 410 struct sk_buff *nskb = NULL;
409 struct sk_buff *user_skb; /* to be queued to userspace */ 411 struct sk_buff *user_skb = NULL; /* to be queued to userspace */
410 struct nlattr *nla; 412 struct nlattr *nla;
411 struct genl_info info = { 413 struct genl_info info = {
412 .dst_sk = ovs_dp_get_net(dp)->genl_sock, 414 .dst_sk = ovs_dp_get_net(dp)->genl_sock,
@@ -464,7 +466,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
464 upcall->dp_ifindex = dp_ifindex; 466 upcall->dp_ifindex = dp_ifindex;
465 467
466 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); 468 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY);
467 ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); 469 err = ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb);
470 BUG_ON(err);
468 nla_nest_end(user_skb, nla); 471 nla_nest_end(user_skb, nla);
469 472
470 if (upcall_info->userdata) 473 if (upcall_info->userdata)
@@ -495,9 +498,11 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
495 ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; 498 ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len;
496 499
497 err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); 500 err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid);
501 user_skb = NULL;
498out: 502out:
499 if (err) 503 if (err)
500 skb_tx_error(skb); 504 skb_tx_error(skb);
505 kfree_skb(user_skb);
501 kfree_skb(nskb); 506 kfree_skb(nskb);
502 return err; 507 return err;
503} 508}
@@ -759,7 +764,7 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions *act
759{ 764{
760 struct sk_buff *skb; 765 struct sk_buff *skb;
761 766
762 if (!always && !ovs_must_notify(info, &ovs_dp_flow_multicast_group)) 767 if (!always && !ovs_must_notify(&dp_flow_genl_family, info, 0))
763 return NULL; 768 return NULL;
764 769
765 skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, GFP_KERNEL); 770 skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, GFP_KERNEL);
@@ -780,7 +785,7 @@ static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow,
780 785
781 skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts), info, 786 skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts), info,
782 always); 787 always);
783 if (!skb || IS_ERR(skb)) 788 if (IS_ERR_OR_NULL(skb))
784 return skb; 789 return skb;
785 790
786 retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb, 791 retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb,
@@ -1189,7 +1194,7 @@ static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
1189 [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG }, 1194 [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
1190}; 1195};
1191 1196
1192static struct genl_ops dp_flow_genl_ops[] = { 1197static const struct genl_ops dp_flow_genl_ops[] = {
1193 { .cmd = OVS_FLOW_CMD_NEW, 1198 { .cmd = OVS_FLOW_CMD_NEW,
1194 .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ 1199 .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
1195 .policy = flow_policy, 1200 .policy = flow_policy,
@@ -1373,7 +1378,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
1373 parms.options = NULL; 1378 parms.options = NULL;
1374 parms.dp = dp; 1379 parms.dp = dp;
1375 parms.port_no = OVSP_LOCAL; 1380 parms.port_no = OVSP_LOCAL;
1376 parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]); 1381 parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
1377 1382
1378 ovs_dp_change(dp, a); 1383 ovs_dp_change(dp, a);
1379 1384
@@ -1577,7 +1582,7 @@ static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
1577 [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 }, 1582 [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
1578}; 1583};
1579 1584
1580static struct genl_ops dp_datapath_genl_ops[] = { 1585static const struct genl_ops dp_datapath_genl_ops[] = {
1581 { .cmd = OVS_DP_CMD_NEW, 1586 { .cmd = OVS_DP_CMD_NEW,
1582 .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ 1587 .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
1583 .policy = datapath_policy, 1588 .policy = datapath_policy,
@@ -1632,8 +1637,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
1632 1637
1633 if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) || 1638 if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) ||
1634 nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) || 1639 nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) ||
1635 nla_put_string(skb, OVS_VPORT_ATTR_NAME, vport->ops->get_name(vport)) || 1640 nla_put_string(skb, OVS_VPORT_ATTR_NAME,
1636 nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, vport->upcall_portid)) 1641 vport->ops->get_name(vport)))
1637 goto nla_put_failure; 1642 goto nla_put_failure;
1638 1643
1639 ovs_vport_get_stats(vport, &vport_stats); 1644 ovs_vport_get_stats(vport, &vport_stats);
@@ -1641,6 +1646,9 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
1641 &vport_stats)) 1646 &vport_stats))
1642 goto nla_put_failure; 1647 goto nla_put_failure;
1643 1648
1649 if (ovs_vport_get_upcall_portids(vport, skb))
1650 goto nla_put_failure;
1651
1644 err = ovs_vport_get_options(vport, skb); 1652 err = ovs_vport_get_options(vport, skb);
1645 if (err == -EMSGSIZE) 1653 if (err == -EMSGSIZE)
1646 goto error; 1654 goto error;
@@ -1762,7 +1770,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
1762 parms.options = a[OVS_VPORT_ATTR_OPTIONS]; 1770 parms.options = a[OVS_VPORT_ATTR_OPTIONS];
1763 parms.dp = dp; 1771 parms.dp = dp;
1764 parms.port_no = port_no; 1772 parms.port_no = port_no;
1765 parms.upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); 1773 parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID];
1766 1774
1767 vport = new_vport(&parms); 1775 vport = new_vport(&parms);
1768 err = PTR_ERR(vport); 1776 err = PTR_ERR(vport);
@@ -1812,8 +1820,14 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info)
1812 goto exit_unlock_free; 1820 goto exit_unlock_free;
1813 } 1821 }
1814 1822
1815 if (a[OVS_VPORT_ATTR_UPCALL_PID]) 1823
1816 vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); 1824 if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
1825 struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID];
1826
1827 err = ovs_vport_set_upcall_portids(vport, ids);
1828 if (err)
1829 goto exit_unlock_free;
1830 }
1817 1831
1818 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, 1832 err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
1819 info->snd_seq, 0, OVS_VPORT_CMD_NEW); 1833 info->snd_seq, 0, OVS_VPORT_CMD_NEW);
@@ -1944,7 +1958,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
1944 [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED }, 1958 [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
1945}; 1959};
1946 1960
1947static struct genl_ops dp_vport_genl_ops[] = { 1961static const struct genl_ops dp_vport_genl_ops[] = {
1948 { .cmd = OVS_VPORT_CMD_NEW, 1962 { .cmd = OVS_VPORT_CMD_NEW,
1949 .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ 1963 .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
1950 .policy = vport_policy, 1964 .policy = vport_policy,
@@ -2053,10 +2067,14 @@ static int __init dp_init(void)
2053 2067
2054 pr_info("Open vSwitch switching datapath\n"); 2068 pr_info("Open vSwitch switching datapath\n");
2055 2069
2056 err = ovs_flow_init(); 2070 err = ovs_internal_dev_rtnl_link_register();
2057 if (err) 2071 if (err)
2058 goto error; 2072 goto error;
2059 2073
2074 err = ovs_flow_init();
2075 if (err)
2076 goto error_unreg_rtnl_link;
2077
2060 err = ovs_vport_init(); 2078 err = ovs_vport_init();
2061 if (err) 2079 if (err)
2062 goto error_flow_exit; 2080 goto error_flow_exit;
@@ -2083,6 +2101,8 @@ error_vport_exit:
2083 ovs_vport_exit(); 2101 ovs_vport_exit();
2084error_flow_exit: 2102error_flow_exit:
2085 ovs_flow_exit(); 2103 ovs_flow_exit();
2104error_unreg_rtnl_link:
2105 ovs_internal_dev_rtnl_link_unregister();
2086error: 2106error:
2087 return err; 2107 return err;
2088} 2108}
@@ -2095,6 +2115,7 @@ static void dp_cleanup(void)
2095 rcu_barrier(); 2115 rcu_barrier();
2096 ovs_vport_exit(); 2116 ovs_vport_exit();
2097 ovs_flow_exit(); 2117 ovs_flow_exit();
2118 ovs_internal_dev_rtnl_link_unregister();
2098} 2119}
2099 2120
2100module_init(dp_init); 2121module_init(dp_init);