Skip to content

Commit

Permalink
datapath: Turn vports with dependencies into separate modules
Browse files Browse the repository at this point in the history
Upstream commit:
    The internal and netdev vport remain part of openvswitch.ko. Encap
    vports including vxlan, gre, and geneve can be built as separate
    modules and are loaded on demand. Modules can be unloaded after use.
    Datapath ports keep a reference to the vport module during their
    lifetime.

    Allows to remove the error prone maintenance of the global list
    vport_ops_list.

    Signed-off-by: Thomas Graf <tgraf@suug.ch>
    Signed-off-by: David S. Miller <davem@davemloft.net>

Also folds in the follow-up commits 9ba559d9ca3 to turned the non-GPL
symbol exports to GPL exports, and fa2d8ff4e35 which fixes a module
reference release bug.

Exports various backwards compat functions linked into the main
openvswitch module as GPL symbols to ensure vport modules can use them.

Some fiddling with the Makefile was needed to work around the fact
that Makefile variables can't contain '-' characters needed to define
'vport-xxx' module sources. Also, Kbuild complains heavily if a
$(module)-y = $(module).o is defined which is actually backed with a .c
file of the same name. Therefore, a new $(build_multi_modules) variable
is defined which lists all module which consist of more than one source
file.

Upstream: 62b9c8d0372 ("ovs: Turn vports with dependencies into separate modules")
Upstream: 9ba559d9ca3 ("openvswitch: Export symbols as GPL symbols.")
Upstream: fa2d8ff4e35 ("openvswitch: Return vport module ref before destruction")
Signed-off-by: Thomas Graf <tgraf@noironetworks.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
  • Loading branch information
Thomas Graf committed Apr 4, 2015
1 parent 416e713 commit 5a38795
Show file tree
Hide file tree
Showing 18 changed files with 259 additions and 58 deletions.
20 changes: 14 additions & 6 deletions datapath/Modules.mk
Expand Up @@ -2,7 +2,14 @@
#
# Some modules should be built but not distributed, e.g. third-party
# hwtable modules.
both_modules = openvswitch
build_multi_modules = \
openvswitch
both_modules = \
$(build_multi_modules) \
vport_geneve \
vport_gre \
vport_lisp \
vport_vxlan
build_modules = $(both_modules) # Modules to build
dist_modules = $(both_modules) # Modules to distribute

Expand All @@ -14,12 +21,13 @@ openvswitch_sources = \
flow_netlink.c \
flow_table.c \
vport.c \
vport-geneve.c \
vport-gre.c \
vport-internal_dev.c \
vport-lisp.c \
vport-netdev.c \
vport-vxlan.c
vport-netdev.c

vport_geneve_sources = vport-geneve.c
vport_vxlan_sources = vport-vxlan.c
vport_gre_sources = vport-gre.c
vport_lisp_sources = vport-lisp.c

openvswitch_headers = \
compat.h \
Expand Down
17 changes: 15 additions & 2 deletions datapath/datapath.c
Expand Up @@ -61,6 +61,7 @@
#include "vport-netdev.h"

int ovs_net_id __read_mostly;
EXPORT_SYMBOL_GPL(ovs_net_id);

static struct genl_family dp_packet_genl_family;
static struct genl_family dp_flow_genl_family;
Expand Down Expand Up @@ -134,6 +135,7 @@ int lockdep_ovsl_is_held(void)
else
return 1;
}
EXPORT_SYMBOL_GPL(lockdep_ovsl_is_held);
#endif

static int queue_gso_packets(struct datapath *dp, struct sk_buff *,
Expand Down Expand Up @@ -1900,6 +1902,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
return -ENOMEM;

ovs_lock();
restart:
dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
err = -ENODEV;
if (!dp)
Expand Down Expand Up @@ -1931,8 +1934,11 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)

vport = new_vport(&parms);
err = PTR_ERR(vport);
if (IS_ERR(vport))
if (IS_ERR(vport)) {
if (err == -EAGAIN)
goto restart;
goto exit_unlock_free;
}

err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
info->snd_seq, 0, OVS_VPORT_CMD_NEW);
Expand Down Expand Up @@ -2291,12 +2297,18 @@ static int __init dp_init(void)
if (err)
goto error_netns_exit;

