static struct vport *gre_create(const struct vport_parms *parms) { struct vport *vport; vport = gre_tnl_create(parms); if (IS_ERR(vport)) return vport; return ovs_netdev_link(vport, parms->name); }
static struct vport *netdev_create(const struct vport_parms *parms) { struct vport *vport; vport = ovs_vport_alloc(0, &ovs_netdev_vport_ops, parms); if (IS_ERR(vport)) return vport; return ovs_netdev_link(vport, parms->name); }
static struct vport *vxlan_tnl_create(const struct vport_parms *parms) { struct net *net = ovs_dp_get_net(parms->dp); struct nlattr *options = parms->options; struct net_device *dev; struct vport *vport; struct nlattr *a; int err; struct vxlan_config conf = { .no_share = true, .flags = VXLAN_F_COLLECT_METADATA, }; if (!options) { err = -EINVAL; goto error; } a = nla_find_nested(options, OVS_TUNNEL_ATTR_DST_PORT); if (a && nla_len(a) == sizeof(u16)) { conf.dst_port = htons(nla_get_u16(a)); } else { /* Require destination port from userspace. */ err = -EINVAL; goto error; } vport = ovs_vport_alloc(0, &ovs_vxlan_netdev_vport_ops, parms); if (IS_ERR(vport)) return vport; a = nla_find_nested(options, OVS_TUNNEL_ATTR_EXTENSION); if (a) { err = vxlan_configure_exts(vport, a, &conf); if (err) { ovs_vport_free(vport); goto error; } } rtnl_lock(); dev = vxlan_dev_create(net, parms->name, NET_NAME_USER, &conf); if (IS_ERR(dev)) { rtnl_unlock(); ovs_vport_free(vport); return ERR_CAST(dev); } dev_change_flags(dev, dev->flags | IFF_UP); rtnl_unlock(); return vport; error: return ERR_PTR(err); } static struct vport *vxlan_create(const struct vport_parms *parms) { struct vport *vport; vport = vxlan_tnl_create(parms); if (IS_ERR(vport)) return vport; return ovs_netdev_link(vport, parms->name); } static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, struct dp_upcall_info *upcall) { struct vxlan_dev *vxlan = netdev_priv(vport->dev); struct net *net = ovs_dp_get_net(vport->dp); unsigned short family = ip_tunnel_info_af(upcall->egress_tun_info); __be16 dst_port = vxlan_dev_dst_port(vxlan, family); __be16 src_port; int port_min; int port_max; inet_get_local_port_range(net, &port_min, &port_max); src_port = udp_flow_src_port(net, skb, 0, 0, true); return ovs_tunnel_get_egress_info(upcall, net, skb, IPPROTO_UDP, src_port, dst_port); } static struct vport_ops ovs_vxlan_netdev_vport_ops = { .type = OVS_VPORT_TYPE_VXLAN, .create = vxlan_create, .destroy = ovs_netdev_tunnel_destroy, .get_options = vxlan_get_options, .send = ovs_netdev_send, .get_egress_tun_info = vxlan_get_egress_tun_info, }; static int __init ovs_vxlan_tnl_init(void) { return ovs_vport_ops_register(&ovs_vxlan_netdev_vport_ops); } static void __exit ovs_vxlan_tnl_exit(void) { ovs_vport_ops_unregister(&ovs_vxlan_netdev_vport_ops); }