Skip to content

Commit 08271c6

Browse files
wip: openvswtich: add non-tap (l3) support to GRE vports
** This is not yet ready for upstream submission and is provided ** for informational purposes only Signed-off-by: Simon Horman <simon.horman@netronome.com>
1 parent 4b231ff commit 08271c6

File tree

6 files changed

+83
-25
lines changed

6 files changed

+83
-25
lines changed

include/net/gre.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,6 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version);
2525

2626
struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
2727
u8 name_assign_type);
28+
struct net_device *gre_fb_dev_create(struct net *net, const char *name,
29+
u8 name_assign_type);
2830
#endif

include/uapi/linux/openvswitch.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,10 @@ enum ovs_vport_type {
207207
OVS_VPORT_TYPE_UNSPEC,
208208
OVS_VPORT_TYPE_NETDEV, /* network device */
209209
OVS_VPORT_TYPE_INTERNAL, /* network device implemented by datapath */
210-
OVS_VPORT_TYPE_GRE, /* GRE tunnel. */
210+
OVS_VPORT_TYPE_GRE, /* GRE Tap tunnel (L2 in GRE). */
211211
OVS_VPORT_TYPE_VXLAN, /* VXLAN tunnel. */
212212
OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */
213+
OVS_VPORT_TYPE_GRE_L3, /* GRE tunnel (L3 in GRE). */
213214
__OVS_VPORT_TYPE_MAX
214215
};
215216

net/ipv4/ip_gre.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,8 @@ static struct rtable *gre_get_rt(struct sk_buff *skb,
514514
return ip_route_output_key(net, fl);
515515
}
516516

517-
static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
517+
static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev,
518+
__be16 proto)
518519
{
519520
struct ip_tunnel_info *tun_info;
520521
const struct ip_tunnel_key *key;
@@ -557,7 +558,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
557558
}
558559

559560
flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY);
560-
build_header(skb, tunnel_hlen, flags, htons(ETH_P_TEB),
561+
build_header(skb, tunnel_hlen, flags, proto,
561562
tunnel_id_to_key(tun_info->key.tun_id), 0);
562563

563564
df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
@@ -598,7 +599,8 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
598599
const struct iphdr *tnl_params;
599600

600601
if (tunnel->collect_md) {
601-
gre_fb_xmit(skb, dev);
602+
//BUG_ON(dev->header_ops); // XXX: Delete me
603+
gre_fb_xmit(skb, dev, skb->protocol);
602604
return NETDEV_TX_OK;
603605
}
604606

@@ -642,7 +644,7 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb,
642644
struct ip_tunnel *tunnel = netdev_priv(dev);
643645

644646
if (tunnel->collect_md) {
645-
gre_fb_xmit(skb, dev);
647+
gre_fb_xmit(skb, dev, htons(ETH_P_TEB));
646648
return NETDEV_TX_OK;
647649
}
648650

@@ -1218,8 +1220,9 @@ static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
12181220
.get_link_net = ip_tunnel_get_link_net,
12191221
};
12201222

1221-
struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1222-
u8 name_assign_type)
1223+
struct net_device *gretap_fb_dev_create__(struct net *net, const char *name,
1224+
u8 name_assign_type,
1225+
struct rtnl_link_ops *link_ops)
12231226
{
12241227
struct nlattr *tb[IFLA_MAX + 1];
12251228
struct net_device *dev;
@@ -1228,8 +1231,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
12281231

12291232
memset(&tb, 0, sizeof(tb));
12301233

1231-
dev = rtnl_create_link(net, name, name_assign_type,
1232-
&ipgre_tap_ops, tb);
1234+
dev = rtnl_create_link(net, name, name_assign_type, link_ops, tb);
12331235
if (IS_ERR(dev))
12341236
return dev;
12351237

@@ -1245,8 +1247,23 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
12451247
free_netdev(dev);
12461248
return ERR_PTR(err);
12471249
}
1250+
1251+
struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
1252+
u8 name_assign_type)
1253+
{
1254+
return gretap_fb_dev_create__(net, name, name_assign_type,
1255+
&ipgre_tap_ops);
1256+
}
12481257
EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
12491258

