static LIST_HEAD(vport_ops_list);
static bool compat_gre_loaded = false;
+static bool compat_ip6_tunnel_loaded = false;
/* Protected by RCU read lock for reading, ovs_mutex for writing. */
static struct hlist_head *dev_table;
{
int err;
- dev_table = kzalloc(VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
+ dev_table = kcalloc(VPORT_HASH_BUCKETS, sizeof(struct hlist_head),
GFP_KERNEL);
if (!dev_table)
return -ENOMEM;
if (err)
goto err_lisp;
err = gre_init();
- if (err && err != -EEXIST)
+ if (err && err != -EEXIST) {
goto err_gre;
- else if (err == -EEXIST)
- pr_warn("Cannot take GRE protocol entry - The ERSPAN feature may not be supported\n");
- else {
+ } else {
+ if (err == -EEXIST) {
+ pr_warn("Cannot take GRE protocol rx entry"\
+ "- The GRE/ERSPAN rx feature not supported\n");
+ /* continue GRE tx */
+ }
+
err = ipgre_init();
if (err && err != -EEXIST)
goto err_ipgre;
compat_gre_loaded = true;
}
err = ip6gre_init();
- if (err)
+ if (err && err != -EEXIST) {
goto err_ip6gre;
+ } else {
+ if (err == -EEXIST) {
+ pr_warn("IPv6 GRE/ERSPAN Rx mode is not supported\n");
+ goto skip_ip6_tunnel_init;
+ }
+ }
+
err = ip6_tunnel_init();
if (err)
goto err_ip6_tunnel;
+ else
+ compat_ip6_tunnel_loaded = true;
+
+skip_ip6_tunnel_init:
err = geneve_init_module();
if (err)
goto err_geneve;
ovs_stt_cleanup_module();
vxlan_cleanup_module();
geneve_cleanup_module();
- ip6_tunnel_cleanup();
+ if (compat_ip6_tunnel_loaded)
+ ip6_tunnel_cleanup();
ip6gre_fini();
lisp_cleanup_module();
kfree(dev_table);
return vport;
}
+ if (parms->type == OVS_VPORT_TYPE_GRE && !compat_gre_loaded) {
+ pr_warn("GRE protocol already loaded!\n");
+ return ERR_PTR(-EAFNOSUPPORT);
+ }
/* Unlock to attempt module load and return -EAGAIN if load
* was successful as we need to restart the port addition
* workflow.
if (!vport->ops->get_options)
return 0;
- nla = nla_nest_start(skb, OVS_VPORT_ATTR_OPTIONS);
+ nla = nla_nest_start_noflag(skb, OVS_VPORT_ATTR_OPTIONS);
if (!nla)
return -EMSGSIZE;
ids = rcu_dereference(vport->upcall_portids);
- if (ids->n_ids == 1 && ids->ids[0] == 0)
- return 0;
+ /* If there is only one portid, select it in the fast-path. */
+ if (ids->n_ids == 1)
+ return ids->ids[0];
hash = skb_get_hash(skb);
ids_index = hash - ids->n_ids * reciprocal_divide(hash, ids->rn_ids);