iph = ip_hdr(skb);
tnl_flags = gre_flags_to_tunnel_flags(gre_flags, is_gre64);
tnl_tun_key_init(&tun_key, iph, key, tnl_flags);
- OVS_CB(skb)->tun_key = &tun_key;
__skb_pull(skb, hdr_len);
skb_postpull_rcsum(skb, skb_transport_header(skb), hdr_len + ETH_HLEN);
- ovs_tnl_rcv(vport, skb);
+ ovs_tnl_rcv(vport, skb, &tun_key);
return 0;
error:
#endif
};
-static bool inited;
-
+static int gre_ports;
static int gre_init(void)
{
int err;
- if (inited)
+ gre_ports++;
+ if (gre_ports > 1)
return 0;
- inited = true;
err = inet_add_protocol(&gre_protocol_handlers, IPPROTO_GRE);
if (err)
pr_warn("cannot register gre protocol handler\n");
static void gre_exit(void)
{
- if (!inited)
+ gre_ports--;
+ if (gre_ports > 0)
return;
- inited = false;
-
inet_del_protocol(&gre_protocol_handlers, IPPROTO_GRE);
}
-/* GRE vport. */
-static const struct tnl_ops gre_tnl_ops = {
- .ipproto = IPPROTO_GRE,
- .hdr_len = gre_hdr_len,
- .build_header = gre_build_header,
-};
+static const char *gre_get_name(const struct vport *vport)
+{
+ return vport_priv(vport);
+}
static struct vport *gre_create(const struct vport_parms *parms)
{
struct net *net = ovs_dp_get_net(parms->dp);
struct ovs_net *ovs_net;
struct vport *vport;
+ int err;
+
+ err = gre_init();
+ if (err)
+ return ERR_PTR(err);
ovs_net = net_generic(net, ovs_net_id);
- if (rtnl_dereference(ovs_net->vport_net.gre_vport))
- return ERR_PTR(-EEXIST);
+ if (ovsl_dereference(ovs_net->vport_net.gre_vport)) {
+ vport = ERR_PTR(-EEXIST);
+ goto error;
+ }
- vport = ovs_tnl_create(parms, &ovs_gre_vport_ops, &gre_tnl_ops);
+ vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre_vport_ops, parms);
+ if (IS_ERR(vport))
+ goto error;
+ strncpy(vport_priv(vport), parms->name, IFNAMSIZ);
rcu_assign_pointer(ovs_net->vport_net.gre_vport, vport);
return vport;
+
+error:
+ gre_exit();
+ return vport;
}
static void gre_tnl_destroy(struct vport *vport)
ovs_net = net_generic(net, ovs_net_id);
rcu_assign_pointer(ovs_net->vport_net.gre_vport, NULL);
- ovs_tnl_destroy(vport);
+ ovs_vport_deferred_free(vport);
+ gre_exit();
+}
+
+static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
+{
+ int hlen;
+
+ if (unlikely(!OVS_CB(skb)->tun_key))
+ return -EINVAL;
+
+ hlen = gre_hdr_len(OVS_CB(skb)->tun_key);
+ return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre_build_header);
}
const struct vport_ops ovs_gre_vport_ops = {
.type = OVS_VPORT_TYPE_GRE,
- .flags = VPORT_F_TUN_ID,
- .init = gre_init,
- .exit = gre_exit,
.create = gre_create,
.destroy = gre_tnl_destroy,
- .get_name = ovs_tnl_get_name,
- .send = ovs_tnl_send,
+ .get_name = gre_get_name,
+ .send = gre_tnl_send,
};
/* GRE64 vport. */
-static const struct tnl_ops gre64_tnl_ops = {
- .ipproto = IPPROTO_GRE,
- .hdr_len = gre64_hdr_len,
- .build_header = gre64_build_header,
-};
-
static struct vport *gre64_create(const struct vport_parms *parms)
{
struct net *net = ovs_dp_get_net(parms->dp);
struct ovs_net *ovs_net;
struct vport *vport;
+ int err;
+
+ err = gre_init();
+ if (err)
+ return ERR_PTR(err);
ovs_net = net_generic(net, ovs_net_id);
- if (rtnl_dereference(ovs_net->vport_net.gre64_vport))
- return ERR_PTR(-EEXIST);
+ if (ovsl_dereference(ovs_net->vport_net.gre64_vport)) {
+ vport = ERR_PTR(-EEXIST);
+ goto error;
+ }
- vport = ovs_tnl_create(parms, &ovs_gre64_vport_ops, &gre64_tnl_ops);
+ vport = ovs_vport_alloc(IFNAMSIZ, &ovs_gre64_vport_ops, parms);
+ if (IS_ERR(vport))
+ goto error;
+ strncpy(vport_priv(vport), parms->name, IFNAMSIZ);
rcu_assign_pointer(ovs_net->vport_net.gre64_vport, vport);
return vport;
+error:
+ gre_exit();
+ return vport;
}
-
static void gre64_tnl_destroy(struct vport *vport)
{
struct net *net = ovs_dp_get_net(vport->dp);
ovs_net = net_generic(net, ovs_net_id);
rcu_assign_pointer(ovs_net->vport_net.gre64_vport, NULL);
- ovs_tnl_destroy(vport);
+ ovs_vport_deferred_free(vport);
+ gre_exit();
+}
+
+static int gre64_tnl_send(struct vport *vport, struct sk_buff *skb)
+{
+ int hlen;
+
+ if (unlikely(!OVS_CB(skb)->tun_key))
+ return -EINVAL;
+
+ hlen = gre64_hdr_len(OVS_CB(skb)->tun_key);
+ return ovs_tnl_send(vport, skb, IPPROTO_GRE, hlen, gre64_build_header);
}
const struct vport_ops ovs_gre64_vport_ops = {
.type = OVS_VPORT_TYPE_GRE64,
- .flags = VPORT_F_TUN_ID,
- .init = gre_init,
- .exit = gre_exit,
.create = gre64_create,
.destroy = gre64_tnl_destroy,
- .get_name = ovs_tnl_get_name,
- .send = ovs_tnl_send,
+ .get_name = gre_get_name,
+ .send = gre64_tnl_send,
};