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