err = ovs_netdev_init();
if (err)
goto error_unreg_notifier;

err = dp_register_genl();
if (err < 0)
goto error_unreg_notifier;
goto error_unreg_netdev;

return 0;

error_unreg_netdev:
ovs_netdev_exit();
error_unreg_notifier:
unregister_netdevice_notifier(&ovs_dp_device_notifier);
error_netns_exit:
Expand All @@ -2316,6 +2328,7 @@ static int __init dp_init(void)
static void dp_cleanup(void)
{
dp_unregister_genl(ARRAY_SIZE(dp_genl_families));
ovs_netdev_exit();
unregister_netdevice_notifier(&ovs_dp_device_notifier);
unregister_pernet_device(&ovs_net_ops);
rcu_barrier();
Expand Down
4 changes: 2 additions & 2 deletions datapath/linux/Kbuild.in
Expand Up @@ -18,10 +18,10 @@ ccflags-y += -include $(builddir)/kcompat.h
# right place, even though it's conceptually incorrect.
NOSTDINC_FLAGS += -I$(top_srcdir)/include -I$(srcdir)/compat -I$(srcdir)/compat/include

obj-m := $(patsubst %,%.o,$(build_modules))
obj-m := $(subst _,-,$(patsubst %,%.o,$(build_modules)))

define module_template
$(1)-y = $$(notdir $$(patsubst %.c,%.o,$($(1)_sources)))
endef

$(foreach module,$(build_modules),$(eval $(call module_template,$(module))))
$(foreach module,$(build_multi_modules),$(eval $(call module_template,$(module))))
1 change: 1 addition & 0 deletions datapath/linux/compat/flow_dissector.c
Expand Up @@ -231,4 +231,5 @@ u32 __skb_get_hash(struct sk_buff *skb)
#endif
return hash;
}
EXPORT_SYMBOL_GPL(__skb_get_hash);
#endif
3 changes: 3 additions & 0 deletions datapath/linux/compat/geneve.c
Expand Up @@ -118,6 +118,7 @@ int geneve_xmit_skb(struct geneve_sock *gs, struct rtable *rt,
tos, ttl, df, src_port, dst_port, xnet,
!csum);
}
EXPORT_SYMBOL_GPL(geneve_xmit_skb);

/* Callback from net/ipv4/udp.c to receive packets */
static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
Expand Down Expand Up @@ -226,6 +227,7 @@ struct geneve_sock *geneve_sock_add(struct net *net, __be16 port,
{
return geneve_socket_create(net, port, rcv, data, ipv6);
}
EXPORT_SYMBOL_GPL(geneve_sock_add);

static void rcu_free_gs(struct rcu_head *rcu)
{
Expand All @@ -239,3 +241,4 @@ void geneve_sock_release(struct geneve_sock *gs)
udp_tunnel_sock_release(gs->sock);
call_rcu(&gs->rcu, rcu_free_gs);
}
EXPORT_SYMBOL_GPL(geneve_sock_release);
4 changes: 4 additions & 0 deletions datapath/linux/compat/gre.c
Expand Up @@ -250,6 +250,7 @@ int gre_cisco_register(struct gre_cisco_protocol *newp)
return (cmpxchg((struct gre_cisco_protocol **)&gre_cisco_proto, NULL, newp) == NULL) ?
0 : -EBUSY;
}
EXPORT_SYMBOL_GPL(gre_cisco_register);

int gre_cisco_unregister(struct gre_cisco_protocol *proto)
{
Expand All @@ -265,6 +266,7 @@ int gre_cisco_unregister(struct gre_cisco_protocol *proto)
ret = gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
return ret;
}
EXPORT_SYMBOL_GPL(gre_cisco_unregister);

#endif /* !HAVE_GRE_CISCO_REGISTER */

Expand Down Expand Up @@ -297,6 +299,7 @@ struct sk_buff *gre_handle_offloads(struct sk_buff *skb, bool gre_csum)

return ovs_iptunnel_handle_offloads(skb, gre_csum, type, fix_segment);
}
EXPORT_SYMBOL_GPL(gre_handle_offloads);

