[ovs-dev] [PATCH] datapath: work around the single GRE receive limitation.

Yifeng Sun pkusunyifeng at gmail.com
Tue Jul 10 23:27:01 UTC 2018


Looks good to me, thanks.

Reviewed-by: Yifeng Sun <pkusunyifeng at gmail.com>


On Tue, Jul 10, 2018 at 10:50 AM, William Tu <u9012063 at gmail.com> wrote:

> Commit 9f57c67c379d ("gre: Remove support for sharing GRE protocol hook")
> allows only single GRE packet receiver.  When upstream kernel's gre module
> is loaded, the gre.ko exclusively becomes the only gre packet receiver,
> preventing OVS kernel module from registering another gre receiver.
>
> We can either try to unload the gre.ko by removing its dependencies,
> or, in this patch, we try to register OVS as only the GRE transmit
> portion when detecting there already exists another GRE receiver.
>
> Signed-off-by: William Tu <u9012063 at gmail.com>
> Cc: Greg Rose <gvrose8192 at gmail.com>
> Cc: Yifeng Sun <pkusunyifeng at gmail.com>
> ---
>  datapath/linux/compat/ip_gre.c | 60 ++++++++++++++++++++++++++++++
> +++---------
>  datapath/vport.c               | 12 ++++++---
>  2 files changed, 56 insertions(+), 16 deletions(-)
>
> diff --git a/datapath/linux/compat/ip_gre.c b/datapath/linux/compat/ip_
> gre.c
> index 92de70127189..1ab798164894 100644
> --- a/datapath/linux/compat/ip_gre.c
> +++ b/datapath/linux/compat/ip_gre.c
> @@ -71,6 +71,7 @@ static void erspan_build_header(struct sk_buff *skb,
>                                 bool truncate, bool is_ipv4);
>
>  static struct rtnl_link_ops ipgre_link_ops __read_mostly;
> +static bool ip_gre_loaded = false;
>
>  #define ip_gre_calc_hlen rpl_ip_gre_calc_hlen
>  static int ip_gre_calc_hlen(__be16 o_flags)
> @@ -1640,25 +1641,57 @@ int rpl_ipgre_init(void)
>         int err;
>
>         err = register_pernet_device(&ipgre_tap_net_ops);
> -       if (err < 0)
> -               goto pnet_tap_failed;
> +       if (err < 0) {
> +               if (err == -EEXIST)
> +                       goto ip_gre_loaded;
> +               else
> +                       goto pnet_tap_failed;
> +       }
>
>         err = register_pernet_device(&erspan_net_ops);
> -       if (err < 0)
> -               goto pnet_erspan_failed;
> +       if (err < 0) {
> +               if (err == -EEXIST)
> +                       goto ip_gre_loaded;
> +               else
> +                       goto pnet_erspan_failed;
> +       }
>
>         err = register_pernet_device(&ipgre_net_ops);
> -       if (err < 0)
> -               goto pnet_ipgre_failed;
> +       if (err < 0) {
> +               if (err == -EEXIST)
> +                       goto ip_gre_loaded;
> +               else
> +                       goto pnet_ipgre_failed;
> +       }
>
>         err = gre_add_protocol(&ipgre_protocol, GREPROTO_CISCO);
>         if (err < 0) {
>                 pr_info("%s: can't add protocol\n", __func__);
> -               goto add_proto_failed;
> +               if (err == -EBUSY) {
> +                       goto ip_gre_loaded;
> +               } else {
> +                       goto add_proto_failed;
> +               }
>         }
>
>         pr_info("GRE over IPv4 tunneling driver\n");
> -
> +       ovs_vport_ops_register(&ovs_ipgre_vport_ops);
> +       ovs_vport_ops_register(&ovs_erspan_vport_ops);
> +       return 0;
> +
> +ip_gre_loaded:
> +       /* Since GRE only allows single receiver to be registerd,
> +        * we skip here so only gre transmit works, see:
> +        *
> +        * commit 9f57c67c379d88a10e8ad676426fee5ae7341b14
> +        * Author: Pravin B Shelar <pshelar at nicira.com>
> +        * Date:   Fri Aug 7 23:51:52 2015 -0700
> +        *     gre: Remove support for sharing GRE protocol hook
> +        *
> +        * OVS GRE receive part is disabled.
> +        */
> +       pr_info("GRE TX only over IPv4 tunneling driver\n");
> +       ip_gre_loaded = true;
>         ovs_vport_ops_register(&ovs_ipgre_vport_ops);
>         ovs_vport_ops_register(&ovs_erspan_vport_ops);
>         return 0;
> @@ -1678,10 +1711,13 @@ void rpl_ipgre_fini(void)
>  {
>         ovs_vport_ops_unregister(&ovs_erspan_vport_ops);
>         ovs_vport_ops_unregister(&ovs_ipgre_vport_ops);
> -       gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
> -       unregister_pernet_device(&ipgre_net_ops);
> -       unregister_pernet_device(&erspan_net_ops);
> -       unregister_pernet_device(&ipgre_tap_net_ops);
> +
> +       if (!ip_gre_loaded) {
> +               gre_del_protocol(&ipgre_protocol, GREPROTO_CISCO);
> +               unregister_pernet_device(&ipgre_net_ops);
> +               unregister_pernet_device(&erspan_net_ops);
> +               unregister_pernet_device(&ipgre_tap_net_ops);
> +       }
>  }
>
>  #endif
> diff --git a/datapath/vport.c b/datapath/vport.c
> index 02f6b56d3243..05dd9dc2a149 100644
> --- a/datapath/vport.c
> +++ b/datapath/vport.c
> @@ -66,11 +66,15 @@ int ovs_vport_init(void)
>         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 entry"\
> +                               "- The ERSPAN feature may not be
> supported\n");
> +                       /* continue GRE tx */
> +               }
> +
>                 err = ipgre_init();
>                 if (err && err != -EEXIST)
>                         goto err_ipgre;
> --
> 2.7.4
>
>


More information about the dev mailing list