#include "vport-internal_dev.h"
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;
err = lisp_init_module();
if (err)
goto err_lisp;
- err = ipgre_init();
- if (err)
- goto err_ipgre;
+ err = gre_init();
+ if (err && err != -EEXIST) {
+ goto err_gre;
+ } 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;
err = ovs_stt_init_module();
if (err)
goto err_stt;
- err = gre_init();
- if (err)
- goto err_gre;
return 0;
-err_gre:
ovs_stt_cleanup_module();
err_stt:
vxlan_cleanup_module();
err_ip6gre:
ipgre_fini();
err_ipgre:
+ gre_exit();
+err_gre:
lisp_cleanup_module();
err_lisp:
kfree(dev_table);
*/
void ovs_vport_exit(void)
{
- gre_exit();
+ if (compat_gre_loaded) {
+ gre_exit();
+ ipgre_fini();
+ }
ovs_stt_cleanup_module();
vxlan_cleanup_module();
geneve_cleanup_module();
- ip6_tunnel_cleanup();
+ if (compat_ip6_tunnel_loaded)
+ ip6_tunnel_cleanup();
ip6gre_fini();
- ipgre_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);