Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (c) 2014 Nicira, Inc.
0004  */
0005 
0006 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0007 
0008 #include <linux/in.h>
0009 #include <linux/ip.h>
0010 #include <linux/net.h>
0011 #include <linux/rculist.h>
0012 #include <linux/udp.h>
0013 #include <linux/if_vlan.h>
0014 #include <linux/module.h>
0015 
0016 #include <net/geneve.h>
0017 #include <net/icmp.h>
0018 #include <net/ip.h>
0019 #include <net/route.h>
0020 #include <net/udp.h>
0021 #include <net/xfrm.h>
0022 
0023 #include "datapath.h"
0024 #include "vport.h"
0025 #include "vport-netdev.h"
0026 
0027 static struct vport_ops ovs_geneve_vport_ops;
0028 /**
0029  * struct geneve_port - Keeps track of open UDP ports
0030  * @dst_port: destination port.
0031  */
0032 struct geneve_port {
0033     u16 dst_port;
0034 };
0035 
0036 static inline struct geneve_port *geneve_vport(const struct vport *vport)
0037 {
0038     return vport_priv(vport);
0039 }
0040 
0041 static int geneve_get_options(const struct vport *vport,
0042                   struct sk_buff *skb)
0043 {
0044     struct geneve_port *geneve_port = geneve_vport(vport);
0045 
0046     if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, geneve_port->dst_port))
0047         return -EMSGSIZE;
0048     return 0;
0049 }
0050 
0051 static struct vport *geneve_tnl_create(const struct vport_parms *parms)
0052 {
0053     struct net *net = ovs_dp_get_net(parms->dp);
0054     struct nlattr *options = parms->options;
0055     struct geneve_port *geneve_port;
0056     struct net_device *dev;
0057     struct vport *vport;
0058     struct nlattr *a;
0059     u16 dst_port;
0060     int err;
0061 
0062     if (!options) {
0063         err = -EINVAL;
0064         goto error;
0065     }
0066 
0067     a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT);
0068     if (a && nla_len(a) == sizeof(u16)) {
0069         dst_port = nla_get_u16(a);
0070     } else {
0071         /* Require destination port from userspace. */
0072         err = -EINVAL;
0073         goto error;
0074     }
0075 
0076     vport = ovs_vport_alloc(sizeof(struct geneve_port),
0077                 &ovs_geneve_vport_ops, parms);
0078     if (IS_ERR(vport))
0079         return vport;
0080 
0081     geneve_port = geneve_vport(vport);
0082     geneve_port->dst_port = dst_port;
0083 
0084     rtnl_lock();
0085     dev = geneve_dev_create_fb(net, parms->name, NET_NAME_USER, dst_port);
0086     if (IS_ERR(dev)) {
0087         rtnl_unlock();
0088         ovs_vport_free(vport);
0089         return ERR_CAST(dev);
0090     }
0091 
0092     err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
0093     if (err < 0) {
0094         rtnl_delete_link(dev);
0095         rtnl_unlock();
0096         ovs_vport_free(vport);
0097         goto error;
0098     }
0099 
0100     rtnl_unlock();
0101     return vport;
0102 error:
0103     return ERR_PTR(err);
0104 }
0105 
0106 static struct vport *geneve_create(const struct vport_parms *parms)
0107 {
0108     struct vport *vport;
0109 
0110     vport = geneve_tnl_create(parms);
0111     if (IS_ERR(vport))
0112         return vport;
0113 
0114     return ovs_netdev_link(vport, parms->name);
0115 }
0116 
0117 static struct vport_ops ovs_geneve_vport_ops = {
0118     .type       = OVS_VPORT_TYPE_GENEVE,
0119     .create     = geneve_create,
0120     .destroy    = ovs_netdev_tunnel_destroy,
0121     .get_options    = geneve_get_options,
0122     .send       = dev_queue_xmit,
0123 };
0124 
0125 static int __init ovs_geneve_tnl_init(void)
0126 {
0127     return ovs_vport_ops_register(&ovs_geneve_vport_ops);
0128 }
0129 
0130 static void __exit ovs_geneve_tnl_exit(void)
0131 {
0132     ovs_vport_ops_unregister(&ovs_geneve_vport_ops);
0133 }
0134 
0135 module_init(ovs_geneve_tnl_init);
0136 module_exit(ovs_geneve_tnl_exit);
0137 
0138 MODULE_DESCRIPTION("OVS: Geneve switching port");
0139 MODULE_LICENSE("GPL");
0140 MODULE_ALIAS("vport-type-5");