1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Ubuntu16.04 安装VM12:解决网卡驱动vmnet安装失败的问题

Ubuntu16.04 安装VM12:解决网卡驱动vmnet安装失败的问题

时间:2020-01-01 08:39:16

相关推荐

Ubuntu16.04 安装VM12:解决网卡驱动vmnet安装失败的问题

本人Ubuntu是16.04,在尝试安装VM12的时候,发现安装后,首次启动会弹出一个安装驱动的对话框,但安装过程中,第二步就失败了。提示如下:

可见,此错误在于虚拟网卡驱动编译不通过。这个问题在VM 14中并不会出现。

博客主页:/xs1102

经分析日志和查阅资料,发现此问题,是由于linux内核升级导致的。

1、根据日志文件,定位到目录 /usr/lib/vmware/modules/source/ 下的vmnet.tar。解压vmnet.tar到自己的任意目录下,得到vmnet-only文件夹。

2、修改vmnet-only文件夹下的bridge.c文件的第639行,由

atomic_inc(&clone->users);

改为

atomic_inc((atomic_t*)&(clone->users.refs));

强制类型转换 (atomic_t*) 不写也没有问题。若由于版本不同,代码位置有差异的请自行搜索。修改完后,不放心的话,可以使用make命令编译一下,不报错即可。

3、将vmnet-only文件夹打包为vmnet.tar,放回原位置替换掉,替换前最好备份,以防万一。

4、重新运行VMware即可,驱动编译通过。

至此,上述问题完美解决。该问题博主自己遇到了两次,第一次费劲解决了,第二次安装时又有此问题,所以才记录下来,方便下次查阅,也给大家提供些帮助。OK,非技术人员可以离开了,下边开始偏底层的问题代码分析。

出现上述问题的原因在于:linux内核在新版本,修改了一些底层函数,原子操作函数 atomic_inc的形参类型为atomic_t*,而sk_buff结构体中users的类型为refcount_t,在早期的linux内核中,users的类型为atomic_t,refcount_t是把atomic_t又包了一层。所以这就导致了指针类型不同,而编译失败。

所以在编译时,就出现了以下错误信息:

vmnet-only/bridge.c: In function ‘VNetBridgeReceiveFromVNet’:vmnet-only/bridge.c:639:14: error: passing argument 1 of ‘atomic_inc’ from incompatible pointer type [-Werror=incompatible-pointer-types]atomic_inc(&(clone->users));^In file included from ./include/linux/atomic.h:4:0,from ./include/linux/rcupdate.h:38,from ./include/linux/rculist.h:10,from ./include/linux/pid.h:4,from ./include/linux/sched.h:13,from vmnet-only/bridge.c:25:./arch/x86/include/asm/atomic.h:89:29: note: expected ‘atomic_t * {aka struct <anonymous> *}’ but argument is of type ‘refcount_t * {aka struct refcount_struct *}’static __always_inline void atomic_inc(atomic_t *v)^

在linux-4.10-rc2中11个模块,引用计数从atomic_t转为refcount_t:

kernel, mm: convert from atomic_t to refcount_t

net: convert from atomic_t to refcount_t

fs: convert from atomic_t to refcount_t

security: convert from atomic_t to refcount_t

sound: convert from atomic_t to refcount_t

ipc: covert from atomic_t to refcount_t

tools: convert from atomic_t to refcount_t

block: convert from atomic_t to refcount_t

drivers: net convert from atomic_t to refcount_t

drivers: misc drivers convert from atomic_t to refcount_t

drivers: infiniband convert from atomic_t to refcount_t

atomic_t结构体的定义如下:

typedef struct { volatile int counter; } atomic_t;

refcount_t结构体定义如下:

typedef struct refcount_struct {atomic_t refs;} refcount_t;

新版本的linux内核中sk_buff结构体的定义为:(/usr/src/linux-headers-4.13.0-39/include/linux/skbuff.h)

