[ovs-dev] [PATCH] datapath: Add support for kernel 3.13
Kyle Mestery
mestery at noironetworks.com
Thu Mar 27 18:33:43 UTC 2014
On Thu, Mar 27, 2014 at 1:28 PM, Jesse Gross <jesse at nicira.com> wrote:
> I think it would be normally OK although there is currently a patch
> pending that might make it into 3.14 and will require some support in
> OVS:
>
> "core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle
> errors"
>
> OK, given this, I'll wait for adding 3.14.
> On Thu, Mar 27, 2014 at 11:19 AM, Kyle Mestery
> <mestery at noironetworks.com> wrote:
> > Pravin, one more change I want to make here. Since 3.14 is almost out,
> > would you be ok if I bump this up to claim 3.14 support? I don't see any
> > large API changes coming out between now and when 3.14 is due next
> > week, so let me know. Otherwise, I can do another patch for 3.14 next
> > week.
> >
> > Thanks,
> > Kyle
> >
> >
> >
> > On Thu, Mar 27, 2014 at 1:17 PM, Kyle Mestery <mestery at noironetworks.com
> >
> > wrote:
> >>
> >> Add support for building the in-tree kernel datapath for Linux kernel
> >> 3.13.
> >> There were some changes in the netlink area which required adding new
> >> compatibility code for this layer.
> >>
> >> Signed-off-by: Kyle Mestery <mestery at noironetworks.com>
> >> ---
> >> 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.
> >> ---
> >> FAQ | 2 +-
> >> acinclude.m4 | 4 +-
> >> datapath/datapath.c | 28 +++++-----
> >> datapath/datapath.h | 1 +
> >> datapath/dp_notify.c | 11 ++--
> >> datapath/linux/compat/genetlink-openvswitch.c | 20 +++++--
> >> datapath/linux/compat/include/net/genetlink.h | 75
> >> ++++++++++++++++++++++++++-
> >> datapath/linux/compat/include/net/ip.h | 12 +++++
> >> datapath/linux/compat/utils.c | 3 ++
> >> datapath/vport-lisp.c | 7 +--
> >> datapath/vport-vxlan.c | 3 +-
> >> 11 files changed, 130 insertions(+), 36 deletions(-)
> >>
> >> diff --git a/FAQ b/FAQ
> >> index dae5c5b..5ca6d22 100644
> >> --- a/FAQ
> >> +++ b/FAQ
> >> @@ -148,7 +148,7 @@ A: The following table lists the Linux kernel
> versions
> >> against which the
> >> 1.10.x 2.6.18 to 3.8
> >> 1.11.x 2.6.18 to 3.8
> >> 2.0.x 2.6.32 to 3.10
> >> - 2.1.x 2.6.32 to 3.12
> >> + 2.1.x 2.6.32 to 3.13
> >>
> >> Open vSwitch userspace should also work with the Linux kernel module
> >> built into Linux 3.3 and later.
> >> 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/datapath.c b/datapath/datapath.c
> >> index 93f8e36..03db87a 100644
> >> --- a/datapath/datapath.c
> >> +++ b/datapath/datapath.c
> >> @@ -64,11 +64,13 @@
> >>
> >> int ovs_net_id __read_mostly;
> >>
> >> +static struct genl_family dp_packet_genl_family;
> >> +
> >> static void ovs_notify(struct sk_buff *skb, struct genl_info *info,
> >> struct genl_multicast_group *grp)
> >> {
> >> - genl_notify(skb, genl_info_net(info), info->snd_portid,
> >> - grp->id, info->nlhdr, GFP_KERNEL);
> >> + genl_notify(&dp_packet_genl_family, skb, genl_info_net(info),
> >> + info->snd_portid, 0, info->nlhdr, GFP_KERNEL);
> >> }
> >>
> >> /**
> >> @@ -888,8 +890,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff
> >> *skb, struct genl_info *info)
> >> if (!IS_ERR(reply))
> >> ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
> >> 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));
> >> return 0;
> >>
> >> err_flow_free:
> >> @@ -1368,8 +1370,8 @@ static int ovs_dp_cmd_set(struct sk_buff *skb,
> >> struct genl_info *info)
> >> reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW);
> >> if (IS_ERR(reply)) {
> >> err = PTR_ERR(reply);
> >> - netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
> >> - ovs_dp_datapath_multicast_group.id,
> err);
> >> + genl_set_err(&dp_datapath_genl_family,
> sock_net(skb->sk),
> >> 0,
> >> + 0, err);
> >> err = 0;
> >> goto unlock;
> >> }
> >> @@ -1466,7 +1468,7 @@ static const struct nla_policy
> >> vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
> >> [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
> >> };
> >>
> >> -static struct genl_family dp_vport_genl_family = {
> >> +struct genl_family dp_vport_genl_family = {
> >> .id = GENL_ID_GENERATE,
> >> .hdrsize = sizeof(struct ovs_header),
> >> .name = OVS_VPORT_FAMILY,
> >> @@ -1863,19 +1865,13 @@ static int dp_register_genl(void)
> >>
> >> n_registered = 0;
> >> for (i = 0; i < ARRAY_SIZE(dp_genl_families); i++) {
> >> - const struct genl_family_and_ops *f =
> >> &dp_genl_families[i];
> >> + const struct genl_family_and_ops_ovs *f =
> >> + (struct genl_family_and_ops_ovs
> >> *)&dp_genl_families[i];
> >>
> >> - err = genl_register_family_with_ops(f->family, f->ops,
> >> - f->n_ops);
> >> + err = genl_register_family_ovs(f);
> >> if (err)
> >> goto error;
> >> n_registered++;
> >> -
> >> - if (f->group) {
> >> - err = genl_register_mc_group(f->family,
> f->group);
> >> - if (err)
> >> - goto error;
> >> - }
> >> }
> >>
> >> return 0;
> >> 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..b987aff 100644
> >> --- a/datapath/linux/compat/genetlink-openvswitch.c
> >> +++ b/datapath/linux/compat/genetlink-openvswitch.c
> >> @@ -1,17 +1,27 @@
> >> #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,
> >> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
> >> +void genl_notify(struct genl_family *family,
> >> + struct sk_buff *skb, struct net *net, u32 portid, u32
> >> group,
> >> struct nlmsghdr *nlh, gfp_t flags)
> >> {
> >> struct sock *sk = net->genl_sock;
> >> int report = 0;
> >> + struct genl_multicast_group *grp;
> >> + int i = 0;
> >>
> >> if (nlh)
> >> report = nlmsg_report(nlh);
> >>
> >> - nlmsg_notify(sk, skb, portid, group, report, flags);
> >> + list_for_each_entry(grp, &family->mcast_groups, list) {
> >> + if (group == 0)
> >> + break;
> >> + i++;
> >> + }
> >> +
> >> + if (WARN_ON_ONCE(grp == NULL))
> >> + return;
> >> + nlmsg_notify(sk, skb, portid, grp->id, report, flags);
> >> }
> >> +#endif /* kernel version < 3.13.0 */
> >> diff --git a/datapath/linux/compat/include/net/genetlink.h
> >> b/datapath/linux/compat/include/net/genetlink.h
> >> index 09ee23b..d8d1733 100644
> >> --- a/datapath/linux/compat/include/net/genetlink.h
> >> +++ b/datapath/linux/compat/include/net/genetlink.h
> >> @@ -17,8 +17,43 @@
> >> #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)
> >> +#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);
> >> +
> >> +#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)
> >> +{
> >> + struct genl_multicast_group *grp;
> >> +
> >> + list_for_each_entry(grp, &family->mcast_groups, list) {
> >> + if (group == grp->id)
> >> + break;
> >> + }
> >> +
> >> + return netlink_set_err(net->genl_sock, portid, grp->id, code);
> >> +}
> >> +
> >> +#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)
> >> +{
> >> + struct genl_multicast_group *grp;
> >> +
> >> + list_for_each_entry(grp, &family->mcast_groups, list) {
> >> + if (group == grp->id)
> >> + break;
> >> + }
> >> +
> >> + if (WARN_ON_ONCE(grp == NULL))
> >> + return -EINVAL;
> >> + return nlmsg_multicast(net->genl_sock, skb, portid, grp->id,
> >> flags);
> >> +}
> >> +#endif
> >>
> >> #if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0)
> >> static inline struct sk_buff *genlmsg_new_unicast(size_t payload,
> >> @@ -29,4 +64,40 @@ static inline struct sk_buff
> >> *genlmsg_new_unicast(size_t payload,
> >> }
> >> #endif
> >>
> >> +struct genl_family_and_ops_ovs {
> >> + struct genl_family *family;
> >> + struct genl_ops *ops;
> >> + int n_ops;
> >> + struct genl_multicast_group *group;
> >> +};
> >> +
> >> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
> >> +static inline int genl_register_family_ovs(const struct
> >> genl_family_and_ops_ovs *f)
> >> +{
> >> + f->family->ops = f->ops;
> >> + f->family->n_ops = f->n_ops;
> >> + f->family->mcgrps = f->group;
> >> + f->family->n_mcgrps = f->group ? 1 : 0;
> >> +
> >> + return genl_register_family(f->family);
> >> +}
> >> +#else
> >> +static inline int genl_register_family_ovs(const struct
> >> genl_family_and_ops_ovs *f)
> >> +{
> >> + int err;
> >> +
> >> + err = genl_register_family_with_ops(f->family, f->ops,
> f->n_ops);
> >> + if (err)
> >> + goto error;
> >> +
> >> + if (f->group) {
> >> + err = genl_register_mc_group(f->family, f->group);
> >> + if (err)
> >> + goto error;
> >> + }
> >> +error:
> >> + return err;
> >> +}
> >> +#endif
> >> +
> >> #endif /* genetlink.h */
> >> diff --git a/datapath/linux/compat/include/net/ip.h
> >> b/datapath/linux/compat/include/net/ip.h
> >> index 4193d32..4fd0b2c 100644
> >> --- a/datapath/linux/compat/include/net/ip.h
> >> +++ b/datapath/linux/compat/include/net/ip.h
> >> @@ -12,4 +12,16 @@ static inline bool ip_is_fragment(const struct iphdr
> >> *iph)
> >> }
> >> #endif
> >>
> >> +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
> >> +#define inet_get_local_port_range_ovs(a, b, c) \
> >> + inet_get_local_port_range(a, b, c)
> >> +#else
> >> +static inline void inet_get_local_port_range_ovs(struct net *net, int
> >> *low,
> >> + int *high)
> >> +{
> >> + (void)(net);
> >> + inet_get_local_port_range(low, high);
> >> +}
> >> +#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..a1e4ca2 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_ovs(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..4b36253 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_ovs(net, &port_min, &port_max);
> >> src_port = vxlan_src_port(port_min, port_max, skb);
> >>
> >> err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
> >> --
> >> 1.8.5.3
> >>
> >
> >
> > _______________________________________________
> > dev mailing list
> > dev at openvswitch.org
> > http://openvswitch.org/mailman/listinfo/dev
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openvswitch.org/pipermail/ovs-dev/attachments/20140327/9dbac651/attachment-0005.html>
More information about the dev
mailing list