static bool is_gre_gso(struct sk_buff *skb)
{
Expand Down Expand Up @@ -334,6 +337,7 @@ void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,

ovs_skb_set_inner_protocol(skb, tpi->proto);
}
EXPORT_SYMBOL_GPL(gre_build_header);

#endif /* CONFIG_NET_IPGRE_DEMUX */

Expand Down
4 changes: 4 additions & 0 deletions datapath/linux/compat/ip_tunnels_core.c
Expand Up @@ -80,6 +80,7 @@ int rpl_iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
pkt_len = 0;
return pkt_len;
}
EXPORT_SYMBOL_GPL(rpl_iptunnel_xmit);

struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
bool csum_help, int gso_type_mask,
Expand Down Expand Up @@ -132,6 +133,7 @@ struct sk_buff *ovs_iptunnel_handle_offloads(struct sk_buff *skb,
kfree_skb(skb);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(ovs_iptunnel_handle_offloads);

int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
{
Expand Down Expand Up @@ -166,6 +168,7 @@ int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto)
skb->pkt_type = PACKET_HOST;
return 0;
}
EXPORT_SYMBOL_GPL(iptunnel_pull_header);

#endif

Expand All @@ -176,3 +179,4 @@ bool skb_is_encapsulated(struct sk_buff *skb)
*/
return ovs_skb_get_inner_protocol(skb) || skb_encapsulation(skb);
}
EXPORT_SYMBOL_GPL(skb_is_encapsulated);
6 changes: 6 additions & 0 deletions datapath/linux/compat/udp_tunnel.c
Expand Up @@ -95,6 +95,7 @@ int udp_sock_create(struct net *net, struct udp_port_cfg *cfg,
*sockp = NULL;
return err;
}
EXPORT_SYMBOL_GPL(udp_sock_create);

void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
struct udp_tunnel_sock_cfg *cfg)
Expand All @@ -114,6 +115,7 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,

udp_tunnel_encap_enable(sock);
}
EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);

void ovs_udp_gso(struct sk_buff *skb)
{
Expand All @@ -123,6 +125,7 @@ void ovs_udp_gso(struct sk_buff *skb)
uh = udp_hdr(skb);
uh->len = htons(skb->len - udp_offset);
}
EXPORT_SYMBOL_GPL(ovs_udp_gso);

void ovs_udp_csum_gso(struct sk_buff *skb)
{
Expand All @@ -137,6 +140,7 @@ void ovs_udp_csum_gso(struct sk_buff *skb)
udp_set_csum(true, skb, iph->saddr, iph->daddr,
skb->len - udp_offset);
}
EXPORT_SYMBOL_GPL(ovs_udp_csum_gso);

int udp_tunnel_xmit_skb(struct rtable *rt, struct sk_buff *skb,
__be32 src, __be32 dst, __u8 tos, __u8 ttl,
Expand All @@ -158,12 +162,14 @@ int udp_tunnel_xmit_skb(struct rtable *rt, struct sk_buff *skb,
return iptunnel_xmit(skb->sk, rt, skb, src, dst, IPPROTO_UDP,
tos, ttl, df, xnet);
}
EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb);

void udp_tunnel_sock_release(struct socket *sock)
{
rcu_assign_sk_user_data(sock->sk, NULL);
kernel_sock_shutdown(sock, SHUT_RDWR);
sk_release_kernel(sock->sk);
}
EXPORT_SYMBOL_GPL(udp_tunnel_sock_release);

#endif /* Linux version < 3.20 */
3 changes: 3 additions & 0 deletions datapath/linux/compat/vxlan.c
Expand Up @@ -225,6 +225,7 @@ int vxlan_xmit_skb(struct vxlan_sock *vs,
ttl, df, src_port, dst_port, xnet,
!udp_sum);
}
EXPORT_SYMBOL_GPL(vxlan_xmit_skb);

