+static void release_socket(struct net *net)
+{
+ struct capwap_net *capwap_net = ovs_get_capwap_net(net);
+
+ capwap_net->n_tunnels--;
+ if (capwap_net->n_tunnels)
+ return;
+
+ inet_frags_exit_net(&capwap_net->frag_state, &frag_state);
+ sk_release_kernel(capwap_net->capwap_rcv_socket->sk);
+}
+
+static struct vport *capwap_create(const struct vport_parms *parms)
+{
+ struct vport *vport;
+ int err;
+
+ err = init_socket(ovs_dp_get_net(parms->dp));
+ if (err)
+ return ERR_PTR(err);
+
+ vport = ovs_tnl_create(parms, &ovs_capwap_vport_ops, &capwap_tnl_ops);
+ if (IS_ERR(vport))
+ release_socket(ovs_dp_get_net(parms->dp));
+
+ return vport;
+}
+
+static void capwap_destroy(struct vport *vport)
+{
+ ovs_tnl_destroy(vport);
+ release_socket(ovs_dp_get_net(vport->dp));
+}
+
+static int capwap_init(void)
+{
+ inet_frags_init(&frag_state);
+ return 0;
+}
+