Thanks for fixing this up a bit more Pravin! I tested this against the latest
master, it builds fine and loads on Fedora 20 with 3.13.

Also, I think you may have dropped Zoltan's upstream patch from here,
I had incorporated parts of that in the last patch I sent out. Can you
confirm?

One more comment inline.

Acked-by: Kyle Mestery <[email protected]>


On Wed, Apr 2, 2014 at 3:37 PM, Pravin <[email protected]> wrote:
> From: Pravin Shelar <[email protected]>
>
> Add support for building the in-tree kernel datapath for
> Linux kernels up to 3.13. There were some changes in the

This patch also supports 3.14. Please adjust here and in
other places in the patch as well.

> netlink area which required adding new compatibility code
> for this layer. Also, some new per-cpu stats initialization
> code was added.
>
> Based on patch from Kyle Mestery.
>
> Signed-off-by: Kyle Mestery <[email protected]>
> Signed-off-by: Pravin B Shelar <[email protected]>
> ---
> v5:
>     removed struct genl_family_and_ops, datapath looks more like
>     upstream 3.13.
> v4:
>     Handle a few more changes based on upstream commits.
> v3: Correctly make genl_register_family backwards compatible.
>
> v2: Address a few comments from Pravin. Some of those comments
>     proved challenging, please see email reply to the list.
> ---
>  acinclude.m4                                       |    4 +-
>  datapath/compat.h                                  |    6 +-
>  datapath/datapath.c                                |  222 
> ++++++++++----------
>  datapath/datapath.h                                |    1 +
>  datapath/dp_notify.c                               |   11 +-
>  datapath/linux/compat/genetlink-openvswitch.c      |   48 ++++-
>  .../linux/compat/include/linux/u64_stats_sync.h    |   11 +
>  datapath/linux/compat/include/net/genetlink.h      |   80 ++++++-
>  datapath/linux/compat/include/net/ip.h             |   10 +
>  datapath/linux/compat/utils.c                      |    3 +
>  datapath/vport-lisp.c                              |    7 +-
>  datapath/vport-vxlan.c                             |    3 +-
>  datapath/vport.c                                   |    7 +
>  13 files changed, 279 insertions(+), 134 deletions(-)
>
> diff --git a/acinclude.m4 b/acinclude.m4
> index 1f52cf1..4269620 100644
> --- a/acinclude.m4
> +++ b/acinclude.m4
> @@ -134,10 +134,10 @@ AC_DEFUN([OVS_CHECK_LINUX], [
>      AC_MSG_RESULT([$kversion])
>
>      if test "$version" -ge 3; then
> -       if test "$version" = 3 && test "$patchlevel" -le 12; then
> +       if test "$version" = 3 && test "$patchlevel" -le 13; then
>            : # Linux 3.x
>         else
> -         AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version 
> newer than 3.12.x is not supported])
> +         AC_ERROR([Linux kernel in $KBUILD is version $kversion, but version 
> newer than 3.13.x is not supported])
>         fi
>      else
>         if test "$version" -le 1 || test "$patchlevel" -le 5 || test 
> "$sublevel" -le 31; then
> diff --git a/datapath/compat.h b/datapath/compat.h
> index bc7e880..f8f0469 100644
> --- a/datapath/compat.h
> +++ b/datapath/compat.h
> @@ -32,10 +32,10 @@ static inline void skb_clear_rxhash(struct sk_buff *skb)
>  #endif
>  }
>
> -#ifdef HAVE_PARALLEL_OPS
> -#define SET_PARALLEL_OPS       .parallel_ops = true,
> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
> +#define GROUP_ID(grp)  0
>  #else
> -#define SET_PARALLEL_OPS
> +#define GROUP_ID(grp)  ((grp)->id)
>  #endif
>
>  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
> diff --git a/datapath/datapath.c b/datapath/datapath.c
> index 52c76b4..4e4fcbb 100644
> --- a/datapath/datapath.c
> +++ b/datapath/datapath.c
> @@ -64,20 +64,36 @@
>
>  int ovs_net_id __read_mostly;
>
> +static struct genl_family dp_packet_genl_family;
> +static struct genl_family dp_flow_genl_family;
> +static struct genl_family dp_datapath_genl_family;
> +
> +static struct genl_multicast_group ovs_dp_flow_multicast_group = {
> +       .name = OVS_FLOW_MCGROUP
> +};
> +
> +static struct genl_multicast_group ovs_dp_datapath_multicast_group = {
> +       .name = OVS_DATAPATH_MCGROUP
> +};
> +
> +struct genl_multicast_group ovs_dp_vport_multicast_group = {
> +       .name = OVS_VPORT_MCGROUP
> +};
> +
>  /* Check if need to build a reply message.
>   * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */
>  static bool ovs_must_notify(struct genl_info *info,
>                             const struct genl_multicast_group *grp)
>  {
>         return info->nlhdr->nlmsg_flags & NLM_F_ECHO ||
> -               netlink_has_listeners(genl_info_net(info)->genl_sock, 
> grp->id);
> +               netlink_has_listeners(genl_info_net(info)->genl_sock, 
> GROUP_ID(grp));
>  }
>
> -static void ovs_notify(struct sk_buff *skb, struct genl_info *info,
> -                      struct genl_multicast_group *grp)
> +static void ovs_notify(struct genl_family *family, struct 
> genl_multicast_group *grp,
> +                      struct sk_buff *skb, struct genl_info *info)
>  {
> -       genl_notify(skb, genl_info_net(info), info->snd_portid,
> -                   grp->id, info->nlhdr, GFP_KERNEL);
> +       genl_notify(family, skb, genl_info_net(info),
> +                   info->snd_portid, GROUP_ID(grp), info->nlhdr, GFP_KERNEL);
>  }
>
>  /**
> @@ -274,16 +290,6 @@ out:
>         u64_stats_update_end(&stats->sync);
>  }
>
> -static struct genl_family dp_packet_genl_family = {
> -       .id = GENL_ID_GENERATE,
> -       .hdrsize = sizeof(struct ovs_header),
> -       .name = OVS_PACKET_FAMILY,
> -       .version = OVS_PACKET_VERSION,
> -       .maxattr = OVS_PACKET_ATTR_MAX,
> -       .netnsok = true,
> -        SET_PARALLEL_OPS
> -};
> -
>  int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
>                   const struct dp_upcall_info *upcall_info)
>  {
> @@ -601,6 +607,18 @@ static struct genl_ops dp_packet_genl_ops[] = {
>         }
>  };
>
> +static struct genl_family dp_packet_genl_family = {
> +       .id = GENL_ID_GENERATE,
> +       .hdrsize = sizeof(struct ovs_header),
> +       .name = OVS_PACKET_FAMILY,
> +       .version = OVS_PACKET_VERSION,
> +       .maxattr = OVS_PACKET_ATTR_MAX,
> +       .netnsok = true,
> +       .parallel_ops = true,
> +       .ops = dp_packet_genl_ops,
> +       .n_ops = ARRAY_SIZE(dp_packet_genl_ops),
> +};
> +
>  static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats,
>                          struct ovs_dp_megaflow_stats *mega_stats)
>  {
> @@ -632,26 +650,6 @@ static void get_dp_stats(struct datapath *dp, struct 
> ovs_dp_stats *stats,
>         }
>  }
>
> -static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
> -       [OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
> -       [OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
> -       [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
> -};
> -
> -static struct genl_family dp_flow_genl_family = {
> -       .id = GENL_ID_GENERATE,
> -       .hdrsize = sizeof(struct ovs_header),
> -       .name = OVS_FLOW_FAMILY,
> -       .version = OVS_FLOW_VERSION,
> -       .maxattr = OVS_FLOW_ATTR_MAX,
> -       .netnsok = true,
> -        SET_PARALLEL_OPS
> -};
> -
> -static struct genl_multicast_group ovs_dp_flow_multicast_group = {
> -       .name = OVS_FLOW_MCGROUP
> -};
> -
>  static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
>  {
>         return NLMSG_ALIGN(sizeof(struct ovs_header))
> @@ -914,7 +912,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct 
> genl_info *info)
>         }
>
>         if (reply)
> -               ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
> +               ovs_notify(&dp_flow_genl_family, 
> &ovs_dp_flow_multicast_group, reply, info);
>         return 0;
>
>  err_unlock_ovs:
> @@ -1023,7 +1021,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct 
> genl_info *info)
>         ovs_unlock();
>
>         if (reply)
> -               ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
> +               ovs_notify(&dp_flow_genl_family, 
> &ovs_dp_flow_multicast_group, reply, info);
>         if (old_acts)
>                 ovs_nla_free_flow_actions(old_acts);
>         return 0;
> @@ -1135,11 +1133,11 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, 
> struct genl_info *info)
>                                                      OVS_FLOW_CMD_DEL);
>                         rcu_read_unlock();
>                         BUG_ON(err < 0);
> -                       ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
> +                       ovs_notify(&dp_flow_genl_family, 
> &ovs_dp_flow_multicast_group, reply, info);
>                 } else {
> -                       netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
> -                                       ovs_dp_flow_multicast_group.id,
> -                                       PTR_ERR(reply));
> +                       genl_set_err(&dp_flow_genl_family, sock_net(skb->sk), 
> 0,
> +                                    0, PTR_ERR(reply));
> +
>                 }
>         }
>
> @@ -1187,6 +1185,12 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, 
> struct netlink_callback *cb)
>         return skb->len;
>  }
>
> +static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
> +       [OVS_FLOW_ATTR_KEY] = { .type = NLA_NESTED },
> +       [OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
> +       [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
> +};
> +
>  static struct genl_ops dp_flow_genl_ops[] = {
>         { .cmd = OVS_FLOW_CMD_NEW,
>           .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
> @@ -1211,24 +1215,18 @@ static struct genl_ops dp_flow_genl_ops[] = {
>         },
>  };
>
> -static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
> -       [OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
> -       [OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
> -       [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
> -};
> -
> -static struct genl_family dp_datapath_genl_family = {
> +static struct genl_family dp_flow_genl_family = {
>         .id = GENL_ID_GENERATE,
>         .hdrsize = sizeof(struct ovs_header),
> -       .name = OVS_DATAPATH_FAMILY,
> -       .version = OVS_DATAPATH_VERSION,
> -       .maxattr = OVS_DP_ATTR_MAX,
> +       .name = OVS_FLOW_FAMILY,
> +       .version = OVS_FLOW_VERSION,
> +       .maxattr = OVS_FLOW_ATTR_MAX,
>         .netnsok = true,
> -        SET_PARALLEL_OPS
> -};
> -
> -static struct genl_multicast_group ovs_dp_datapath_multicast_group = {
> -       .name = OVS_DATAPATH_MCGROUP
> +       .parallel_ops = true,
> +       .ops = dp_flow_genl_ops,
> +       .n_ops = ARRAY_SIZE(dp_flow_genl_ops),
> +       .mcgrps = &ovs_dp_flow_multicast_group,
> +       .n_mcgrps = 1,
>  };
>
>  static size_t ovs_dp_cmd_msg_size(void)
> @@ -1361,6 +1359,12 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
> genl_info *info)
>                 goto err_destroy_table;
>         }
>
> +       for_each_possible_cpu(i) {
> +               struct dp_stats_percpu *dpath_stats;
> +               dpath_stats = per_cpu_ptr(dp->stats_percpu, i);
> +               u64_stats_init(&dpath_stats->sync);
> +       }
> +
>         dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
>                             GFP_KERNEL);
>         if (!dp->ports) {
> @@ -1411,7 +1415,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct 
> genl_info *info)
>
>         ovs_unlock();
>
> -       ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
> +       ovs_notify(&dp_datapath_genl_family, 
> &ovs_dp_datapath_multicast_group, reply, info);
>         return 0;
>
>  err_destroy_ports_array:
> @@ -1480,7 +1484,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct 
> genl_info *info)
>         __dp_destroy(dp);
>
>         ovs_unlock();
> -       ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
> +       ovs_notify(&dp_datapath_genl_family, 
> &ovs_dp_datapath_multicast_group, reply, info);
>         return 0;
>
>  err_unlock_free:
> @@ -1512,7 +1516,7 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct 
> genl_info *info)
>         BUG_ON(err < 0);
>
>         ovs_unlock();
> -       ovs_notify(reply, info, &ovs_dp_datapath_multicast_group);
> +       ovs_notify(&dp_datapath_genl_family, 
> &ovs_dp_datapath_multicast_group, reply, info);
>         return 0;
>
>  err_unlock_free:
> @@ -1573,6 +1577,12 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct 
> netlink_callback *cb)
>         return skb->len;
>  }
>
> +static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
> +       [OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
> +       [OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
> +       [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
> +};
> +
>  static struct genl_ops dp_datapath_genl_ops[] = {
>         { .cmd = OVS_DP_CMD_NEW,
>           .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
> @@ -1597,27 +1607,18 @@ static struct genl_ops dp_datapath_genl_ops[] = {
>         },
>  };
>
> -static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
> -       [OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 
> },
> -       [OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
> -       [OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
> -       [OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
> -       [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_U32 },
> -       [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
> -};
> -
> -static struct genl_family dp_vport_genl_family = {
> +static struct genl_family dp_datapath_genl_family = {
>         .id = GENL_ID_GENERATE,
>         .hdrsize = sizeof(struct ovs_header),
> -       .name = OVS_VPORT_FAMILY,
> -       .version = OVS_VPORT_VERSION,
> -       .maxattr = OVS_VPORT_ATTR_MAX,
> +       .name = OVS_DATAPATH_FAMILY,
> +       .version = OVS_DATAPATH_VERSION,
> +       .maxattr = OVS_DP_ATTR_MAX,
>         .netnsok = true,
> -        SET_PARALLEL_OPS
> -};
> -
> -struct genl_multicast_group ovs_dp_vport_multicast_group = {
> -       .name = OVS_VPORT_MCGROUP
> +       .parallel_ops = true,
> +       .ops = dp_datapath_genl_ops,
> +       .n_ops = ARRAY_SIZE(dp_datapath_genl_ops),
> +       .mcgrps = &ovs_dp_datapath_multicast_group,
> +       .n_mcgrps = 1,
>  };
>
>  /* Called with ovs_mutex or RCU read lock. */
> @@ -1783,7 +1784,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, 
> struct genl_info *info)
>         BUG_ON(err < 0);
>         ovs_unlock();
>
> -       ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
> +       ovs_notify(&dp_vport_genl_family, &ovs_dp_vport_multicast_group, 
> reply, info);
>         return 0;
>
>  exit_unlock_free:
> @@ -1832,7 +1833,7 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, 
> struct genl_info *info)
>         BUG_ON(err < 0);
>         ovs_unlock();
>
> -       ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
> +       ovs_notify(&dp_vport_genl_family, &ovs_dp_vport_multicast_group, 
> reply, info);
>         return 0;
>
>  exit_unlock_free:
> @@ -1869,7 +1870,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, 
> struct genl_info *info)
>         ovs_dp_detach_port(vport);
>         ovs_unlock();
>
> -       ovs_notify(reply, info, &ovs_dp_vport_multicast_group);
> +       ovs_notify(&dp_vport_genl_family, &ovs_dp_vport_multicast_group, 
> reply, info);
>         return 0;
>
>  exit_unlock_free:
> @@ -1947,6 +1948,15 @@ out:
>         return skb->len;
>  }
>
> +static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
> +       [OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 
> },
> +       [OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
> +       [OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
> +       [OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
> +       [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_U32 },
> +       [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
> +};
> +
>  static struct genl_ops dp_vport_genl_ops[] = {
>         { .cmd = OVS_VPORT_CMD_NEW,
>           .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */
> @@ -1971,26 +1981,25 @@ static struct genl_ops dp_vport_genl_ops[] = {
>         },
>  };
>
> -struct genl_family_and_ops {
> -       struct genl_family *family;
> -       struct genl_ops *ops;
> -       int n_ops;
> -       struct genl_multicast_group *group;
> +struct genl_family dp_vport_genl_family = {
> +       .id = GENL_ID_GENERATE,
> +       .hdrsize = sizeof(struct ovs_header),
> +       .name = OVS_VPORT_FAMILY,
> +       .version = OVS_VPORT_VERSION,
> +       .maxattr = OVS_VPORT_ATTR_MAX,
> +       .netnsok = true,
> +       .parallel_ops = true,
> +       .ops = dp_vport_genl_ops,
> +       .n_ops = ARRAY_SIZE(dp_vport_genl_ops),
> +       .mcgrps = &ovs_dp_vport_multicast_group,
> +       .n_mcgrps = 1,
>  };
>
> -static const struct genl_family_and_ops dp_genl_families[] = {
> -       { &dp_datapath_genl_family,
> -         dp_datapath_genl_ops, ARRAY_SIZE(dp_datapath_genl_ops),
> -         &ovs_dp_datapath_multicast_group },
> -       { &dp_vport_genl_family,
> -         dp_vport_genl_ops, ARRAY_SIZE(dp_vport_genl_ops),
> -         &ovs_dp_vport_multicast_group },
> -       { &dp_flow_genl_family,
> -         dp_flow_genl_ops, ARRAY_SIZE(dp_flow_genl_ops),
> -         &ovs_dp_flow_multicast_group },
> -       { &dp_packet_genl_family,
> -         dp_packet_genl_ops, ARRAY_SIZE(dp_packet_genl_ops),
> -         NULL },
> +static struct genl_family *dp_genl_families[] = {
> +       &dp_datapath_genl_family,
> +       &dp_vport_genl_family,
> +       &dp_flow_genl_family,
> +       &dp_packet_genl_family,
>  };
>
>  static void dp_unregister_genl(int n_families)
> @@ -1998,36 +2007,25 @@ static void dp_unregister_genl(int n_families)
>         int i;
>
>         for (i = 0; i < n_families; i++)
> -               genl_unregister_family(dp_genl_families[i].family);
> +               genl_unregister_family(dp_genl_families[i]);
>  }
>
>  static int dp_register_genl(void)
>  {
> -       int n_registered;
>         int err;
>         int i;
>
> -       n_registered = 0;
>         for (i = 0; i < ARRAY_SIZE(dp_genl_families); i++) {
> -               const struct genl_family_and_ops *f = &dp_genl_families[i];
>
> -               err = genl_register_family_with_ops(f->family, f->ops,
> -                                                   f->n_ops);
> +               err = genl_register_family(dp_genl_families[i]);
>                 if (err)
>                         goto error;
> -               n_registered++;
> -
> -               if (f->group) {
> -                       err = genl_register_mc_group(f->family, f->group);
> -                       if (err)
> -                               goto error;
> -               }
>         }
>
>         return 0;
>
>  error:
> -       dp_unregister_genl(n_registered);
> +       dp_unregister_genl(i);
>         return err;
>  }
>
> diff --git a/datapath/datapath.h b/datapath/datapath.h
> index d81e05c..40e0f90 100644
> --- a/datapath/datapath.h
> +++ b/datapath/datapath.h
> @@ -184,6 +184,7 @@ static inline struct vport *ovs_vport_ovsl(const struct 
> datapath *dp, int port_n
>  }
>
>  extern struct notifier_block ovs_dp_device_notifier;
> +extern struct genl_family dp_vport_genl_family;
>  extern struct genl_multicast_group ovs_dp_vport_multicast_group;
>
>  void ovs_dp_process_received_packet(struct vport *, struct sk_buff *);
> diff --git a/datapath/dp_notify.c b/datapath/dp_notify.c
> index 0b22d0c..e96b242 100644
> --- a/datapath/dp_notify.c
> +++ b/datapath/dp_notify.c
> @@ -35,15 +35,14 @@ static void dp_detach_port_notify(struct vport *vport)
>                                           OVS_VPORT_CMD_DEL);
>         ovs_dp_detach_port(vport);
>         if (IS_ERR(notify)) {
> -               netlink_set_err(ovs_dp_get_net(dp)->genl_sock, 0,
> -                               ovs_dp_vport_multicast_group.id,
> -                               PTR_ERR(notify));
> +               genl_set_err(&dp_vport_genl_family, ovs_dp_get_net(dp), 0,
> +                            0, PTR_ERR(notify));
>                 return;
>         }
>
> -       genlmsg_multicast_netns(ovs_dp_get_net(dp), notify, 0,
> -                               ovs_dp_vport_multicast_group.id,
> -                               GFP_KERNEL);
> +       genlmsg_multicast_netns(&dp_vport_genl_family,
> +                               ovs_dp_get_net(dp), notify, 0,
> +                               0, GFP_KERNEL);
>  }
>
>  void ovs_dp_notify_wq(struct work_struct *work)
> diff --git a/datapath/linux/compat/genetlink-openvswitch.c 
> b/datapath/linux/compat/genetlink-openvswitch.c
> index 359f916..08f0fab 100644
> --- a/datapath/linux/compat/genetlink-openvswitch.c
> +++ b/datapath/linux/compat/genetlink-openvswitch.c
> @@ -1,12 +1,15 @@
>  #include <net/genetlink.h>
>  #include <linux/version.h>
>
> -/* This is analogous to rtnl_notify() but uses genl_sock instead of rtnl.
> - *
> - * This is not (yet) in any upstream kernel. */
> -void genl_notify(struct sk_buff *skb, struct net *net, u32 portid, u32 group,
> -                struct nlmsghdr *nlh, gfp_t flags)
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
> +
> +#undef genl_notify
> +
> +void rpl_genl_notify(struct rpl_genl_family *family, struct sk_buff *skb,
> +                    struct net *net, u32 portid, u32 group,
> +                    struct nlmsghdr *nlh, gfp_t flags)
>  {
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
>         struct sock *sk = net->genl_sock;
>         int report = 0;
>
> @@ -14,4 +17,39 @@ void genl_notify(struct sk_buff *skb, struct net *net, u32 
> portid, u32 group,
>                 report = nlmsg_report(nlh);
>
>         nlmsg_notify(sk, skb, portid, group, report, flags);
> +#else
> +       genl_notify(skb, net, portid, group, nlh, flags);
> +#endif
> +}
> +
> +int rpl___genl_register_family(struct rpl_genl_family *f)
> +{
> +       int err;
> +
> +       f->compat_family.id = f->id;
> +       f->compat_family.hdrsize = f->hdrsize;
> +       strncpy(f->compat_family.name, f->name, GENL_NAMSIZ);
> +       f->compat_family.version = f->version;
> +       f->compat_family.maxattr = f->maxattr;
> +       f->compat_family.netnsok = f->netnsok;
> +#ifdef HAVE_PARALLEL_OPS
> +       f->compat_family.parallel_ops = f->parallel_ops;
> +#endif
> +       err = genl_register_family_with_ops(&f->compat_family,
> +                                           (struct genl_ops *) f->ops, 
> f->n_ops);
> +       if (err)
> +               goto error;
> +
> +       if (f->mcgrps) {
> +               /* Need to Fix GROUP_ID() for more than one group. */
> +               BUG_ON(f->n_mcgrps > 1);
> +               err = genl_register_mc_group(&f->compat_family,
> +                                            (struct genl_multicast_group *) 
> f->mcgrps);
> +               if (err)
> +                       goto error;
> +       }
> +error:
> +       return err;
> +
>  }
> +#endif /* kernel version < 3.13.0 */
> diff --git a/datapath/linux/compat/include/linux/u64_stats_sync.h 
> b/datapath/linux/compat/include/linux/u64_stats_sync.h
> index 45b617a..234fd91 100644
> --- a/datapath/linux/compat/include/linux/u64_stats_sync.h
> +++ b/datapath/linux/compat/include/linux/u64_stats_sync.h
> @@ -144,4 +144,15 @@ static inline bool u64_stats_fetch_retry_bh(const struct 
> u64_stats_sync *syncp,
>  }
>
>  #endif /* Linux kernel < 2.6.36 */
> +
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
> +
> +#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
> +# define u64_stats_init(syncp)  seqcount_init(syncp.seq)
> +#else
> +# define u64_stats_init(syncp)  do { } while (0)
> +#endif
> +
> +#endif
> +
>  #endif /* _LINUX_U64_STATS_SYNC_WRAPPER_H */
> diff --git a/datapath/linux/compat/include/net/genetlink.h 
> b/datapath/linux/compat/include/net/genetlink.h
> index 09ee23b..532e4cf 100644
> --- a/datapath/linux/compat/include/net/genetlink.h
> +++ b/datapath/linux/compat/include/net/genetlink.h
> @@ -17,8 +17,84 @@
>  #define portid pid
>  #endif
>
> -extern void genl_notify(struct sk_buff *skb, struct net *net, u32 portid,
> -                       u32 group, struct nlmsghdr *nlh, gfp_t flags);
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
> +struct rpl_genl_family {
> +       struct genl_family      compat_family;
> +       unsigned int            id;
> +       unsigned int            hdrsize;
> +       char                    name[GENL_NAMSIZ];
> +       unsigned int            version;
> +       unsigned int            maxattr;
> +       bool                    netnsok;
> +       bool                    parallel_ops;
> +       int                     (*pre_doit)(const struct genl_ops *ops,
> +                       struct sk_buff *skb,
> +                       struct genl_info *info);
> +       void                    (*post_doit)(const struct genl_ops *ops,
> +                       struct sk_buff *skb,
> +                       struct genl_info *info);
> +       struct nlattr **        attrbuf;        /* private */
> +       const struct genl_ops * ops;            /* private */
> +       const struct genl_multicast_group *mcgrps; /* private */
> +       unsigned int            n_ops;          /* private */
> +       unsigned int            n_mcgrps;       /* private */
> +       unsigned int            mcgrp_offset;   /* private */
> +       struct list_head        family_list;    /* private */
> +       struct module           *module;
> +};
> +
> +#define genl_family rpl_genl_family
> +#define genl_notify rpl_genl_notify
> +void genl_notify(struct genl_family *family,
> +                struct sk_buff *skb, struct net *net, u32 portid, u32 group,
> +                struct nlmsghdr *nlh, gfp_t flags);
> +
> +static inline void *rpl_genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
> +                                   struct genl_family *family, int flags, u8 
> cmd)
> +{
> +       return genlmsg_put(skb, portid, seq, &family->compat_family, flags, 
> cmd);
> +}
> +
> +#define genlmsg_put rpl_genlmsg_put
> +
> +static inline int rpl_genl_unregister_family(struct genl_family *family)
> +{
> +       return genl_unregister_family(&family->compat_family);
> +}
> +#define genl_unregister_family rpl_genl_unregister_family
> +
> +#define genl_set_err rpl_genl_set_err
> +static inline int genl_set_err(struct genl_family *family, struct net *net,
> +                              u32 portid, u32 group, int code)
> +{
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
> +       netlink_set_err(net->genl_sock, portid, group, code);
> +       return 0;
> +#else
> +       return netlink_set_err(net->genl_sock, portid, group, code);
> +#endif
> +}
> +
> +#define genlmsg_multicast_netns rpl_genlmsg_multicast_netns
> +static inline int genlmsg_multicast_netns(struct genl_family *family,
> +                                         struct net *net, struct sk_buff 
> *skb,
> +                                         u32 portid, unsigned int group, 
> gfp_t flags)
> +{
> +       return nlmsg_multicast(net->genl_sock, skb, portid, group, flags);
> +}
> +
> +
> +#define __genl_register_family rpl___genl_register_family
> +int rpl___genl_register_family(struct genl_family *family);
> +
> +#define genl_register_family rpl_genl_register_family
> +static inline int rpl_genl_register_family(struct genl_family *family)
> +{
> +       family->module = THIS_MODULE;
> +       return rpl___genl_register_family(family);
> +}
> +
> +#endif
>
>  #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
>  static inline struct sk_buff *genlmsg_new_unicast(size_t payload,
> diff --git a/datapath/linux/compat/include/net/ip.h 
> b/datapath/linux/compat/include/net/ip.h
> index 4193d32..c819e4d 100644
> --- a/datapath/linux/compat/include/net/ip.h
> +++ b/datapath/linux/compat/include/net/ip.h
> @@ -12,4 +12,14 @@ static inline bool ip_is_fragment(const struct iphdr *iph)
>  }
>  #endif
>
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
> +static inline void rpl_inet_get_local_port_range(struct net *net, int *low,
> +                                            int *high)
> +{
> +       inet_get_local_port_range(low, high);
> +}
> +#define inet_get_local_port_range rpl_inet_get_local_port_range
> +
> +#endif
> +
>  #endif
> diff --git a/datapath/linux/compat/utils.c b/datapath/linux/compat/utils.c
> index dc4df2a..9404e20 100644
> --- a/datapath/linux/compat/utils.c
> +++ b/datapath/linux/compat/utils.c
> @@ -6,6 +6,7 @@
>  #include <linux/mm.h>
>  #include <linux/net.h>
>  #include <net/checksum.h>
> +#include <net/ip.h>
>  #include <linux/string.h>
>  #include <linux/types.h>
>  #include <linux/percpu.h>
> @@ -38,6 +39,7 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff 
> *skb,
>  }
>  #endif
>
> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
>  bool __net_get_random_once(void *buf, int nbytes, bool *done,
>                            atomic_t *done_key)
>  {
> @@ -58,3 +60,4 @@ bool __net_get_random_once(void *buf, int nbytes, bool 
> *done,
>
>         return true;
>  }
> +#endif
> diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c
> index e33cffe..8e3ff69 100644
> --- a/datapath/vport-lisp.c
> +++ b/datapath/vport-lisp.c
> @@ -163,7 +163,7 @@ static __be64 instance_id_to_tunnel_id(__u8 *iid)
>  /* Compute source UDP port for outgoing packet.
>   * Currently we use the flow hash.
>   */
> -static u16 get_src_port(struct sk_buff *skb)
> +static u16 get_src_port(struct net *net, struct sk_buff *skb)
>  {
>         u32 hash = skb_get_rxhash(skb);
>         unsigned int range;
> @@ -177,7 +177,7 @@ static u16 get_src_port(struct sk_buff *skb)
>                             sizeof(*pkt_key) / sizeof(u32), 0);
>         }
>
> -       inet_get_local_port_range(&low, &high);
> +       inet_get_local_port_range(net, &low, &high);
>         range = (high - low) + 1;
>         return (((u64) hash * range) >> 32) + low;
>  }
> @@ -185,13 +185,14 @@ static u16 get_src_port(struct sk_buff *skb)
>  static void lisp_build_header(const struct vport *vport,
>                               struct sk_buff *skb)
>  {
> +       struct net *net = ovs_dp_get_net(vport->dp);
>         struct lisp_port *lisp_port = lisp_vport(vport);
>         struct udphdr *udph = udp_hdr(skb);
>         struct lisphdr *lisph = (struct lisphdr *)(udph + 1);
>         const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
>
>         udph->dest = lisp_port->dst_port;
> -       udph->source = htons(get_src_port(skb));
> +       udph->source = htons(get_src_port(net, skb));
>         udph->check = 0;
>         udph->len = htons(skb->len - skb_transport_offset(skb));
>
> diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
> index d264785..cc9477d 100644
> --- a/datapath/vport-vxlan.c
> +++ b/datapath/vport-vxlan.c
> @@ -139,6 +139,7 @@ error:
>
>  static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
>  {
> +       struct net *net = ovs_dp_get_net(vport->dp);
>         struct vxlan_port *vxlan_port = vxlan_vport(vport);
>         __be16 dst_port = inet_sport(vxlan_port->vs->sock->sk);
>         struct rtable *rt;
> @@ -172,7 +173,7 @@ static int vxlan_tnl_send(struct vport *vport, struct 
> sk_buff *skb)
>
>         skb->local_df = 1;
>
> -       inet_get_local_port_range(&port_min, &port_max);
> +       inet_get_local_port_range(net, &port_min, &port_max);
>         src_port = vxlan_src_port(port_min, port_max, skb);
>
>         err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
> diff --git a/datapath/vport.c b/datapath/vport.c
> index 7f12acc..2673b81 100644
> --- a/datapath/vport.c
> +++ b/datapath/vport.c
> @@ -122,6 +122,7 @@ struct vport *ovs_vport_alloc(int priv_size, const struct 
> vport_ops *ops,
>  {
>         struct vport *vport;
>         size_t alloc_size;
> +       int i;
>
>         alloc_size = sizeof(struct vport);
>         if (priv_size) {
> @@ -145,6 +146,12 @@ struct vport *ovs_vport_alloc(int priv_size, const 
> struct vport_ops *ops,
>                 return ERR_PTR(-ENOMEM);
>         }
>
> +       for_each_possible_cpu(i) {
> +               struct pcpu_tstats *vport_stats;
> +               vport_stats = per_cpu_ptr(vport->percpu_stats, i);
> +               u64_stats_init(&vport_stats->syncp);
> +       }
> +
>         spin_lock_init(&vport->stats_lock);
>
>         return vport;
> --
> 1.7.9.5
>
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to