From 436c78db6872aa9c4d682004ef445f73cbd15129 Mon Sep 17 00:00:00 2001 From: Kiran KN Date: Wed, 9 Nov 2016 11:38:22 -0800 Subject: [PATCH] Changes to support Ubuntu 16.04 v4.15 kernel. DPDK: Ubuntu 16.04 compilation fix Partial-Bug: 1638643 Changes to make vrouter code compile against linux kernel v4.15. Timer_list structure has changed in 4.15 releases. Also some changes introduced to vr_host_interface.c, removing NETIF_F_UFO reference for v4.15. closes-bug: #1765229 Fix vrouter build for kernels from 4.11 to 4.13 - linux/vhost_dev.c: Rename netdev destructor to priv_destructor due to API change. New signature of rtnl_link_ops.validate due to API change. - linux/vr_mem.c Remove vma from mem_fault function since VMA pointer now accessable via VMF structure. Partial-Bug: #1633387 (cherry picked from commit 60c903128ddee5737e0fd8bb34fc6f03cc043426) Modify generic netlink family registration for kernel 4.10 support Closes-bug: #1696745 Fix netlink family registration for kernel 4.10 When we call genl_register_family with "ops" field provided, we need to provide "n_ops" field as well. Closes-bug: #1696745 Register information about multicast group Pass to vrouter module information about multicast group. Withouth that user space client (vif) was unable to join vrouter netlink broadcast group when kernel 4.10 or higher was used. Closes-Bug: #1771999 Change-Id: I7d01633fca50a3c76ce1ea9d9233623e4a2abd45 Closes Jira Bug:JCB-218796 --- include/vr_dpdk.h | 2 +- include/vrouter.h | 5 +++++ linux/vhost_dev.c | 13 +++++++++++- linux/vr_genetlink.c | 21 ++++++++++++++----- linux/vr_host_interface.c | 8 +++++-- linux/vr_mem.c | 9 ++++++++ linux/vrouter_mod.c | 44 ++++++++++++++++++++++++++++++--------- 7 files changed, 83 insertions(+), 19 deletions(-) diff --git a/include/vr_dpdk.h b/include/vr_dpdk.h index a2c4359b0..bae6f2b07 100644 --- a/include/vr_dpdk.h +++ b/include/vr_dpdk.h @@ -658,7 +658,7 @@ int vr_dpdk_ulog(uint32_t level, uint32_t logtype, uint32_t *last_hash, void dpdk_adjust_tcp_mss(struct tcphdr *tcph, unsigned short overlay_len, unsigned char iph_len); /* Creates a copy of the given packet mbuf */ -inline struct rte_mbuf * +struct rte_mbuf * vr_dpdk_pktmbuf_copy(struct rte_mbuf *md, struct rte_mempool *mp); /* diff --git a/include/vrouter.h b/include/vrouter.h index d67b2a16a..abe59066c 100644 --- a/include/vrouter.h +++ b/include/vrouter.h @@ -135,7 +135,12 @@ struct vr_ip; struct vr_timer { void (*vt_timer)(void *); void *vt_vr_arg; +#if (defined(__linux__) && defined(__KERNEL__)) + struct timer_list timer; +#else void *vt_os_arg; +#endif + unsigned int vt_stop_timer; unsigned int vt_msecs; }; diff --git a/linux/vhost_dev.c b/linux/vhost_dev.c index 686cf1b0d..409330857 100644 --- a/linux/vhost_dev.c +++ b/linux/vhost_dev.c @@ -463,7 +463,12 @@ vhost_setup(struct net_device *dev) dev->needed_headroom = sizeof(struct vr_eth) + sizeof(struct agent_hdr); dev->netdev_ops = &vhost_dev_ops; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,9)) + dev->priv_destructor = vhost_dev_destructor; + dev->needs_free_netdev = true; +#else dev->destructor = vhost_dev_destructor; +#endif /*KERNEL_4.11*/ #ifdef CONFIG_XEN dev->ethtool_ops = &vhost_ethtool_ops; dev->features |= NETIF_F_GRO; @@ -514,8 +519,15 @@ vhost_dellink(struct net_device *dev, struct list_head *head) return; } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,13,0)) +static int +vhost_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +#else static int vhost_validate(struct nlattr *tb[], struct nlattr *data[]) +#endif /*KERNEL_4.13*/ { if (vhost_num_interfaces >= VHOST_MAX_INTERFACES) return -ENOMEM; @@ -531,7 +543,6 @@ static struct rtnl_link_ops vhost_link_ops = { .dellink = vhost_dellink, }; - static void vhost_netlink_exit(void) { diff --git a/linux/vr_genetlink.c b/linux/vr_genetlink.c index d22257c29..b90846287 100644 --- a/linux/vr_genetlink.c +++ b/linux/vr_genetlink.c @@ -19,9 +19,10 @@ #include "sandesh.h" #include "vr_response.h" -#if (defined(RHEL_MAJOR) && (RHEL_MAJOR >= 7) && (RHEL_MINOR >= 5)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) || \ + (defined(RHEL_MAJOR) && (RHEL_MAJOR >= 7) && (RHEL_MINOR >= 5)) #define GENL_ID_GENERATE 0 -#endif +#endif /* Linux 4.10.0 */ static int netlink_trans_request(struct sk_buff *, struct genl_info *); static struct genl_ops vrouter_genl_ops[] = { @@ -32,16 +33,25 @@ static struct genl_ops vrouter_genl_ops[] = { }, }; +/* This becomes the group id 0x4 since group id allocation starts at */ +/* 0x4 and it is the only group for this family */ +struct genl_multicast_group vrouter_genl_groups[] = { + { .name = "VRouterGroup" }, +}; + struct genl_family vrouter_genl_family = { .id = GENL_ID_GENERATE, .name = "vrouter", .version = 1, .maxattr = NL_ATTR_MAX - 1, .netnsok = true, -#if (defined(RHEL_MAJOR) && (RHEL_MAJOR >= 7) && (RHEL_MINOR >= 5)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) || \ + (defined(RHEL_MAJOR) && (RHEL_MAJOR >= 7) && (RHEL_MINOR >= 5)) .ops = vrouter_genl_ops, .n_ops = ARRAY_SIZE(vrouter_genl_ops), -#endif + .mcgrps = vrouter_genl_groups, + .n_mcgrps = ARRAY_SIZE(vrouter_genl_groups), +#endif /* Linux 4.10.0 */ }; #define NETLINK_RESPONSE_HEADER_LEN (NLMSG_HDRLEN + GENL_HDRLEN + \ @@ -187,7 +197,8 @@ vr_genetlink_init(void) (!(defined(RHEL_MAJOR) && (RHEL_MAJOR >= 7)))) return genl_register_family_with_ops(&vrouter_genl_family, vrouter_genl_ops, ARRAY_SIZE(vrouter_genl_ops)); -#elif (defined(RHEL_MAJOR) && (RHEL_MAJOR >= 7) && (RHEL_MINOR >= 5)) +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)) || \ + (defined(RHEL_MAJOR) && (RHEL_MAJOR >= 7) && (RHEL_MINOR >= 5)) return genl_register_family(&vrouter_genl_family); #else return genl_register_family_with_ops(&vrouter_genl_family, diff --git a/linux/vr_host_interface.c b/linux/vr_host_interface.c index e6f99c4a1..24b92bfd9 100644 --- a/linux/vr_host_interface.c +++ b/linux/vr_host_interface.c @@ -247,7 +247,9 @@ linux_inet_fragment(struct vr_interface *vif, struct sk_buff *skb, netdev_features_t features; features = netif_skb_features(skb); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)) + features &= (~(NETIF_F_ALL_TSO | NETIF_F_GSO)); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) features &= (~(NETIF_F_ALL_TSO | NETIF_F_UFO | NETIF_F_GSO)); #else features &= ~(NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO); @@ -493,7 +495,9 @@ linux_gso_xmit(struct vr_interface *vif, struct sk_buff *skb, struct net_device *ndev = (struct net_device *)vif->vif_os; features = netif_skb_features(skb); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0)) + features &= (~(NETIF_F_ALL_TSO | NETIF_F_GSO)); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) features &= (~(NETIF_F_ALL_TSO | NETIF_F_UFO | NETIF_F_GSO)); #else features &= (~(NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO)); diff --git a/linux/vr_mem.c b/linux/vr_mem.c index 9014a9f31..ef56e20d1 100644 --- a/linux/vr_mem.c +++ b/linux/vr_mem.c @@ -5,6 +5,7 @@ * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. */ #include +#include #include #include #include @@ -22,10 +23,18 @@ short vr_flow_major = -1; static dev_t mem_dev; struct cdev *mem_cdev; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0)) static int mem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct vrouter *router = (struct vrouter *)vma->vm_private_data; +#else +static int +mem_fault(struct vm_fault *vmf) +{ + struct vrouter *router = + (struct vrouter *)vmf->vma->vm_private_data; +#endif /*KERNEL_4.11*/ struct page *page; pgoff_t offset; diff --git a/linux/vrouter_mod.c b/linux/vrouter_mod.c index b88867497..f8b971ad6 100644 --- a/linux/vrouter_mod.c +++ b/linux/vrouter_mod.c @@ -2046,11 +2046,22 @@ lh_network_header(struct vr_packet *pkt) return NULL; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) + typedef unsigned long linux_timer_callback_param_t; +#else + typedef struct timer_list * linux_timer_callback_param_t; +#endif + static void -linux_timer(unsigned long arg) +linux_timer(linux_timer_callback_param_t arg) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) struct vr_timer *vtimer = (struct vr_timer *)arg; - struct timer_list *timer = (struct timer_list *)vtimer->vt_os_arg; + struct timer_list *timer = &vtimer->timer; +#else + struct timer_list *timer = arg; + struct vr_timer *vtimer = from_timer(vtimer, timer, timer); +#endif vtimer->vt_timer(vtimer->vt_vr_arg); mod_timer(timer, get_jiffies_64() + msecs_to_jiffies(vtimer->vt_msecs)); @@ -2061,30 +2072,43 @@ linux_timer(unsigned long arg) static void lh_delete_timer(struct vr_timer *vtimer) { - struct timer_list *timer = (struct timer_list *)vtimer->vt_os_arg; + struct timer_list *timer = &vtimer->timer; if (timer) { del_timer_sync(timer); - vr_free(vtimer->vt_os_arg, VR_TIMER_OBJECT); - vtimer->vt_os_arg = NULL; } return; } +static int +lh_restart_timer(struct vr_timer *vtimer) +{ + struct timer_list *timer = &vtimer->timer; + if (!timer || !vtimer->vt_msecs) + return -1; + + vtimer->vt_stop_timer = 0; + + mod_timer(timer, get_jiffies_64() + msecs_to_jiffies(vtimer->vt_msecs)); + + return 0; +} + static int lh_create_timer(struct vr_timer *vtimer) { struct timer_list *timer; - timer = vr_zalloc(sizeof(*timer), VR_TIMER_OBJECT); - if (!timer) - return -ENOMEM; + timer = &vtimer->timer; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4,15,0) init_timer(timer); - - vtimer->vt_os_arg = (void *)timer; timer->data = (unsigned long)vtimer; timer->function = linux_timer; +#else + /* timer_list api has changed in 4.15 */ + timer_setup(timer, linux_timer, 0); +#endif timer->expires = get_jiffies_64() + msecs_to_jiffies(vtimer->vt_msecs); timer->expires = get_jiffies_64() + msecs_to_jiffies(vtimer->vt_msecs); add_timer(timer);