struct sk_buff {union {struct {/* These two members must be first. */struct sk_buff*next;struct sk_buff*prev;union {ktime_ttstamp;u64skb_mstamp;};};struct rb_noderbnode; /* used in netem & tcp stack */};struct sock*sk;union {struct net_device*dev;/* Some protocols might use this space to store information,* while device pointer would be NULL.* UDP receive path is one user.*/unsigned longdev_scratch;};/** This is the control buffer. It is free to use for every* layer. Please put your private variables there. If you* want to keep them across layers you have to do a skb_clone()* first. This is owned by whoever has the skb queued ATM.*/charcb[48] __aligned(8);unsigned long_skb_refdst;void(*destructor)(struct sk_buff *skb);#ifdef CONFIG_XFRMstructsec_path*sp;#endif#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)unsigned long _nfct;#endif#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)struct nf_bridge_info*nf_bridge;#endifunsigned intlen,data_len;__u16mac_len,hdr_len;/* Following fields are _not_ copied in __copy_skb_header()* Note that queue_mapping is here mostly to fill a hole.*/kmemcheck_bitfield_begin(flags1);__u16queue_mapping;/* if you move cloned around you also must adapt those constants */#ifdef __BIG_ENDIAN_BITFIELD#define CLONED_MASK(1 << 7)#else#define CLONED_MASK1#endif#define CLONED_OFFSET()offsetof(struct sk_buff, __cloned_offset)__u8__cloned_offset[0];__u8cloned:1,nohdr:1,fclone:2,peeked:1,head_frag:1,xmit_more:1,__unused:1; /* one bit hole */kmemcheck_bitfield_end(flags1);/* fields enclosed in headers_start/headers_end are copied* using a single memcpy() in __copy_skb_header()*//* private: */__u32headers_start[0];/* public: *//* if you move pkt_type around you also must adapt those constants */#ifdef __BIG_ENDIAN_BITFIELD#define PKT_TYPE_MAX(7 << 5)#else#define PKT_TYPE_MAX7#endif#define PKT_TYPE_OFFSET()offsetof(struct sk_buff, __pkt_type_offset)__u8__pkt_type_offset[0];__u8pkt_type:3;__u8pfmemalloc:1;__u8ignore_df:1;__u8nf_trace:1;__u8ip_summed:2;__u8ooo_okay:1;__u8l4_hash:1;__u8sw_hash:1;__u8wifi_acked_valid:1;__u8wifi_acked:1;__u8no_fcs:1;/* Indicates the inner headers are valid in the skbuff. */__u8encapsulation:1;__u8encap_hdr_csum:1;__u8csum_valid:1;__u8csum_complete_sw:1;__u8csum_level:2;__u8csum_not_inet:1;__u8dst_pending_confirm:1;#ifdef CONFIG_IPV6_NDISC_NODETYPE__u8ndisc_nodetype:2;#endif__u8ipvs_property:1;__u8inner_protocol_type:1;__u8remcsum_offload:1;#ifdef CONFIG_NET_SWITCHDEV__u8offload_fwd_mark:1;#endif#ifdef CONFIG_NET_CLS_ACT__u8tc_skip_classify:1;__u8tc_at_ingress:1;__u8tc_redirected:1;__u8tc_from_ingress:1;#endif#ifdef CONFIG_NET_SCHED__u16tc_index;/* traffic control index */#endifunion {__wsumcsum;struct {__u16csum_start;__u16csum_offset;};};__u32priority;intskb_iif;__u32hash;__be16vlan_proto;__u16vlan_tci;#if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS)union {unsigned intnapi_id;unsigned intsender_cpu;};#endif#ifdef CONFIG_NETWORK_SECMARK__u32secmark;#endifunion {__u32mark;__u32reserved_tailroom;};union {__be16inner_protocol;__u8inner_ipproto;};__u16inner_transport_header;__u16inner_network_header;__u16inner_mac_header;__be16protocol;__u16transport_header;__u16network_header;__u16mac_header;/* private: */__u32headers_end[0];/* public: *//* These elements must be at the end, see alloc_skb() for details. */sk_buff_data_ttail;sk_buff_data_tend;unsigned char*head,*data;unsigned inttruesize;refcount_tusers;};

旧版本的linux内核sk_buff结构体定义:

struct sk_buff { /* These two members must be first. */ struct sk_buff*next; struct sk_buff*prev; struct sock *sk; struct skb_timevaltstamp; struct net_device *dev; struct net_device *input_dev; union { struct tcphdr *th; struct udphdr *uh; struct icmphdr *icmph; struct igmphdr *igmph; struct iphdr *ipiph; struct ipv6hdr *ipv6h; unsigned char *raw; } h; union { struct iphdr *iph; struct ipv6hdr *ipv6h; struct arphdr *arph; unsigned char *raw; } nh; union { unsigned char *raw; } mac; struct dst_entry *dst; struct sec_path *sp; /* * This is the control buffer. It is free to use for every * layer. Please put your private variables there. If you * want to keep them across layers you have to do a skb_clone() * first. This is owned by whoever has the skb queued ATM. */ charcb[48]; unsigned int len, data_len, mac_len, csum; __u32 priority; __u8local_df:1, cloned:1, ip_summed:2, nohdr:1, nfctinfo:3; __u8pkt_type:3, fclone:2, ipvs_property:1; __be16 protocol; void(*destructor)(struct sk_buff *skb); #ifdef CONFIG_NETFILTER __u32 nfmark; struct nf_conntrack*nfct; #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct sk_buff*nfct_reasm; #endif #ifdef CONFIG_BRIDGE_NETFILTER struct nf_bridge_info *nf_bridge; #endif #endif /* CONFIG_NETFILTER */ #ifdef CONFIG_NET_SCHED __u16 tc_index; /* traffic control index */ #ifdef CONFIG_NET_CLS_ACT __u16 tc_verd; /* traffic control verdict */ #endif #endif /* These elements must be at the end, see alloc_skb() for details. */ unsigned int truesize; atomic_tusers; unsigned char *head, *data, *tail, *end; };

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。