static void rcu_free_vs(struct rcu_head *rcu)
{
Expand Down Expand Up @@ -313,12 +314,14 @@ struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
{
return vxlan_socket_create(net, port, rcv, data, flags);
}
EXPORT_SYMBOL_GPL(vxlan_sock_add);

void vxlan_sock_release(struct vxlan_sock *vs)
{
ASSERT_OVSL();

queue_work(system_wq, &vs->del_work);
}
EXPORT_SYMBOL_GPL(vxlan_sock_release);

#endif /* !USE_UPSTREAM_VXLAN */
22 changes: 21 additions & 1 deletion datapath/vport-geneve.c
Expand Up @@ -27,6 +27,8 @@
#include "datapath.h"
#include "vport.h"

static struct vport_ops ovs_geneve_vport_ops;

/**
* struct geneve_port - Keeps track of open UDP ports
* @gs: The socket created for this port number.
Expand Down Expand Up @@ -248,12 +250,30 @@ static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
IPPROTO_UDP, skb->mark, sport, dport);
}

const struct vport_ops ovs_geneve_vport_ops = {
static struct vport_ops ovs_geneve_vport_ops = {
.type = OVS_VPORT_TYPE_GENEVE,
.create = geneve_tnl_create,
.destroy = geneve_tnl_destroy,
.get_name = geneve_get_name,
.get_options = geneve_get_options,
.send = geneve_tnl_send,
.get_egress_tun_info = geneve_get_egress_tun_info,
.owner = THIS_MODULE,
};

static int __init ovs_geneve_tnl_init(void)
{
return ovs_vport_ops_register(&ovs_geneve_vport_ops);
}

static void __exit ovs_geneve_tnl_exit(void)
{
ovs_vport_ops_unregister(&ovs_geneve_vport_ops);
}

module_init(ovs_geneve_tnl_init);
module_exit(ovs_geneve_tnl_exit);

MODULE_DESCRIPTION("OVS: Geneve swiching port");
MODULE_LICENSE("GPL");
MODULE_ALIAS("vport-type-5");
39 changes: 37 additions & 2 deletions datapath/vport-gre.c
Expand Up @@ -31,6 +31,7 @@
#include <linux/jhash.h>
#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/rculist.h>
#include <net/net_namespace.h>
Expand All @@ -47,6 +48,9 @@
#include "datapath.h"
#include "vport.h"

static struct vport_ops ovs_gre_vport_ops;
static struct vport_ops ovs_gre64_vport_ops;

/* Returns the least-significant 32 bits of a __be64. */
static __be32 be64_get_low32(__be64 x)
{
Expand Down Expand Up @@ -308,13 +312,14 @@ static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
IPPROTO_GRE, skb->mark, 0, 0);
}

const struct vport_ops ovs_gre_vport_ops = {
static struct vport_ops ovs_gre_vport_ops = {
.type = OVS_VPORT_TYPE_GRE,
.create = gre_create,
.destroy = gre_tnl_destroy,
.get_name = gre_get_name,
.send = gre_send,
.get_egress_tun_info = gre_get_egress_tun_info,
.owner = THIS_MODULE,
};

/* GRE64 vport. */
Expand Down Expand Up @@ -387,12 +392,42 @@ static int gre64_send(struct vport *vport, struct sk_buff *skb)
return __send(vport, skb, hlen, seq, (TUNNEL_KEY|TUNNEL_SEQ));
}

const struct vport_ops ovs_gre64_vport_ops = {
static struct vport_ops ovs_gre64_vport_ops = {
.type = OVS_VPORT_TYPE_GRE64,
.create = gre64_create,
.destroy = gre64_tnl_destroy,
.get_name = gre_get_name,
.send = gre64_send,
.get_egress_tun_info = gre_get_egress_tun_info,
.owner = THIS_MODULE,
};

static int __init ovs_gre_tnl_init(void)
{
int err;

err = ovs_vport_ops_register(&ovs_gre_vport_ops);
if (err < 0)
return err;

err = ovs_vport_ops_register(&ovs_gre64_vport_ops);
if (err < 0)
ovs_vport_ops_unregister(&ovs_gre_vport_ops);

return err;
}

static void __exit ovs_gre_tnl_exit(void)
{
ovs_vport_ops_unregister(&ovs_gre64_vport_ops);
ovs_vport_ops_unregister(&ovs_gre_vport_ops);
}

module_init(ovs_gre_tnl_init);
module_exit(ovs_gre_tnl_exit);

MODULE_DESCRIPTION("OVS: GRE switching port");
MODULE_LICENSE("GPL");
MODULE_ALIAS("vport-type-3");
MODULE_ALIAS("vport-type-104");
#endif

0 comments on commit 5a38795

Please sign in to comment.