1259+
struct net_device *gre_fb_dev_create(struct net *net, const char *name,
1260+
u8 name_assign_type)
1261+
{
1262+
return gretap_fb_dev_create__(net, name, name_assign_type,
1263+
&ipgre_link_ops);
1264+
}
1265+
EXPORT_SYMBOL_GPL(gre_fb_dev_create);
1266+
12501267
static int __net_init ipgre_tap_init_net(struct net *net)
12511268
{
12521269
return ip_tunnel_init_net(net, gre_tap_net_id, &ipgre_tap_ops, "gretap0");

net/openvswitch/vport-gre.c

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,25 @@
4747
#include "vport.h"
4848
#include "vport-netdev.h"
4949

50+
static struct vport_ops ovs_gre_tap_vport_ops;
5051
static struct vport_ops ovs_gre_vport_ops;
5152

52-
static struct vport *gre_tnl_create(const struct vport_parms *parms)
53+
static struct vport *gre_tnl_create(const struct vport_parms *parms,
54+
const struct vport_ops *ops,
55+
struct net_device *fn(struct net *net,
56+
const char *name,
57+
u8 name_assign_type))
5358
{
5459
struct net *net = ovs_dp_get_net(parms->dp);
5560
struct net_device *dev;
5661
struct vport *vport;
5762

58-
vport = ovs_vport_alloc(0, &ovs_gre_vport_ops, parms);
63+
vport = ovs_vport_alloc(0, ops, parms);
5964
if (IS_ERR(vport))
6065
return vport;
6166

6267
rtnl_lock();
63-
dev = gretap_fb_dev_create(net, parms->name, NET_NAME_USER);
68+
dev = fn(net, parms->name, NET_NAME_USER);
6469
if (IS_ERR(dev)) {
6570
rtnl_unlock();
6671
ovs_vport_free(vport);
@@ -70,34 +75,53 @@ static struct vport *gre_tnl_create(const struct vport_parms *parms)
7075
dev_change_flags(dev, dev->flags | IFF_UP);
7176
rtnl_unlock();
7277

73-
return vport;
78+
return ovs_netdev_link(vport, parms->name);
7479
}
7580

76-
static struct vport *gre_create(const struct vport_parms *parms)
81+
static struct vport *gre_tap_create(const struct vport_parms *parms)
7782
{
78-
struct vport *vport;
79-
80-
vport = gre_tnl_create(parms);
81-
if (IS_ERR(vport))
82-
return vport;
83+
return gre_tnl_create(parms, &ovs_gre_tap_vport_ops,
84+
gretap_fb_dev_create);
85+
}
8386

84-
return ovs_netdev_link(vport, parms->name);
87+
static struct vport *gre_create(const struct vport_parms *parms)
88+
{
89+
return gre_tnl_create(parms, &ovs_gre_vport_ops, gre_fb_dev_create);
8590
}
8691

87-
static struct vport_ops ovs_gre_vport_ops = {
92+
static struct vport_ops ovs_gre_tap_vport_ops = {
8893
.type = OVS_VPORT_TYPE_GRE,
89-
.create = gre_create,
94+
.create = gre_tap_create,
9095
.send = ovs_netdev_send_tap,
9196
.destroy = ovs_netdev_tunnel_destroy,
9297
};
9398

99+
static struct vport_ops ovs_gre_vport_ops = {
100+
.type = OVS_VPORT_TYPE_GRE_L3,
101+
.is_layer3 = true,
102+
.create = gre_create,
103+
.send = ovs_netdev_send,
104+
.destroy = ovs_netdev_tunnel_destroy,
105+
};
106+
94107
static int __init ovs_gre_tnl_init(void)
95108
{
96-
return ovs_vport_ops_register(&ovs_gre_vport_ops);
109+
int err;
110+
111+
err = ovs_vport_ops_register(&ovs_gre_tap_vport_ops);
112+
if (err)
113+
return err;
114+
115+
err = ovs_vport_ops_register(&ovs_gre_vport_ops);
116+
if (err)
117+
ovs_vport_ops_unregister(&ovs_gre_tap_vport_ops);
118+
119+
return err;
97120
}
98121

99122
static void __exit ovs_gre_tnl_exit(void)
100123
{
124+
ovs_vport_ops_unregister(&ovs_gre_tap_vport_ops);
101125
ovs_vport_ops_unregister(&ovs_gre_vport_ops);
102126
}
103127

@@ -106,4 +130,5 @@ module_exit(ovs_gre_tnl_exit);
106130

107131
MODULE_DESCRIPTION("OVS: GRE switching port");
108132
MODULE_LICENSE("GPL");
109-
MODULE_ALIAS("vport-type-3");
133+
MODULE_ALIAS("vport-type-3"); /* OVS_VPORT_TYPE_GRE (3) */
134+
MODULE_ALIAS("vport-type-6"); /* OVS_VPORT_TYPE_GRE_L3 (6) */

net/openvswitch/vport-netdev.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ struct vport *ovs_netdev_link(struct vport *vport, const char *name)
9999
}
100100

101101
if (vport->dev->flags & IFF_LOOPBACK ||
102-
vport->dev->type != ARPHRD_ETHER ||
102+
(vport->dev->type != ARPHRD_ETHER &&
103+
vport->dev->type != ARPHRD_IPGRE) ||
103104
ovs_is_internal_dev(vport->dev)) {
104105
err = -EINVAL;
105106
goto error_put;
@@ -207,6 +208,17 @@ int ovs_netdev_send_tap(struct sk_buff *skb)
207208
}
208209
EXPORT_SYMBOL_GPL(ovs_netdev_send_tap);
209210

211+
int ovs_netdev_send(struct sk_buff *skb)
212+
{
213+
/* Only send L3 packets */
214+
if (!skb->mac_len)
215+
return dev_queue_xmit(skb);
216+
217+
kfree_skb(skb);
218+
return -EINVAL;
219+
}
220+
EXPORT_SYMBOL_GPL(ovs_netdev_send);
221+
210222
/* Returns null if this device is not attached to a datapath. */
211223
struct vport *ovs_netdev_get_vport(struct net_device *dev)
212224
{

net/openvswitch/vport-netdev.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ void ovs_netdev_exit(void);
3535
void ovs_netdev_tunnel_destroy(struct vport *vport);
3636

3737
int ovs_netdev_send_tap(struct sk_buff *skb);
38+
int ovs_netdev_send(struct sk_buff *skb);
3839
#endif /* vport_netdev.h */

0 commit comments

Comments
 (0)