linux/net/openvswitch/vport-geneve.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (c) 2014 Nicira, Inc.
   4 */
   5
   6#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   7
   8#include <linux/in.h>
   9#include <linux/ip.h>
  10#include <linux/net.h>
  11#include <linux/rculist.h>
  12#include <linux/udp.h>
  13#include <linux/if_vlan.h>
  14#include <linux/module.h>
  15
  16#include <net/geneve.h>
  17#include <net/icmp.h>
  18#include <net/ip.h>
  19#include <net/route.h>
  20#include <net/udp.h>
  21#include <net/xfrm.h>
  22
  23#include "datapath.h"
  24#include "vport.h"
  25#include "vport-netdev.h"
  26
  27static struct vport_ops ovs_geneve_vport_ops;
  28/**
  29 * struct geneve_port - Keeps track of open UDP ports
  30 * @dst_port: destination port.
  31 */
  32struct geneve_port {
  33        u16 dst_port;
  34};
  35
  36static inline struct geneve_port *geneve_vport(const struct vport *vport)
  37{
  38        return vport_priv(vport);
  39}
  40
  41static int geneve_get_options(const struct vport *vport,
  42                              struct sk_buff *skb)
  43{
  44        struct geneve_port *geneve_port = geneve_vport(vport);
  45
  46        if (nla_put_u16(skb, OVS_TUNNEL_ATTR_DST_PORT, geneve_port->dst_port))
  47                return -EMSGSIZE;
  48        return 0;
  49}
  50
  51static struct vport *geneve_tnl_create(const struct vport_parms *parms)
  52{
  53        struct net *net = ovs_dp_get_net(parms->dp);
  54        struct nlattr *options = parms->options;
  55        struct geneve_port *geneve_port;
  56        struct net_device *dev;
  57        struct vport *vport;
  58        struct nlattr *a;
  59        u16 dst_port;
  60        int err;
  61
  62        if (!options) {
  63                err = -EINVAL;
  64                goto error;
  65        }
  66
  67        a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT);
  68        if (a && nla_len(a) == sizeof(u16)) {
  69                dst_port = nla_get_u16(a);
  70        } else {
  71                /* Require destination port from userspace. */
  72                err = -EINVAL;
  73                goto error;
  74        }
  75
  76        vport = ovs_vport_alloc(sizeof(struct geneve_port),
  77                                &ovs_geneve_vport_ops, parms);
  78        if (IS_ERR(vport))
  79                return vport;
  80
  81        geneve_port = geneve_vport(vport);
  82        geneve_port->dst_port = dst_port;
  83
  84        rtnl_lock();
  85        dev = geneve_dev_create_fb(net, parms->name, NET_NAME_USER, dst_port);
  86        if (IS_ERR(dev)) {
  87                rtnl_unlock();
  88                ovs_vport_free(vport);
  89                return ERR_CAST(dev);
  90        }
  91
  92        err = dev_change_flags(dev, dev->flags | IFF_UP, NULL);
  93        if (err < 0) {
  94                rtnl_delete_link(dev);
  95                rtnl_unlock();
  96                ovs_vport_free(vport);
  97                goto error;
  98        }
  99
 100        rtnl_unlock();
 101        return vport;
 102error:
 103        return ERR_PTR(err);
 104}
 105
 106static struct vport *geneve_create(const struct vport_parms *parms)
 107{
 108        struct vport *vport;
 109
 110        vport = geneve_tnl_create(parms);
 111        if (IS_ERR(vport))
 112                return vport;
 113
 114        return ovs_netdev_link(vport, parms->name);
 115}
 116
 117static struct vport_ops ovs_geneve_vport_ops = {
 118        .type           = OVS_VPORT_TYPE_GENEVE,
 119        .create         = geneve_create,
 120        .destroy        = ovs_netdev_tunnel_destroy,
 121        .get_options    = geneve_get_options,
 122        .send           = dev_queue_xmit,
 123};
 124
 125static int __init ovs_geneve_tnl_init(void)
 126{
 127        return ovs_vport_ops_register(&ovs_geneve_vport_ops);
 128}
 129
 130static void __exit ovs_geneve_tnl_exit(void)
 131{
 132        ovs_vport_ops_unregister(&ovs_geneve_vport_ops);
 133}
 134
 135module_init(ovs_geneve_tnl_init);
 136module_exit(ovs_geneve_tnl_exit);
 137
 138MODULE_DESCRIPTION("OVS: Geneve switching port");
 139MODULE_LICENSE("GPL");
 140MODULE_ALIAS("vport-type-5");
 141