From 5b9e7e1607956e2454ccbd94ccf5631309ade054 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 26 Jun 2014 09:58:26 +0200 Subject: openvswitch: introduce rtnl ops stub This stub now allows userspace to see IFLA_INFO_KIND for ovs master and IFLA_INFO_SLAVE_KIND for slave. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 0d407bca81e3..fe95b6c224a7 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -2054,10 +2054,14 @@ static int __init dp_init(void) pr_info("Open vSwitch switching datapath\n"); - err = ovs_flow_init(); + err = ovs_internal_dev_rtnl_link_register(); if (err) goto error; + err = ovs_flow_init(); + if (err) + goto error_unreg_rtnl_link; + err = ovs_vport_init(); if (err) goto error_flow_exit; @@ -2084,6 +2088,8 @@ error_vport_exit: ovs_vport_exit(); error_flow_exit: ovs_flow_exit(); +error_unreg_rtnl_link: + ovs_internal_dev_rtnl_link_unregister(); error: return err; } @@ -2096,6 +2102,7 @@ static void dp_cleanup(void) rcu_barrier(); ovs_vport_exit(); ovs_flow_exit(); + ovs_internal_dev_rtnl_link_unregister(); } module_init(dp_init); -- cgit v1.2.2 From 48e48a70c08a8a68f8697f8b30cb83775bda8001 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Wed, 16 Jul 2014 11:25:52 -0700 Subject: openvswitch: make generic netlink group const Generic netlink tables can be const. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 493b5141a618..20f59b62721a 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -66,16 +66,16 @@ static struct genl_family dp_packet_genl_family; static struct genl_family dp_flow_genl_family; static struct genl_family dp_datapath_genl_family; -static struct genl_multicast_group ovs_dp_flow_multicast_group = { - .name = OVS_FLOW_MCGROUP +static const struct genl_multicast_group ovs_dp_flow_multicast_group = { + .name = OVS_FLOW_MCGROUP, }; -static struct genl_multicast_group ovs_dp_datapath_multicast_group = { - .name = OVS_DATAPATH_MCGROUP +static const struct genl_multicast_group ovs_dp_datapath_multicast_group = { + .name = OVS_DATAPATH_MCGROUP, }; -struct genl_multicast_group ovs_dp_vport_multicast_group = { - .name = OVS_VPORT_MCGROUP +static const struct genl_multicast_group ovs_dp_vport_multicast_group = { + .name = OVS_VPORT_MCGROUP, }; /* Check if need to build a reply message. @@ -1189,7 +1189,7 @@ static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = { [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG }, }; -static struct genl_ops dp_flow_genl_ops[] = { +static const struct genl_ops dp_flow_genl_ops[] = { { .cmd = OVS_FLOW_CMD_NEW, .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = flow_policy, @@ -1577,7 +1577,7 @@ static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = { [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 }, }; -static struct genl_ops dp_datapath_genl_ops[] = { +static const struct genl_ops dp_datapath_genl_ops[] = { { .cmd = OVS_DP_CMD_NEW, .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = datapath_policy, @@ -1944,7 +1944,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = { [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED }, }; -static struct genl_ops dp_vport_genl_ops[] = { +static const struct genl_ops dp_vport_genl_ops[] = { { .cmd = OVS_VPORT_CMD_NEW, .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ .policy = vport_policy, -- cgit v1.2.2 From 5cd667b0a4567048bb555927d6ee564f4e5620a9 Mon Sep 17 00:00:00 2001 From: Alex Wang Date: Thu, 17 Jul 2014 15:14:13 -0700 Subject: openvswitch: Allow each vport to have an array of 'port_id's. In order to allow handlers directly read upcalls from datapath, we need to support per-handler netlink socket for each vport in datapath. This commit makes this happen. Also, it is guaranteed to be backward compatible with previous branch. Signed-off-by: Alex Wang Acked-by: Thomas Graf Signed-off-by: Pravin B Shelar --- net/openvswitch/datapath.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 20f59b62721a..65a8e5c089e4 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -266,7 +266,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) upcall.cmd = OVS_PACKET_CMD_MISS; upcall.key = &key; upcall.userdata = NULL; - upcall.portid = p->upcall_portid; + upcall.portid = ovs_vport_find_upcall_portid(p, skb); ovs_dp_upcall(dp, skb, &upcall); consume_skb(skb); stats_counter = &stats->n_missed; @@ -1373,7 +1373,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) parms.options = NULL; parms.dp = dp; parms.port_no = OVSP_LOCAL; - parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]); + parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID]; ovs_dp_change(dp, a); @@ -1632,8 +1632,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) || nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) || - nla_put_string(skb, OVS_VPORT_ATTR_NAME, vport->ops->get_name(vport)) || - nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, vport->upcall_portid)) + nla_put_string(skb, OVS_VPORT_ATTR_NAME, + vport->ops->get_name(vport))) goto nla_put_failure; ovs_vport_get_stats(vport, &vport_stats); @@ -1641,6 +1641,9 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, &vport_stats)) goto nla_put_failure; + if (ovs_vport_get_upcall_portids(vport, skb)) + goto nla_put_failure; + err = ovs_vport_get_options(vport, skb); if (err == -EMSGSIZE) goto error; @@ -1762,7 +1765,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info) parms.options = a[OVS_VPORT_ATTR_OPTIONS]; parms.dp = dp; parms.port_no = port_no; - parms.upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); + parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID]; vport = new_vport(&parms); err = PTR_ERR(vport); @@ -1812,8 +1815,14 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) goto exit_unlock_free; } - if (a[OVS_VPORT_ATTR_UPCALL_PID]) - vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); + + if (a[OVS_VPORT_ATTR_UPCALL_PID]) { + struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID]; + + err = ovs_vport_set_upcall_portids(vport, ids); + if (err) + goto exit_unlock_free; + } err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, info->snd_seq, 0, OVS_VPORT_CMD_NEW); -- cgit v1.2.2 From f53e38317d581399eb67809d6b6b6c2c107db50c Mon Sep 17 00:00:00 2001 From: Andy Zhou Date: Thu, 17 Jul 2014 15:17:44 -0700 Subject: openvswitch: Avoid memory corruption in queue_userspace_packet() In queue_userspace_packet(), the ovs_nla_put_flow return value is not checked. This is fine as long as key_attr_size() returns the correct value. In case it does not, the current code may corrupt buffer memory. Add a run time assertion catch this case to avoid silent failure. Reported-by: Ben Pfaff Signed-off-by: Andy Zhou Signed-off-by: Pravin B Shelar --- net/openvswitch/datapath.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 65a8e5c089e4..3c461e1e4554 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -464,7 +464,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, upcall->dp_ifindex = dp_ifindex; nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); - ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); + err = ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); + BUG_ON(err); nla_nest_end(user_skb, nla); if (upcall_info->userdata) -- cgit v1.2.2 From d0e992aa0270663872c56f07473a7f43adee5bd5 Mon Sep 17 00:00:00 2001 From: Himangi Saraogi Date: Sun, 27 Jul 2014 12:37:46 +0530 Subject: openvswitch: Use IS_ERR_OR_NULL This patch introduces the use of the macro IS_ERR_OR_NULL in place of tests for NULL and IS_ERR. The following Coccinelle semantic patch was used for making the change: @@ expression e; @@ - e == NULL || IS_ERR(e) + IS_ERR_OR_NULL(e) || ... Signed-off-by: Himangi Saraogi Acked-by: Julia Lawall Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 3c461e1e4554..7ad3f029baae 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -781,7 +781,7 @@ static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow, skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts), info, always); - if (!skb || IS_ERR(skb)) + if (IS_ERR_OR_NULL(skb)) return skb; retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb, -- cgit v1.2.2 From 2072ec846a4c4ee99a6e59ce989b49b22edad59d Mon Sep 17 00:00:00 2001 From: Jean Sacren Date: Thu, 7 Aug 2014 06:50:44 -0600 Subject: openvswitch: fix duplicate #include headers The #include headers net/genetlink.h and linux/genetlink.h both were included twice, so delete each of the duplicate. Signed-off-by: Jean Sacren Cc: Pravin Shelar Cc: dev@openvswitch.org Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 7ad3f029baae..7228ec3faf19 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -47,8 +47,6 @@ #include #include #include -#include -#include #include #include #include -- cgit v1.2.2 From 4ee45ea05c8710c7ab8a5eb1a72700b874712746 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Tue, 2 Sep 2014 20:52:28 +0800 Subject: openvswitch: fix a memory leak The user_skb maybe be leaked if the operation on it failed and codes skipped into the label "out:" without calling genlmsg_unicast. Cc: Pravin Shelar Signed-off-by: Li RongQing Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 7228ec3faf19..35d866f036e7 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -404,7 +404,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, { struct ovs_header *upcall; struct sk_buff *nskb = NULL; - struct sk_buff *user_skb; /* to be queued to userspace */ + struct sk_buff *user_skb = NULL; /* to be queued to userspace */ struct nlattr *nla; struct genl_info info = { .dst_sk = ovs_dp_get_net(dp)->genl_sock, @@ -494,9 +494,11 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); + user_skb = NULL; out: if (err) skb_tx_error(skb); + kfree_skb(user_skb); kfree_skb(nskb); return err; } -- cgit v1.2.2 From c5eba0b6f84eb4f0fdc1d8a4abc1c7d40db6e8a6 Mon Sep 17 00:00:00 2001 From: Li RongQing Date: Wed, 3 Sep 2014 17:43:45 +0800 Subject: openvswitch: distinguish between the dropped and consumed skb distinguish between the dropped and consumed skb, not assume the skb is consumed always Cc: Thomas Graf Cc: Pravin Shelar Signed-off-by: Li RongQing Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 35d866f036e7..91d66b7e64ac 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -265,8 +265,11 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) upcall.key = &key; upcall.userdata = NULL; upcall.portid = ovs_vport_find_upcall_portid(p, skb); - ovs_dp_upcall(dp, skb, &upcall); - consume_skb(skb); + error = ovs_dp_upcall(dp, skb, &upcall); + if (unlikely(error)) + kfree_skb(skb); + else + consume_skb(skb); stats_counter = &stats->n_missed; goto out; } -- cgit v1.2.2 From 9b67aa4a82492f128adfccc63e61ab57c1ce1dfd Mon Sep 17 00:00:00 2001 From: Samuel Gauthier Date: Thu, 18 Sep 2014 10:31:04 +0200 Subject: openvswitch: restore OVS_FLOW_CMD_NEW notifications Since commit fb5d1e9e127a ("openvswitch: Build flow cmd netlink reply only if needed."), the new flows are not notified to the listeners of OVS_FLOW_MCGROUP. This commit fixes the problem by using the genl function, ie genl_has_listerners() instead of netlink_has_listeners(). Signed-off-by: Samuel Gauthier Signed-off-by: Nicolas Dichtel Acked-by: Pravin B Shelar Signed-off-by: David S. Miller --- net/openvswitch/datapath.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net/openvswitch/datapath.c') diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 91d66b7e64ac..64dc864a417f 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -78,11 +78,12 @@ static const struct genl_multicast_group ovs_dp_vport_multicast_group = { /* Check if need to build a reply message. * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */ -static bool ovs_must_notify(struct genl_info *info, - const struct genl_multicast_group *grp) +static bool ovs_must_notify(struct genl_family *family, struct genl_info *info, + unsigned int group) { return info->nlhdr->nlmsg_flags & NLM_F_ECHO || - netlink_has_listeners(genl_info_net(info)->genl_sock, 0); + genl_has_listeners(family, genl_info_net(info)->genl_sock, + group); } static void ovs_notify(struct genl_family *family, @@ -763,7 +764,7 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions *act { struct sk_buff *skb; - if (!always && !ovs_must_notify(info, &ovs_dp_flow_multicast_group)) + if (!always && !ovs_must_notify(&dp_flow_genl_family, info, 0)) return NULL; skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, GFP_KERNEL); -- cgit v1.2.2