vxlan.ko: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <__vxlan_find_mac>: } /* Look up Ethernet address in forwarding table */ static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { 0: e8 00 00 00 00 callq 5 <__vxlan_find_mac+0x5> 5: 55 push %rbp 6: 48 8b 16 mov (%rsi),%rdx 9: 48 b8 eb 83 b5 80 46 movabs $0x61c8864680b583eb,%rax 10: 86 c8 61 13: 48 89 e5 mov %rsp,%rbp 16: 48 c1 e2 10 shl $0x10,%rdx 1a: 48 0f af c2 imul %rdx,%rax 1e: 48 c1 e8 38 shr $0x38,%rax 22: 48 8d 84 c7 60 01 00 lea 0x160(%rdi,%rax,8),%rax 29: 00 2a: 48 8b 00 mov (%rax),%rax 2d: 48 85 c0 test %rax,%rax 30: 74 22 je 54 <__vxlan_find_mac+0x54> 32: 8b 3e mov (%rsi),%edi 34: 0f b7 76 04 movzwl 0x4(%rsi),%esi struct hlist_head *head = vxlan_fdb_head(vxlan, mac); struct vxlan_fdb *f; hlist_for_each_entry_rcu(f, head, hlist) { 38: 89 f2 mov %esi,%edx 3a: 66 33 50 44 xor 0x44(%rax),%dx 3e: 8b 48 40 mov 0x40(%rax),%ecx 41: 31 f9 xor %edi,%ecx } /* Look up Ethernet address in forwarding table */ static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { 43: 0f b7 d2 movzwl %dx,%edx struct hlist_head *head = vxlan_fdb_head(vxlan, mac); struct vxlan_fdb *f; hlist_for_each_entry_rcu(f, head, hlist) { 46: 09 d1 or %edx,%ecx 48: 74 08 je 52 <__vxlan_find_mac+0x52> 4a: 48 8b 00 mov (%rax),%rax 4d: 48 85 c0 test %rax,%rax 50: 75 e6 jne 38 <__vxlan_find_mac+0x38> 52: 5d pop %rbp 53: c3 retq 54: 31 c0 xor %eax,%eax 56: 5d pop %rbp 57: c3 retq 58: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 5f: 00 0000000000000060 : 60: e8 00 00 00 00 callq 65 65: 55 push %rbp 66: 48 89 e5 mov %rsp,%rbp if (ether_addr_equal(mac, f->eth_addr)) 69: 5d pop %rbp 6a: c3 retq 6b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 0000000000000070 : 70: e8 00 00 00 00 callq 75 75: 55 push %rbp 76: b8 c8 00 00 00 mov $0xc8,%eax }) static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; 7b: 48 89 e5 mov %rsp,%rbp const u8 *mac) { struct hlist_head *head = vxlan_fdb_head(vxlan, mac); struct vxlan_fdb *f; hlist_for_each_entry_rcu(f, head, hlist) { 7e: 5d pop %rbp 7f: c3 retq 0000000000000080 : 80: e8 00 00 00 00 callq 85 if (ether_addr_equal(mac, f->eth_addr)) return f; } return NULL; 85: 55 push %rbp } 86: 48 8b 87 78 08 00 00 mov 0x878(%rdi),%rax 8d: 48 89 e5 mov %rsp,%rbp return ret; } /* Stub, nothing needs to be done. */ static void vxlan_set_multicast_list(struct net_device *dev) { 90: 5d pop %rbp 91: c3 retq 92: 0f 1f 40 00 nopl 0x0(%rax) 96: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 9d: 00 00 00 00000000000000a0 : list_del(&vxlan->next); unregister_netdevice_queue(dev, head); } static size_t vxlan_get_size(const struct net_device *dev) { a0: e8 00 00 00 00 callq a5 a5: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # ab ab: 48 8b 97 88 14 00 00 mov 0x1488(%rdi),%rdx nla_put_failure: return -EMSGSIZE; } static struct net *vxlan_get_link_net(const struct net_device *dev) { b2: 55 push %rbp b3: 83 e8 01 sub $0x1,%eax struct vxlan_dev *vxlan = netdev_priv(dev); return vxlan->net; b6: 48 89 e5 mov %rsp,%rbp b9: 48 98 cltq bb: 48 8b 54 c2 18 mov 0x18(%rdx,%rax,8),%rdx } c0: 48 89 12 mov %rdx,(%rdx) c3: 48 89 52 08 mov %rdx,0x8(%rdx) c7: 48 8d 42 10 lea 0x10(%rdx),%rax cb: c7 82 10 08 00 00 00 movl $0x0,0x810(%rdx) d2: 00 00 00 struct net_generic *ng; void *ptr; rcu_read_lock(); ng = rcu_dereference(net->gen); ptr = ng->ptr[id - 1]; d5: 48 81 c2 10 08 00 00 add $0x810,%rdx dc: 48 c7 00 00 00 00 00 movq $0x0,(%rax) e3: 48 83 c0 08 add $0x8,%rax static struct notifier_block vxlan_notifier_block __read_mostly = { .notifier_call = vxlan_netdevice_event, }; static __net_init int vxlan_init_net(struct net *net) { e7: 48 39 d0 cmp %rdx,%rax ea: 75 f0 jne dc ec: 31 c0 xor %eax,%eax ee: 5d pop %rbp ef: c3 retq 00000000000000f0 : { switch (size) { case 1: *(volatile __u8 *)p = *(__u8 *)res; break; case 2: *(volatile __u16 *)p = *(__u16 *)res; break; case 4: *(volatile __u32 *)p = *(__u32 *)res; break; case 8: *(volatile __u64 *)p = *(__u64 *)res; break; f0: e8 00 00 00 00 callq f5 struct list_head name = LIST_HEAD_INIT(name) static inline void INIT_LIST_HEAD(struct list_head *list) { WRITE_ONCE(list->next, list); list->prev = list; f5: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # fb struct vxlan_net *vn = net_generic(net, vxlan_net_id); unsigned int h; INIT_LIST_HEAD(&vn->vxlan_list); spin_lock_init(&vn->sock_lock); fb: 55 push %rbp fc: 41 89 d0 mov %edx,%r8d ff: 4c 8b 8f 88 14 00 00 mov 0x1488(%rdi),%r9 106: 66 c1 c2 08 rol $0x8,%dx 10a: 81 e1 00 7d 00 00 and $0x7d00,%ecx for (h = 0; h < PORT_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vn->sock_list[h]); 110: 48 89 e5 mov %rsp,%rbp 113: 8d 78 ff lea -0x1(%rax),%edi 116: 0f b7 c2 movzwl %dx,%eax unsigned int h; INIT_LIST_HEAD(&vn->vxlan_list); spin_lock_init(&vn->sock_lock); for (h = 0; h < PORT_HASH_SIZE; ++h) 119: 69 c0 47 86 c8 61 imul $0x61c88647,%eax,%eax INIT_HLIST_HEAD(&vn->sock_list[h]); return 0; } 11f: 48 63 ff movslq %edi,%rdi /* Find VXLAN socket based on network namespace, address family and UDP port * and enabled unshareable flags. */ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family, __be16 port, u32 flags) { 122: 49 8b 54 f9 18 mov 0x18(%r9,%rdi,8),%rdx 127: c1 e8 18 shr $0x18,%eax 12a: 48 8d 44 c2 10 lea 0x10(%rdx,%rax,8),%rax }) static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; 12f: 48 8b 00 mov (%rax),%rax 132: 48 85 c0 test %rax,%rax 135: 75 1a jne 151 /* Socket hash table head */ static inline struct hlist_head *vs_head(struct net *net, __be16 port) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)]; 137: 31 c0 xor %eax,%eax 139: 5d pop %rbp static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family, __be16 port, u32 flags) { struct vxlan_sock *vs; flags &= VXLAN_F_RCV_FLAGS; 13a: c3 retq 13b: 66 3b 72 10 cmp 0x10(%rdx),%si 13f: 75 08 jne 149 /* Find VXLAN socket based on network namespace, address family and UDP port * and enabled unshareable flags. */ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family, __be16 port, u32 flags) { 141: 3b 88 1c 20 00 00 cmp 0x201c(%rax),%ecx struct vxlan_sock *vs; flags &= VXLAN_F_RCV_FLAGS; hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { 147: 74 f0 je 139 149: 48 8b 00 mov (%rax),%rax 14c: 48 85 c0 test %rax,%rax 14f: 74 e8 je 139 151: 48 8b 50 10 mov 0x10(%rax),%rdx 155: 48 8b 52 20 mov 0x20(%rdx),%rdx 159: 66 44 3b 82 e0 02 00 cmp 0x2e0(%rdx),%r8w 160: 00 161: 75 e6 jne 149 163: eb d6 jmp 13b 165: 90 nop 166: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 16d: 00 00 00 0000000000000170 : if (inet_sk(vs->sock->sk)->inet_sport == port && 170: e8 00 00 00 00 callq 175 vxlan_get_sk_family(vs) == family && 175: 55 push %rbp 176: 48 89 e5 mov %rsp,%rbp 179: 53 push %rbx 17a: 89 f3 mov %esi,%ebx { struct vxlan_sock *vs; flags &= VXLAN_F_RCV_FLAGS; hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { 17c: 89 d6 mov %edx,%esi 17e: 0f b7 d1 movzwl %cx,%edx if (inet_sk(vs->sock->sk)->inet_sport == port && 181: 44 89 c1 mov %r8d,%ecx 184: 0f b7 f6 movzwl %si,%esi 187: e8 64 ff ff ff callq f0 18c: 48 85 c0 test %rax,%rax 18f: 74 2f je 1c0 191: f6 80 1d 20 00 00 20 testb $0x20,0x201d(%rax) 198: 75 2b jne 1c5 19a: 69 d3 47 86 c8 61 imul $0x61c88647,%ebx,%edx /* Look up VNI in a per net namespace table */ static struct vxlan_dev *vxlan_find_vni(struct net *net, __be32 vni, sa_family_t family, __be16 port, u32 flags) { 1a0: c1 ea 16 shr $0x16,%edx 1a3: 48 8d 44 d0 10 lea 0x10(%rax,%rdx,8),%rax 1a8: 48 8b 50 08 mov 0x8(%rax),%rdx 1ac: 31 c0 xor %eax,%eax struct vxlan_sock *vs; vs = vxlan_find_sock(net, family, port, flags); 1ae: 48 85 d2 test %rdx,%rdx 1b1: 74 0f je 1c2 1b3: 3b 5a 60 cmp 0x60(%rdx),%ebx 1b6: 74 13 je 1cb 1b8: 48 8b 12 mov (%rdx),%rdx 1bb: 48 85 d2 test %rdx,%rdx if (!vs) 1be: 75 f3 jne 1b3 1c0: 31 c0 xor %eax,%eax static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, __be32 vni) { struct vxlan_dev *vxlan; /* For flow based devices, map all packets to VNI 0 */ if (vs->flags & VXLAN_F_COLLECT_METADATA) 1c2: 5b pop %rbx 1c3: 5d pop %rbp 1c4: c3 retq 1c5: 31 d2 xor %edx,%edx 1c7: 31 db xor %ebx,%ebx 1c9: eb d8 jmp 1a3 1cb: 48 89 d0 mov %rdx,%rax 1ce: 5b pop %rbx 1cf: 5d pop %rbp 1d0: c3 retq 1d1: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) vni = 0; hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) { 1d6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 1dd: 00 00 00 00000000000001e0 : 1e0: e8 00 00 00 00 callq 1e5 if (vxlan->default_dst.remote_vni == vni) 1e5: 55 push %rbp 1e6: 48 8b 47 08 mov 0x8(%rdi),%rax 1ea: 48 89 e5 mov %rsp,%rbp /* For flow based devices, map all packets to VNI 0 */ if (vs->flags & VXLAN_F_COLLECT_METADATA) vni = 0; hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) { 1ed: 48 85 c0 test %rax,%rax { struct vxlan_sock *vs; vs = vxlan_find_sock(net, family, port, flags); if (!vs) return NULL; 1f0: 74 3c je 22e return vxlan_vs_find_vni(vs, vni); } 1f2: 66 83 38 0a cmpw $0xa,(%rax) static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, __be32 vni) { struct vxlan_dev *vxlan; /* For flow based devices, map all packets to VNI 0 */ if (vs->flags & VXLAN_F_COLLECT_METADATA) 1f6: 74 26 je 21e vni = 0; 1f8: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) { if (vxlan->default_dst.remote_vni == vni) 1fd: b8 ea ff ff ff mov $0xffffffea,%eax vs = vxlan_find_sock(net, family, port, flags); if (!vs) return NULL; return vxlan_vs_find_vni(vs, vni); } 202: 5d pop %rbp 203: c3 retq 204: 48 c7 c6 00 00 00 00 mov $0x0,%rsi 20b: 48 c7 c7 00 00 00 00 mov $0x0,%rdi [IFLA_VXLAN_GPE] = { .type = NLA_FLAG, }, [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG }, }; static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) { 212: e8 00 00 00 00 callq 217 if (tb[IFLA_ADDRESS]) { 217: b8 ea ff ff ff mov $0xffffffea,%eax [IFLA_VXLAN_GPE] = { .type = NLA_FLAG, }, [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG }, }; static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) { 21c: 5d pop %rbp if (tb[IFLA_ADDRESS]) { 21d: c3 retq 21e: 8b 50 04 mov 0x4(%rax),%edx 221: f6 c2 01 test $0x1,%dl if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { 224: 75 46 jne 26c 226: 0f b7 40 08 movzwl 0x8(%rax),%eax 22a: 09 d0 or %edx,%eax 22c: 74 3e je 26c = nla_data(data[IFLA_VXLAN_PORT_RANGE]); if (ntohs(p->high) < ntohs(p->low)) { pr_debug("port range %u .. %u not valid\n", ntohs(p->low), ntohs(p->high)); return -EINVAL; 22e: 48 85 f6 test %rsi,%rsi 231: 74 5e je 291 } } return 0; } 233: 48 8b 46 08 mov 0x8(%rsi),%rax static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[]) { if (tb[IFLA_ADDRESS]) { if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) { pr_debug("invalid link address (not ethernet)\n"); 237: 48 85 c0 test %rax,%rax 23a: 74 09 je 245 23c: 81 78 04 fe ff ff 00 cmpl $0xfffffe,0x4(%rax) 243: 77 71 ja 2b6 245: 48 8b 46 50 mov 0x50(%rsi),%rax return -EINVAL; 249: 48 85 c0 test %rax,%rax return -EINVAL; } } return 0; } 24c: 74 64 je 2b2 * By definition the broadcast address is also a multicast address. */ static inline bool is_multicast_ether_addr(const u8 *addr) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) u32 a = *(const u32 *)addr; 24e: 0f b7 48 06 movzwl 0x6(%rax),%ecx */ static inline bool is_valid_ether_addr(const u8 *addr) { /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to * explicitly check for it here. */ return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr); 252: 0f b7 50 04 movzwl 0x4(%rax),%edx 256: 31 c0 xor %eax,%eax 258: 66 c1 c1 08 rol $0x8,%cx 25c: 66 c1 c2 08 rol $0x8,%dx pr_debug("invalid all zero ethernet address\n"); return -EADDRNOTAVAIL; } } if (!data) 260: 66 39 d1 cmp %dx,%cx return -EINVAL; if (data[IFLA_VXLAN_ID]) { 263: 73 9d jae 202 265: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 26a: eb 91 jmp 1fd __u32 id = nla_get_u32(data[IFLA_VXLAN_ID]); if (id >= VXLAN_VID_MASK) 26c: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 271: b8 9d ff ff ff mov $0xffffff9d,%eax return -ERANGE; } if (data[IFLA_VXLAN_PORT_RANGE]) { 276: 5d pop %rbp 277: c3 retq 278: 0f b7 c9 movzwl %cx,%ecx 27b: 0f b7 d2 movzwl %dx,%edx const struct ifla_vxlan_port_range *p = nla_data(data[IFLA_VXLAN_PORT_RANGE]); if (ntohs(p->high) < ntohs(p->low)) { 27e: 48 c7 c6 00 00 00 00 mov $0x0,%rsi 285: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 28c: e8 00 00 00 00 callq 291 291: b8 ea ff ff ff mov $0xffffffea,%eax 296: 5d pop %rbp 297: c3 retq 298: 48 c7 c6 00 00 00 00 mov $0x0,%rsi #include #include static __always_inline bool arch_static_branch(struct static_key *key, bool branch) { asm_volatile_goto("1:" 29f: 48 c7 c7 00 00 00 00 mov $0x0,%rdi return -EINVAL; } } return 0; } 2a6: e8 00 00 00 00 callq 2ab if (data[IFLA_VXLAN_PORT_RANGE]) { const struct ifla_vxlan_port_range *p = nla_data(data[IFLA_VXLAN_PORT_RANGE]); if (ntohs(p->high) < ntohs(p->low)) { pr_debug("port range %u .. %u not valid\n", 2ab: b8 9d ff ff ff mov $0xffffff9d,%eax 2b0: 5d pop %rbp 2b1: c3 retq 2b2: 31 c0 xor %eax,%eax 2b4: 5d pop %rbp 2b5: c3 retq 2b6: b8 de ff ff ff mov $0xffffffde,%eax 2bb: 5d pop %rbp 2bc: c3 retq 2bd: 0f 1f 00 nopl (%rax) 00000000000002c0 : 2c0: e8 00 00 00 00 callq 2c5 ntohs(p->low), ntohs(p->high)); return -EINVAL; 2c5: 55 push %rbp } } return 0; } 2c6: 48 89 e5 mov %rsp,%rbp pr_debug("invalid link address (not ethernet)\n"); return -EINVAL; } if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) { pr_debug("invalid all zero ethernet address\n"); 2c9: 41 56 push %r14 2cb: 41 55 push %r13 2cd: 41 54 push %r12 2cf: 53 push %rbx 2d0: 4c 8d 6f 20 lea 0x20(%rdi),%r13 2d4: 48 8b 47 20 mov 0x20(%rdi),%rax 2d8: 4c 8d 77 f0 lea -0x10(%rdi),%r14 return -EADDRNOTAVAIL; 2dc: 48 8b 08 mov (%rax),%rcx 2df: 49 39 c5 cmp %rax,%r13 ntohs(p->low), ntohs(p->high)); return -EINVAL; } } return 0; 2e2: 4c 8d 60 d8 lea -0x28(%rax),%r12 return -EINVAL; if (data[IFLA_VXLAN_ID]) { __u32 id = nla_get_u32(data[IFLA_VXLAN_ID]); if (id >= VXLAN_VID_MASK) return -ERANGE; 2e6: 48 8d 59 d8 lea -0x28(%rcx),%rbx 2ea: 74 26 je 312 return -EINVAL; } } return 0; } 2ec: 49 8d 7c 24 48 lea 0x48(%r12),%rdi return 0; } static void vxlan_fdb_free(struct rcu_head *head) { 2f1: e8 00 00 00 00 callq 2f6 2f6: 4c 89 e7 mov %r12,%rdi 2f9: 49 89 dc mov %rbx,%r12 2fc: e8 00 00 00 00 callq 301 struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); struct vxlan_rdst *rd, *nd; list_for_each_entry_safe(rd, nd, &f->remotes, list) { 301: 48 8d 43 28 lea 0x28(%rbx),%rax 305: 48 8b 53 28 mov 0x28(%rbx),%rdx return 0; } static void vxlan_fdb_free(struct rcu_head *head) { struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); 309: 4c 39 e8 cmp %r13,%rax struct vxlan_rdst *rd, *nd; list_for_each_entry_safe(rd, nd, &f->remotes, list) { 30c: 48 8d 5a d8 lea -0x28(%rdx),%rbx 310: 75 da jne 2ec 312: 4c 89 f7 mov %r14,%rdi 315: e8 00 00 00 00 callq 31a 31a: 5b pop %rbx 31b: 41 5c pop %r12 dst_cache_destroy(&rd->dst_cache); 31d: 41 5d pop %r13 31f: 41 5e pop %r14 321: 5d pop %rbp 322: c3 retq 323: 0f 1f 00 nopl (%rax) kfree(rd); 326: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 32d: 00 00 00 0000000000000330 : 330: 55 push %rbp static void vxlan_fdb_free(struct rcu_head *head) { struct vxlan_fdb *f = container_of(head, struct vxlan_fdb, rcu); struct vxlan_rdst *rd, *nd; list_for_each_entry_safe(rd, nd, &f->remotes, list) { 331: 48 89 e5 mov %rsp,%rbp 334: 41 56 push %r14 336: 41 55 push %r13 338: 45 31 ed xor %r13d,%r13d 33b: 85 f6 test %esi,%esi 33d: 41 54 push %r12 33f: 53 push %rbx 340: 7e 6e jle 3b0 dst_cache_destroy(&rd->dst_cache); kfree(rd); } kfree(f); 342: 41 89 f5 mov %esi,%r13d 345: 48 8b 77 e8 mov -0x18(%rdi),%rsi 349: 4c 8d 77 e8 lea -0x18(%rdi),%r14 } 34d: 48 89 fb mov %rdi,%rbx 350: 49 39 f6 cmp %rsi,%r14 353: 74 4d je 3a2 355: 48 85 f6 test %rsi,%rsi 358: 74 48 je 3a2 35a: 45 31 e4 xor %r12d,%r12d 35d: 83 6b f8 01 subl $0x1,-0x8(%rbx) return NET_RX_SUCCESS; } /* called under BH context */ static inline int gro_cell_poll(struct napi_struct *napi, int budget) { 361: 48 89 df mov %rbx,%rdi 364: 41 83 c4 01 add $0x1,%r12d struct gro_cell *cell = container_of(napi, struct gro_cell, napi); struct sk_buff *skb; int work_done = 0; 368: 48 8b 16 mov (%rsi),%rdx while (work_done < budget) { 36b: 48 8b 46 08 mov 0x8(%rsi),%rax return NET_RX_SUCCESS; } /* called under BH context */ static inline int gro_cell_poll(struct napi_struct *napi, int budget) { 36f: 48 c7 06 00 00 00 00 movq $0x0,(%rsi) * The reference count is not incremented and the reference is therefore * volatile. Use with caution. */ static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_) { struct sk_buff *skb = list_->next; 376: 48 c7 46 08 00 00 00 movq $0x0,0x8(%rsi) 37d: 00 struct gro_cell *cell = container_of(napi, struct gro_cell, napi); struct sk_buff *skb; int work_done = 0; while (work_done < budget) { skb = __skb_dequeue(&cell->napi_skbs); 37e: 48 89 42 08 mov %rax,0x8(%rdx) */ struct sk_buff *skb_dequeue(struct sk_buff_head *list); static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list) { struct sk_buff *skb = skb_peek(list); if (skb) 382: 48 89 10 mov %rdx,(%rax) 385: e8 00 00 00 00 callq 38a 38a: 45 39 e5 cmp %r12d,%r13d void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list); static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) { struct sk_buff *next, *prev; list->qlen--; 38d: 74 21 je 3b0 38f: 48 8b 73 e8 mov -0x18(%rbx),%rsi if (!skb) break; napi_gro_receive(napi, skb); 393: 48 85 f6 test %rsi,%rsi work_done++; 396: 74 05 je 39d next = skb->next; 398: 4c 39 f6 cmp %r14,%rsi prev = skb->prev; 39b: 75 c0 jne 35d 39d: 45 89 e5 mov %r12d,%r13d skb->next = skb->prev = NULL; 3a0: eb 03 jmp 3a5 3a2: 45 31 ed xor %r13d,%r13d 3a5: 44 89 ee mov %r13d,%esi 3a8: 48 89 df mov %rbx,%rdi 3ab: e8 00 00 00 00 callq 3b0 next->prev = prev; 3b0: 5b pop %rbx 3b1: 44 89 e8 mov %r13d,%eax prev->next = next; 3b4: 41 5c pop %r12 while (work_done < budget) { skb = __skb_dequeue(&cell->napi_skbs); if (!skb) break; napi_gro_receive(napi, skb); 3b6: 41 5d pop %r13 3b8: 41 5e pop %r14 { struct gro_cell *cell = container_of(napi, struct gro_cell, napi); struct sk_buff *skb; int work_done = 0; while (work_done < budget) { 3ba: 5d pop %rbp 3bb: c3 retq 3bc: 0f 1f 40 00 nopl 0x0(%rax) 00000000000003c0 : * The reference count is not incremented and the reference is therefore * volatile. Use with caution. */ static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_) { struct sk_buff *skb = list_->next; 3c0: e8 00 00 00 00 callq 3c5 */ struct sk_buff *skb_dequeue(struct sk_buff_head *list); static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list) { struct sk_buff *skb = skb_peek(list); if (skb) 3c5: 55 push %rbp 3c6: be 06 00 00 00 mov $0x6,%esi 3cb: 48 89 e5 mov %rsp,%rbp skb = __skb_dequeue(&cell->napi_skbs); if (!skb) break; napi_gro_receive(napi, skb); work_done++; 3ce: 41 55 push %r13 3d0: 41 54 push %r12 /* called under BH context */ static inline int gro_cell_poll(struct napi_struct *napi, int budget) { struct gro_cell *cell = container_of(napi, struct gro_cell, napi); struct sk_buff *skb; int work_done = 0; 3d2: 53 push %rbx 3d3: 48 8b 9f 38 03 00 00 mov 0x338(%rdi),%rbx napi_gro_receive(napi, skb); work_done++; } if (work_done < budget) napi_complete_done(napi, work_done); 3da: 49 89 fc mov %rdi,%r12 3dd: c6 87 74 02 00 00 01 movb $0x1,0x274(%rdi) return work_done; } 3e4: 48 89 df mov %rbx,%rdi 3e7: e8 00 00 00 00 callq 3ec 3ec: 0f b6 03 movzbl (%rbx),%eax 3ef: 4c 89 e7 mov %r12,%rdi spin_unlock(&vn->sock_lock); } /* Initialize the device structure. */ static void vxlan_setup(struct net_device *dev) { 3f2: 83 e0 fe and $0xfffffffe,%eax 3f5: 83 c8 02 or $0x2,%eax * Generate a random Ethernet address (MAC) that is not multicast * and has the local assigned bit set. */ static inline void eth_random_addr(u8 *addr) { get_random_bytes(addr, ETH_ALEN); 3f8: 88 03 mov %al,(%rbx) 3fa: 49 8d 9c 24 40 08 00 lea 0x840(%r12),%rbx 401: 00 402: e8 00 00 00 00 callq 407 407: 49 8b 8c 24 f0 00 00 mov 0xf0(%r12),%rcx 40e: 00 * and set addr_assign_type so the state can be read by sysfs and be * used by userspace. */ static inline void eth_hw_addr_random(struct net_device *dev) { dev->addr_assign_type = NET_ADDR_RANDOM; 40f: 48 b8 89 10 3b 80 20 movabs $0x420803b1089,%rax 416: 04 00 00 * Generate a random Ethernet address (MAC) that is not multicast * and has the local assigned bit set. */ static inline void eth_random_addr(u8 *addr) { get_random_bytes(addr, ETH_ALEN); 419: 48 ba 09 10 3b 80 20 movabs $0x20803b1009,%rdx 420: 00 00 00 addr[0] &= 0xfe; /* clear multicast bit */ addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ 423: 49 8d bc 24 e0 08 00 lea 0x8e0(%r12),%rdi 42a: 00 dev->hw_features |= NETIF_F_GSO_SOFTWARE; dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; netif_keep_dst(dev); dev->priv_flags |= IFF_NO_QUEUE; INIT_LIST_HEAD(&vxlan->next); 42b: be 00 00 08 00 mov $0x80000,%esi 430: 49 c7 84 24 70 04 00 movq $0x0,0x470(%r12) 437: 00 00 00 00 00 ether_setup(dev); dev->destructor = free_netdev; SET_NETDEV_DEVTYPE(dev, &vxlan_type); dev->features |= NETIF_F_LLTX; 43c: 49 c7 84 24 f8 04 00 movq $0x0,0x4f8(%r12) 443: 00 00 00 00 00 dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; dev->features |= NETIF_F_RXCSUM; dev->features |= NETIF_F_GSO_SOFTWARE; dev->vlan_features = dev->features; dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; 448: 41 c7 84 24 28 09 00 movl $0x0,0x928(%r12) 44f: 00 00 00 00 00 dev->priv_flags |= IFF_NO_QUEUE; INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); init_timer_deferrable(&vxlan->age_timer); 454: 48 09 c8 or %rcx,%rax 457: 48 09 ca or %rcx,%rdx 45a: 31 c9 xor %ecx,%ecx 45c: 49 89 84 24 f0 00 00 mov %rax,0xf0(%r12) 463: 00 unsigned int h; eth_hw_addr_random(dev); ether_setup(dev); dev->destructor = free_netdev; 464: 48 b8 89 00 3b 80 20 movabs $0x420803b0089,%rax 46b: 04 00 00 SET_NETDEV_DEVTYPE(dev, &vxlan_type); 46e: 49 09 84 24 f8 00 00 or %rax,0xf8(%r12) 475: 00 476: 41 8b 84 24 3c 02 00 mov 0x23c(%r12),%eax 47d: 00 dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; netif_keep_dst(dev); dev->priv_flags |= IFF_NO_QUEUE; INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); 47e: 49 89 94 24 08 01 00 mov %rdx,0x108(%r12) 485: 00 dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; dev->features |= NETIF_F_RXCSUM; dev->features |= NETIF_F_GSO_SOFTWARE; dev->vlan_features = dev->features; dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; 486: 31 d2 xor %edx,%edx dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; dev->features |= NETIF_F_RXCSUM; dev->features |= NETIF_F_GSO_SOFTWARE; dev->vlan_features = dev->features; 488: 25 df ff fd ff and $0xfffdffdf,%eax dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; 48d: 0d 00 00 20 00 or $0x200000,%eax 492: 41 89 84 24 3c 02 00 mov %eax,0x23c(%r12) 499: 00 dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM; dev->hw_features |= NETIF_F_GSO_SOFTWARE; dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; 49a: 49 8d 84 24 50 08 00 lea 0x850(%r12),%rax 4a1: 00 4a2: 49 89 84 24 50 08 00 mov %rax,0x850(%r12) 4a9: 00 netif_keep_dst(dev); dev->priv_flags |= IFF_NO_QUEUE; 4aa: 49 89 84 24 58 08 00 mov %rax,0x858(%r12) 4b1: 00 dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; dev->features |= NETIF_F_RXCSUM; dev->features |= NETIF_F_GSO_SOFTWARE; dev->vlan_features = dev->features; 4b2: e8 00 00 00 00 callq 4b7 dev->priv_flags |= IFF_NO_QUEUE; INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); init_timer_deferrable(&vxlan->age_timer); 4b7: 0f b7 05 00 00 00 00 movzwl 0x0(%rip),%eax # 4be dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM; dev->hw_features |= NETIF_F_GSO_SOFTWARE; dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX; netif_keep_dst(dev); dev->priv_flags |= IFF_NO_QUEUE; 4be: 49 c7 84 24 f8 08 00 movq $0x0,0x8f8(%r12) 4c5: 00 00 00 00 00 INIT_LIST_HEAD(&vxlan->next); 4ca: be 08 00 00 00 mov $0x8,%esi 4cf: 49 89 9c 24 00 09 00 mov %rbx,0x900(%r12) 4d6: 00 { switch (size) { case 1: *(volatile __u8 *)p = *(__u8 *)res; break; case 2: *(volatile __u16 *)p = *(__u16 *)res; break; case 4: *(volatile __u32 *)p = *(__u32 *)res; break; case 8: *(volatile __u64 *)p = *(__u64 *)res; break; 4d7: 4d 89 a4 24 70 08 00 mov %r12,0x870(%r12) 4de: 00 4df: bf e0 00 00 00 mov $0xe0,%edi spin_lock_init(&vxlan->hash_lock); init_timer_deferrable(&vxlan->age_timer); 4e4: 66 c1 c0 08 rol $0x8,%ax vxlan->age_timer.function = vxlan_cleanup; vxlan->age_timer.data = (unsigned long) vxlan; vxlan->cfg.dst_port = htons(vxlan_port); 4e8: 66 41 89 84 24 7c 09 mov %ax,0x97c(%r12) 4ef: 00 00 INIT_LIST_HEAD(&vxlan->next); spin_lock_init(&vxlan->hash_lock); init_timer_deferrable(&vxlan->age_timer); vxlan->age_timer.function = vxlan_cleanup; 4f1: e8 00 00 00 00 callq 4f6 4f6: 48 85 c0 test %rax,%rax 4f9: 49 89 84 24 30 09 00 mov %rax,0x930(%r12) 500: 00 vxlan->age_timer.data = (unsigned long) vxlan; 501: 74 77 je 57a 503: 41 bd ff ff ff ff mov $0xffffffff,%r13d vxlan->cfg.dst_port = htons(vxlan_port); vxlan->dev = dev; 509: eb 0a jmp 515 50b: f0 80 63 28 fe lock andb $0xfe,0x28(%rbx) static inline int gro_cells_init(struct gro_cells *gcells, struct net_device *dev) { int i; gcells->cells = alloc_percpu(struct gro_cell); 510: f0 80 63 28 fb lock andb $0xfb,0x28(%rbx) init_timer_deferrable(&vxlan->age_timer); vxlan->age_timer.function = vxlan_cleanup; vxlan->age_timer.data = (unsigned long) vxlan; vxlan->cfg.dst_port = htons(vxlan_port); 515: 41 8d 55 01 lea 0x1(%r13),%edx 519: be 00 01 00 00 mov $0x100,%esi 51e: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 525: 48 63 d2 movslq %edx,%rdx if (!gcells->cells) 528: e8 00 00 00 00 callq 52d static inline int gro_cells_init(struct gro_cells *gcells, struct net_device *dev) { int i; gcells->cells = alloc_percpu(struct gro_cell); 52d: 3b 05 00 00 00 00 cmp 0x0(%rip),%eax # 533 if (!gcells->cells) 533: 41 89 c5 mov %eax,%r13d 536: 7d 42 jge 57a 538: 48 98 cltq 53a: 49 8b 9c 24 30 09 00 mov 0x930(%r12),%rbx 541: 00 */ static __always_inline void clear_bit(long nr, volatile unsigned long *addr) { if (IS_IMMEDIATE(nr)) { asm volatile(LOCK_PREFIX "andb %1,%0" 542: b9 40 00 00 00 mov $0x40,%ecx static inline unsigned int cpumask_next(int n, const struct cpumask *srcp) { /* -1 is a legal arg here. */ if (n != -1) cpumask_check(n); return find_next_bit(cpumask_bits(srcp), nr_cpumask_bits, n+1); 547: 48 03 1c c5 00 00 00 add 0x0(,%rax,8),%rbx 54e: 00 54f: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 556: 4c 89 e7 mov %r12,%rdi 559: 48 8d 73 18 lea 0x18(%rbx),%rsi return -ENOMEM; for_each_possible_cpu(i) { 55d: 48 89 1b mov %rbx,(%rbx) 560: 48 89 5b 08 mov %rbx,0x8(%rbx) 564: c7 43 10 00 00 00 00 movl $0x0,0x10(%rbx) struct gro_cell *cell = per_cpu_ptr(gcells->cells, i); 56b: e8 00 00 00 00 callq 570 570: 48 8b 43 28 mov 0x28(%rbx),%rax __skb_queue_head_init(&cell->napi_skbs); netif_napi_add(dev, &cell->napi, gro_cell_poll, 64); 574: a8 01 test $0x1,%al 576: 75 93 jne 50b gcells->cells = alloc_percpu(struct gro_cell); if (!gcells->cells) return -ENOMEM; for_each_possible_cpu(i) { struct gro_cell *cell = per_cpu_ptr(gcells->cells, i); 578: 0f 0b ud2 57a: 49 8d 84 24 a0 09 00 lea 0x9a0(%r12),%rax 581: 00 __skb_queue_head_init(&cell->napi_skbs); netif_napi_add(dev, &cell->napi, gro_cell_poll, 64); 582: 49 8d 94 24 a0 11 00 lea 0x11a0(%r12),%rdx 589: 00 58a: 48 c7 00 00 00 00 00 movq $0x0,(%rax) * the spinlock. It can also be used for on-stack sk_buff_head * objects where the spinlock is known to not be used. */ static inline void __skb_queue_head_init(struct sk_buff_head *list) { list->prev = list->next = (struct sk_buff *)list; 591: 48 83 c0 08 add $0x8,%rax list->qlen = 0; 595: 48 39 d0 cmp %rdx,%rax 598: 75 f0 jne 58a 59a: 5b pop %rbx 59b: 41 5c pop %r12 59d: 41 5d pop %r13 59f: 5d pop %rbp } static __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr) { return ((1UL << (nr & (BITS_PER_LONG-1))) & (addr[nr >> _BITOPS_LONG_SHIFT])) != 0; 5a0: c3 retq 5a1: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) * Resume NAPI from being scheduled on this context. * Must be paired with napi_disable. */ static inline void napi_enable(struct napi_struct *n) { BUG_ON(!test_bit(NAPI_STATE_SCHED, &n->state)); 5a6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 5ad: 00 00 00 00000000000005b0 : 5b0: e8 00 00 00 00 callq 5b5 5b5: 55 push %rbp 5b6: 48 89 e5 mov %rsp,%rbp 5b9: 41 54 push %r12 vxlan->dev = dev; gro_cells_init(&vxlan->gro_cells, dev); for (h = 0; h < FDB_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vxlan->fdb_head[h]); 5bb: 41 89 f4 mov %esi,%r12d 5be: 53 push %rbx 5bf: 48 89 fb mov %rdi,%rbx 5c2: 8b b7 a4 08 00 00 mov 0x8a4(%rdi),%esi vxlan->dev = dev; gro_cells_init(&vxlan->gro_cells, dev); for (h = 0; h < FDB_HASH_SIZE; ++h) 5c8: 48 8b bf 78 08 00 00 mov 0x878(%rdi),%rdi INIT_HLIST_HEAD(&vxlan->fdb_head[h]); } 5cf: e8 00 00 00 00 callq 5d4 5d4: 48 85 c0 test %rax,%rax 5d7: 74 30 je 609 5d9: 8b 80 48 02 00 00 mov 0x248(%rax),%eax 5df: 8d 50 ba lea -0x46(%rax),%edx dev->mtu = new_mtu; return 0; } static int vxlan_change_mtu(struct net_device *dev, int new_mtu) { 5e2: 83 e8 32 sub $0x32,%eax 5e5: 66 83 bb 80 08 00 00 cmpw $0xa,0x880(%rbx) 5ec: 0a 5ed: 0f 44 c2 cmove %edx,%eax 5f0: 41 39 c4 cmp %eax,%r12d struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *dst = &vxlan->default_dst; struct net_device *lowerdev = __dev_get_by_index(vxlan->net, 5f3: 7f 1b jg 610 5f5: 41 83 fc 43 cmp $0x43,%r12d 5f9: 7e 15 jle 610 5fb: 44 89 a3 48 02 00 00 mov %r12d,0x248(%rbx) 602: 31 c0 xor %eax,%eax struct net_device *lowerdev, struct vxlan_rdst *dst, int new_mtu, bool strict) { int max_mtu = IP_MAX_MTU; if (lowerdev) 604: 5b pop %rbx 605: 41 5c pop %r12 607: 5d pop %rbp 608: c3 retq max_mtu = lowerdev->mtu; 609: b8 ff ff 00 00 mov $0xffff,%eax 60e: eb cf jmp 5df if (dst->remote_ip.sa.sa_family == AF_INET6) max_mtu -= VXLAN6_HEADROOM; 610: b8 ea ff ff ff mov $0xffffffea,%eax 615: eb ed jmp 604 617: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 61e: 00 00 0000000000000620 : max_mtu -= VXLAN_HEADROOM; if (new_mtu < 68) return -EINVAL; if (new_mtu > max_mtu) { 620: e8 00 00 00 00 callq 625 625: 55 push %rbp 626: 48 89 e5 mov %rsp,%rbp 629: 41 56 push %r14 return -EINVAL; new_mtu = max_mtu; } dev->mtu = new_mtu; 62b: 41 55 push %r13 62d: 41 54 push %r12 62f: 53 push %rbx 630: 49 89 f5 mov %rsi,%r13 return 0; 633: 48 89 fb mov %rdi,%rbx struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_rdst *dst = &vxlan->default_dst; struct net_device *lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex); return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true); } 636: 49 89 d4 mov %rdx,%r12 static int __vxlan_change_mtu(struct net_device *dev, struct net_device *lowerdev, struct vxlan_rdst *dst, int new_mtu, bool strict) { int max_mtu = IP_MAX_MTU; 639: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 63d: 48 83 ec 40 sub $0x40,%rsp if (new_mtu < 68) return -EINVAL; if (new_mtu > max_mtu) { if (strict) return -EINVAL; 641: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 648: 00 00 64a: 48 89 44 24 38 mov %rax,0x38(%rsp) 64f: 31 c0 xor %eax,%eax } static int vxlan_fdb_parse(struct nlattr *tb[], struct vxlan_dev *vxlan, union vxlan_addr *ip, __be16 *port, __be32 *vni, u32 *ifindex) { 651: 48 8b 46 30 mov 0x30(%rsi),%rax 655: 48 8b 77 08 mov 0x8(%rdi),%rsi 659: 48 85 f6 test %rsi,%rsi 65c: 4c 8b b0 80 04 00 00 mov 0x480(%rax),%r14 663: 0f 84 ad 00 00 00 je 716 669: 0f b7 06 movzwl (%rsi),%eax 66c: 83 e8 04 sub $0x4,%eax 66f: 83 f8 0f cmp $0xf,%eax 672: 0f 87 fd 00 00 00 ja 775 678: 83 f8 03 cmp $0x3,%eax 67b: 0f 86 68 01 00 00 jbe 7e9 } static inline struct net *read_pnet(const possible_net_t *pnet) { #ifdef CONFIG_NET_NS return pnet->net; 681: 8b 46 04 mov 0x4(%rsi),%eax 684: be 02 00 00 00 mov $0x2,%esi struct net *net = dev_net(vxlan->dev); int err; if (tb[NDA_DST]) { 689: 66 89 32 mov %si,(%rdx) 68c: 89 42 04 mov %eax,0x4(%rdx) 68f: 48 8b 43 30 mov 0x30(%rbx),%rax 693: 48 85 c0 test %rax,%rax 696: 0f 84 b5 00 00 00 je 751 return IN_MULTICAST(ntohl(ipa->sin.sin_addr.s_addr)); } static int vxlan_nla_get_addr(union vxlan_addr *ip, struct nlattr *nla) { if (nla_len(nla) >= sizeof(struct in6_addr)) { 69c: 66 83 38 06 cmpw $0x6,(%rax) 6a0: 75 6d jne 70f 6a2: 0f b7 40 04 movzwl 0x4(%rax),%eax 6a6: 66 89 01 mov %ax,(%rcx) ip->sin6.sin6_addr = nla_get_in6_addr(nla); ip->sa.sa_family = AF_INET6; return 0; } else if (nla_len(nla) >= sizeof(__be32)) { 6a9: 48 8b 43 38 mov 0x38(%rbx),%rax 6ad: 48 85 c0 test %rax,%rax 6b0: 0f 84 b3 00 00 00 je 769 ip->sin.sin_addr.s_addr = nla_get_in_addr(nla); ip->sa.sa_family = AF_INET; 6b6: 66 83 38 08 cmpw $0x8,(%rax) 6ba: 75 53 jne 70f if (nla_len(nla) >= sizeof(struct in6_addr)) { ip->sin6.sin6_addr = nla_get_in6_addr(nla); ip->sa.sa_family = AF_INET6; return 0; } else if (nla_len(nla) >= sizeof(__be32)) { ip->sin.sin_addr.s_addr = nla_get_in_addr(nla); 6bc: 8b 40 04 mov 0x4(%rax),%eax ip->sa.sa_family = AF_INET6; #endif } } if (tb[NDA_PORT]) { 6bf: 0f c8 bswap %eax 6c1: 41 89 00 mov %eax,(%r8) 6c4: 48 8b 43 40 mov 0x40(%rbx),%rax 6c8: 48 85 c0 test %rax,%rax 6cb: 0f 84 f4 00 00 00 je 7c5 if (nla_len(tb[NDA_PORT]) != sizeof(__be16)) 6d1: 66 83 38 08 cmpw $0x8,(%rax) * nla_get_be16 - return payload of __be16 attribute * @nla: __be16 netlink attribute */ static inline __be16 nla_get_be16(const struct nlattr *nla) { return *(__be16 *) nla_data(nla); 6d5: 75 38 jne 70f return -EINVAL; *port = nla_get_be16(tb[NDA_PORT]); 6d7: 8b 70 04 mov 0x4(%rax),%esi } else { *port = vxlan->cfg.dst_port; } if (tb[NDA_VNI]) { 6da: 4c 89 f7 mov %r14,%rdi 6dd: 41 89 31 mov %esi,(%r9) 6e0: e8 00 00 00 00 callq 6e5 6e5: 48 83 f8 01 cmp $0x1,%rax if (nla_len(tb[NDA_VNI]) != sizeof(u32)) 6e9: 19 c0 sbb %eax,%eax 6eb: 83 e0 9d and $0xffffff9d,%eax return -EINVAL; *vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI])); 6ee: 48 8b 54 24 38 mov 0x38(%rsp),%rdx 6f3: 65 48 33 14 25 28 00 xor %gs:0x28,%rdx 6fa: 00 00 } else { *vni = vxlan->default_dst.remote_vni; } if (tb[NDA_IFINDEX]) { 6fc: 0f 85 f1 00 00 00 jne 7f3 struct net_device *tdev; if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32)) 702: 48 8d 65 e0 lea -0x20(%rbp),%rsp 706: 5b pop %rbx * nla_get_u32 - return payload of u32 attribute * @nla: u32 netlink attribute */ static inline u32 nla_get_u32(const struct nlattr *nla) { return *(u32 *) nla_data(nla); 707: 41 5c pop %r12 709: 41 5d pop %r13 return -EINVAL; *ifindex = nla_get_u32(tb[NDA_IFINDEX]); tdev = __dev_get_by_index(net, *ifindex); 70b: 41 5e pop %r14 if (tb[NDA_IFINDEX]) { struct net_device *tdev; if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32)) return -EINVAL; *ifindex = nla_get_u32(tb[NDA_IFINDEX]); 70d: 5d pop %rbp 70e: c3 retq 70f: b8 ea ff ff ff mov $0xffffffea,%eax tdev = __dev_get_by_index(net, *ifindex); 714: eb d8 jmp 6ee return -EADDRNOTAVAIL; } else { *ifindex = 0; } return 0; 716: 66 41 83 7d 40 02 cmpw $0x2,0x40(%r13) 71c: 0f 84 b1 00 00 00 je 7d3 } 722: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 729 729: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # 730 730: 49 89 44 24 08 mov %rax,0x8(%r12) 735: b8 0a 00 00 00 mov $0xa,%eax 73a: 49 89 54 24 10 mov %rdx,0x10(%r12) } } if (tb[NDA_PORT]) { if (nla_len(tb[NDA_PORT]) != sizeof(__be16)) return -EINVAL; 73f: 66 41 89 04 24 mov %ax,(%r12) 744: 48 8b 43 30 mov 0x30(%rbx),%rax err = vxlan_nla_get_addr(ip, tb[NDA_DST]); if (err) return err; } else { union vxlan_addr *remote = &vxlan->default_dst.remote_ip; if (remote->sa.sa_family == AF_INET) { 748: 48 85 c0 test %rax,%rax 74b: 0f 85 4b ff ff ff jne 69c 751: 41 0f b7 85 3c 01 00 movzwl 0x13c(%r13),%eax 758: 00 ip->sin.sin_addr.s_addr = htonl(INADDR_ANY); ip->sa.sa_family = AF_INET; #if IS_ENABLED(CONFIG_IPV6) } else { ip->sin6.sin6_addr = in6addr_any; 759: 66 89 01 mov %ax,(%rcx) 75c: 48 8b 43 38 mov 0x38(%rbx),%rax 760: 48 85 c0 test %rax,%rax 763: 0f 85 4d ff ff ff jne 6b6 ip->sa.sa_family = AF_INET6; 769: 41 8b 45 60 mov 0x60(%r13),%eax if (remote->sa.sa_family == AF_INET) { ip->sin.sin_addr.s_addr = htonl(INADDR_ANY); ip->sa.sa_family = AF_INET; #if IS_ENABLED(CONFIG_IPV6) } else { ip->sin6.sin6_addr = in6addr_any; 76d: 41 89 00 mov %eax,(%r8) ip->sa.sa_family = AF_INET6; 770: e9 4f ff ff ff jmpq 6c4 #endif } } if (tb[NDA_PORT]) { 775: 48 8d 7c 24 20 lea 0x20(%rsp),%rdi 77a: ba 10 00 00 00 mov $0x10,%edx 77f: 4c 89 4c 24 08 mov %r9,0x8(%rsp) if (nla_len(tb[NDA_PORT]) != sizeof(__be16)) return -EINVAL; *port = nla_get_be16(tb[NDA_PORT]); } else { *port = vxlan->cfg.dst_port; 784: 4c 89 44 24 10 mov %r8,0x10(%rsp) 789: 48 89 4c 24 18 mov %rcx,0x18(%rsp) } if (tb[NDA_VNI]) { 78e: e8 00 00 00 00 callq 793 793: 48 8b 44 24 20 mov 0x20(%rsp),%rax 798: 48 8b 54 24 28 mov 0x28(%rsp),%rdx if (nla_len(tb[NDA_VNI]) != sizeof(u32)) return -EINVAL; *vni = cpu_to_be32(nla_get_u32(tb[NDA_VNI])); } else { *vni = vxlan->default_dst.remote_vni; 79d: bf 0a 00 00 00 mov $0xa,%edi 7a2: 66 41 89 3c 24 mov %di,(%r12) */ static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla) { struct in6_addr tmp; nla_memcpy(&tmp, nla, sizeof(tmp)); 7a7: 48 8b 4c 24 18 mov 0x18(%rsp),%rcx 7ac: 4c 8b 44 24 10 mov 0x10(%rsp),%r8 7b1: 4c 8b 4c 24 08 mov 0x8(%rsp),%r9 7b6: 49 89 44 24 08 mov %rax,0x8(%r12) 7bb: 49 89 54 24 10 mov %rdx,0x10(%r12) 7c0: e9 ca fe ff ff jmpq 68f return tmp; 7c5: 41 c7 01 00 00 00 00 movl $0x0,(%r9) 7cc: 31 c0 xor %eax,%eax static int vxlan_nla_get_addr(union vxlan_addr *ip, struct nlattr *nla) { if (nla_len(nla) >= sizeof(struct in6_addr)) { ip->sin6.sin6_addr = nla_get_in6_addr(nla); ip->sa.sa_family = AF_INET6; 7ce: e9 1b ff ff ff jmpq 6ee 7d3: c7 42 04 00 00 00 00 movl $0x0,0x4(%rdx) 7da: ba 02 00 00 00 mov $0x2,%edx 7df: 66 41 89 14 24 mov %dx,(%r12) 7e4: e9 a6 fe ff ff jmpq 68f } static int vxlan_nla_get_addr(union vxlan_addr *ip, struct nlattr *nla) { if (nla_len(nla) >= sizeof(struct in6_addr)) { ip->sin6.sin6_addr = nla_get_in6_addr(nla); 7e9: b8 9f ff ff ff mov $0xffffff9f,%eax 7ee: e9 fb fe ff ff jmpq 6ee 7f3: e8 00 00 00 00 callq 7f8 *ifindex = nla_get_u32(tb[NDA_IFINDEX]); tdev = __dev_get_by_index(net, *ifindex); if (!tdev) return -EADDRNOTAVAIL; } else { *ifindex = 0; 7f8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 7ff: 00 0000000000000800 : } return 0; 800: e8 00 00 00 00 callq 805 if (err) return err; } else { union vxlan_addr *remote = &vxlan->default_dst.remote_ip; if (remote->sa.sa_family == AF_INET) { ip->sin.sin_addr.s_addr = htonl(INADDR_ANY); 805: 55 push %rbp 806: 48 8d 7e 24 lea 0x24(%rsi),%rdi ip->sa.sa_family = AF_INET; 80a: ba 20 00 00 00 mov $0x20,%edx 80f: 48 89 e5 mov %rsp,%rbp 812: 53 push %rbx 813: 48 89 f3 mov %rsi,%rbx 816: 48 c7 c6 00 00 00 00 mov $0x0,%rsi } else if (nla_len(nla) >= sizeof(__be32)) { ip->sin.sin_addr.s_addr = nla_get_in_addr(nla); ip->sa.sa_family = AF_INET; return 0; } else { return -EAFNOSUPPORT; 81d: e8 00 00 00 00 callq 822 822: 48 8d 7b 04 lea 0x4(%rbx),%rdi } else { *ifindex = 0; } return 0; } 826: ba 20 00 00 00 mov $0x20,%edx 82b: 48 c7 c6 00 00 00 00 mov $0x0,%rsi return 0; } static void vxlan_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { 832: e8 00 00 00 00 callq 837 strlcpy(drvinfo->version, VXLAN_VERSION, sizeof(drvinfo->version)); 837: 5b pop %rbx 838: 5d pop %rbp 839: c3 retq 83a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 0000000000000840 : return 0; } static void vxlan_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { 840: f0 ff 4f 30 lock decl 0x30(%rdi) 844: 74 01 je 847 strlcpy(drvinfo->version, VXLAN_VERSION, sizeof(drvinfo->version)); 846: c3 retq 847: 55 push %rbp 848: 48 89 e5 mov %rsp,%rbp 84b: e8 00 00 00 00 callq 850 850: 5d pop %rbp 851: c3 retq strlcpy(drvinfo->driver, "vxlan", sizeof(drvinfo->driver)); 852: 0f 1f 40 00 nopl 0x0(%rax) 856: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 85d: 00 00 00 0000000000000860 : 860: e8 00 00 00 00 callq 865 865: 55 push %rbp 866: 48 89 f7 mov %rsi,%rdi } 869: 8d 72 08 lea 0x8(%rdx),%esi 86c: 48 89 e5 mov %rsp,%rbp 86f: e8 00 00 00 00 callq 874 * returns true if the result is 0, or false for all other * cases. */ static __always_inline bool atomic_dec_and_test(atomic_t *v) { GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", e); 874: 5d pop %rbp 875: c3 retq 876: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 87d: 00 00 00 0000000000000880 : static inline void neigh_release(struct neighbour *neigh) { if (atomic_dec_and_test(&neigh->refcnt)) neigh_destroy(neigh); } 880: e8 00 00 00 00 callq 885 885: 55 push %rbp 886: ba c0 00 40 02 mov $0x24000c0,%edx 88b: be 08 00 00 00 mov $0x8,%esi return pp; } static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff) { 890: 48 89 e5 mov %rsp,%rbp 893: 41 54 push %r12 895: 53 push %rbx 896: 49 89 fc mov %rdi,%r12 /* Sets 'skb->inner_mac_header' since we are always called with * 'skb->encapsulation' set. */ return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr)); 899: bf 20 00 00 00 mov $0x20,%edi return pp; } static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff) { 89e: e8 00 00 00 00 callq 8a3 /* Sets 'skb->inner_mac_header' since we are always called with * 'skb->encapsulation' set. */ return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr)); 8a3: 48 85 c0 test %rax,%rax } 8a6: 74 38 je 8e0 8a8: 48 89 c3 mov %rax,%rbx 8ab: ba ff ff ff ff mov $0xffffffff,%edx spin_unlock(&vn->sock_lock); } /* Setup stats when device is created */ static int vxlan_init(struct net_device *dev) { 8b0: 83 c2 01 add $0x1,%edx 8b3: be 00 01 00 00 mov $0x100,%esi dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 8b8: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 8bf: 48 63 d2 movslq %edx,%rdx spin_unlock(&vn->sock_lock); } /* Setup stats when device is created */ static int vxlan_init(struct net_device *dev) { 8c2: e8 00 00 00 00 callq 8c7 8c7: 3b 05 00 00 00 00 cmp 0x0(%rip),%eax # 8cd dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 8cd: 89 c2 mov %eax,%edx 8cf: 7c df jl 8b0 8d1: 49 89 9c 24 88 04 00 mov %rbx,0x488(%r12) 8d8: 00 8d9: 31 c0 xor %eax,%eax 8db: 5b pop %rbx 8dc: 41 5c pop %r12 8de: 5d pop %rbp 8df: c3 retq 8e0: 5b pop %rbx 8e1: 49 c7 84 24 88 04 00 movq $0x0,0x488(%r12) 8e8: 00 00 00 00 00 8ed: b8 f4 ff ff ff mov $0xfffffff4,%eax 8f2: 41 5c pop %r12 8f4: 5d pop %rbp 8f5: c3 retq 8f6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 8fd: 00 00 00 0000000000000900 : 900: e8 00 00 00 00 callq 905 905: 55 push %rbp 906: 48 89 e5 mov %rsp,%rbp if (!dev->tstats) return -ENOMEM; return 0; 909: 41 56 push %r14 } 90b: 41 55 push %r13 90d: 41 54 push %r12 90f: 53 push %rbx 910: 49 89 fd mov %rdi,%r13 } /* Setup stats when device is created */ static int vxlan_init(struct net_device *dev) { dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); 913: 48 8b 87 78 08 00 00 mov 0x878(%rdi),%rax 91a: 49 89 f6 mov %rsi,%r14 if (!dev->tstats) return -ENOMEM; 91d: 48 8b 90 88 14 00 00 mov 0x1488(%rax),%rdx return 0; } 924: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 92a 92a: 83 e8 01 sub $0x1,%eax 92d: 48 98 cltq 92f: 48 8b 5c c2 18 mov 0x18(%rdx,%rax,8),%rbx return vxlan_dev_configure(src_net, dev, &conf); } static void vxlan_dellink(struct net_device *dev, struct list_head *head) { 934: 48 81 c3 10 08 00 00 add $0x810,%rbx 93b: 48 89 df mov %rbx,%rdi 93e: e8 00 00 00 00 callq 943 struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); 943: 49 8b 85 48 08 00 00 mov 0x848(%r13),%rax return vxlan_dev_configure(src_net, dev, &conf); } static void vxlan_dellink(struct net_device *dev, struct list_head *head) { 94a: 48 85 c0 test %rax,%rax }) static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; 94d: 74 24 je 973 94f: 49 8b 95 40 08 00 00 mov 0x840(%r13),%rdx 956: 48 85 d2 test %rdx,%rdx 959: 48 89 10 mov %rdx,(%rax) 95c: 74 04 je 962 95e: 48 89 42 08 mov %rax,0x8(%rdx) raw_spin_lock_init(&(_lock)->rlock); \ } while (0) static __always_inline void spin_lock(spinlock_t *lock) { raw_spin_lock(&lock->rlock); 962: 48 b8 00 02 00 00 00 movabs $0xdead000000000200,%rax 969: 00 ad de 96c: 49 89 85 48 08 00 00 mov %rax,0x848(%r13) 973: 48 89 df mov %rbx,%rdi 976: ff 14 25 00 00 00 00 callq *0x0 struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); spin_lock(&vn->sock_lock); if (!hlist_unhashed(&vxlan->hlist)) 97d: 49 83 bd 30 09 00 00 cmpq $0x0,0x930(%r13) 984: 00 return !READ_ONCE(h->first); } static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; 985: 41 bc ff ff ff ff mov $0xffffffff,%r12d { switch (size) { case 1: *(volatile __u8 *)p = *(__u8 *)res; break; case 2: *(volatile __u16 *)p = *(__u16 *)res; break; case 4: *(volatile __u32 *)p = *(__u32 *)res; break; case 8: *(volatile __u64 *)p = *(__u64 *)res; break; 98b: 0f 84 8a 00 00 00 je a1b struct hlist_node **pprev = n->pprev; WRITE_ONCE(*pprev, next); if (next) next->pprev = pprev; 991: 41 8d 54 24 01 lea 0x1(%r12),%edx * hlist_for_each_entry(). */ static inline void hlist_del_rcu(struct hlist_node *n) { __hlist_del(n); n->pprev = LIST_POISON2; 996: be 00 01 00 00 mov $0x100,%esi 99b: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 9a2: 48 63 d2 movslq %edx,%rdx PVOP_VCALL2(pv_lock_ops.queued_spin_lock_slowpath, lock, val); } static __always_inline void pv_queued_spin_unlock(struct qspinlock *lock) { PVOP_VCALLEE1(pv_lock_ops.queued_spin_unlock, lock); 9a5: e8 00 00 00 00 callq 9aa 9aa: 3b 05 00 00 00 00 cmp 0x0(%rip),%eax # 9b0 static inline void gro_cells_destroy(struct gro_cells *gcells) { int i; if (!gcells->cells) 9b0: 41 89 c4 mov %eax,%r12d 9b3: 7d 4f jge a04 9b5: 48 98 cltq 9b7: 49 8b 9d 30 09 00 00 mov 0x930(%r13),%rbx 9be: 48 03 1c c5 00 00 00 add 0x0(,%rax,8),%rbx 9c5: 00 9c6: 48 8d 7b 18 lea 0x18(%rbx),%rdi 9ca: e8 00 00 00 00 callq 9cf 9cf: 48 8b 3b mov (%rbx),%rdi 9d2: 48 39 fb cmp %rdi,%rbx 9d5: 74 ba je 991 9d7: 48 85 ff test %rdi,%rdi return; for_each_possible_cpu(i) { 9da: 74 b5 je 991 9dc: 83 6b 10 01 subl $0x1,0x10(%rbx) 9e0: 48 8b 17 mov (%rdi),%rdx 9e3: 48 8b 47 08 mov 0x8(%rdi),%rax struct gro_cell *cell = per_cpu_ptr(gcells->cells, i); 9e7: 48 c7 07 00 00 00 00 movq $0x0,(%rdi) 9ee: 48 c7 47 08 00 00 00 movq $0x0,0x8(%rdi) 9f5: 00 netif_napi_del(&cell->napi); 9f6: 48 89 42 08 mov %rax,0x8(%rdx) 9fa: 48 89 10 mov %rdx,(%rax) 9fd: e8 00 00 00 00 callq a02 */ static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_) { struct sk_buff *skb = list_->next; if (skb == (struct sk_buff *)list_) a02: eb cb jmp 9cf a04: 49 8b bd 30 09 00 00 mov 0x930(%r13),%rdi */ struct sk_buff *skb_dequeue(struct sk_buff_head *list); static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list) { struct sk_buff *skb = skb_peek(list); if (skb) a0b: e8 00 00 00 00 callq a10 static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) { struct sk_buff *next, *prev; list->qlen--; next = skb->next; a10: 49 c7 85 30 09 00 00 movq $0x0,0x930(%r13) a17: 00 00 00 00 prev = skb->prev; skb->next = skb->prev = NULL; a1b: 49 8b 85 58 08 00 00 mov 0x858(%r13),%rax a22: 49 8b 95 50 08 00 00 mov 0x850(%r13),%rdx next->prev = prev; a29: 4c 89 f6 mov %r14,%rsi prev->next = next; a2c: 4c 89 ef mov %r13,%rdi void skb_queue_purge(struct sk_buff_head *list); static inline void __skb_queue_purge(struct sk_buff_head *list) { struct sk_buff *skb; while ((skb = __skb_dequeue(list)) != NULL) kfree_skb(skb); a2f: 48 89 42 08 mov %rax,0x8(%rdx) a33: 48 89 10 mov %rdx,(%rax) __skb_queue_purge(&cell->napi_skbs); } free_percpu(gcells->cells); a36: 48 b8 00 01 00 00 00 movabs $0xdead000000000100,%rax a3d: 00 ad de gcells->cells = NULL; a40: 49 89 85 50 08 00 00 mov %rax,0x850(%r13) a47: 48 b8 00 02 00 00 00 movabs $0xdead000000000200,%rax a4e: 00 ad de __list_del(entry->prev, entry->next); } static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); a51: 49 89 85 58 08 00 00 mov %rax,0x858(%r13) a58: e8 00 00 00 00 callq a5d hlist_del_rcu(&vxlan->hlist); spin_unlock(&vn->sock_lock); gro_cells_destroy(&vxlan->gro_cells); list_del(&vxlan->next); unregister_netdevice_queue(dev, head); a5d: 5b pop %rbx a5e: 41 5c pop %r12 * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_del(struct list_head * prev, struct list_head * next) { next->prev = prev; a60: 41 5d pop %r13 a62: 41 5e pop %r14 a64: 5d pop %rbp a65: c3 retq } static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; a66: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) a6d: 00 00 00 0000000000000a70 : a70: e8 00 00 00 00 callq a75 a75: 55 push %rbp a76: 48 89 e5 mov %rsp,%rbp entry->prev = LIST_POISON2; a79: 41 57 push %r15 a7b: 41 56 push %r14 a7d: 41 55 push %r13 a7f: 41 54 push %r12 a81: 49 89 f7 mov %rsi,%r15 a84: 53 push %rbx a85: 89 cb mov %ecx,%ebx a87: 49 89 fe mov %rdi,%r14 a8a: 48 83 ec 68 sub $0x68,%rsp } a8e: 8b b6 b4 00 00 00 mov 0xb4(%rsi),%esi a94: 4c 8b 65 10 mov 0x10(%rbp),%r12 a98: 65 48 8b 0c 25 28 00 mov %gs:0x28,%rcx a9f: 00 00 __be32 label, const struct in6_addr *daddr, struct in6_addr *saddr, struct dst_cache *dst_cache, const struct ip_tunnel_info *info) { aa1: 48 89 4c 24 60 mov %rcx,0x60(%rsp) aa6: 31 c9 xor %ecx,%ecx aa8: 4c 8b 6d 18 mov 0x18(%rbp),%r13 aac: 48 8b 45 20 mov 0x20(%rbp),%rax ab0: 85 f6 test %esi,%esi ab2: 75 51 jne b05 ab4: 48 85 c0 test %rax,%rax ab7: 74 48 je b01 ab9: f6 40 28 20 testb $0x20,0x28(%rax) abd: 75 46 jne b05 abf: 4c 89 e6 mov %r12,%rsi ac2: 4c 89 ef mov %r13,%rdi ac5: 4c 89 0c 24 mov %r9,(%rsp) ac9: 44 89 44 24 08 mov %r8d,0x8(%rsp) ace: 89 54 24 0c mov %edx,0xc(%rsp) ad2: e8 00 00 00 00 callq ad7 ad7: 48 85 c0 test %rax,%rax ada: 48 89 44 24 10 mov %rax,0x10(%rsp) adf: 8b 54 24 0c mov 0xc(%rsp),%edx static inline bool ip_tunnel_dst_cache_usable(const struct sk_buff *skb, const struct ip_tunnel_info *info) { if (skb->mark) ae3: 44 8b 44 24 08 mov 0x8(%rsp),%r8d return false; if (!info) ae8: 4c 8b 0c 24 mov (%rsp),%r9 return true; if (info->key.tun_flags & TUNNEL_NOCACHE) aec: 0f 85 ac 00 00 00 jne b9e int err; if (tos && !info) use_cache = false; if (use_cache) { ndst = dst_cache_get_ip6(dst_cache, saddr); af2: 41 8b b7 b4 00 00 00 mov 0xb4(%r15),%esi af9: 41 bf 01 00 00 00 mov $0x1,%r15d aff: eb 07 jmp b08 b01: 84 db test %bl,%bl b03: 74 ba je abf b05: 45 31 ff xor %r15d,%r15d if (ndst) b08: 4c 8d 54 24 18 lea 0x18(%rsp),%r10 int err; if (tos && !info) use_cache = false; if (use_cache) { ndst = dst_cache_get_ip6(dst_cache, saddr); b0d: 31 c0 xor %eax,%eax if (ndst) b0f: b9 09 00 00 00 mov $0x9,%ecx b14: 83 e3 1e and $0x1e,%ebx b17: 4c 89 d7 mov %r10,%rdi b1a: c1 e3 14 shl $0x14,%ebx b1d: f3 48 ab rep stos %rax,%es:(%rdi) b20: 49 8b 01 mov (%r9),%rax b23: 89 54 24 18 mov %edx,0x18(%rsp) b27: 0f cb bswap %ebx b29: 49 8b 51 08 mov 0x8(%r9),%rdx b2d: 41 09 d8 or %ebx,%r8d b30: 89 74 24 20 mov %esi,0x20(%rsp) bool use_cache = ip_tunnel_dst_cache_usable(skb, info); struct dst_entry *ndst; struct flowi6 fl6; int err; if (tos && !info) b34: 44 89 44 24 58 mov %r8d,0x58(%rsp) ndst = dst_cache_get_ip6(dst_cache, saddr); if (ndst) return ndst; } memset(&fl6, 0, sizeof(fl6)); b39: c6 44 24 26 11 movb $0x11,0x26(%rsp) b3e: 4c 89 d1 mov %r10,%rcx b41: 48 89 44 24 38 mov %rax,0x38(%rsp) return ntohl(flowinfo & IPV6_TCLASS_MASK) >> IPV6_TCLASS_SHIFT; } static inline __be32 ip6_make_flowinfo(unsigned int tclass, __be32 flowlabel) { return htonl(tclass << IPV6_TCLASS_SHIFT) | flowlabel; b46: 49 8b 04 24 mov (%r12),%rax b4a: 48 89 54 24 40 mov %rdx,0x40(%rsp) b4f: 49 8b 54 24 08 mov 0x8(%r12),%rdx fl6.flowi6_oif = oif; b54: 49 8b 7e 38 mov 0x38(%r14),%rdi b58: 48 89 44 24 48 mov %rax,0x48(%rsp) fl6.daddr = *daddr; fl6.saddr = *saddr; fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label); b5d: 49 8b 46 28 mov 0x28(%r14),%rax fl6.flowi6_mark = skb->mark; b61: 48 89 54 24 50 mov %rdx,0x50(%rsp) memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_oif = oif; fl6.daddr = *daddr; fl6.saddr = *saddr; fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label); b66: 48 8d 54 24 10 lea 0x10(%rsp),%rdx fl6.flowi6_mark = skb->mark; fl6.flowi6_proto = IPPROTO_UDP; b6b: 48 8b 40 10 mov 0x10(%rax),%rax err = ipv6_stub->ipv6_dst_lookup(vxlan->net, b6f: 48 8b 70 20 mov 0x20(%rax),%rsi return ndst; } memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_oif = oif; fl6.daddr = *daddr; b73: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # b7a b7a: ff 50 10 callq *0x10(%rax) b7d: 85 c0 test %eax,%eax fl6.saddr = *saddr; b7f: 78 3c js bbd b81: 48 8b 44 24 48 mov 0x48(%rsp),%rax fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label); fl6.flowi6_mark = skb->mark; fl6.flowi6_proto = IPPROTO_UDP; err = ipv6_stub->ipv6_dst_lookup(vxlan->net, b86: 48 8b 54 24 50 mov 0x50(%rsp),%rdx } memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_oif = oif; fl6.daddr = *daddr; fl6.saddr = *saddr; b8b: 45 84 ff test %r15b,%r15b fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label); fl6.flowi6_mark = skb->mark; fl6.flowi6_proto = IPPROTO_UDP; err = ipv6_stub->ipv6_dst_lookup(vxlan->net, vxlan->vn6_sock->sock->sk, b8e: 49 89 04 24 mov %rax,(%r12) } memset(&fl6, 0, sizeof(fl6)); fl6.flowi6_oif = oif; fl6.daddr = *daddr; fl6.saddr = *saddr; b92: 49 89 54 24 08 mov %rdx,0x8(%r12) fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label); fl6.flowi6_mark = skb->mark; fl6.flowi6_proto = IPPROTO_UDP; err = ipv6_stub->ipv6_dst_lookup(vxlan->net, b97: 75 28 jne bc1 b99: 48 8b 44 24 10 mov 0x10(%rsp),%rax b9e: 48 8b 4c 24 60 mov 0x60(%rsp),%rcx ba3: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx baa: 00 00 bac: 75 25 jne bd3 vxlan->vn6_sock->sock->sk, &ndst, &fl6); if (err < 0) bae: 48 83 c4 68 add $0x68,%rsp return ERR_PTR(err); *saddr = fl6.saddr; bb2: 5b pop %rbx bb3: 41 5c pop %r12 bb5: 41 5d pop %r13 bb7: 41 5e pop %r14 bb9: 41 5f pop %r15 if (use_cache) bbb: 5d pop %rbp bbc: c3 retq bbd: 48 98 cltq vxlan->vn6_sock->sock->sk, &ndst, &fl6); if (err < 0) return ERR_PTR(err); *saddr = fl6.saddr; bbf: eb dd jmp b9e bc1: 48 8b 74 24 10 mov 0x10(%rsp),%rsi bc6: 4c 89 e2 mov %r12,%rdx if (use_cache) dst_cache_set_ip6(dst_cache, ndst, saddr); return ndst; bc9: 4c 89 ef mov %r13,%rdi bcc: e8 00 00 00 00 callq bd1 } bd1: eb c6 jmp b99 bd3: e8 00 00 00 00 callq bd8 bd8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) bdf: 00 0000000000000be0 <__vxlan_sock_release_prep>: be0: e8 00 00 00 00 callq be5 <__vxlan_sock_release_prep+0x5> be5: 48 85 ff test %rdi,%rdi be8: 0f 84 92 00 00 00 je c80 <__vxlan_sock_release_prep+0xa0> #define IS_ERR_VALUE(x) unlikely((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO) static inline void * __must_check ERR_PTR(long error) { return (void *) error; bee: f0 ff 8f 18 20 00 00 lock decl 0x2018(%rdi) if (err < 0) return ERR_PTR(err); *saddr = fl6.saddr; if (use_cache) dst_cache_set_ip6(dst_cache, ndst, saddr); bf5: 74 03 je bfa <__vxlan_sock_release_prep+0x1a> bf7: 31 c0 xor %eax,%eax bf9: c3 retq bfa: 55 push %rbp bfb: 48 89 e5 mov %rsp,%rbp bfe: 41 54 push %r12 c00: 53 push %rbx c01: 48 8b 47 10 mov 0x10(%rdi),%rax return ndst; } c05: 48 89 fb mov %rdi,%rbx c08: 48 8b 40 20 mov 0x20(%rax),%rax c0c: 48 8b 40 30 mov 0x30(%rax),%rax return false; } static bool __vxlan_sock_release_prep(struct vxlan_sock *vs) { c10: 48 8b 90 88 14 00 00 mov 0x1488(%rax),%rdx struct vxlan_net *vn; if (!vs) c17: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # c1d <__vxlan_sock_release_prep+0x3d> c1d: 83 e8 01 sub $0x1,%eax c20: 48 98 cltq c22: 4c 8b 64 c2 18 mov 0x18(%rdx,%rax,8),%r12 return false; if (!atomic_dec_and_test(&vs->refcnt)) return false; c27: 49 81 c4 10 08 00 00 add $0x810,%r12 return false; } static bool __vxlan_sock_release_prep(struct vxlan_sock *vs) { c2e: 4c 89 e7 mov %r12,%rdi if (!vs) return false; if (!atomic_dec_and_test(&vs->refcnt)) return false; vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id); c31: e8 00 00 00 00 callq c36 <__vxlan_sock_release_prep+0x56> c36: 48 8b 03 mov (%rbx),%rax c39: 48 8b 53 08 mov 0x8(%rbx),%rdx c3d: 48 85 c0 test %rax,%rax }) static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; c40: 48 89 02 mov %rax,(%rdx) c43: 74 04 je c49 <__vxlan_sock_release_prep+0x69> c45: 48 89 50 08 mov %rdx,0x8(%rax) c49: 8b b3 1c 20 00 00 mov 0x201c(%rbx),%esi c4f: 48 8b 7b 10 mov 0x10(%rbx),%rdi c53: 48 b8 00 02 00 00 00 movabs $0xdead000000000200,%rax c5a: 00 ad de c5d: 48 89 43 08 mov %rax,0x8(%rbx) c61: c1 ee 0d shr $0xd,%esi c64: 83 e6 02 and $0x2,%esi return !READ_ONCE(h->first); } static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; c67: e8 00 00 00 00 callq c6c <__vxlan_sock_release_prep+0x8c> struct hlist_node **pprev = n->pprev; c6c: 4c 89 e7 mov %r12,%rdi WRITE_ONCE(*pprev, next); if (next) c6f: ff 14 25 00 00 00 00 callq *0x0 next->pprev = pprev; c76: b8 01 00 00 00 mov $0x1,%eax spin_lock(&vn->sock_lock); hlist_del_rcu(&vs->hlist); udp_tunnel_notify_del_rx_port(vs->sock, c7b: 5b pop %rbx c7c: 41 5c pop %r12 c7e: 5d pop %rbp c7f: c3 retq c80: 31 c0 xor %eax,%eax c82: c3 retq c83: 0f 1f 00 nopl (%rax) c86: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) c8d: 00 00 00 0000000000000c90 : c90: e8 00 00 00 00 callq c95 c95: 55 push %rbp c96: 48 89 e5 mov %rsp,%rbp c99: 41 56 push %r14 c9b: 41 55 push %r13 c9d: 41 54 push %r12 c9f: 49 89 fc mov %rdi,%r12 ca2: 53 push %rbx ca3: 48 8b 3f mov (%rdi),%rdi static inline void __raw_spin_unlock(raw_spinlock_t *lock) { spin_release(&lock->dep_map, 1, _RET_IP_); do_raw_spin_unlock(lock); preempt_enable(); ca6: 48 89 f3 mov %rsi,%rbx ca9: e8 32 ff ff ff callq be0 <__vxlan_sock_release_prep> UDP_TUNNEL_TYPE_VXLAN_GPE : UDP_TUNNEL_TYPE_VXLAN); spin_unlock(&vn->sock_lock); return true; } cae: 48 8b 3b mov (%rbx),%rdi static bool __vxlan_sock_release_prep(struct vxlan_sock *vs) { struct vxlan_net *vn; if (!vs) return false; cb1: 41 89 c6 mov %eax,%r14d cb4: e8 27 ff ff ff callq be0 <__vxlan_sock_release_prep> cb9: 41 89 c5 mov %eax,%r13d cbc: e8 00 00 00 00 callq cc1 spin_unlock(&vn->sock_lock); return true; } static void vxlan_sock_release(struct vxlan_dev *vxlan) cc1: 45 84 f6 test %r14b,%r14b cc4: 75 22 jne ce8 cc6: 45 84 ed test %r13b,%r13b cc9: 74 14 je cdf ccb: 48 8b 03 mov (%rbx),%rax cce: 48 8b 78 10 mov 0x10(%rax),%rdi cd2: e8 00 00 00 00 callq cd7 cd7: 48 8b 3b mov (%rbx),%rdi { bool ipv4 = __vxlan_sock_release_prep(vxlan->vn4_sock); cda: e8 00 00 00 00 callq cdf #if IS_ENABLED(CONFIG_IPV6) bool ipv6 = __vxlan_sock_release_prep(vxlan->vn6_sock); cdf: 5b pop %rbx ce0: 41 5c pop %r12 return true; } static void vxlan_sock_release(struct vxlan_dev *vxlan) { bool ipv4 = __vxlan_sock_release_prep(vxlan->vn4_sock); ce2: 41 5d pop %r13 #if IS_ENABLED(CONFIG_IPV6) bool ipv6 = __vxlan_sock_release_prep(vxlan->vn6_sock); ce4: 41 5e pop %r14 ce6: 5d pop %rbp ce7: c3 retq ce8: 49 8b 04 24 mov (%r12),%rax #endif synchronize_net(); cec: 48 8b 78 10 mov 0x10(%rax),%rdi cf0: e8 00 00 00 00 callq cf5 if (ipv4) { cf5: 49 8b 3c 24 mov (%r12),%rdi udp_tunnel_sock_release(vxlan->vn4_sock->sock); kfree(vxlan->vn4_sock); } #if IS_ENABLED(CONFIG_IPV6) if (ipv6) { cf9: e8 00 00 00 00 callq cfe udp_tunnel_sock_release(vxlan->vn6_sock->sock); cfe: eb c6 jmp cc6 0000000000000d00 : d00: e8 00 00 00 00 callq d05 d05: 55 push %rbp d06: 48 89 e5 mov %rsp,%rbp kfree(vxlan->vn6_sock); d09: 41 56 push %r14 d0b: 41 55 push %r13 d0d: 41 54 push %r12 } #endif } d0f: 53 push %rbx d10: 48 83 ec 18 sub $0x18,%rsp d14: 4c 8b 22 mov (%rdx),%r12 d17: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax d1e: 00 00 #endif synchronize_net(); if (ipv4) { udp_tunnel_sock_release(vxlan->vn4_sock->sock); d20: 48 89 45 d8 mov %rax,-0x28(%rbp) d24: 31 c0 xor %eax,%eax kfree(vxlan->vn4_sock); d26: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # d2c d2c: 49 8b 94 24 80 04 00 mov 0x480(%r12),%rdx d33: 00 unregister_netdevice_many(&list_kill); } static int vxlan_netdevice_event(struct notifier_block *unused, unsigned long event, void *ptr) { d34: 83 e8 01 sub $0x1,%eax d37: 48 83 fe 06 cmp $0x6,%rsi d3b: 48 8b 8a 88 14 00 00 mov 0x1488(%rdx),%rcx d42: 0f 84 8a 00 00 00 je dd2 d48: 48 83 fe 1c cmp $0x1c,%rsi d4c: 74 22 je d70 d4e: 31 c0 xor %eax,%eax d50: 48 8b 4d d8 mov -0x28(%rbp),%rcx d54: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx d5b: 00 00 d5d: 0f 85 d7 00 00 00 jne e3a d63: 48 83 c4 18 add $0x18,%rsp struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id); if (event == NETDEV_UNREGISTER) d67: 5b pop %rbx d68: 41 5c pop %r12 d6a: 41 5d pop %r13 d6c: 41 5e pop %r14 d6e: 5d pop %rbp d6f: c3 retq d70: 48 8b 92 88 14 00 00 mov 0x1488(%rdx),%rdx d77: 48 98 cltq vxlan_handle_lowerdev_unregister(vn, dev); else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO) d79: 4c 8b 6c c2 18 mov 0x18(%rdx,%rax,8),%r13 vxlan_push_rx_ports(dev); return NOTIFY_DONE; } d7e: 4d 8d b5 10 08 00 00 lea 0x810(%r13),%r14 d85: 49 83 c5 10 add $0x10,%r13 d89: 4c 89 f7 mov %r14,%rdi d8c: e8 00 00 00 00 callq d91 d91: 49 8b 5d 00 mov 0x0(%r13),%rbx d95: 48 85 db test %rbx,%rbx d98: 74 20 je dba d9a: 8b 93 1c 20 00 00 mov 0x201c(%rbx),%edx da0: 48 8b 73 10 mov 0x10(%rbx),%rsi da4: 4c 89 e7 mov %r12,%rdi da7: c1 ea 0d shr $0xd,%edx daa: 83 e2 02 and $0x2,%edx dad: e8 00 00 00 00 callq db2 db2: 48 8b 1b mov (%rbx),%rbx db5: 48 85 db test %rbx,%rbx db8: 75 e0 jne d9a dba: 49 83 c5 08 add $0x8,%r13 dbe: 4d 39 ee cmp %r13,%r14 dc1: 75 ce jne d91 dc3: 4c 89 f7 mov %r14,%rdi struct vxlan_net *vn = net_generic(net, vxlan_net_id); unsigned int i; spin_lock(&vn->sock_lock); for (i = 0; i < PORT_HASH_SIZE; ++i) { hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) dc6: ff 14 25 00 00 00 00 callq *0x0 udp_tunnel_push_rx_port(dev, vs->sock, dcd: e9 7c ff ff ff jmpq d4e dd2: 48 98 cltq dd4: 4c 8d 75 c8 lea -0x38(%rbp),%r14 dd8: 4c 8b 6c c1 18 mov 0x18(%rcx,%rax,8),%r13 ddd: 4c 89 75 c8 mov %r14,-0x38(%rbp) de1: 4c 89 75 d0 mov %r14,-0x30(%rbp) struct vxlan_net *vn = net_generic(net, vxlan_net_id); unsigned int i; spin_lock(&vn->sock_lock); for (i = 0; i < PORT_HASH_SIZE; ++i) { hlist_for_each_entry_rcu(vs, &vn->sock_list[i], hlist) de5: 49 8b 45 00 mov 0x0(%r13),%rax de9: 48 8b 08 mov (%rax),%rcx dec: 49 39 c5 cmp %rax,%r13 struct net *net = dev_net(dev); struct vxlan_net *vn = net_generic(net, vxlan_net_id); unsigned int i; spin_lock(&vn->sock_lock); for (i = 0; i < PORT_HASH_SIZE; ++i) { def: 48 8d 50 f0 lea -0x10(%rax),%rdx df3: 48 8d 59 f0 lea -0x10(%rcx),%rbx df7: 75 19 jne e12 df9: eb 32 jmp e2d dfb: 48 8b 43 10 mov 0x10(%rbx),%rax dff: 48 8d 4b 10 lea 0x10(%rbx),%rcx e03: 48 89 da mov %rbx,%rdx static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn, struct net_device *dev) { struct vxlan_dev *vxlan, *next; LIST_HEAD(list_kill); e06: 48 83 e8 10 sub $0x10,%rax e0a: 49 39 cd cmp %rcx,%r13 e0d: 74 1e je e2d e0f: 48 89 c3 mov %rax,%rbx e12: 41 8b 84 24 28 01 00 mov 0x128(%r12),%eax e19: 00 list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) { e1a: 39 42 64 cmp %eax,0x64(%rdx) e1d: 75 dc jne dfb e1f: 48 8b 7a 30 mov 0x30(%rdx),%rdi e23: 4c 89 f6 mov %r14,%rsi e26: e8 d5 fa ff ff callq 900 e2b: eb ce jmp dfb e2d: 4c 89 f7 mov %r14,%rdi e30: e8 00 00 00 00 callq e35 e35: e9 14 ff ff ff jmpq d4e e3a: e8 00 00 00 00 callq e3f e3f: 90 nop 0000000000000e40 <__vxlan_sock_add>: e40: e8 00 00 00 00 callq e45 <__vxlan_sock_add+0x5> * and we loose the carrier due to module unload * we also need to remove vxlan device. In other * cases, it's not necessary and remote_ifindex * is 0 here, so no matches. */ if (dst->remote_ifindex == dev->ifindex) e45: 55 push %rbp e46: 48 89 e5 mov %rsp,%rbp e49: 41 57 push %r15 e4b: 41 56 push %r14 e4d: 41 55 push %r13 vxlan_dellink(vxlan->dev, &list_kill); e4f: 41 54 push %r12 e51: 41 89 f5 mov %esi,%r13d e54: 53 push %rbx e55: 48 89 fb mov %rdi,%rbx e58: 48 81 ec 88 00 00 00 sub $0x88,%rsp } unregister_netdevice_many(&list_kill); e5f: 4c 8b 77 38 mov 0x38(%rdi),%r14 e63: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax e6a: 00 00 vxlan_handle_lowerdev_unregister(vn, dev); else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO) vxlan_push_rx_ports(dev); return NOTIFY_DONE; } e6c: 48 89 45 d0 mov %rax,-0x30(%rbp) return vs; } static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6) { e70: 31 c0 xor %eax,%eax e72: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # e78 <__vxlan_sock_add+0x38> e78: 49 8b 96 88 14 00 00 mov 0x1488(%r14),%rdx e7f: 83 e8 01 sub $0x1,%eax e82: 80 bf 5c 01 00 00 00 cmpb $0x0,0x15c(%rdi) e89: 0f 84 e6 01 00 00 je 1075 <__vxlan_sock_add+0x235> struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); e8f: 49 8b 96 88 14 00 00 mov 0x1488(%r14),%rdx return vs; } static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6) { e96: 48 98 cltq e98: 8b 8b 98 00 00 00 mov 0x98(%rbx),%ecx e9e: be c0 80 40 02 mov $0x24080c0,%esi ea3: bf 20 20 00 00 mov $0x2020,%edi ea8: 44 0f b7 a3 3c 01 00 movzwl 0x13c(%rbx),%r12d eaf: 00 eb0: 48 8b 44 c2 18 mov 0x18(%rdx,%rax,8),%rax struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); struct vxlan_sock *vs = NULL; if (!vxlan->cfg.no_share) { eb5: ba 02 00 00 00 mov $0x2,%edx eba: 89 8d 68 ff ff ff mov %ecx,-0x98(%rbp) ec0: 48 89 85 58 ff ff ff mov %rax,-0xa8(%rbp) ec7: e8 00 00 00 00 callq ecc <__vxlan_sock_add+0x8c> return -EBUSY; } spin_unlock(&vn->sock_lock); } if (!vs) vs = vxlan_socket_create(vxlan->net, ipv6, ecc: 48 85 c0 test %rax,%rax #endif static __always_inline void *kmalloc_large(size_t size, gfp_t flags) { unsigned int order = get_order(size); return kmalloc_order_trace(size, flags, order); ecf: 49 89 c7 mov %rax,%r15 ed2: 0f 84 d1 02 00 00 je 11a9 <__vxlan_sock_add+0x369> vxlan->cfg.dst_port, vxlan->flags); ed8: 48 8d 40 18 lea 0x18(%rax),%rax edc: 49 8d 97 18 20 00 00 lea 0x2018(%r15),%rdx ee3: 48 c7 00 00 00 00 00 movq $0x0,(%rax) return -EBUSY; } spin_unlock(&vn->sock_lock); } if (!vs) vs = vxlan_socket_create(vxlan->net, ipv6, eea: 48 83 c0 08 add $0x8,%rax eee: 48 39 c2 cmp %rax,%rdx ef1: 75 f0 jne ee3 <__vxlan_sock_add+0xa3> ef3: 48 8d 75 a4 lea -0x5c(%rbp),%rsi ef7: 48 8d 7d a8 lea -0x58(%rbp),%rdi efb: 31 c0 xor %eax,%eax struct socket *sock; unsigned int h; struct udp_tunnel_sock_cfg tunnel_cfg; vs = kzalloc(sizeof(*vs), GFP_KERNEL); if (!vs) efd: 48 c7 45 a4 00 00 00 movq $0x0,-0x5c(%rbp) f04: 00 f05: 48 c7 45 c8 00 00 00 movq $0x0,-0x38(%rbp) f0c: 00 f0d: 48 89 f1 mov %rsi,%rcx f10: 48 29 f9 sub %rdi,%rcx return ERR_PTR(-ENOMEM); for (h = 0; h < VNI_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vs->vni_list[h]); f13: 83 c1 2c add $0x2c,%ecx f16: c1 e9 03 shr $0x3,%ecx f19: 45 84 ed test %r13b,%r13b f1c: f3 48 ab rep stos %rax,%es:(%rdi) vs = kzalloc(sizeof(*vs), GFP_KERNEL); if (!vs) return ERR_PTR(-ENOMEM); for (h = 0; h < VNI_HASH_SIZE; ++h) f1f: 0f 85 bc 02 00 00 jne 11e1 <__vxlan_sock_add+0x3a1> { struct socket *sock; struct udp_port_cfg udp_conf; int err; memset(&udp_conf, 0, sizeof(udp_conf)); f25: 48 8d 85 70 ff ff ff lea -0x90(%rbp),%rax f2c: 4c 89 f7 mov %r14,%rdi f2f: c6 45 a4 02 movb $0x2,-0x5c(%rbp) f33: 66 44 89 65 c8 mov %r12w,-0x38(%rbp) f38: 48 89 c2 mov %rax,%rdx f3b: 48 89 85 60 ff ff ff mov %rax,-0xa0(%rbp) f42: e8 00 00 00 00 callq f47 <__vxlan_sock_add+0x107> f47: 85 c0 test %eax,%eax if (ipv6) { f49: 0f 88 16 03 00 00 js 1265 <__vxlan_sock_add+0x425> f4f: 4c 8b 9d 70 ff ff ff mov -0x90(%rbp),%r11 static inline int udp_sock_create(struct net *net, struct udp_port_cfg *cfg, struct socket **sockp) { if (cfg->family == AF_INET) return udp_sock_create4(net, cfg, sockp); f56: 49 81 fb 00 f0 ff ff cmp $0xfffffffffffff000,%r11 f5d: 0f 87 c6 02 00 00 ja 1229 <__vxlan_sock_add+0x3e9> udp_conf.ipv6_v6only = 1; } else { udp_conf.family = AF_INET; } udp_conf.local_udp_port = port; f63: 8b 85 68 ff ff ff mov -0x98(%rbp),%eax f69: 4d 89 5f 10 mov %r11,0x10(%r15) f6d: 66 41 c1 c4 08 rol $0x8,%r12w f72: 41 c7 87 18 20 00 00 movl $0x1,0x2018(%r15) f79: 01 00 00 00 /* Open UDP socket */ err = udp_sock_create(net, &udp_conf, &sock); if (err < 0) f7d: 4c 89 9d 50 ff ff ff mov %r11,-0xb0(%rbp) return ERR_PTR(err); return sock; f84: 25 00 7d 00 00 and $0x7d00,%eax for (h = 0; h < VNI_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vs->vni_list[h]); sock = vxlan_create_sock(net, ipv6, port, flags); if (IS_ERR(sock)) { f89: 41 89 87 1c 20 00 00 mov %eax,0x201c(%r15) f90: 48 8b 85 58 ff ff ff mov -0xa8(%rbp),%rax return ERR_CAST(sock); } vs->sock = sock; atomic_set(&vs->refcnt, 1); vs->flags = (flags & VXLAN_F_RCV_FLAGS); f97: 48 05 10 08 00 00 add $0x810,%rax /* Socket hash table head */ static inline struct hlist_head *vs_head(struct net *net, __be16 port) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)]; f9d: 48 89 c7 mov %rax,%rdi fa0: 48 89 85 68 ff ff ff mov %rax,-0x98(%rbp) static __always_inline void __write_once_size(volatile void *p, void *res, int size) { switch (size) { case 1: *(volatile __u8 *)p = *(__u8 *)res; break; case 2: *(volatile __u16 *)p = *(__u16 *)res; break; case 4: *(volatile __u32 *)p = *(__u32 *)res; break; fa7: e8 00 00 00 00 callq fac <__vxlan_sock_add+0x16c> fac: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # fb2 <__vxlan_sock_add+0x172> PTR_ERR(sock)); kfree(vs); return ERR_CAST(sock); } vs->sock = sock; fb2: 49 8b 96 88 14 00 00 mov 0x1488(%r14),%rdx atomic_set(&vs->refcnt, 1); vs->flags = (flags & VXLAN_F_RCV_FLAGS); fb9: 83 e8 01 sub $0x1,%eax fbc: 48 98 cltq fbe: 48 8b 54 c2 18 mov 0x18(%rdx,%rax,8),%rdx fc3: 41 0f b7 c4 movzwl %r12w,%eax fc7: 69 c0 47 86 c8 61 imul $0x61c88647,%eax,%eax fcd: c1 e8 18 shr $0x18,%eax fd0: 48 83 c0 02 add $0x2,%rax fd4: 48 8d 0c c2 lea (%rdx,%rax,8),%rcx fd8: 48 8b 04 c2 mov (%rdx,%rax,8),%rax fdc: 49 89 4f 08 mov %rcx,0x8(%r15) fe0: 49 89 07 mov %rax,(%r15) }) static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; fe3: 48 85 c0 test %rax,%rax fe6: 4c 89 39 mov %r15,(%rcx) fe9: 4c 8b 9d 50 ff ff ff mov -0xb0(%rbp),%r11 ff0: 74 04 je ff6 <__vxlan_sock_add+0x1b6> ff2: 4c 89 78 08 mov %r15,0x8(%rax) #define hash_32 hash_32_generic #endif static inline u32 hash_32_generic(u32 val, unsigned int bits) { /* High bits are more random, so use them. */ return __hash_32(val) >> (32 - bits); ff6: 41 8b b7 1c 20 00 00 mov 0x201c(%r15),%esi ffd: 4c 89 df mov %r11,%rdi /* Socket hash table head */ static inline struct hlist_head *vs_head(struct net *net, __be16 port) { struct vxlan_net *vn = net_generic(net, vxlan_net_id); return &vn->sock_list[hash_32(ntohs(port), PORT_HASH_BITS)]; 1000: 4c 89 9d 58 ff ff ff mov %r11,-0xa8(%rbp) 1007: c1 ee 0d shr $0xd,%esi * list-traversal primitive must be guarded by rcu_read_lock(). */ static inline void hlist_add_head_rcu(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; 100a: 83 e6 02 and $0x2,%esi n->next = first; n->pprev = &h->first; 100d: e8 00 00 00 00 callq 1012 <__vxlan_sock_add+0x1d2> static inline void hlist_add_head_rcu(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; n->next = first; 1012: 48 8b bd 68 ff ff ff mov -0x98(%rbp),%rdi n->pprev = &h->first; rcu_assign_pointer(hlist_first_rcu(h), n); if (first) 1019: ff 14 25 00 00 00 00 callq *0x0 1020: 48 8b bd 60 ff ff ff mov -0xa0(%rbp),%rdi atomic_set(&vs->refcnt, 1); vs->flags = (flags & VXLAN_F_RCV_FLAGS); spin_lock(&vn->sock_lock); hlist_add_head_rcu(&vs->hlist, vs_head(net, port)); udp_tunnel_notify_add_rx_port(sock, 1027: 31 c0 xor %eax,%eax 1029: b9 06 00 00 00 mov $0x6,%ecx 102e: 4c 8b 9d 58 ff ff ff mov -0xa8(%rbp),%r11 1035: 48 8b 95 60 ff ff ff mov -0xa0(%rbp),%rdx 103c: f3 48 ab rep stos %rax,%es:(%rdi) 103f: 4c 89 de mov %r11,%rsi 1042: 4c 89 f7 mov %r14,%rdi 1045: 4c 89 bd 70 ff ff ff mov %r15,-0x90(%rbp) 104c: c6 85 78 ff ff ff 01 movb $0x1,-0x88(%rbp) UDP_TUNNEL_TYPE_VXLAN_GPE : UDP_TUNNEL_TYPE_VXLAN); spin_unlock(&vn->sock_lock); /* Mark socket as an encapsulation socket. */ memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); 1053: 48 c7 45 80 00 00 00 movq $0x0,-0x80(%rbp) 105a: 00 105b: 48 c7 45 90 00 00 00 movq $0x0,-0x70(%rbp) 1062: 00 tunnel_cfg.encap_rcv = vxlan_rcv; tunnel_cfg.encap_destroy = NULL; tunnel_cfg.gro_receive = vxlan_gro_receive; tunnel_cfg.gro_complete = vxlan_gro_complete; setup_udp_tunnel_sock(net, sock, &tunnel_cfg); 1063: 48 c7 45 98 00 00 00 movq $0x0,-0x68(%rbp) 106a: 00 106b: e8 00 00 00 00 callq 1070 <__vxlan_sock_add+0x230> 1070: e9 80 00 00 00 jmpq 10f5 <__vxlan_sock_add+0x2b5> UDP_TUNNEL_TYPE_VXLAN); spin_unlock(&vn->sock_lock); /* Mark socket as an encapsulation socket. */ memset(&tunnel_cfg, 0, sizeof(tunnel_cfg)); tunnel_cfg.sk_user_data = vs; 1075: 48 98 cltq 1077: 4c 8b 64 c2 18 mov 0x18(%rdx,%rax,8),%r12 tunnel_cfg.encap_type = 1; 107c: 49 81 c4 10 08 00 00 add $0x810,%r12 tunnel_cfg.encap_rcv = vxlan_rcv; 1083: 4c 89 e7 mov %r12,%rdi 1086: e8 00 00 00 00 callq 108b <__vxlan_sock_add+0x24b> tunnel_cfg.encap_destroy = NULL; tunnel_cfg.gro_receive = vxlan_gro_receive; 108b: 41 80 fd 01 cmp $0x1,%r13b 108f: 0f b7 93 3c 01 00 00 movzwl 0x13c(%rbx),%edx tunnel_cfg.gro_complete = vxlan_gro_complete; 1096: 8b 8b 98 00 00 00 mov 0x98(%rbx),%ecx setup_udp_tunnel_sock(net, sock, &tunnel_cfg); 109c: 19 f6 sbb %esi,%esi 109e: 48 8b 7b 38 mov 0x38(%rbx),%rdi 10a2: 83 e6 f8 and $0xfffffff8,%esi 10a5: 83 c6 0a add $0xa,%esi 10a8: e8 43 f0 ff ff callq f0 10ad: 48 85 c0 test %rax,%rax 10b0: 49 89 c7 mov %rax,%r15 10b3: 74 2d je 10e2 <__vxlan_sock_add+0x2a2> 10b5: 8b 88 18 20 00 00 mov 0x2018(%rax),%ecx struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); struct vxlan_sock *vs = NULL; if (!vxlan->cfg.no_share) { spin_lock(&vn->sock_lock); vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET, 10bb: 85 c9 test %ecx,%ecx 10bd: 0f 84 0d 01 00 00 je 11d0 <__vxlan_sock_add+0x390> 10c3: 48 8d b0 18 20 00 00 lea 0x2018(%rax),%rsi 10ca: 8d 51 01 lea 0x1(%rcx),%edx 10cd: 89 c8 mov %ecx,%eax 10cf: f0 41 0f b1 97 18 20 lock cmpxchg %edx,0x2018(%r15) 10d6: 00 00 10d8: 39 c1 cmp %eax,%ecx 10da: 89 c2 mov %eax,%edx 10dc: 0f 85 d3 00 00 00 jne 11b5 <__vxlan_sock_add+0x375> 10e2: 4c 89 e7 mov %r12,%rdi 10e5: ff 14 25 00 00 00 00 callq *0x0 static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u) { int c, old; c = atomic_read(v); for (;;) { if (unlikely(c == (u))) 10ec: 4d 85 ff test %r15,%r15 10ef: 0f 84 78 01 00 00 je 126d <__vxlan_sock_add+0x42d> return xadd(&v->counter, -i); } static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new) { return cmpxchg(&v->counter, old, new); 10f5: 4d 89 fb mov %r15,%r11 10f8: 49 81 fb 00 f0 ff ff cmp $0xfffffffffffff000,%r11 10ff: 0f 87 ab 00 00 00 ja 11b0 <__vxlan_sock_add+0x370> 1105: 45 84 ed test %r13b,%r13b c = atomic_read(v); for (;;) { if (unlikely(c == (u))) break; old = atomic_cmpxchg((v), c, c + (a)); if (likely(old == c)) 1108: 0f 84 92 00 00 00 je 11a0 <__vxlan_sock_add+0x360> 110e: 4c 89 7b 28 mov %r15,0x28(%rbx) 1112: 48 8b 43 38 mov 0x38(%rbx),%rax 1116: 44 8b 63 60 mov 0x60(%rbx),%r12d 111a: 48 8b 90 88 14 00 00 mov 0x1488(%rax),%rdx spin_unlock(&vn->sock_lock); return -EBUSY; } spin_unlock(&vn->sock_lock); } if (!vs) 1121: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 1127 <__vxlan_sock_add+0x2e7> 1127: 83 e8 01 sub $0x1,%eax vs = vxlan_socket_create(vxlan->net, ipv6, vxlan->cfg.dst_port, vxlan->flags); if (IS_ERR(vs)) 112a: 48 98 cltq 112c: 4c 8b 6c c2 18 mov 0x18(%rdx,%rax,8),%r13 1131: 49 81 c5 10 08 00 00 add $0x810,%r13 return PTR_ERR(vs); #if IS_ENABLED(CONFIG_IPV6) if (ipv6) 1138: 4c 89 ef mov %r13,%rdi 113b: e8 00 00 00 00 callq 1140 <__vxlan_sock_add+0x300> vxlan->vn6_sock = vs; 1140: 41 69 d4 47 86 c8 61 imul $0x61c88647,%r12d,%edx } static void vxlan_vs_add_dev(struct vxlan_sock *vs, struct vxlan_dev *vxlan) { struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); __be32 vni = vxlan->default_dst.remote_vni; 1147: c1 ea 16 shr $0x16,%edx 114a: 48 83 c2 02 add $0x2,%rdx 114e: 49 8d 0c d7 lea (%r15,%rdx,8),%rcx 1152: 49 8b 44 d7 08 mov 0x8(%r15,%rdx,8),%rax 1157: 48 8d 71 08 lea 0x8(%rcx),%rsi 115b: 48 89 03 mov %rax,(%rbx) 115e: 48 89 73 08 mov %rsi,0x8(%rbx) 1162: 48 85 c0 test %rax,%rax 1165: 48 89 59 08 mov %rbx,0x8(%rcx) 1169: 74 04 je 116f <__vxlan_sock_add+0x32f> 116b: 48 89 58 08 mov %rbx,0x8(%rax) 116f: 4c 89 ef mov %r13,%rdi 1172: ff 14 25 00 00 00 00 callq *0x0 1179: 31 c0 xor %eax,%eax #endif /* Virtual Network hash table head */ static inline struct hlist_head *vni_head(struct vxlan_sock *vs, __be32 vni) { return &vs->vni_list[hash_32((__force u32)vni, VNI_HASH_BITS)]; 117b: 48 8b 75 d0 mov -0x30(%rbp),%rsi 117f: 65 48 33 34 25 28 00 xor %gs:0x28,%rsi 1186: 00 00 1188: 0f 85 d2 00 00 00 jne 1260 <__vxlan_sock_add+0x420> struct hlist_head *h) { struct hlist_node *first = h->first; n->next = first; n->pprev = &h->first; 118e: 48 81 c4 88 00 00 00 add $0x88,%rsp { switch (size) { case 1: *(volatile __u8 *)p = *(__u8 *)res; break; case 2: *(volatile __u16 *)p = *(__u16 *)res; break; case 4: *(volatile __u32 *)p = *(__u32 *)res; break; case 8: *(volatile __u64 *)p = *(__u64 *)res; break; 1195: 5b pop %rbx 1196: 41 5c pop %r12 1198: 41 5d pop %r13 rcu_assign_pointer(hlist_first_rcu(h), n); if (first) 119a: 41 5e pop %r14 first->pprev = &n->next; 119c: 41 5f pop %r15 119e: 5d pop %rbp 119f: c3 retq 11a0: 4c 89 7b 20 mov %r15,0x20(%rbx) 11a4: e9 69 ff ff ff jmpq 1112 <__vxlan_sock_add+0x2d2> vxlan->vn6_sock = vs; else #endif vxlan->vn4_sock = vs; vxlan_vs_add_dev(vs, vxlan); return 0; 11a9: 49 c7 c7 f4 ff ff ff mov $0xfffffffffffffff4,%r15 } 11b0: 44 89 f8 mov %r15d,%eax 11b3: eb c6 jmp 117b <__vxlan_sock_add+0x33b> 11b5: 85 d2 test %edx,%edx 11b7: 74 17 je 11d0 <__vxlan_sock_add+0x390> 11b9: 8d 4a 01 lea 0x1(%rdx),%ecx 11bc: 89 d0 mov %edx,%eax 11be: f0 0f b1 0e lock cmpxchg %ecx,(%rsi) 11c2: 39 d0 cmp %edx,%eax 11c4: 0f 84 18 ff ff ff je 10e2 <__vxlan_sock_add+0x2a2> 11ca: 89 c2 mov %eax,%edx 11cc: 85 d2 test %edx,%edx 11ce: 75 e9 jne 11b9 <__vxlan_sock_add+0x379> #if IS_ENABLED(CONFIG_IPV6) if (ipv6) vxlan->vn6_sock = vs; else #endif vxlan->vn4_sock = vs; 11d0: 4c 89 e7 mov %r12,%rdi 11d3: ff 14 25 00 00 00 00 callq *0x0 unsigned int h; struct udp_tunnel_sock_cfg tunnel_cfg; vs = kzalloc(sizeof(*vs), GFP_KERNEL); if (!vs) return ERR_PTR(-ENOMEM); 11da: b8 f0 ff ff ff mov $0xfffffff0,%eax 11df: eb 9a jmp 117b <__vxlan_sock_add+0x33b> } if (!vs) vs = vxlan_socket_create(vxlan->net, ipv6, vxlan->cfg.dst_port, vxlan->flags); if (IS_ERR(vs)) return PTR_ERR(vs); 11e1: 8b 85 68 ff ff ff mov -0x98(%rbp),%eax static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u) { int c, old; c = atomic_read(v); for (;;) { if (unlikely(c == (u))) 11e7: 0f b6 55 cc movzbl -0x34(%rbp),%edx break; old = atomic_cmpxchg((v), c, c + (a)); 11eb: 4c 89 f7 mov %r14,%rdi return xadd(&v->counter, -i); } static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new) { return cmpxchg(&v->counter, old, new); 11ee: c6 45 a4 0a movb $0xa,-0x5c(%rbp) c = atomic_read(v); for (;;) { if (unlikely(c == (u))) break; old = atomic_cmpxchg((v), c, c + (a)); if (likely(old == c)) 11f2: 66 44 89 65 c8 mov %r12w,-0x38(%rbp) 11f7: c1 e8 08 shr $0x8,%eax 11fa: 83 f0 01 xor $0x1,%eax static __always_inline int __atomic_add_unless(atomic_t *v, int a, int u) { int c, old; c = atomic_read(v); for (;;) { if (unlikely(c == (u))) 11fd: 83 e2 fb and $0xfffffffb,%edx 1200: 83 e0 01 and $0x1,%eax 1203: c1 e0 02 shl $0x2,%eax 1206: 09 d0 or %edx,%eax 1208: 83 c8 08 or $0x8,%eax spin_lock(&vn->sock_lock); vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET, vxlan->cfg.dst_port, vxlan->flags); if (vs && !atomic_add_unless(&vs->refcnt, 1, 0)) { spin_unlock(&vn->sock_lock); return -EBUSY; 120b: 88 45 cc mov %al,-0x34(%rbp) 120e: 48 8d 85 70 ff ff ff lea -0x90(%rbp),%rax memset(&udp_conf, 0, sizeof(udp_conf)); if (ipv6) { udp_conf.family = AF_INET6; udp_conf.use_udp6_rx_checksums = 1215: 48 89 c2 mov %rax,%rdx 1218: 48 89 85 60 ff ff ff mov %rax,-0xa0(%rbp) int err; memset(&udp_conf, 0, sizeof(udp_conf)); if (ipv6) { udp_conf.family = AF_INET6; 121f: e8 00 00 00 00 callq 1224 <__vxlan_sock_add+0x3e4> udp_conf.ipv6_v6only = 1; } else { udp_conf.family = AF_INET; } udp_conf.local_udp_port = port; 1224: e9 1e fd ff ff jmpq f47 <__vxlan_sock_add+0x107> memset(&udp_conf, 0, sizeof(udp_conf)); if (ipv6) { udp_conf.family = AF_INET6; udp_conf.use_udp6_rx_checksums = 1229: 44 89 e6 mov %r12d,%esi 122c: 4c 89 da mov %r11,%rdx 122f: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 1236: 66 c1 c6 08 rol $0x8,%si !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX); udp_conf.ipv6_v6only = 1; 123a: 4c 89 9d 68 ff ff ff mov %r11,-0x98(%rbp) if (cfg->family == AF_INET6) return udp_sock_create6(net, cfg, sockp); 1241: 0f b7 f6 movzwl %si,%esi 1244: e8 00 00 00 00 callq 1249 <__vxlan_sock_add+0x409> 1249: 4c 89 ff mov %r15,%rdi 124c: e8 00 00 00 00 callq 1251 <__vxlan_sock_add+0x411> 1251: 4c 8b 9d 68 ff ff ff mov -0x98(%rbp),%r11 1258: 4d 89 df mov %r11,%r15 for (h = 0; h < VNI_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vs->vni_list[h]); sock = vxlan_create_sock(net, ipv6, port, flags); if (IS_ERR(sock)) { pr_info("Cannot bind port %d, err=%ld\n", ntohs(port), 125b: e9 98 fe ff ff jmpq 10f8 <__vxlan_sock_add+0x2b8> 1260: e8 00 00 00 00 callq 1265 <__vxlan_sock_add+0x425> 1265: 4c 63 d8 movslq %eax,%r11 1268: e9 e9 fc ff ff jmpq f56 <__vxlan_sock_add+0x116> 126d: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 1273 <__vxlan_sock_add+0x433> 1273: 4c 8b 73 38 mov 0x38(%rbx),%r14 1277: 83 e8 01 sub $0x1,%eax PTR_ERR(sock)); kfree(vs); 127a: e9 10 fc ff ff jmpq e8f <__vxlan_sock_add+0x4f> 127f: 90 nop 0000000000001280 : 1280: e8 00 00 00 00 callq 1285 1285: 55 push %rbp 1286: 48 89 e5 mov %rsp,%rbp 1289: 41 57 push %r15 128b: 41 56 push %r14 128d: 41 55 push %r13 128f: 41 54 push %r12 else #endif vxlan->vn4_sock = vs; vxlan_vs_add_dev(vs, vxlan); return 0; } 1291: 4c 8d bf 40 08 00 00 lea 0x840(%rdi),%r15 1298: 53 push %rbx 1299: 48 89 fb mov %rdi,%rbx 129c: 48 83 ec 18 sub $0x18,%rsp 12a0: 48 c7 87 60 08 00 00 movq $0x0,0x860(%rdi) 12a7: 00 00 00 00 12ab: 48 c7 87 68 08 00 00 movq $0x0,0x868(%rdi) 12b2: 00 00 00 00 free_percpu(dev->tstats); } /* Start ageing timer and join group when device is brought up */ static int vxlan_open(struct net_device *dev) { 12b6: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 12bd: 00 00 12bf: 48 89 45 d0 mov %rax,-0x30(%rbp) * * Get network device private data */ static inline void *netdev_priv(const struct net_device *dev) { return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); 12c3: 31 c0 xor %eax,%eax 12c5: 8b 87 d8 08 00 00 mov 0x8d8(%rdi),%eax 12cb: 41 89 c5 mov %eax,%r13d 12ce: 41 c1 ed 0d shr $0xd,%r13d { bool ipv6 = vxlan->flags & VXLAN_F_IPV6; bool metadata = vxlan->flags & VXLAN_F_COLLECT_METADATA; int ret = 0; vxlan->vn4_sock = NULL; 12d2: 41 83 e5 01 and $0x1,%r13d 12d6: 83 e0 20 and $0x20,%eax 12d9: 41 89 c4 mov %eax,%r12d #if IS_ENABLED(CONFIG_IPV6) vxlan->vn6_sock = NULL; 12dc: 0f 85 94 00 00 00 jne 1376 12e2: 45 84 ed test %r13b,%r13b 12e5: 0f 85 8b 00 00 00 jne 1376 free_percpu(dev->tstats); } /* Start ageing timer and join group when device is brought up */ static int vxlan_open(struct net_device *dev) { 12eb: 45 85 e4 test %r12d,%r12d 12ee: 0f 84 3f 01 00 00 je 1433 12f4: 45 84 ed test %r13b,%r13b return 0; } static int vxlan_sock_add(struct vxlan_dev *vxlan) { bool ipv6 = vxlan->flags & VXLAN_F_IPV6; 12f7: 0f 85 36 01 00 00 jne 1433 bool metadata = vxlan->flags & VXLAN_F_COLLECT_METADATA; 12fd: 45 31 f6 xor %r14d,%r14d 1300: 0f b7 83 80 08 00 00 movzwl 0x880(%rbx),%eax int ret = 0; vxlan->vn4_sock = NULL; #if IS_ENABLED(CONFIG_IPV6) vxlan->vn6_sock = NULL; if (ipv6 || metadata) 1307: 66 83 f8 0a cmp $0xa,%ax 130b: 0f 84 9b 00 00 00 je 13ac 1311: 8b 93 84 08 00 00 mov 0x884(%rbx),%edx 1317: 89 d1 mov %edx,%ecx 1319: 81 e1 f0 00 00 00 and $0xf0,%ecx ret = __vxlan_sock_add(vxlan, true); #endif if (!ret && (!ipv6 || metadata)) 131f: 81 f9 e0 00 00 00 cmp $0xe0,%ecx 1325: 0f 84 9c 00 00 00 je 13c7 132b: 48 83 bb 90 09 00 00 cmpq $0x0,0x990(%rbx) 1332: 00 return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); } static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 1333: 75 25 jne 135a 1335: 48 8b 55 d0 mov -0x30(%rbp),%rdx 1339: 65 48 33 14 25 28 00 xor %gs:0x28,%rdx 1340: 00 00 return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr); else return IN_MULTICAST(ntohl(ipa->sin.sin_addr.s_addr)); 1342: 44 89 f0 mov %r14d,%eax 1345: 0f 85 3b 01 00 00 jne 1486 ret = vxlan_sock_add(vxlan); if (ret < 0) return ret; if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { 134b: 48 83 c4 18 add $0x18,%rsp 134f: 5b pop %rbx 1350: 41 5c pop %r12 1352: 41 5d pop %r13 1354: 41 5e pop %r14 1356: 41 5f pop %r15 1358: 5d pop %rbp 1359: c3 retq 135a: 48 8b 35 00 00 00 00 mov 0x0(%rip),%rsi # 1361 vxlan_sock_release(vxlan); return ret; } } if (vxlan->cfg.age_interval) 1361: 48 8d bb e0 08 00 00 lea 0x8e0(%rbx),%rdi mod_timer(&vxlan->age_timer, jiffies + FDB_AGE_INTERVAL); return ret; } 1368: 48 81 c6 c4 09 00 00 add $0x9c4,%rsi 136f: e8 00 00 00 00 callq 1374 1374: eb bf jmp 1335 1376: be 01 00 00 00 mov $0x1,%esi 137b: 4c 89 ff mov %r15,%rdi 137e: e8 bd fa ff ff callq e40 <__vxlan_sock_add> 1383: 85 c0 test %eax,%eax 1385: 41 89 c6 mov %eax,%r14d 1388: 0f 84 5d ff ff ff je 12eb return ret; } } if (vxlan->cfg.age_interval) mod_timer(&vxlan->age_timer, jiffies + FDB_AGE_INTERVAL); 138e: 45 85 f6 test %r14d,%r14d 1391: 0f 89 69 ff ff ff jns 1300 1397: 48 8d b3 68 08 00 00 lea 0x868(%rbx),%rsi 139e: 48 8d bb 60 08 00 00 lea 0x860(%rbx),%rdi 13a5: e8 e6 f8 ff ff callq c90 vxlan->vn4_sock = NULL; #if IS_ENABLED(CONFIG_IPV6) vxlan->vn6_sock = NULL; if (ipv6 || metadata) ret = __vxlan_sock_add(vxlan, true); 13aa: eb 89 jmp 1335 13ac: 0f b6 83 88 08 00 00 movzbl 0x888(%rbx),%eax #endif if (!ret && (!ipv6 || metadata)) 13b3: 3d ff 00 00 00 cmp $0xff,%eax 13b8: 0f 85 6d ff ff ff jne 132b ret = __vxlan_sock_add(vxlan, false); if (ret < 0) 13be: 44 8b ab a4 08 00 00 mov 0x8a4(%rbx),%r13d 13c5: eb 0d jmp 13d4 13c7: 66 83 f8 02 cmp $0x2,%ax 13cb: 44 8b ab a4 08 00 00 mov 0x8a4(%rbx),%r13d 13d2: 74 71 je 1445 13d4: 48 8b 83 68 08 00 00 mov 0x868(%rbx),%rax ret = vxlan_igmp_join(vxlan); if (ret == -EADDRINUSE) ret = 0; if (ret) { vxlan_sock_release(vxlan); return ret; 13db: 31 f6 xor %esi,%esi ret = vxlan_sock_add(vxlan); if (ret < 0) return ret; if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { 13dd: 48 8b 40 10 mov 0x10(%rax),%rax 13e1: 4c 8b 60 20 mov 0x20(%rax),%r12 13e5: 4c 89 e7 mov %r12,%rdi 13e8: e8 00 00 00 00 callq 13ed 13ed: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 13f4 */ static int vxlan_igmp_join(struct vxlan_dev *vxlan) { struct sock *sk; union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; 13f4: 4c 89 e7 mov %r12,%rdi int ret = -EINVAL; if (ip->sa.sa_family == AF_INET) { 13f7: 48 8d 93 88 08 00 00 lea 0x888(%rbx),%rdx */ static int vxlan_igmp_join(struct vxlan_dev *vxlan) { struct sock *sk; union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; 13fe: 44 89 ee mov %r13d,%esi 1401: ff 10 callq *(%rax) int ret = -EINVAL; if (ip->sa.sa_family == AF_INET) { 1403: 4c 89 e7 mov %r12,%rdi lock_sock(sk); ret = ip_mc_join_group(sk, &mreq); release_sock(sk); #if IS_ENABLED(CONFIG_IPV6) } else { sk = vxlan->vn6_sock->sock->sk; 1406: 41 89 c6 mov %eax,%r14d 1409: e8 00 00 00 00 callq 140e 140e: 41 83 fe 9e cmp $0xffffff9e,%r14d 1412: 74 09 je 141d 1414: 45 85 f6 test %r14d,%r14d void lock_sock_nested(struct sock *sk, int subclass); static inline void lock_sock(struct sock *sk) { lock_sock_nested(sk, 0); 1417: 0f 85 7a ff ff ff jne 1397 lock_sock(sk); ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex, 141d: 45 31 f6 xor %r14d,%r14d 1420: 48 83 bb 90 09 00 00 cmpq $0x0,0x990(%rbx) 1427: 00 &ip->sin6.sin6_addr); 1428: 0f 84 07 ff ff ff je 1335 release_sock(sk); #if IS_ENABLED(CONFIG_IPV6) } else { sk = vxlan->vn6_sock->sock->sk; lock_sock(sk); ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex, 142e: e9 27 ff ff ff jmpq 135a &ip->sin6.sin6_addr); release_sock(sk); 1433: 31 f6 xor %esi,%esi 1435: 4c 89 ff mov %r15,%rdi release_sock(sk); #if IS_ENABLED(CONFIG_IPV6) } else { sk = vxlan->vn6_sock->sock->sk; lock_sock(sk); ret = ipv6_stub->ipv6_sock_mc_join(sk, ifindex, 1438: e8 03 fa ff ff callq e40 <__vxlan_sock_add> &ip->sin6.sin6_addr); release_sock(sk); 143d: 41 89 c6 mov %eax,%r14d if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) { ret = vxlan_igmp_join(vxlan); if (ret == -EADDRINUSE) ret = 0; if (ret) { 1440: e9 49 ff ff ff jmpq 138e 1445: 48 8b 83 60 08 00 00 mov 0x860(%rbx),%rax 144c: 31 f6 xor %esi,%esi 144e: 48 c7 45 c4 00 00 00 movq $0x0,-0x3c(%rbp) 1455: 00 vxlan_sock_release(vxlan); return ret; } } if (vxlan->cfg.age_interval) 1456: 44 89 6d cc mov %r13d,-0x34(%rbp) 145a: 89 55 c4 mov %edx,-0x3c(%rbp) 145d: 48 8b 40 10 mov 0x10(%rax),%rax 1461: 4c 8b 60 20 mov 0x20(%rax),%r12 vxlan->vn6_sock = NULL; if (ipv6 || metadata) ret = __vxlan_sock_add(vxlan, true); #endif if (!ret && (!ipv6 || metadata)) ret = __vxlan_sock_add(vxlan, false); 1465: 4c 89 e7 mov %r12,%rdi 1468: e8 00 00 00 00 callq 146d 146d: 48 8d 75 c4 lea -0x3c(%rbp),%rsi 1471: 4c 89 e7 mov %r12,%rdi 1474: e8 00 00 00 00 callq 1479 struct ip_mreqn mreq = { .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr, .imr_ifindex = ifindex, }; sk = vxlan->vn4_sock->sock->sk; 1479: 4c 89 e7 mov %r12,%rdi 147c: 41 89 c6 mov %eax,%r14d union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; int ret = -EINVAL; if (ip->sa.sa_family == AF_INET) { struct ip_mreqn mreq = { 147f: e8 00 00 00 00 callq 1484 1484: eb 88 jmp 140e 1486: e8 00 00 00 00 callq 148b 148b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 0000000000001490 : .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr, .imr_ifindex = ifindex, }; sk = vxlan->vn4_sock->sock->sk; 1490: e8 00 00 00 00 callq 1495 1495: 55 push %rbp 1496: ba 04 00 00 00 mov $0x4,%edx 149b: 48 89 e5 mov %rsp,%rbp lock_sock(sk); ret = ip_mc_join_group(sk, &mreq); 149e: 41 55 push %r13 14a0: 41 54 push %r12 14a2: 53 push %rbx 14a3: 48 8d 4d c0 lea -0x40(%rbp),%rcx 14a7: 48 89 f3 mov %rsi,%rbx release_sock(sk); 14aa: 49 89 fc mov %rdi,%r12 .imr_ifindex = ifindex, }; sk = vxlan->vn4_sock->sock->sk; lock_sock(sk); ret = ip_mc_join_group(sk, &mreq); 14ad: 48 83 ec 38 sub $0x38,%rsp release_sock(sk); 14b1: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 14b8: 00 00 if (vxlan->cfg.age_interval) mod_timer(&vxlan->age_timer, jiffies + FDB_AGE_INTERVAL); return ret; } 14ba: 48 89 45 e0 mov %rax,-0x20(%rbp) 14be: 31 c0 xor %eax,%eax nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */ 0; } static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) { 14c0: 0f b7 86 7e 09 00 00 movzwl 0x97e(%rsi),%eax * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) { return nla_put(skb, attrtype, sizeof(u32), &value); 14c7: 66 c1 c0 08 rol $0x8,%ax 14cb: 66 89 45 dc mov %ax,-0x24(%rbp) 14cf: 0f b7 86 80 09 00 00 movzwl 0x980(%rsi),%eax 14d6: 66 c1 c0 08 rol $0x8,%ax 14da: 66 89 45 de mov %ax,-0x22(%rbp) 14de: 8b 86 a0 08 00 00 mov 0x8a0(%rsi),%eax 14e4: be 01 00 00 00 mov $0x1,%esi 14e9: 0f c8 bswap %eax 14eb: 89 45 c0 mov %eax,-0x40(%rbp) 14ee: e8 00 00 00 00 callq 14f3 const struct vxlan_dev *vxlan = netdev_priv(dev); const struct vxlan_rdst *dst = &vxlan->default_dst; struct ifla_vxlan_port_range ports = { .low = htons(vxlan->cfg.port_min), 14f3: 85 c0 test %eax,%eax 14f5: 0f 85 9b 03 00 00 jne 1896 static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) { const struct vxlan_dev *vxlan = netdev_priv(dev); const struct vxlan_rdst *dst = &vxlan->default_dst; struct ifla_vxlan_port_range ports = { 14fb: 0f b7 83 80 08 00 00 movzwl 0x880(%rbx),%eax .low = htons(vxlan->cfg.port_min), .high = htons(vxlan->cfg.port_max), 1502: 66 83 f8 0a cmp $0xa,%ax 1506: 0f 84 2d 04 00 00 je 1939 static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) { const struct vxlan_dev *vxlan = netdev_priv(dev); const struct vxlan_rdst *dst = &vxlan->default_dst; struct ifla_vxlan_port_range ports = { 150c: 8b 93 84 08 00 00 mov 0x884(%rbx),%edx .low = htons(vxlan->cfg.port_min), .high = htons(vxlan->cfg.port_max), }; if (nla_put_u32(skb, IFLA_VXLAN_ID, be32_to_cpu(dst->remote_vni))) 1512: 85 d2 test %edx,%edx 1514: 0f 85 a3 03 00 00 jne 18bd 151a: 8b 83 a4 08 00 00 mov 0x8a4(%rbx),%eax 1520: 85 c0 test %eax,%eax 1522: 0f 85 ca 03 00 00 jne 18f2 1528: 0f b7 83 54 09 00 00 movzwl 0x954(%rbx),%eax return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 152f: 66 83 f8 0a cmp $0xa,%ax 1533: 0f 84 e7 03 00 00 je 1920 1539: 8b 93 58 09 00 00 mov 0x958(%rbx),%edx return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); 153f: 85 d2 test %edx,%edx 1541: 74 2b je 156e }; if (nla_put_u32(skb, IFLA_VXLAN_ID, be32_to_cpu(dst->remote_vni))) goto nla_put_failure; if (!vxlan_addr_any(&dst->remote_ip)) { 1543: 66 83 f8 02 cmp $0x2,%ax 1547: 0f 84 05 04 00 00 je 1952 goto nla_put_failure; #endif } } if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex)) 154d: 48 8d 8b 5c 09 00 00 lea 0x95c(%rbx),%rcx 1554: ba 10 00 00 00 mov $0x10,%edx return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 1559: be 11 00 00 00 mov $0x11,%esi 155e: 4c 89 e7 mov %r12,%rdi 1561: e8 00 00 00 00 callq 1566 1566: 85 c0 test %eax,%eax 1568: 0f 85 28 03 00 00 jne 1896 return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); 156e: 0f b6 83 83 09 00 00 movzbl 0x983(%rbx),%eax if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex)) goto nla_put_failure; if (!vxlan_addr_any(&vxlan->cfg.saddr)) { if (vxlan->cfg.saddr.sa.sa_family == AF_INET) { 1575: 48 8d 4d b1 lea -0x4f(%rbp),%rcx 1579: ba 01 00 00 00 mov $0x1,%edx if (nla_put_in_addr(skb, IFLA_VXLAN_LOCAL, vxlan->cfg.saddr.sin.sin_addr.s_addr)) goto nla_put_failure; #if IS_ENABLED(CONFIG_IPV6) } else { if (nla_put_in6_addr(skb, IFLA_VXLAN_LOCAL6, 157e: be 05 00 00 00 mov $0x5,%esi 1583: 4c 89 e7 mov %r12,%rdi * @addr: IPv6 address */ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype, const struct in6_addr *addr) { return nla_put(skb, attrtype, sizeof(*addr), addr); 1586: 88 45 b1 mov %al,-0x4f(%rbp) 1589: e8 00 00 00 00 callq 158e 158e: 85 c0 test %eax,%eax 1590: 0f 85 00 03 00 00 jne 1896 1596: 0f b6 83 82 09 00 00 movzbl 0x982(%rbx),%eax 159d: 48 8d 4d b2 lea -0x4e(%rbp),%rcx 15a1: ba 01 00 00 00 mov $0x1,%edx * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value) { return nla_put(skb, attrtype, sizeof(u8), &value); 15a6: be 06 00 00 00 mov $0x6,%esi 15ab: 4c 89 e7 mov %r12,%rdi 15ae: 88 45 b2 mov %al,-0x4e(%rbp) 15b1: e8 00 00 00 00 callq 15b6 15b6: 85 c0 test %eax,%eax 15b8: 0f 85 d8 02 00 00 jne 1896 goto nla_put_failure; #endif } } if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->cfg.ttl) || 15be: 8b 83 84 09 00 00 mov 0x984(%rbx),%eax 15c4: 48 8d 4d d0 lea -0x30(%rbp),%rcx 15c8: ba 04 00 00 00 mov $0x4,%edx 15cd: be 1a 00 00 00 mov $0x1a,%esi 15d2: 4c 89 e7 mov %r12,%rdi 15d5: 89 45 d0 mov %eax,-0x30(%rbp) 15d8: e8 00 00 00 00 callq 15dd 15dd: 85 c0 test %eax,%eax 15df: 0f 85 b1 02 00 00 jne 1896 15e5: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 15eb: 48 8d 4d b3 lea -0x4d(%rbp),%rcx 15ef: ba 01 00 00 00 mov $0x1,%edx * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) { return nla_put(skb, attrtype, sizeof(__be32), &value); 15f4: be 07 00 00 00 mov $0x7,%esi 15f9: 4c 89 e7 mov %r12,%rdi 15fc: 88 45 b3 mov %al,-0x4d(%rbp) 15ff: 80 65 b3 01 andb $0x1,-0x4d(%rbp) 1603: e8 00 00 00 00 callq 1608 1608: 85 c0 test %eax,%eax 160a: 0f 85 86 02 00 00 jne 1896 nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->cfg.tos) || 1610: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 1616: 48 8d 4d b4 lea -0x4c(%rbp),%rcx 161a: ba 01 00 00 00 mov $0x1,%edx * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value) { return nla_put(skb, attrtype, sizeof(u8), &value); 161f: be 0b 00 00 00 mov $0xb,%esi 1624: 4c 89 e7 mov %r12,%rdi 1627: d1 e8 shr %eax 1629: 83 e0 01 and $0x1,%eax 162c: 88 45 b4 mov %al,-0x4c(%rbp) 162f: e8 00 00 00 00 callq 1634 1634: 85 c0 test %eax,%eax 1636: 0f 85 5a 02 00 00 jne 1896 nla_put_be32(skb, IFLA_VXLAN_LABEL, vxlan->cfg.label) || 163c: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 1642: 48 8d 4d b5 lea -0x4b(%rbp),%rcx 1646: ba 01 00 00 00 mov $0x1,%edx 164b: be 0c 00 00 00 mov $0xc,%esi 1650: 4c 89 e7 mov %r12,%rdi 1653: c1 e8 02 shr $0x2,%eax 1656: 83 e0 01 and $0x1,%eax 1659: 88 45 b5 mov %al,-0x4b(%rbp) 165c: e8 00 00 00 00 callq 1661 1661: 85 c0 test %eax,%eax 1663: 0f 85 2d 02 00 00 jne 1896 nla_put_u8(skb, IFLA_VXLAN_LEARNING, !!(vxlan->flags & VXLAN_F_LEARN)) || 1669: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 166f: 48 8d 4d b6 lea -0x4a(%rbp),%rcx 1673: ba 01 00 00 00 mov $0x1,%edx 1678: be 0d 00 00 00 mov $0xd,%esi 167d: 4c 89 e7 mov %r12,%rdi 1680: c1 e8 03 shr $0x3,%eax 1683: 83 e0 01 and $0x1,%eax 1686: 88 45 b6 mov %al,-0x4a(%rbp) 1689: e8 00 00 00 00 callq 168e 168e: 85 c0 test %eax,%eax 1690: 0f 85 00 02 00 00 jne 1896 nla_put_u8(skb, IFLA_VXLAN_PROXY, !!(vxlan->flags & VXLAN_F_PROXY)) || 1696: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 169c: 48 8d 4d b7 lea -0x49(%rbp),%rcx 16a0: ba 01 00 00 00 mov $0x1,%edx 16a5: be 0e 00 00 00 mov $0xe,%esi 16aa: 4c 89 e7 mov %r12,%rdi 16ad: c1 e8 04 shr $0x4,%eax 16b0: 83 e0 01 and $0x1,%eax 16b3: 88 45 b7 mov %al,-0x49(%rbp) 16b6: e8 00 00 00 00 callq 16bb 16bb: 85 c0 test %eax,%eax 16bd: 0f 85 d3 01 00 00 jne 1896 nla_put_u8(skb, IFLA_VXLAN_RSC, !!(vxlan->flags & VXLAN_F_RSC)) || 16c3: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 16c9: 48 8d 4d b8 lea -0x48(%rbp),%rcx 16cd: ba 01 00 00 00 mov $0x1,%edx 16d2: be 19 00 00 00 mov $0x19,%esi 16d7: 4c 89 e7 mov %r12,%rdi 16da: c1 e8 0d shr $0xd,%eax 16dd: 83 e0 01 and $0x1,%eax 16e0: 88 45 b8 mov %al,-0x48(%rbp) 16e3: e8 00 00 00 00 callq 16e8 16e8: 85 c0 test %eax,%eax 16ea: 0f 85 a6 01 00 00 jne 1896 nla_put_u8(skb, IFLA_VXLAN_L2MISS, !!(vxlan->flags & VXLAN_F_L2MISS)) || 16f0: 48 8b 83 90 09 00 00 mov 0x990(%rbx),%rax 16f7: 48 8d 4d d4 lea -0x2c(%rbp),%rcx 16fb: ba 04 00 00 00 mov $0x4,%edx 1700: be 08 00 00 00 mov $0x8,%esi 1705: 4c 89 e7 mov %r12,%rdi 1708: 89 45 d4 mov %eax,-0x2c(%rbp) 170b: e8 00 00 00 00 callq 1710 1710: 85 c0 test %eax,%eax 1712: 0f 85 7e 01 00 00 jne 1896 nla_put_u8(skb, IFLA_VXLAN_L3MISS, !!(vxlan->flags & VXLAN_F_L3MISS)) || 1718: 8b 83 98 09 00 00 mov 0x998(%rbx),%eax 171e: 48 8d 4d d8 lea -0x28(%rbp),%rcx 1722: ba 04 00 00 00 mov $0x4,%edx * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) { return nla_put(skb, attrtype, sizeof(u32), &value); 1727: be 09 00 00 00 mov $0x9,%esi 172c: 4c 89 e7 mov %r12,%rdi 172f: 89 45 d8 mov %eax,-0x28(%rbp) 1732: e8 00 00 00 00 callq 1737 1737: 85 c0 test %eax,%eax 1739: 0f 85 57 01 00 00 jne 1896 173f: 0f b7 83 7c 09 00 00 movzwl 0x97c(%rbx),%eax nla_put_u8(skb, IFLA_VXLAN_COLLECT_METADATA, !!(vxlan->flags & VXLAN_F_COLLECT_METADATA)) || 1746: 48 8d 4d be lea -0x42(%rbp),%rcx 174a: ba 02 00 00 00 mov $0x2,%edx 174f: be 0f 00 00 00 mov $0xf,%esi 1754: 4c 89 e7 mov %r12,%rdi 1757: 66 89 45 be mov %ax,-0x42(%rbp) 175b: e8 00 00 00 00 callq 1760 1760: 85 c0 test %eax,%eax 1762: 0f 85 2e 01 00 00 jne 1896 nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->cfg.age_interval) || 1768: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 176e: 48 8d 4d b9 lea -0x47(%rbp),%rcx 1772: ba 01 00 00 00 mov $0x1,%edx * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) { return nla_put(skb, attrtype, sizeof(__be16), &value); 1777: be 12 00 00 00 mov $0x12,%esi 177c: 4c 89 e7 mov %r12,%rdi 177f: c1 e8 06 shr $0x6,%eax 1782: 83 f0 01 xor $0x1,%eax 1785: 83 e0 01 and $0x1,%eax 1788: 88 45 b9 mov %al,-0x47(%rbp) 178b: e8 00 00 00 00 callq 1790 nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->cfg.addrmax) || 1790: 85 c0 test %eax,%eax 1792: 0f 85 fe 00 00 00 jne 1896 1798: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value) { return nla_put(skb, attrtype, sizeof(u8), &value); 179e: 48 8d 4d ba lea -0x46(%rbp),%rcx 17a2: ba 01 00 00 00 mov $0x1,%edx 17a7: be 13 00 00 00 mov $0x13,%esi 17ac: 4c 89 e7 mov %r12,%rdi 17af: c1 e8 07 shr $0x7,%eax 17b2: 83 e0 01 and $0x1,%eax 17b5: 88 45 ba mov %al,-0x46(%rbp) 17b8: e8 00 00 00 00 callq 17bd 17bd: 85 c0 test %eax,%eax 17bf: 0f 85 d1 00 00 00 jne 1896 nla_put_be16(skb, IFLA_VXLAN_PORT, vxlan->cfg.dst_port) || 17c5: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 17cb: 48 8d 4d bb lea -0x45(%rbp),%rcx 17cf: ba 01 00 00 00 mov $0x1,%edx 17d4: be 14 00 00 00 mov $0x14,%esi 17d9: 4c 89 e7 mov %r12,%rdi 17dc: c1 e8 08 shr $0x8,%eax 17df: 83 e0 01 and $0x1,%eax 17e2: 88 45 bb mov %al,-0x45(%rbp) 17e5: e8 00 00 00 00 callq 17ea 17ea: 85 c0 test %eax,%eax 17ec: 0f 85 a4 00 00 00 jne 1896 nla_put_u8(skb, IFLA_VXLAN_UDP_CSUM, !(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM_TX)) || 17f2: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 17f8: 48 8d 4d bc lea -0x44(%rbp),%rcx 17fc: ba 01 00 00 00 mov $0x1,%edx 1801: be 15 00 00 00 mov $0x15,%esi 1806: 4c 89 e7 mov %r12,%rdi 1809: c1 e8 09 shr $0x9,%eax 180c: 83 e0 01 and $0x1,%eax 180f: 88 45 bc mov %al,-0x44(%rbp) 1812: e8 00 00 00 00 callq 1817 1817: 85 c0 test %eax,%eax 1819: 75 7b jne 1896 nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !!(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) || 181b: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 1821: 48 8d 4d bd lea -0x43(%rbp),%rcx 1825: ba 01 00 00 00 mov $0x1,%edx 182a: be 16 00 00 00 mov $0x16,%esi 182f: 4c 89 e7 mov %r12,%rdi 1832: c1 e8 0a shr $0xa,%eax 1835: 83 e0 01 and $0x1,%eax 1838: 88 45 bd mov %al,-0x43(%rbp) 183b: e8 00 00 00 00 callq 1840 1840: 85 c0 test %eax,%eax 1842: 75 52 jne 1896 1844: 48 8d 4d dc lea -0x24(%rbp),%rcx nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !!(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) || 1848: ba 04 00 00 00 mov $0x4,%edx 184d: be 0a 00 00 00 mov $0xa,%esi 1852: 4c 89 e7 mov %r12,%rdi 1855: e8 00 00 00 00 callq 185a 185a: 85 c0 test %eax,%eax 185c: 41 89 c5 mov %eax,%r13d 185f: 75 35 jne 1896 1861: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 1867: f6 c4 08 test $0x8,%ah 186a: 0f 85 2e 01 00 00 jne 199e nla_put_u8(skb, IFLA_VXLAN_REMCSUM_TX, !!(vxlan->flags & VXLAN_F_REMCSUM_TX)) || 1870: f6 c4 40 test $0x40,%ah 1873: 0f 85 49 01 00 00 jne 19c2 nla_put_u8(skb, IFLA_VXLAN_REMCSUM_RX, !!(vxlan->flags & VXLAN_F_REMCSUM_RX))) goto nla_put_failure; if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) 1879: f6 c4 10 test $0x10,%ah 187c: 74 1e je 189c 187e: 31 c9 xor %ecx,%ecx 1880: 31 d2 xor %edx,%edx 1882: be 18 00 00 00 mov $0x18,%esi 1887: 4c 89 e7 mov %r12,%rdi 188a: e8 00 00 00 00 callq 188f 188f: 85 c0 test %eax,%eax goto nla_put_failure; if (vxlan->flags & VXLAN_F_GBP && 1891: 41 89 c5 mov %eax,%r13d 1894: 74 06 je 189c 1896: 41 bd a6 ff ff ff mov $0xffffffa6,%r13d 189c: 48 8b 75 e0 mov -0x20(%rbp),%rsi nla_put_flag(skb, IFLA_VXLAN_GBP)) goto nla_put_failure; if (vxlan->flags & VXLAN_F_GPE && 18a0: 65 48 33 34 25 28 00 xor %gs:0x28,%rsi 18a7: 00 00 nla_put_flag(skb, IFLA_VXLAN_GPE)) goto nla_put_failure; if (vxlan->flags & VXLAN_F_REMCSUM_NOPARTIAL && 18a9: 44 89 e8 mov %r13d,%eax 18ac: 0f 85 34 01 00 00 jne 19e6 * @skb: socket buffer to add attribute to * @attrtype: attribute type */ static inline int nla_put_flag(struct sk_buff *skb, int attrtype) { return nla_put(skb, attrtype, 0, NULL); 18b2: 48 83 c4 38 add $0x38,%rsp 18b6: 5b pop %rbx 18b7: 41 5c pop %r12 18b9: 41 5d pop %r13 18bb: 5d pop %rbp 18bc: c3 retq 18bd: 66 83 f8 02 cmp $0x2,%ax 18c1: 0f 84 b1 00 00 00 je 1978 goto nla_put_failure; return 0; nla_put_failure: return -EMSGSIZE; 18c7: 48 8d 8b 88 08 00 00 lea 0x888(%rbx),%rcx } 18ce: ba 10 00 00 00 mov $0x10,%edx 18d3: be 10 00 00 00 mov $0x10,%esi 18d8: 4c 89 e7 mov %r12,%rdi 18db: e8 00 00 00 00 callq 18e0 18e0: 85 c0 test %eax,%eax 18e2: 75 b2 jne 1896 18e4: 8b 83 a4 08 00 00 mov 0x8a4(%rbx),%eax 18ea: 85 c0 test %eax,%eax 18ec: 0f 84 36 fc ff ff je 1528 if (nla_put_u32(skb, IFLA_VXLAN_ID, be32_to_cpu(dst->remote_vni))) goto nla_put_failure; if (!vxlan_addr_any(&dst->remote_ip)) { if (dst->remote_ip.sa.sa_family == AF_INET) { 18f2: 48 8d 4d c8 lea -0x38(%rbp),%rcx 18f6: ba 04 00 00 00 mov $0x4,%edx if (nla_put_in_addr(skb, IFLA_VXLAN_GROUP, dst->remote_ip.sin.sin_addr.s_addr)) goto nla_put_failure; #if IS_ENABLED(CONFIG_IPV6) } else { if (nla_put_in6_addr(skb, IFLA_VXLAN_GROUP6, 18fb: be 03 00 00 00 mov $0x3,%esi * @addr: IPv6 address */ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype, const struct in6_addr *addr) { return nla_put(skb, attrtype, sizeof(*addr), addr); 1900: 4c 89 e7 mov %r12,%rdi 1903: 89 45 c8 mov %eax,-0x38(%rbp) 1906: e8 00 00 00 00 callq 190b 190b: 85 c0 test %eax,%eax 190d: 75 87 jne 1896 190f: 0f b7 83 54 09 00 00 movzwl 0x954(%rbx),%eax goto nla_put_failure; #endif } } if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex)) 1916: 66 83 f8 0a cmp $0xa,%ax 191a: 0f 85 19 fc ff ff jne 1539 1920: 48 8b 83 5c 09 00 00 mov 0x95c(%rbx),%rax * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) { return nla_put(skb, attrtype, sizeof(u32), &value); 1927: 48 0b 83 64 09 00 00 or 0x964(%rbx),%rax 192e: 0f 85 19 fc ff ff jne 154d 1934: e9 35 fc ff ff jmpq 156e 1939: 48 8b 83 88 08 00 00 mov 0x888(%rbx),%rax return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 1940: 48 0b 83 90 08 00 00 or 0x890(%rbx),%rax 1947: 0f 85 7a ff ff ff jne 18c7 194d: e9 c8 fb ff ff jmpq 151a } if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex)) goto nla_put_failure; if (!vxlan_addr_any(&vxlan->cfg.saddr)) { 1952: 48 8d 4d cc lea -0x34(%rbp),%rcx 1956: 89 55 cc mov %edx,-0x34(%rbp) 1959: be 04 00 00 00 mov $0x4,%esi 195e: ba 04 00 00 00 mov $0x4,%edx 1963: 4c 89 e7 mov %r12,%rdi 1966: e8 00 00 00 00 callq 196b }; if (nla_put_u32(skb, IFLA_VXLAN_ID, be32_to_cpu(dst->remote_vni))) goto nla_put_failure; if (!vxlan_addr_any(&dst->remote_ip)) { 196b: 85 c0 test %eax,%eax 196d: 0f 84 fb fb ff ff je 156e 1973: e9 1e ff ff ff jmpq 1896 1978: 48 8d 4d c4 lea -0x3c(%rbp),%rcx 197c: 89 55 c4 mov %edx,-0x3c(%rbp) 197f: be 02 00 00 00 mov $0x2,%esi * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) { return nla_put(skb, attrtype, sizeof(__be32), &value); 1984: ba 04 00 00 00 mov $0x4,%edx 1989: 4c 89 e7 mov %r12,%rdi 198c: e8 00 00 00 00 callq 1991 1991: 85 c0 test %eax,%eax 1993: 0f 84 81 fb ff ff je 151a 1999: e9 f8 fe ff ff jmpq 1896 if (dst->remote_ifindex && nla_put_u32(skb, IFLA_VXLAN_LINK, dst->remote_ifindex)) goto nla_put_failure; if (!vxlan_addr_any(&vxlan->cfg.saddr)) { if (vxlan->cfg.saddr.sa.sa_family == AF_INET) { if (nla_put_in_addr(skb, IFLA_VXLAN_LOCAL, 199e: 31 c9 xor %ecx,%ecx 19a0: 31 d2 xor %edx,%edx 19a2: be 17 00 00 00 mov $0x17,%esi 19a7: 4c 89 e7 mov %r12,%rdi 19aa: e8 00 00 00 00 callq 19af 19af: 85 c0 test %eax,%eax 19b1: 0f 85 df fe ff ff jne 1896 19b7: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax 19bd: e9 ae fe ff ff jmpq 1870 if (nla_put_u32(skb, IFLA_VXLAN_ID, be32_to_cpu(dst->remote_vni))) goto nla_put_failure; if (!vxlan_addr_any(&dst->remote_ip)) { if (dst->remote_ip.sa.sa_family == AF_INET) { if (nla_put_in_addr(skb, IFLA_VXLAN_GROUP, 19c2: 31 c9 xor %ecx,%ecx 19c4: 31 d2 xor %edx,%edx 19c6: be 1b 00 00 00 mov $0x1b,%esi 19cb: 4c 89 e7 mov %r12,%rdi * @skb: socket buffer to add attribute to * @attrtype: attribute type */ static inline int nla_put_flag(struct sk_buff *skb, int attrtype) { return nla_put(skb, attrtype, 0, NULL); 19ce: e8 00 00 00 00 callq 19d3 19d3: 85 c0 test %eax,%eax 19d5: 0f 85 bb fe ff ff jne 1896 19db: 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%eax goto nla_put_failure; if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) goto nla_put_failure; if (vxlan->flags & VXLAN_F_GBP && 19e1: e9 93 fe ff ff jmpq 1879 19e6: e8 00 00 00 00 callq 19eb 19eb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 00000000000019f0 : 19f0: e8 00 00 00 00 callq 19f5 19f5: 55 push %rbp 19f6: 48 89 e5 mov %rsp,%rbp 19f9: 41 57 push %r15 19fb: 41 56 push %r14 19fd: 41 55 push %r13 19ff: 41 54 push %r12 1a01: 53 push %rbx 1a02: 48 83 ec 40 sub $0x40,%rsp nla_put_flag(skb, IFLA_VXLAN_GBP)) goto nla_put_failure; if (vxlan->flags & VXLAN_F_GPE && 1a06: 44 8b 97 84 00 00 00 mov 0x84(%rdi),%r10d 1a0d: 4c 8b 75 18 mov 0x18(%rbp),%r14 1a11: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 1a18: 00 00 return 0; nla_put_failure: return -EMSGSIZE; } 1a1a: 48 89 45 d0 mov %rax,-0x30(%rbp) 1a1e: 31 c0 xor %eax,%eax /* Fill in neighbour message in skbuff. */ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, const struct vxlan_fdb *fdb, u32 portid, u32 seq, int type, unsigned int flags, const struct vxlan_rdst *rdst) { 1a20: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 1a27 1a27: 45 85 d2 test %r10d,%r10d 1a2a: 48 89 45 a0 mov %rax,-0x60(%rbp) 1a2e: 0f 85 34 02 00 00 jne 1c68 1a34: 8b 87 cc 00 00 00 mov 0xcc(%rdi),%eax * * Return the number of bytes of free space at the tail of an sk_buff */ static inline int skb_tailroom(const struct sk_buff *skb) { return skb_is_nonlinear(skb) ? 0 : skb->end - skb->tail; 1a3a: 2b 87 c8 00 00 00 sub 0xc8(%rdi),%eax 1a40: 49 89 fc mov %rdi,%r12 1a43: 83 f8 1b cmp $0x1b,%eax 1a46: 0f 8e 1c 02 00 00 jle 1c68 1a4c: 45 89 cb mov %r9d,%r11d 1a4f: 44 8b 4d 10 mov 0x10(%rbp),%r9d unsigned long now = jiffies; 1a53: 49 89 f7 mov %rsi,%r15 1a56: 49 89 d5 mov %rdx,%r13 1a59: 89 ce mov %ecx,%esi 1a5b: 44 89 c2 mov %r8d,%edx 1a5e: 44 89 d9 mov %r11d,%ecx 1a61: 41 b8 0c 00 00 00 mov $0xc,%r8d * the message header and payload. */ static inline struct nlmsghdr *nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int payload, int flags) { if (unlikely(skb_tailroom(skb) < nlmsg_total_size(payload))) 1a67: 44 89 5d 9c mov %r11d,-0x64(%rbp) 1a6b: e8 00 00 00 00 callq 1a70 1a70: 48 85 c0 test %rax,%rax 1a73: 48 89 c3 mov %rax,%rbx 1a76: 0f 84 ec 01 00 00 je 1c68 1a7c: 44 8b 5d 9c mov -0x64(%rbp),%r11d return NULL; return __nlmsg_put(skb, portid, seq, type, payload, flags); 1a80: 48 c7 40 10 00 00 00 movq $0x0,0x10(%rax) 1a87: 00 1a88: c7 40 18 00 00 00 00 movl $0x0,0x18(%rax) 1a8f: 41 83 fb 1e cmp $0x1e,%r11d 1a93: 0f 84 22 02 00 00 je 1cbb 1a99: c6 40 10 07 movb $0x7,0x10(%rax) 1a9d: 41 b9 01 00 00 00 mov $0x1,%r9d 1aa3: 41 b8 01 00 00 00 mov $0x1,%r8d struct nlmsghdr *nlh; struct ndmsg *ndm; bool send_ip, send_eth; nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); if (nlh == NULL) 1aa9: 41 0f b7 45 46 movzwl 0x46(%r13),%eax ndm = nlmsg_data(nlh); memset(ndm, 0, sizeof(*ndm)); send_eth = send_ip = true; if (type == RTM_GETNEIGH) { 1aae: 66 89 43 18 mov %ax,0x18(%rbx) nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); if (nlh == NULL) return -EMSGSIZE; ndm = nlmsg_data(nlh); memset(ndm, 0, sizeof(*ndm)); 1ab2: 49 8b 47 30 mov 0x30(%r15),%rax 1ab6: 8b 80 28 01 00 00 mov 0x128(%rax),%eax 1abc: 89 43 14 mov %eax,0x14(%rbx) send_eth = send_ip = true; if (type == RTM_GETNEIGH) { 1abf: 41 0f b6 45 48 movzbl 0x48(%r13),%eax 1ac4: c6 43 1b 01 movb $0x1,0x1b(%rbx) 1ac8: 88 43 1a mov %al,0x1a(%rbx) ndm->ndm_family = AF_INET; send_ip = !vxlan_addr_any(&rdst->remote_ip); send_eth = !is_zero_ether_addr(fdb->eth_addr); } else ndm->ndm_family = AF_BRIDGE; 1acb: 49 8b 47 30 mov 0x30(%r15),%rax return -EMSGSIZE; ndm = nlmsg_data(nlh); memset(ndm, 0, sizeof(*ndm)); send_eth = send_ip = true; 1acf: 49 8b 77 38 mov 0x38(%r15),%rsi 1ad3: 48 8b b8 80 04 00 00 mov 0x480(%rax),%rdi ndm->ndm_family = AF_INET; send_ip = !vxlan_addr_any(&rdst->remote_ip); send_eth = !is_zero_ether_addr(fdb->eth_addr); } else ndm->ndm_family = AF_BRIDGE; ndm->ndm_state = fdb->state; 1ada: 48 39 fe cmp %rdi,%rsi 1add: 74 38 je 1b17 1adf: 44 88 4d 9b mov %r9b,-0x65(%rbp) ndm->ndm_ifindex = vxlan->dev->ifindex; 1ae3: 44 88 45 9c mov %r8b,-0x64(%rbp) 1ae7: e8 00 00 00 00 callq 1aec 1aec: 48 8d 4d b0 lea -0x50(%rbp),%rcx ndm->ndm_flags = fdb->flags; 1af0: ba 04 00 00 00 mov $0x4,%edx ndm->ndm_type = RTN_UNICAST; 1af5: be 0a 00 00 00 mov $0xa,%esi send_eth = !is_zero_ether_addr(fdb->eth_addr); } else ndm->ndm_family = AF_BRIDGE; ndm->ndm_state = fdb->state; ndm->ndm_ifindex = vxlan->dev->ifindex; ndm->ndm_flags = fdb->flags; 1afa: 4c 89 e7 mov %r12,%rdi 1afd: 89 45 b0 mov %eax,-0x50(%rbp) ndm->ndm_type = RTN_UNICAST; if (!net_eq(dev_net(vxlan->dev), vxlan->net) && 1b00: e8 00 00 00 00 callq 1b05 1b05: 85 c0 test %eax,%eax 1b07: 44 0f b6 45 9c movzbl -0x64(%rbp),%r8d 1b0c: 44 0f b6 4d 9b movzbl -0x65(%rbp),%r9d 1b11: 0f 85 32 01 00 00 jne 1c49 nla_put_s32(skb, NDA_LINK_NETNSID, 1b17: 45 84 c9 test %r9b,%r9b 1b1a: 0f 85 72 01 00 00 jne 1c92 * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value) { return nla_put(skb, attrtype, sizeof(s32), &value); 1b20: 45 84 c0 test %r8b,%r8b 1b23: 0f 85 f0 00 00 00 jne 1c19 1b29: 41 0f b7 46 1c movzwl 0x1c(%r14),%eax 1b2e: 66 85 c0 test %ax,%ax 1b31: 74 2c je 1b5f 1b33: 66 41 3b 87 3c 01 00 cmp 0x13c(%r15),%ax 1b3a: 00 ndm->ndm_state = fdb->state; ndm->ndm_ifindex = vxlan->dev->ifindex; ndm->ndm_flags = fdb->flags; ndm->ndm_type = RTN_UNICAST; if (!net_eq(dev_net(vxlan->dev), vxlan->net) && 1b3b: 74 22 je 1b5f 1b3d: 48 8d 4d ae lea -0x52(%rbp),%rcx 1b41: ba 02 00 00 00 mov $0x2,%edx 1b46: be 06 00 00 00 mov $0x6,%esi nla_put_s32(skb, NDA_LINK_NETNSID, peernet2id_alloc(dev_net(vxlan->dev), vxlan->net))) goto nla_put_failure; if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr)) 1b4b: 4c 89 e7 mov %r12,%rdi 1b4e: 66 89 45 ae mov %ax,-0x52(%rbp) goto nla_put_failure; if (send_ip && vxlan_nla_put_addr(skb, NDA_DST, &rdst->remote_ip)) 1b52: e8 00 00 00 00 callq 1b57 1b57: 85 c0 test %eax,%eax goto nla_put_failure; if (rdst->remote_port && rdst->remote_port != vxlan->cfg.dst_port && 1b59: 0f 85 ea 00 00 00 jne 1c49 1b5f: 41 8b 46 20 mov 0x20(%r14),%eax 1b63: 41 3b 47 60 cmp 0x60(%r15),%eax 1b67: 74 23 je 1b8c 1b69: 48 8d 4d b4 lea -0x4c(%rbp),%rcx * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) { return nla_put(skb, attrtype, sizeof(__be16), &value); 1b6d: 0f c8 bswap %eax 1b6f: ba 04 00 00 00 mov $0x4,%edx 1b74: be 07 00 00 00 mov $0x7,%esi 1b79: 4c 89 e7 mov %r12,%rdi 1b7c: 89 45 b4 mov %eax,-0x4c(%rbp) 1b7f: e8 00 00 00 00 callq 1b84 1b84: 85 c0 test %eax,%eax 1b86: 0f 85 bd 00 00 00 jne 1c49 1b8c: 41 8b 46 24 mov 0x24(%r14),%eax nla_put_be16(skb, NDA_PORT, rdst->remote_port)) goto nla_put_failure; if (rdst->remote_vni != vxlan->default_dst.remote_vni && 1b90: 85 c0 test %eax,%eax 1b92: 0f 85 d7 00 00 00 jne 1c6f 1b98: 4c 8b 75 a0 mov -0x60(%rbp),%r14 * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) { return nla_put(skb, attrtype, sizeof(u32), &value); 1b9c: 4c 89 f7 mov %r14,%rdi 1b9f: 49 2b 7d 28 sub 0x28(%r13),%rdi 1ba3: e8 00 00 00 00 callq 1ba8 1ba8: 4c 89 f7 mov %r14,%rdi 1bab: 49 2b 7d 20 sub 0x20(%r13),%rdi 1baf: 89 45 c4 mov %eax,-0x3c(%rbp) 1bb2: c7 45 c0 00 00 00 00 movl $0x0,-0x40(%rbp) 1bb9: e8 00 00 00 00 callq 1bbe nla_put_u32(skb, NDA_VNI, be32_to_cpu(rdst->remote_vni))) goto nla_put_failure; if (rdst->remote_ifindex && 1bbe: 48 8d 4d c0 lea -0x40(%rbp),%rcx 1bc2: ba 10 00 00 00 mov $0x10,%edx 1bc7: be 03 00 00 00 mov $0x3,%esi nla_put_u32(skb, NDA_IFINDEX, rdst->remote_ifindex)) goto nla_put_failure; ci.ndm_used = jiffies_to_clock_t(now - fdb->used); 1bcc: 4c 89 e7 mov %r12,%rdi 1bcf: 89 45 c8 mov %eax,-0x38(%rbp) 1bd2: c7 45 cc 00 00 00 00 movl $0x0,-0x34(%rbp) ci.ndm_confirmed = 0; ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); 1bd9: e8 00 00 00 00 callq 1bde 1bde: 85 c0 test %eax,%eax goto nla_put_failure; if (rdst->remote_ifindex && nla_put_u32(skb, NDA_IFINDEX, rdst->remote_ifindex)) goto nla_put_failure; ci.ndm_used = jiffies_to_clock_t(now - fdb->used); 1be0: 75 67 jne 1c49 ci.ndm_confirmed = 0; 1be2: 41 8b 94 24 c8 00 00 mov 0xc8(%r12),%edx 1be9: 00 ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); 1bea: 49 03 94 24 d0 00 00 add 0xd0(%r12),%rdx 1bf1: 00 ci.ndm_refcnt = 0; if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) 1bf2: 48 29 da sub %rbx,%rdx 1bf5: 89 13 mov %edx,(%rbx) 1bf7: 48 8b 4d d0 mov -0x30(%rbp),%rcx 1bfb: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx 1c02: 00 00 goto nla_put_failure; ci.ndm_used = jiffies_to_clock_t(now - fdb->used); ci.ndm_confirmed = 0; ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); ci.ndm_refcnt = 0; 1c04: 0f 85 23 01 00 00 jne 1d2d if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) 1c0a: 48 83 c4 40 add $0x40,%rsp 1c0e: 5b pop %rbx 1c0f: 41 5c pop %r12 1c11: 41 5d pop %r13 * attributes. Only necessary if attributes have been added to * the message. */ static inline void nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh) { nlh->nlmsg_len = skb_tail_pointer(skb) - (unsigned char *)nlh; 1c13: 41 5e pop %r14 1c15: 41 5f pop %r15 1c17: 5d pop %rbp 1c18: c3 retq 1c19: 66 41 83 3e 0a cmpw $0xa,(%r14) 1c1e: 0f 84 d0 00 00 00 je 1cf4 1c24: 41 8b 46 04 mov 0x4(%r14),%eax return 0; nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } 1c28: 48 8d 4d bc lea -0x44(%rbp),%rcx 1c2c: ba 04 00 00 00 mov $0x4,%edx 1c31: be 01 00 00 00 mov $0x1,%esi 1c36: 4c 89 e7 mov %r12,%rdi 1c39: 89 45 bc mov %eax,-0x44(%rbp) 1c3c: e8 00 00 00 00 callq 1c41 1c41: 85 c0 test %eax,%eax 1c43: 0f 84 e0 fe ff ff je 1b29 } static int vxlan_nla_put_addr(struct sk_buff *skb, int attr, const union vxlan_addr *ip) { if (ip->sa.sa_family == AF_INET6) 1c49: 49 8b 84 24 d8 00 00 mov 0xd8(%r12),%rax 1c50: 00 1c51: 48 39 d8 cmp %rbx,%rax 1c54: 0f 87 b5 00 00 00 ja 1d0f * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) { return nla_put(skb, attrtype, sizeof(__be32), &value); 1c5a: 48 29 c3 sub %rax,%rbx 1c5d: 4c 89 e7 mov %r12,%rdi 1c60: 48 89 de mov %rbx,%rsi 1c63: e8 00 00 00 00 callq 1c68 1c68: b8 a6 ff ff ff mov $0xffffffa6,%eax 1c6d: eb 88 jmp 1bf7 1c6f: 48 8d 4d b8 lea -0x48(%rbp),%rcx goto nla_put_failure; if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr)) goto nla_put_failure; if (send_ip && vxlan_nla_put_addr(skb, NDA_DST, &rdst->remote_ip)) 1c73: ba 04 00 00 00 mov $0x4,%edx 1c78: be 08 00 00 00 mov $0x8,%esi * Trims the message to the provided mark. */ static inline void nlmsg_trim(struct sk_buff *skb, const void *mark) { if (mark) { WARN_ON((unsigned char *) mark < skb->data); 1c7d: 4c 89 e7 mov %r12,%rdi 1c80: 89 45 b8 mov %eax,-0x48(%rbp) 1c83: e8 00 00 00 00 callq 1c88 1c88: 85 c0 test %eax,%eax skb_trim(skb, (unsigned char *) mark - skb->data); 1c8a: 0f 84 08 ff ff ff je 1b98 1c90: eb b7 jmp 1c49 1c92: 49 8d 4d 40 lea 0x40(%r13),%rcx 1c96: ba 06 00 00 00 mov $0x6,%edx nlmsg_end(skb, nlh); return 0; nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; 1c9b: be 02 00 00 00 mov $0x2,%esi * @attrtype: attribute type * @value: numeric value */ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) { return nla_put(skb, attrtype, sizeof(u32), &value); 1ca0: 4c 89 e7 mov %r12,%rdi 1ca3: 44 88 45 9c mov %r8b,-0x64(%rbp) 1ca7: e8 00 00 00 00 callq 1cac 1cac: 85 c0 test %eax,%eax 1cae: 44 0f b6 45 9c movzbl -0x64(%rbp),%r8d 1cb3: 0f 84 67 fe ff ff je 1b20 nla_put_be16(skb, NDA_PORT, rdst->remote_port)) goto nla_put_failure; if (rdst->remote_vni != vxlan->default_dst.remote_vni && nla_put_u32(skb, NDA_VNI, be32_to_cpu(rdst->remote_vni))) goto nla_put_failure; if (rdst->remote_ifindex && 1cb9: eb 8e jmp 1c49 1cbb: c6 40 10 02 movb $0x2,0x10(%rax) 1cbf: 66 41 83 3e 0a cmpw $0xa,(%r14) if (!net_eq(dev_net(vxlan->dev), vxlan->net) && nla_put_s32(skb, NDA_LINK_NETNSID, peernet2id_alloc(dev_net(vxlan->dev), vxlan->net))) goto nla_put_failure; if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr)) 1cc4: 74 20 je 1ce6 1cc6: 41 8b 46 04 mov 0x4(%r14),%eax 1cca: 85 c0 test %eax,%eax 1ccc: 41 0f 94 c0 sete %r8b 1cd0: 41 0f b7 45 44 movzwl 0x44(%r13),%eax 1cd5: 41 83 f0 01 xor $0x1,%r8d 1cd9: 41 0b 45 40 or 0x40(%r13),%eax 1cdd: 41 0f 95 c1 setne %r9b 1ce1: e9 c3 fd ff ff jmpq 1aa9 1ce6: 49 8b 46 08 mov 0x8(%r14),%rax 1cea: 49 0b 46 10 or 0x10(%r14),%rax memset(ndm, 0, sizeof(*ndm)); send_eth = send_ip = true; if (type == RTM_GETNEIGH) { ndm->ndm_family = AF_INET; 1cee: 41 0f 94 c0 sete %r8b return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 1cf2: eb dc jmp 1cd0 1cf4: 49 8d 4e 08 lea 0x8(%r14),%rcx return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); 1cf8: ba 10 00 00 00 mov $0x10,%edx 1cfd: be 01 00 00 00 mov $0x1,%esi send_eth = send_ip = true; if (type == RTM_GETNEIGH) { ndm->ndm_family = AF_INET; send_ip = !vxlan_addr_any(&rdst->remote_ip); send_eth = !is_zero_ether_addr(fdb->eth_addr); 1d02: 4c 89 e7 mov %r12,%rdi send_eth = send_ip = true; if (type == RTM_GETNEIGH) { ndm->ndm_family = AF_INET; send_ip = !vxlan_addr_any(&rdst->remote_ip); 1d05: e8 00 00 00 00 callq 1d0a send_eth = !is_zero_ether_addr(fdb->eth_addr); 1d0a: e9 32 ff ff ff jmpq 1c41 1d0f: be 16 02 00 00 mov $0x216,%esi 1d14: 48 c7 c7 00 00 00 00 mov $0x0,%rdi static inline bool ipv6_addr_any(const struct in6_addr *a) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 const unsigned long *ul = (const unsigned long *)a; return (ul[0] | ul[1]) == 0UL; 1d1b: e8 00 00 00 00 callq 1d20 1d20: 49 8b 84 24 d8 00 00 mov 0xd8(%r12),%rax 1d27: 00 * @addr: IPv6 address */ static inline int nla_put_in6_addr(struct sk_buff *skb, int attrtype, const struct in6_addr *addr) { return nla_put(skb, attrtype, sizeof(*addr), addr); 1d28: e9 2d ff ff ff jmpq 1c5a 1d2d: e8 00 00 00 00 callq 1d32 1d32: 0f 1f 40 00 nopl 0x0(%rax) 1d36: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 1d3d: 00 00 00 0000000000001d40 : * Trims the message to the provided mark. */ static inline void nlmsg_trim(struct sk_buff *skb, const void *mark) { if (mark) { WARN_ON((unsigned char *) mark < skb->data); 1d40: e8 00 00 00 00 callq 1d45 1d45: 55 push %rbp 1d46: 48 89 e5 mov %rsp,%rbp 1d49: 41 57 push %r15 1d4b: 41 56 push %r14 1d4d: 41 55 push %r13 1d4f: 41 54 push %r12 1d51: 49 89 f6 mov %rsi,%r14 1d54: 53 push %rbx 1d55: 49 89 fc mov %rdi,%r12 1d58: 49 89 d7 mov %rdx,%r15 1d5b: be 20 00 08 02 mov $0x2080020,%esi return 0; nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } 1d60: 31 d2 xor %edx,%edx 1d62: 48 83 ec 18 sub $0x18,%rsp 1d66: 48 8b 47 30 mov 0x30(%rdi),%rax 1d6a: 89 4d d4 mov %ecx,-0x2c(%rbp) 1d6d: bf 70 00 00 00 mov $0x70,%edi + nla_total_size(sizeof(struct nda_cacheinfo)); } static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, struct vxlan_rdst *rd, int type) { 1d72: b9 ff ff ff ff mov $0xffffffff,%ecx 1d77: 4c 8b a8 80 04 00 00 mov 0x480(%rax),%r13 1d7e: e8 00 00 00 00 callq 1d83 1d83: 48 85 c0 test %rax,%rax 1d86: 0f 84 83 00 00 00 je 1e0f struct sk_buff *__build_skb(void *data, unsigned int frag_size); struct sk_buff *build_skb(void *data, unsigned int frag_size); static inline struct sk_buff *alloc_skb(unsigned int size, gfp_t priority) { return __alloc_skb(size, priority, 0, NUMA_NO_NODE); 1d8c: 44 8b 4d d4 mov -0x2c(%rbp),%r9d 1d90: 45 31 c0 xor %r8d,%r8d 1d93: 31 c9 xor %ecx,%ecx 1d95: 4c 89 e6 mov %r12,%rsi 1d98: 4c 89 7c 24 08 mov %r15,0x8(%rsp) 1d9d: c7 04 24 00 00 00 00 movl $0x0,(%rsp) 1da4: 4c 89 f2 mov %r14,%rdx 1da7: 48 89 c7 mov %rax,%rdi 1daa: 48 89 c3 mov %rax,%rbx 1dad: e8 3e fc ff ff callq 19f0 1db2: 85 c0 test %eax,%eax struct net *net = dev_net(vxlan->dev); struct sk_buff *skb; int err = -ENOBUFS; skb = nlmsg_new(vxlan_nlmsg_size(), GFP_ATOMIC); if (skb == NULL) 1db4: 41 89 c4 mov %eax,%r12d 1db7: 79 2c jns 1de5 1db9: 83 f8 a6 cmp $0xffffffa6,%eax goto errout; err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, rd); 1dbc: 74 59 je 1e17 1dbe: 48 89 df mov %rbx,%rdi 1dc1: e8 00 00 00 00 callq 1dc6 1dc6: 44 89 e2 mov %r12d,%edx 1dc9: 4c 89 ef mov %r13,%rdi 1dcc: be 03 00 00 00 mov $0x3,%esi 1dd1: e8 00 00 00 00 callq 1dd6 1dd6: 48 83 c4 18 add $0x18,%rsp 1dda: 5b pop %rbx 1ddb: 41 5c pop %r12 1ddd: 41 5d pop %r13 1ddf: 41 5e pop %r14 1de1: 41 5f pop %r15 if (err < 0) { 1de3: 5d pop %rbp skb = nlmsg_new(vxlan_nlmsg_size(), GFP_ATOMIC); if (skb == NULL) goto errout; err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, rd); 1de4: c3 retq 1de5: 4c 89 ee mov %r13,%rsi if (err < 0) { 1de8: 48 89 df mov %rbx,%rdi /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); 1deb: 41 b9 20 00 08 02 mov $0x2080020,%r9d kfree_skb(skb); 1df1: 45 31 c0 xor %r8d,%r8d 1df4: b9 03 00 00 00 mov $0x3,%ecx rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); return; errout: if (err < 0) rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); 1df9: 31 d2 xor %edx,%edx 1dfb: e8 00 00 00 00 callq 1e00 1e00: 48 83 c4 18 add $0x18,%rsp 1e04: 5b pop %rbx 1e05: 41 5c pop %r12 } 1e07: 41 5d pop %r13 1e09: 41 5e pop %r14 1e0b: 41 5f pop %r15 1e0d: 5d pop %rbp 1e0e: c3 retq 1e0f: 41 bc 97 ff ff ff mov $0xffffff97,%r12d WARN_ON(err == -EMSGSIZE); kfree_skb(skb); goto errout; } rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); 1e15: eb af jmp 1dc6 1e17: be 60 01 00 00 mov $0x160,%esi 1e1c: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 1e23: e8 00 00 00 00 callq 1e28 1e28: eb 94 jmp 1dbe 1e2a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 0000000000001e30 : return; errout: if (err < 0) rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); } 1e30: e8 00 00 00 00 callq 1e35 1e35: 55 push %rbp 1e36: 48 89 e5 mov %rsp,%rbp 1e39: 41 54 push %r12 1e3b: 53 push %rbx 1e3c: 49 89 fc mov %rdi,%r12 static void vxlan_fdb_notify(struct vxlan_dev *vxlan, struct vxlan_fdb *fdb, struct vxlan_rdst *rd, int type) { struct net *net = dev_net(vxlan->dev); struct sk_buff *skb; int err = -ENOBUFS; 1e3f: 48 89 f3 mov %rsi,%rbx 1e42: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) goto errout; err = vxlan_fdb_info(skb, vxlan, fdb, 0, 0, type, 0, rd); if (err < 0) { /* -EMSGSIZE implies BUG in vxlan_nlmsg_size() */ WARN_ON(err == -EMSGSIZE); 1e47: 41 83 ac 24 ec 00 00 subl $0x1,0xec(%r12) 1e4e: 00 01 1e50: b9 1d 00 00 00 mov $0x1d,%ecx 1e55: 48 89 de mov %rbx,%rsi 1e58: 48 8b 43 30 mov 0x30(%rbx),%rax 1e5c: 4c 89 e7 mov %r12,%rdi 1e5f: 48 8d 50 d8 lea -0x28(%rax),%rdx } kfree(f); } static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) { 1e63: e8 d8 fe ff ff callq 1d40 1e68: 48 8b 03 mov (%rbx),%rax 1e6b: 48 8b 53 08 mov 0x8(%rbx),%rdx 1e6f: 48 85 c0 test %rax,%rax 1e72: 48 89 02 mov %rax,(%rdx) 1e75: 74 04 je 1e7b netdev_dbg(vxlan->dev, "delete %pM\n", f->eth_addr); --vxlan->addrcnt; 1e77: 48 89 50 08 mov %rdx,0x8(%rax) 1e7b: 48 b8 00 02 00 00 00 movabs $0xdead000000000200,%rax 1e82: 00 ad de vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_DELNEIGH); 1e85: 48 8d 7b 10 lea 0x10(%rbx),%rdi 1e89: 48 c7 c6 00 00 00 00 mov $0x0,%rsi 1e90: 48 89 43 08 mov %rax,0x8(%rbx) 1e94: e8 00 00 00 00 callq 1e99 return !READ_ONCE(h->first); } static inline void __hlist_del(struct hlist_node *n) { struct hlist_node *next = n->next; 1e99: 5b pop %rbx 1e9a: 41 5c pop %r12 struct hlist_node **pprev = n->pprev; 1e9c: 5d pop %rbp 1e9d: c3 retq 1e9e: 48 8d 4e 40 lea 0x40(%rsi),%rcx 1ea2: 48 8b 77 30 mov 0x30(%rdi),%rsi WRITE_ONCE(*pprev, next); if (next) 1ea6: 48 c7 c2 00 00 00 00 mov $0x0,%rdx * hlist_for_each_entry(). */ static inline void hlist_del_rcu(struct hlist_node *n) { __hlist_del(n); n->pprev = LIST_POISON2; 1ead: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 1eb4: e8 00 00 00 00 callq 1eb9 hlist_del_rcu(&f->hlist); call_rcu(&f->rcu, vxlan_fdb_free); 1eb9: eb 8c jmp 1e47 1ebb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 0000000000001ec0 : 1ec0: e8 00 00 00 00 callq 1ec5 1ec5: 55 push %rbp 1ec6: 48 89 e5 mov %rsp,%rbp } 1ec9: 41 57 push %r15 1ecb: 41 56 push %r14 1ecd: 41 55 push %r13 kfree(f); } static void vxlan_fdb_destroy(struct vxlan_dev *vxlan, struct vxlan_fdb *f) { netdev_dbg(vxlan->dev, 1ecf: 41 54 push %r12 1ed1: 53 push %rbx 1ed2: 48 83 ec 10 sub $0x10,%rsp 1ed6: 48 8b 47 30 mov 0x30(%rdi),%rax 1eda: 4c 8b 25 00 00 00 00 mov 0x0(%rip),%r12 # 1ee1 1ee1: 48 8b 40 48 mov 0x48(%rax),%rax 1ee5: a8 01 test $0x1,%al 1ee7: 0f 84 b3 00 00 00 je 1fa0 1eed: 48 8d 87 e8 00 00 00 lea 0xe8(%rdi),%rax return NETDEV_TX_OK; } /* Walk the forwarding table and purge stale entries */ static void vxlan_cleanup(unsigned long arg) { 1ef4: 4c 8d af 60 01 00 00 lea 0x160(%rdi),%r13 1efb: 48 89 fb mov %rdi,%rbx 1efe: 49 81 c4 c4 09 00 00 add $0x9c4,%r12 1f05: 48 89 45 d0 mov %rax,-0x30(%rbp) struct vxlan_dev *vxlan = (struct vxlan_dev *) arg; unsigned long next_timer = jiffies + FDB_AGE_INTERVAL; unsigned int h; if (!netif_running(vxlan->dev)) 1f09: 48 8d 87 60 09 00 00 lea 0x960(%rdi),%rax /* Walk the forwarding table and purge stale entries */ static void vxlan_cleanup(unsigned long arg) { struct vxlan_dev *vxlan = (struct vxlan_dev *) arg; unsigned long next_timer = jiffies + FDB_AGE_INTERVAL; 1f10: 48 89 45 c8 mov %rax,-0x38(%rbp) 1f14: 48 8b 7d d0 mov -0x30(%rbp),%rdi unsigned int h; if (!netif_running(vxlan->dev)) 1f18: e8 00 00 00 00 callq 1f1d 1f1d: 4d 8b 7d 00 mov 0x0(%r13),%r15 1f21: 4d 85 ff test %r15,%r15 1f24: 75 24 jne 1f4a 1f26: eb 56 jmp 1f7e 1f28: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 1f2d: b8 04 00 00 00 mov $0x4,%eax /* Walk the forwarding table and purge stale entries */ static void vxlan_cleanup(unsigned long arg) { struct vxlan_dev *vxlan = (struct vxlan_dev *) arg; unsigned long next_timer = jiffies + FDB_AGE_INTERVAL; 1f32: 4c 89 fe mov %r15,%rsi 1f35: 48 89 df mov %rbx,%rdi 1f38: 66 41 89 47 46 mov %ax,0x46(%r15) 1f3d: e8 ee fe ff ff callq 1e30 1f42: 4d 85 f6 test %r14,%r14 } static __always_inline void spin_lock_bh(spinlock_t *lock) { raw_spin_lock_bh(&lock->rlock); 1f45: 4d 89 f7 mov %r14,%r15 1f48: 74 34 je 1f7e 1f4a: 41 f6 47 46 80 testb $0x80,0x46(%r15) for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n; spin_lock_bh(&vxlan->hash_lock); hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { 1f4f: 4d 8b 37 mov (%r15),%r14 1f52: 75 ee jne 1f42 1f54: 48 69 93 50 01 00 00 imul $0xfa,0x150(%rbx),%rdx 1f5b: fa 00 00 00 timeout = f->used + vxlan->cfg.age_interval * HZ; if (time_before_eq(timeout, jiffies)) { netdev_dbg(vxlan->dev, "garbage collect %pM\n", f->eth_addr); f->state = NUD_STALE; 1f5f: 48 8b 0d 00 00 00 00 mov 0x0(%rip),%rcx # 1f66 vxlan_fdb_destroy(vxlan, f); 1f66: 49 03 57 28 add 0x28(%r15),%rdx timeout = f->used + vxlan->cfg.age_interval * HZ; if (time_before_eq(timeout, jiffies)) { netdev_dbg(vxlan->dev, "garbage collect %pM\n", f->eth_addr); f->state = NUD_STALE; 1f6a: 48 39 d1 cmp %rdx,%rcx vxlan_fdb_destroy(vxlan, f); 1f6d: 79 b9 jns 1f28 1f6f: 4c 39 e2 cmp %r12,%rdx for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n; spin_lock_bh(&vxlan->hash_lock); hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { 1f72: 4d 89 f7 mov %r14,%r15 1f75: 4c 0f 48 e2 cmovs %rdx,%r12 1f79: 4d 85 f6 test %r14,%r14 struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); unsigned long timeout; if (f->state & NUD_PERMANENT) 1f7c: 75 cc jne 1f4a 1f7e: 48 8b 7d d0 mov -0x30(%rbp),%rdi 1f82: 49 83 c5 08 add $0x8,%r13 continue; timeout = f->used + vxlan->cfg.age_interval * HZ; 1f86: e8 00 00 00 00 callq 1f8b 1f8b: 4c 3b 6d c8 cmp -0x38(%rbp),%r13 if (time_before_eq(timeout, jiffies)) { 1f8f: 75 83 jne 1f14 1f91: 48 8d bb a0 00 00 00 lea 0xa0(%rbx),%rdi unsigned long timeout; if (f->state & NUD_PERMANENT) continue; timeout = f->used + vxlan->cfg.age_interval * HZ; 1f98: 4c 89 e6 mov %r12,%rsi if (time_before_eq(timeout, jiffies)) { 1f9b: e8 00 00 00 00 callq 1fa0 "garbage collect %pM\n", f->eth_addr); f->state = NUD_STALE; vxlan_fdb_destroy(vxlan, f); } else if (time_before(timeout, next_timer)) next_timer = timeout; 1fa0: 48 83 c4 10 add $0x10,%rsp 1fa4: 5b pop %rbx 1fa5: 41 5c pop %r12 1fa7: 41 5d pop %r13 for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n; spin_lock_bh(&vxlan->hash_lock); hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { 1fa9: 41 5e pop %r14 1fab: 41 5f pop %r15 1fad: 5d pop %rbp raw_spin_unlock(&lock->rlock); } static __always_inline void spin_unlock_bh(spinlock_t *lock) { raw_spin_unlock_bh(&lock->rlock); 1fae: c3 retq 1faf: 48 8b 73 30 mov 0x30(%rbx),%rsi 1fb3: 49 8d 4f 40 lea 0x40(%r15),%rcx 1fb7: 48 c7 c2 00 00 00 00 mov $0x0,%rdx unsigned int h; if (!netif_running(vxlan->dev)) return; for (h = 0; h < FDB_HASH_SIZE; ++h) { 1fbe: 48 c7 c7 00 00 00 00 mov $0x0,%rdi next_timer = timeout; } spin_unlock_bh(&vxlan->hash_lock); } mod_timer(&vxlan->age_timer, next_timer); 1fc5: e8 00 00 00 00 callq 1fca 1fca: e9 5e ff ff ff jmpq 1f2d 1fcf: 90 nop 0000000000001fd0 : } 1fd0: e8 00 00 00 00 callq 1fd5 1fd5: 55 push %rbp 1fd6: 48 89 e5 mov %rsp,%rbp 1fd9: 41 54 push %r12 1fdb: 4c 8d a7 e8 00 00 00 lea 0xe8(%rdi),%r12 if (f->state & NUD_PERMANENT) continue; timeout = f->used + vxlan->cfg.age_interval * HZ; if (time_before_eq(timeout, jiffies)) { netdev_dbg(vxlan->dev, 1fe2: 53 push %rbx 1fe3: 48 89 fb mov %rdi,%rbx 1fe6: 4c 89 e7 mov %r12,%rdi 1fe9: e8 00 00 00 00 callq 1fee 1fee: 48 c7 c6 00 00 00 00 mov $0x0,%rsi 1ff5: 48 89 df mov %rbx,%rdi 1ff8: e8 03 e0 ff ff callq 0 <__vxlan_find_mac> 1ffd: 48 85 c0 test %rax,%rax return 0; } static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan) { 2000: 74 0b je 200d 2002: 48 89 c6 mov %rax,%rsi 2005: 48 89 df mov %rbx,%rdi 2008: e8 23 fe ff ff callq 1e30 raw_spin_lock(&lock->rlock); } static __always_inline void spin_lock_bh(spinlock_t *lock) { raw_spin_lock_bh(&lock->rlock); 200d: 4c 89 e7 mov %r12,%rdi 2010: e8 00 00 00 00 callq 2015 2015: 5b pop %rbx 2016: 41 5c pop %r12 2018: 5d pop %rbp 2019: c3 retq 201a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 0000000000002020 : struct vxlan_fdb *f; spin_lock_bh(&vxlan->hash_lock); f = __vxlan_find_mac(vxlan, all_zeros_mac); 2020: e8 00 00 00 00 callq 2025 2025: 55 push %rbp 2026: 48 89 e5 mov %rsp,%rbp 2029: 53 push %rbx 202a: 48 89 fb mov %rdi,%rbx if (f) 202d: 48 8d bf 40 08 00 00 lea 0x840(%rdi),%rdi vxlan_fdb_destroy(vxlan, f); 2034: e8 97 ff ff ff callq 1fd0 2039: 48 8b bb 88 04 00 00 mov 0x488(%rbx),%rdi raw_spin_unlock(&lock->rlock); } static __always_inline void spin_unlock_bh(spinlock_t *lock) { raw_spin_unlock_bh(&lock->rlock); 2040: e8 00 00 00 00 callq 2045 spin_unlock_bh(&vxlan->hash_lock); } 2045: 5b pop %rbx 2046: 5d pop %rbp 2047: c3 retq 2048: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 204f: 00 0000000000002050 : static void vxlan_uninit(struct net_device *dev) { 2050: e8 00 00 00 00 callq 2055 2055: 55 push %rbp 2056: 48 89 fa mov %rdi,%rdx 2059: b9 0a 00 00 00 mov $0xa,%ecx struct vxlan_dev *vxlan = netdev_priv(dev); vxlan_fdb_delete_default(vxlan); 205e: 48 89 e5 mov %rsp,%rbp 2061: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 2065: 48 81 ec b0 00 00 00 sub $0xb0,%rsp free_percpu(dev->tstats); 206c: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 2073: 00 00 } 2075: 48 89 84 24 a8 00 00 mov %rax,0xa8(%rsp) 207c: 00 207d: 31 c0 xor %eax,%eax 207f: 48 89 e7 mov %rsp,%rdi if (err < 0) rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); } static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa) { 2082: f3 48 ab rep stos %rax,%es:(%rdi) 2085: b9 04 00 00 00 mov $0x4,%ecx struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb f = { 208a: 48 8d 7c 24 50 lea 0x50(%rsp),%rdi if (err < 0) rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); } static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa) { 208f: 66 89 4c 24 46 mov %cx,0x46(%rsp) 2094: b9 0b 00 00 00 mov $0xb,%ecx 2099: f3 48 ab rep stos %rax,%es:(%rdi) 209c: 48 8b 06 mov (%rsi),%rax 209f: 48 8d ba 40 08 00 00 lea 0x840(%rdx),%rdi 20a6: 48 8d 54 24 50 lea 0x50(%rsp),%rdx 20ab: b9 1e 00 00 00 mov $0x1e,%ecx struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb f = { 20b0: c7 44 24 70 01 00 00 movl $0x1,0x70(%rsp) 20b7: 00 20b8: 48 89 44 24 50 mov %rax,0x50(%rsp) .state = NUD_STALE, }; struct vxlan_rdst remote = { 20bd: 48 8b 46 08 mov 0x8(%rsi),%rax } static void vxlan_ip_miss(struct net_device *dev, union vxlan_addr *ipa) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb f = { 20c1: 48 89 44 24 58 mov %rax,0x58(%rsp) .state = NUD_STALE, }; struct vxlan_rdst remote = { 20c6: 48 8b 46 10 mov 0x10(%rsi),%rax 20ca: 48 89 44 24 60 mov %rax,0x60(%rsp) .remote_ip = *ipa, /* goes to NDA_DST */ .remote_vni = cpu_to_be32(VXLAN_N_VID), }; vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); 20cf: 8b 46 18 mov 0x18(%rsi),%eax 20d2: 48 89 e6 mov %rsp,%rsi 20d5: 89 44 24 68 mov %eax,0x68(%rsp) 20d9: e8 62 fc ff ff callq 1d40 20de: 48 8b 84 24 a8 00 00 mov 0xa8(%rsp),%rax 20e5: 00 { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_fdb f = { .state = NUD_STALE, }; struct vxlan_rdst remote = { 20e6: 65 48 33 04 25 28 00 xor %gs:0x28,%rax 20ed: 00 00 20ef: 75 02 jne 20f3 20f1: c9 leaveq 20f2: c3 retq 20f3: e8 00 00 00 00 callq 20f8 20f8: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 20ff: 00 0000000000002100 : 2100: e8 00 00 00 00 callq 2105 2105: 55 push %rbp 2106: 49 89 f8 mov %rdi,%r8 .remote_ip = *ipa, /* goes to NDA_DST */ .remote_vni = cpu_to_be32(VXLAN_N_VID), }; vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); 2109: b9 0a 00 00 00 mov $0xa,%ecx } 210e: ba 04 00 00 00 mov $0x4,%edx 2113: 48 89 e5 mov %rsp,%rbp 2116: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 211a: 48 81 ec b0 00 00 00 sub $0xb0,%rsp 2121: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 2128: 00 00 212a: 48 89 84 24 a8 00 00 mov %rax,0xa8(%rsp) 2131: 00 static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) { 2132: 31 c0 xor %eax,%eax 2134: 48 89 e7 mov %rsp,%rdi 2137: f3 48 ab rep stos %rax,%es:(%rdi) struct vxlan_fdb f = { 213a: 48 8d 7c 24 50 lea 0x50(%rsp),%rdi 213f: b9 0b 00 00 00 mov $0xb,%ecx vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); } static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) { 2144: 66 89 54 24 46 mov %dx,0x46(%rsp) 2149: 48 8d 54 24 50 lea 0x50(%rsp),%rdx 214e: f3 48 ab rep stos %rax,%es:(%rdi) 2151: 8b 06 mov (%rsi),%eax 2153: b9 1e 00 00 00 mov $0x1e,%ecx 2158: 4c 89 c7 mov %r8,%rdi 215b: 89 44 24 40 mov %eax,0x40(%rsp) 215f: 0f b7 46 04 movzwl 0x4(%rsi),%eax 2163: 48 89 e6 mov %rsp,%rsi struct vxlan_fdb f = { 2166: 66 89 44 24 44 mov %ax,0x44(%rsp) .state = NUD_STALE, }; struct vxlan_rdst remote = { }; 216b: e8 d0 fb ff ff callq 1d40 2170: 48 8b 84 24 a8 00 00 mov 0xa8(%rsp),%rax 2177: 00 vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); } static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN]) { struct vxlan_fdb f = { 2178: 65 48 33 04 25 28 00 xor %gs:0x28,%rax 217f: 00 00 .state = NUD_STALE, }; struct vxlan_rdst remote = { }; memcpy(f.eth_addr, eth_addr, ETH_ALEN); 2181: 75 02 jne 2185 vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); 2183: c9 leaveq 2184: c3 retq 2185: e8 00 00 00 00 callq 218a 218a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 0000000000002190 : struct vxlan_fdb f = { .state = NUD_STALE, }; struct vxlan_rdst remote = { }; memcpy(f.eth_addr, eth_addr, ETH_ALEN); 2190: e8 00 00 00 00 callq 2195 vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); 2195: 55 push %rbp struct vxlan_fdb f = { .state = NUD_STALE, }; struct vxlan_rdst remote = { }; memcpy(f.eth_addr, eth_addr, ETH_ALEN); 2196: 48 8d 82 40 08 00 00 lea 0x840(%rdx),%rax vxlan_fdb_notify(vxlan, &f, &remote, RTM_GETNEIGH); 219d: 48 89 e5 mov %rsp,%rbp } 21a0: 41 57 push %r15 21a2: 41 56 push %r14 21a4: 41 55 push %r13 21a6: 41 54 push %r12 21a8: 49 89 f6 mov %rsi,%r14 21ab: 53 push %rbx 21ac: 44 89 c3 mov %r8d,%ebx 21af: 48 83 ec 30 sub $0x30,%rsp 21b3: 48 89 45 d0 mov %rax,-0x30(%rbp) 21b7: 48 8d 82 a0 09 00 00 lea 0x9a0(%rdx),%rax 21be: 48 89 7d c8 mov %rdi,-0x38(%rbp) /* Dump forwarding table */ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, struct net_device *filter_dev, int idx) { 21c2: 48 89 45 c0 mov %rax,-0x40(%rbp) 21c6: 48 8d 82 a0 11 00 00 lea 0x11a0(%rdx),%rax 21cd: 48 89 45 b8 mov %rax,-0x48(%rbp) 21d1: 48 8b 45 c0 mov -0x40(%rbp),%rax 21d5: 4c 8b 28 mov (%rax),%r13 21d8: 4d 85 ed test %r13,%r13 21db: 0f 84 91 00 00 00 je 2272 21e1: 49 8b 45 30 mov 0x30(%r13),%rax 21e5: 4d 8d 7d 30 lea 0x30(%r13),%r15 21e9: 49 39 c7 cmp %rax,%r15 21ec: 4c 8d 60 d8 lea -0x28(%rax),%r12 21f0: 74 73 je 2265 21f2: 4c 89 f0 mov %r14,%rax 21f5: 4d 89 fe mov %r15,%r14 21f8: 49 89 c7 mov %rax,%r15 21fb: eb 11 jmp 220e 21fd: 49 8b 44 24 28 mov 0x28(%r12),%rax }) static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; 2202: 83 c3 01 add $0x1,%ebx 2205: 49 39 c6 cmp %rax,%r14 for (h = 0; h < FDB_HASH_SIZE; ++h) { struct vxlan_fdb *f; int err; hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) { 2208: 4c 8d 60 d8 lea -0x28(%rax),%r12 220c: 74 54 je 2262 220e: 48 63 c3 movslq %ebx,%rax 2211: 49 3b 47 48 cmp 0x48(%r15),%rax struct vxlan_rdst *rd; list_for_each_entry_rcu(rd, &f->remotes, list) { 2215: 7c e6 jl 21fd 2217: 49 8b 47 08 mov 0x8(%r15),%rax 221b: 48 8b 75 d0 mov -0x30(%rbp),%rsi 221f: 41 b9 1c 00 00 00 mov $0x1c,%r9d 2225: 48 8b 7d c8 mov -0x38(%rbp),%rdi 2229: 4c 89 ea mov %r13,%rdx 222c: 44 8b 40 08 mov 0x8(%rax),%r8d 2230: 49 8b 07 mov (%r15),%rax if (err < 0) { cb->args[1] = err; goto out; } skip: ++idx; 2233: 8b 48 34 mov 0x34(%rax),%ecx int err; hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) { struct vxlan_rdst *rd; list_for_each_entry_rcu(rd, &f->remotes, list) { 2236: 4c 89 64 24 08 mov %r12,0x8(%rsp) 223b: c7 04 24 02 00 00 00 movl $0x2,(%rsp) if (idx < cb->args[0]) 2242: e8 a9 f7 ff ff callq 19f0 goto skip; err = vxlan_fdb_info(skb, vxlan, f, 2247: 85 c0 test %eax,%eax 2249: 79 b2 jns 21fd 224b: 48 98 cltq 224d: 49 89 47 50 mov %rax,0x50(%r15) 2251: 48 83 c4 30 add $0x30,%rsp 2255: 89 d8 mov %ebx,%eax 2257: 5b pop %rbx 2258: 41 5c pop %r12 225a: 41 5d pop %r13 225c: 41 5e pop %r14 225e: 41 5f pop %r15 2260: 5d pop %rbp 2261: c3 retq 2262: 4d 89 fe mov %r15,%r14 2265: 4d 8b 6d 00 mov 0x0(%r13),%r13 2269: 4d 85 ed test %r13,%r13 226c: 0f 85 6f ff ff ff jne 21e1 2272: 48 83 45 c0 08 addq $0x8,-0x40(%rbp) NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, RTM_NEWNEIGH, NLM_F_MULTI, rd); if (err < 0) { 2277: 48 8b 45 c0 mov -0x40(%rbp),%rax cb->args[1] = err; 227b: 48 39 45 b8 cmp %rax,-0x48(%rbp) 227f: 0f 85 4c ff ff ff jne 21d1 } } } out: return idx; } 2285: eb ca jmp 2251 2287: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 228e: 00 00 0000000000002290 : 2290: e8 00 00 00 00 callq 2295 2295: 55 push %rbp 2296: 4c 8b 4f 30 mov 0x30(%rdi),%r9 for (h = 0; h < FDB_HASH_SIZE; ++h) { struct vxlan_fdb *f; int err; hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) { 229a: 48 83 c7 30 add $0x30,%rdi 229e: 48 89 e5 mov %rsp,%rbp 22a1: 4c 39 cf cmp %r9,%rdi 22a4: 74 61 je 2307 22a6: 49 8d 41 d8 lea -0x28(%r9),%rax 22aa: 44 0f b7 16 movzwl (%rsi),%r10d struct net_device *filter_dev, int idx) { struct vxlan_dev *vxlan = netdev_priv(dev); unsigned int h; for (h = 0; h < FDB_HASH_SIZE; ++h) { 22ae: eb 0d jmp 22bd 22b0: 4c 8b 48 28 mov 0x28(%rax),%r9 22b4: 4c 39 cf cmp %r9,%rdi 22b7: 49 8d 41 d8 lea -0x28(%r9),%rax 22bb: 74 4a je 2307 22bd: 66 44 3b 10 cmp (%rax),%r10w /* caller should hold vxlan->hash_lock */ static struct vxlan_rdst *vxlan_fdb_find_rdst(struct vxlan_fdb *f, union vxlan_addr *ip, __be16 port, __be32 vni, __u32 ifindex) { 22c1: 75 ed jne 22b0 22c3: 66 41 83 fa 0a cmp $0xa,%r10w struct vxlan_rdst *rd; list_for_each_entry(rd, &f->remotes, list) { 22c8: 74 24 je 22ee 22ca: 44 8b 5e 04 mov 0x4(%rsi),%r11d /* caller should hold vxlan->hash_lock */ static struct vxlan_rdst *vxlan_fdb_find_rdst(struct vxlan_fdb *f, union vxlan_addr *ip, __be16 port, __be32 vni, __u32 ifindex) { 22ce: 44 39 58 04 cmp %r11d,0x4(%rax) struct vxlan_rdst *rd; list_for_each_entry(rd, &f->remotes, list) { 22d2: 41 0f 94 c1 sete %r9b 22d6: 45 84 c9 test %r9b,%r9b 22d9: 74 d5 je 22b0 22db: 66 39 50 1c cmp %dx,0x1c(%rax) 22df: 75 cf jne 22b0 22e1: 39 48 20 cmp %ecx,0x20(%rax) 22e4: 75 ca jne 22b0 22e6: 44 39 40 24 cmp %r8d,0x24(%rax) 22ea: 75 c4 jne 22b0 22ec: 5d pop %rbp #if IS_ENABLED(CONFIG_IPV6) static inline bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b) { if (a->sa.sa_family != b->sa.sa_family) 22ed: c3 retq 22ee: 4c 8b 58 08 mov 0x8(%rax),%r11 22f2: 4c 8b 48 10 mov 0x10(%rax),%r9 return false; if (a->sa.sa_family == AF_INET6) 22f6: 4c 33 5e 08 xor 0x8(%rsi),%r11 return ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr); else return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; 22fa: 4c 33 4e 10 xor 0x10(%rsi),%r9 22fe: 4d 09 cb or %r9,%r11 2301: 41 0f 94 c1 sete %r9b 2305: eb cf jmp 22d6 __be32 vni, __u32 ifindex) { struct vxlan_rdst *rd; list_for_each_entry(rd, &f->remotes, list) { if (vxlan_addr_equal(&rd->remote_ip, ip) && 2307: 31 c0 xor %eax,%eax 2309: 5d pop %rbp 230a: c3 retq 230b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 0000000000002310 : 2310: e8 00 00 00 00 callq 2315 rd->remote_port == port && 2315: 55 push %rbp rd->remote_vni == vni && 2316: 48 89 f7 mov %rsi,%rdi 2319: 48 89 e5 mov %rsp,%rbp rd->remote_ifindex == ifindex) return rd; } return NULL; } 231c: 41 57 push %r15 { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 const unsigned long *ul1 = (const unsigned long *)a1; const unsigned long *ul2 = (const unsigned long *)a2; return ((ul1[0] ^ ul2[0]) | (ul1[1] ^ ul2[1])) == 0UL; 231e: 41 56 push %r14 2320: 41 55 push %r13 2322: 41 54 push %r12 2324: 4c 8d b2 40 08 00 00 lea 0x840(%rdx),%r14 232b: 53 push %rbx 232c: 49 89 d4 mov %rdx,%r12 232f: 49 89 cf mov %rcx,%r15 2332: 4c 89 f6 mov %r14,%rsi 2335: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 2339: 48 83 ec 40 sub $0x40,%rsp 233d: 4c 8d 4c 24 0c lea 0xc(%rsp),%r9 /* Delete entry (via netlink) */ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid) { 2342: 4c 8d 44 24 08 lea 0x8(%rsp),%r8 2347: 48 8d 4c 24 06 lea 0x6(%rsp),%rcx 234c: 48 8d 54 24 10 lea 0x10(%rsp),%rdx 2351: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 2358: 00 00 235a: 48 89 44 24 38 mov %rax,0x38(%rsp) 235f: 31 c0 xor %eax,%eax 2361: e8 ba e2 ff ff callq 620 2366: 85 c0 test %eax,%eax 2368: 89 c3 mov %eax,%ebx 236a: 74 25 je 2391 236c: 89 d8 mov %ebx,%eax __be16 port; __be32 vni; u32 ifindex; int err; err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &vni, &ifindex); 236e: 48 8b 5c 24 38 mov 0x38(%rsp),%rbx 2373: 65 48 33 1c 25 28 00 xor %gs:0x28,%rbx 237a: 00 00 237c: 0f 85 10 01 00 00 jne 2492 /* Delete entry (via netlink) */ static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid) { 2382: 48 8d 65 d8 lea -0x28(%rbp),%rsp 2386: 5b pop %rbx 2387: 41 5c pop %r12 2389: 41 5d pop %r13 238b: 41 5e pop %r14 238d: 41 5f pop %r15 238f: 5d pop %rbp 2390: c3 retq __be16 port; __be32 vni; u32 ifindex; int err; err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &vni, &ifindex); 2391: 4d 8d ac 24 28 09 00 lea 0x928(%r12),%r13 2398: 00 2399: 4c 89 ef mov %r13,%rdi out: spin_unlock_bh(&vxlan->hash_lock); return err; } 239c: e8 00 00 00 00 callq 23a1 23a1: 4c 89 fe mov %r15,%rsi 23a4: 4c 89 f7 mov %r14,%rdi 23a7: e8 54 dc ff ff callq 0 <__vxlan_find_mac> 23ac: 48 85 c0 test %rax,%rax 23af: 49 89 c4 mov %rax,%r12 23b2: 0f 84 d0 00 00 00 je 2488 23b8: 66 83 7c 24 10 0a cmpw $0xa,0x10(%rsp) 23be: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 23c5 raw_spin_lock(&lock->rlock); } static __always_inline void spin_lock_bh(spinlock_t *lock) { raw_spin_lock_bh(&lock->rlock); 23c5: 49 89 44 24 28 mov %rax,0x28(%r12) 23ca: 0f 84 a6 00 00 00 je 2476 23d0: 8b 44 24 14 mov 0x14(%rsp),%eax static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 23d4: 85 c0 test %eax,%eax 23d6: 0f 94 c0 sete %al 23d9: 84 c0 test %al,%al 23db: 74 18 je 23f5 if (f) 23dd: 4c 89 e6 mov %r12,%rsi static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 23e0: 4c 89 f7 mov %r14,%rdi if (f) 23e3: e8 48 fa ff ff callq 1e30 return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 23e8: 4c 89 ef mov %r13,%rdi 23eb: e8 00 00 00 00 callq 23f0 { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); if (f) f->used = jiffies; 23f0: e9 77 ff ff ff jmpq 236c 23f5: 0f b7 54 24 06 movzwl 0x6(%rsp),%edx return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 23fa: 44 8b 44 24 0c mov 0xc(%rsp),%r8d 23ff: 48 8d 74 24 10 lea 0x10(%rsp),%rsi return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); 2404: 8b 4c 24 08 mov 0x8(%rsp),%ecx 2408: 4c 89 e7 mov %r12,%rdi spin_lock_bh(&vxlan->hash_lock); f = vxlan_find_mac(vxlan, addr); if (!f) goto out; if (!vxlan_addr_any(&ip)) { 240b: e8 80 fe ff ff callq 2290 vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); kfree_rcu(rd, rcu); goto out; } vxlan_fdb_destroy(vxlan, f); 2410: 48 85 c0 test %rax,%rax 2413: 49 89 c7 mov %rax,%r15 2416: 74 70 je 2488 raw_spin_unlock(&lock->rlock); } static __always_inline void spin_unlock_bh(spinlock_t *lock) { raw_spin_unlock_bh(&lock->rlock); 2418: 49 8b 44 24 30 mov 0x30(%r12),%rax 241d: 49 8d 54 24 30 lea 0x30(%r12),%rdx out: spin_unlock_bh(&vxlan->hash_lock); return err; 2422: 48 39 c2 cmp %rax,%rdx f = vxlan_find_mac(vxlan, addr); if (!f) goto out; if (!vxlan_addr_any(&ip)) { rd = vxlan_fdb_find_rdst(f, &ip, port, vni, ifindex); 2425: 74 0c je 2433 2427: 49 8b 44 24 38 mov 0x38(%r12),%rax 242c: 49 39 44 24 30 cmp %rax,0x30(%r12) 2431: 74 aa je 23dd 2433: 49 8b 47 30 mov 0x30(%r15),%rax 2437: 49 8b 57 28 mov 0x28(%r15),%rdx 243b: 4c 89 e6 mov %r12,%rsi 243e: 4c 89 f7 mov %r14,%rdi if (!rd) 2441: b9 1d 00 00 00 mov $0x1d,%ecx 2446: 48 89 42 08 mov %rax,0x8(%rdx) 244a: 48 89 10 mov %rdx,(%rax) err = 0; /* remove a destination if it's not the only one on the list, * otherwise destroy the fdb entry */ if (rd && !list_is_singular(&f->remotes)) { 244d: 48 b8 00 02 00 00 00 movabs $0xdead000000000200,%rax 2454: 00 ad de * list_is_singular - tests whether a list has just one entry. * @head: the list to test. */ static inline int list_is_singular(const struct list_head *head) { return !list_empty(head) && (head->next == head->prev); 2457: 49 89 47 30 mov %rax,0x30(%r15) 245b: 4c 89 fa mov %r15,%rdx 245e: e8 dd f8 ff ff callq 1d40 * in an undefined state. */ #ifndef CONFIG_DEBUG_LIST static inline void __list_del_entry(struct list_head *entry) { __list_del(entry->prev, entry->next); 2463: 49 8d 7f 38 lea 0x38(%r15),%rdi 2467: be 38 00 00 00 mov $0x38,%esi list_del_rcu(&rd->list); vxlan_fdb_notify(vxlan, f, rd, RTM_DELNEIGH); 246c: e8 00 00 00 00 callq 2471 2471: e9 72 ff ff ff jmpq 23e8 * This is only for internal list manipulation where we know * the prev/next entries already! */ static inline void __list_del(struct list_head * prev, struct list_head * next) { next->prev = prev; 2476: 48 8b 44 24 18 mov 0x18(%rsp),%rax { switch (size) { case 1: *(volatile __u8 *)p = *(__u8 *)res; break; case 2: *(volatile __u16 *)p = *(__u16 *)res; break; case 4: *(volatile __u32 *)p = *(__u32 *)res; break; case 8: *(volatile __u64 *)p = *(__u64 *)res; break; 247b: 48 0b 44 24 20 or 0x20(%rsp),%rax * grace period has elapsed. */ static inline void list_del_rcu(struct list_head *entry) { __list_del_entry(entry); entry->prev = LIST_POISON2; 2480: 0f 94 c0 sete %al 2483: e9 51 ff ff ff jmpq 23d9 2488: bb fe ff ff ff mov $0xfffffffe,%ebx 248d: e9 56 ff ff ff jmpq 23e8 2492: e8 00 00 00 00 callq 2497 kfree_rcu(rd, rcu); 2497: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 249e: 00 00 00000000000024a0 : 24a0: e8 00 00 00 00 callq 24a5 goto out; 24a5: 55 push %rbp static inline bool ipv6_addr_any(const struct in6_addr *a) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 const unsigned long *ul = (const unsigned long *)a; return (ul[0] | ul[1]) == 0UL; 24a6: 48 89 e5 mov %rsp,%rbp 24a9: 41 57 push %r15 24ab: 41 56 push %r14 24ad: 41 55 push %r13 24af: 41 54 push %r12 24b1: 41 89 d6 mov %edx,%r14d 24b4: 53 push %rbx 24b5: 0f b7 d2 movzwl %dx,%edx err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &vni, &ifindex); if (err) return err; err = -ENOENT; 24b8: 48 89 fb mov %rdi,%rbx 24bb: 49 89 f7 mov %rsi,%r15 24be: 41 89 cd mov %ecx,%r13d 24c1: 45 89 c4 mov %r8d,%r12d out: spin_unlock_bh(&vxlan->hash_lock); return err; } 24c4: 48 83 ec 10 sub $0x10,%rsp 24c8: 4c 89 4d d0 mov %r9,-0x30(%rbp) 24cc: e8 bf fd ff ff callq 2290 /* Add/update destinations for multicast */ static int vxlan_fdb_append(struct vxlan_fdb *f, union vxlan_addr *ip, __be16 port, __be32 vni, __u32 ifindex, struct vxlan_rdst **rdp) { 24d1: 31 d2 xor %edx,%edx 24d3: 48 85 c0 test %rax,%rax 24d6: 74 11 je 24e9 24d8: 48 83 c4 10 add $0x10,%rsp 24dc: 89 d0 mov %edx,%eax 24de: 5b pop %rbx 24df: 41 5c pop %r12 24e1: 41 5d pop %r13 24e3: 41 5e pop %r14 struct vxlan_rdst *rd; rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex); 24e5: 41 5f pop %r15 24e7: 5d pop %rbp /* Add/update destinations for multicast */ static int vxlan_fdb_append(struct vxlan_fdb *f, union vxlan_addr *ip, __be16 port, __be32 vni, __u32 ifindex, struct vxlan_rdst **rdp) { 24e8: c3 retq 24e9: 48 8b 3d 00 00 00 00 mov 0x0(%rip),%rdi # 24f0 24f0: ba 58 00 00 00 mov $0x58,%edx 24f5: be 20 00 08 02 mov $0x2080020,%esi 24fa: e8 00 00 00 00 callq 24ff struct vxlan_rdst *rd; rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex); 24ff: 48 85 c0 test %rax,%rax if (rd) return 0; 2502: 74 70 je 2574 __u32 ifindex, struct vxlan_rdst **rdp) { struct vxlan_rdst *rd; rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex); if (rd) 2504: 48 8d 78 48 lea 0x48(%rax),%rdi list_add_tail_rcu(&rd->list, &f->remotes); *rdp = rd; return 1; } 2508: be 20 00 08 02 mov $0x2080020,%esi 250d: 48 89 45 c8 mov %rax,-0x38(%rbp) 2511: e8 00 00 00 00 callq 2516 2516: 85 c0 test %eax,%eax 2518: 48 8b 55 c8 mov -0x38(%rbp),%rdx int index = kmalloc_index(size); if (!index) return ZERO_SIZE_PTR; return kmem_cache_alloc_trace(kmalloc_caches[index], 251c: 75 60 jne 257e 251e: 49 8b 07 mov (%r15),%rax 2521: 48 8b 4b 38 mov 0x38(%rbx),%rcx 2525: 48 8d 73 30 lea 0x30(%rbx),%rsi 2529: 66 44 89 72 1c mov %r14w,0x1c(%rdx) 252e: 44 89 6a 20 mov %r13d,0x20(%rdx) rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex); if (rd) return 0; rd = kmalloc(sizeof(*rd), GFP_ATOMIC); if (rd == NULL) 2532: 44 89 62 24 mov %r12d,0x24(%rdx) return -ENOBUFS; if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) { 2536: 48 89 72 28 mov %rsi,0x28(%rdx) 253a: 48 89 02 mov %rax,(%rdx) 253d: 49 8b 47 08 mov 0x8(%r15),%rax 2541: 48 89 4a 30 mov %rcx,0x30(%rdx) 2545: 48 89 42 08 mov %rax,0x8(%rdx) 2549: 49 8b 47 10 mov 0x10(%r15),%rax 254d: 48 89 42 10 mov %rax,0x10(%rdx) * list_for_each_entry_rcu(). */ static inline void list_add_tail_rcu(struct list_head *new, struct list_head *head) { __list_add_rcu(new, head->prev, head); 2551: 41 8b 47 18 mov 0x18(%r15),%eax rd->remote_ip = *ip; rd->remote_port = port; rd->remote_vni = vni; rd->remote_ifindex = ifindex; list_add_tail_rcu(&rd->list, &f->remotes); 2555: 89 42 18 mov %eax,0x18(%rdx) 2558: 48 8d 42 28 lea 0x28(%rdx),%rax kfree(rd); return -ENOBUFS; } rd->remote_ip = *ip; rd->remote_port = port; 255c: 48 89 01 mov %rax,(%rcx) rd->remote_vni = vni; 255f: 48 89 43 38 mov %rax,0x38(%rbx) rd->remote_ifindex = ifindex; 2563: 48 8b 45 d0 mov -0x30(%rbp),%rax list_add_tail_rcu(&rd->list, &f->remotes); 2567: 48 89 10 mov %rdx,(%rax) if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) { kfree(rd); return -ENOBUFS; } rd->remote_ip = *ip; 256a: ba 01 00 00 00 mov $0x1,%edx 256f: e9 64 ff ff ff jmpq 24d8 #ifndef CONFIG_DEBUG_LIST static inline void __list_add_rcu(struct list_head *new, struct list_head *prev, struct list_head *next) { new->next = next; new->prev = prev; 2574: ba 97 ff ff ff mov $0xffffff97,%edx 2579: e9 5a ff ff ff jmpq 24d8 257e: 48 89 d7 mov %rdx,%rdi 2581: e8 00 00 00 00 callq 2586 2586: ba 97 ff ff ff mov $0xffffff97,%edx rd->remote_port = port; rd->remote_vni = vni; rd->remote_ifindex = ifindex; list_add_tail_rcu(&rd->list, &f->remotes); 258b: e9 48 ff ff ff jmpq 24d8 0000000000002590 : rcu_assign_pointer(list_next_rcu(prev), new); next->prev = new; 2590: e8 00 00 00 00 callq 2595 *rdp = rd; 2595: 55 push %rbp 2596: 48 89 e5 mov %rsp,%rbp 2599: 41 57 push %r15 return 1; 259b: 41 56 push %r14 259d: 41 55 push %r13 259f: 41 54 push %r12 25a1: 49 89 f7 mov %rsi,%r15 if (rd) return 0; rd = kmalloc(sizeof(*rd), GFP_ATOMIC); if (rd == NULL) return -ENOBUFS; 25a4: 53 push %rbx 25a5: 49 89 fc mov %rdi,%r12 25a8: 45 89 c5 mov %r8d,%r13d 25ab: 48 83 ec 20 sub $0x20,%rsp if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) { kfree(rd); 25af: 48 89 55 b8 mov %rdx,-0x48(%rbp) 25b3: 89 4d c4 mov %ecx,-0x3c(%rbp) return -ENOBUFS; 25b6: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 25bd: 00 00 25bf: 48 89 45 d0 mov %rax,-0x30(%rbp) static int vxlan_fdb_create(struct vxlan_dev *vxlan, const u8 *mac, union vxlan_addr *ip, __u16 state, __u16 flags, __be16 port, __be32 vni, __u32 ifindex, __u8 ndm_flags) { 25c3: 31 c0 xor %eax,%eax 25c5: 44 89 4d c0 mov %r9d,-0x40(%rbp) 25c9: 44 8b 75 20 mov 0x20(%rbp),%r14d 25cd: 48 c7 45 c8 00 00 00 movq $0x0,-0x38(%rbp) 25d4: 00 25d5: e8 26 da ff ff callq 0 <__vxlan_find_mac> 25da: 48 85 c0 test %rax,%rax 25dd: 0f 84 41 01 00 00 je 2724 25e3: 41 f7 c5 00 02 00 00 test $0x200,%r13d 25ea: 0f 85 e6 00 00 00 jne 26d6 25f0: 48 89 c3 mov %rax,%rbx 25f3: 45 31 ff xor %r15d,%r15d 25f6: 8b 45 c4 mov -0x3c(%rbp),%eax 25f9: 66 39 43 46 cmp %ax,0x46(%rbx) struct vxlan_rdst *rd = NULL; 25fd: 74 15 je 2614 25ff: 66 89 43 46 mov %ax,0x46(%rbx) 2603: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 260a struct vxlan_fdb *f; int notify = 0; f = __vxlan_find_mac(vxlan, mac); if (f) { 260a: 41 bf 01 00 00 00 mov $0x1,%r15d 2610: 48 89 43 20 mov %rax,0x20(%rbx) if (flags & NLM_F_EXCL) { 2614: 44 38 73 48 cmp %r14b,0x48(%rbx) 2618: 74 15 je 262f 261a: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 2621 2621: 44 88 73 48 mov %r14b,0x48(%rbx) __be16 port, __be32 vni, __u32 ifindex, __u8 ndm_flags) { struct vxlan_rdst *rd = NULL; struct vxlan_fdb *f; int notify = 0; 2625: 41 bf 01 00 00 00 mov $0x1,%r15d if (flags & NLM_F_EXCL) { netdev_dbg(vxlan->dev, "lost race to create %pM\n", mac); return -EEXIST; } if (f->state != state) { 262b: 48 89 43 20 mov %rax,0x20(%rbx) f->state = state; 262f: 41 f7 c5 00 01 00 00 test $0x100,%r13d f->updated = jiffies; 2636: 74 3c je 2674 2638: 8b 43 40 mov 0x40(%rbx),%eax notify = 1; 263b: a8 01 test $0x1,%al 263d: 0f 85 0f 02 00 00 jne 2852 "lost race to create %pM\n", mac); return -EEXIST; } if (f->state != state) { f->state = state; f->updated = jiffies; 2643: 0f b7 53 44 movzwl 0x44(%rbx),%edx notify = 1; } if (f->flags != ndm_flags) { 2647: 09 c2 or %eax,%edx 2649: 0f 84 03 02 00 00 je 2852 f->flags = ndm_flags; f->updated = jiffies; 264f: 0f b7 55 c0 movzwl -0x40(%rbp),%edx f->state = state; f->updated = jiffies; notify = 1; } if (f->flags != ndm_flags) { f->flags = ndm_flags; 2653: 44 8b 45 18 mov 0x18(%rbp),%r8d f->updated = jiffies; notify = 1; 2657: 48 89 df mov %rbx,%rdi 265a: 8b 4d 10 mov 0x10(%rbp),%ecx f->updated = jiffies; notify = 1; } if (f->flags != ndm_flags) { f->flags = ndm_flags; f->updated = jiffies; 265d: 48 8b 75 b8 mov -0x48(%rbp),%rsi notify = 1; } if ((flags & NLM_F_REPLACE)) { 2661: e8 2a fc ff ff callq 2290 2666: 31 d2 xor %edx,%edx * By definition the broadcast address is also a multicast address. */ static inline bool is_multicast_ether_addr(const u8 *addr) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) u32 a = *(const u32 *)addr; 2668: 48 85 c0 test %rax,%rax /* Only change unicasts */ if (!(is_multicast_ether_addr(f->eth_addr) || 266b: 0f 84 fc 01 00 00 je 286d 2671: 41 09 d7 or %edx,%r15d 2674: 41 81 e5 00 08 00 00 and $0x800,%r13d 267b: 74 31 je 26ae 267d: 8b 43 40 mov 0x40(%rbx),%eax union vxlan_addr *ip, __be16 port, __be32 vni, __u32 ifindex) { struct vxlan_rdst *rd; rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex); 2680: a8 01 test $0x1,%al 2682: 75 08 jne 268c 2684: 0f b7 53 44 movzwl 0x44(%rbx),%edx 2688: 09 c2 or %eax,%edx 268a: 75 22 jne 26ae 268c: 0f b7 55 c0 movzwl -0x40(%rbp),%edx 2690: 44 8b 45 18 mov 0x18(%rbp),%r8d 2694: 4c 8d 4d c8 lea -0x38(%rbp),%r9 if (rd) 2698: 8b 4d 10 mov 0x10(%rbp),%ecx 269b: 48 8b 75 b8 mov -0x48(%rbp),%rsi 269f: 48 89 df mov %rbx,%rdi } if ((flags & NLM_F_REPLACE)) { /* Only change unicasts */ if (!(is_multicast_ether_addr(f->eth_addr) || is_zero_ether_addr(f->eth_addr))) { notify |= vxlan_fdb_replace(f, ip, port, vni, 26a2: e8 f9 fd ff ff callq 24a0 ifindex); } else return -EOPNOTSUPP; } if ((flags & NLM_F_APPEND) && 26a7: 85 c0 test %eax,%eax 26a9: 78 35 js 26e0 26ab: 41 09 c7 or %eax,%r15d 26ae: 31 c0 xor %eax,%eax 26b0: 45 85 ff test %r15d,%r15d 26b3: 74 2b je 26e0 (is_multicast_ether_addr(f->eth_addr) || 26b5: 48 8b 55 c8 mov -0x38(%rbp),%rdx 26b9: 48 85 d2 test %rdx,%rdx is_zero_ether_addr(f->eth_addr))) { int rc = vxlan_fdb_append(f, ip, port, vni, ifindex, 26bc: 0f 84 9a 01 00 00 je 285c 26c2: b9 1c 00 00 00 mov $0x1c,%ecx 26c7: 48 89 de mov %rbx,%rsi 26ca: 4c 89 e7 mov %r12,%rdi 26cd: e8 6e f6 ff ff callq 1d40 26d2: 31 c0 xor %eax,%eax 26d4: eb 0a jmp 26e0 26d6: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) &rd); if (rc < 0) return rc; notify |= rc; 26db: b8 ef ff ff ff mov $0xffffffef,%eax ++vxlan->addrcnt; hlist_add_head_rcu(&f->hlist, vxlan_fdb_head(vxlan, mac)); } if (notify) { 26e0: 48 8b 4d d0 mov -0x30(%rbp),%rcx 26e4: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx 26eb: 00 00 if (rd == NULL) 26ed: 0f 85 01 02 00 00 jne 28f4 rd = first_remote_rtnl(f); vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH); 26f3: 48 83 c4 20 add $0x20,%rsp 26f7: 5b pop %rbx 26f8: 41 5c pop %r12 26fa: 41 5d pop %r13 26fc: 41 5e pop %r14 26fe: 41 5f pop %r15 2700: 5d pop %rbp 2701: c3 retq } return 0; 2702: 49 8b 74 24 30 mov 0x30(%r12),%rsi 2707: 4c 89 f9 mov %r15,%rcx 270a: 48 c7 c2 00 00 00 00 mov $0x0,%rdx } 2711: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 2718: e8 00 00 00 00 callq 271d 271d: b8 ef ff ff ff mov $0xffffffef,%eax 2722: eb bc jmp 26e0 2724: 41 f7 c5 00 04 00 00 test $0x400,%r13d 272b: 0f 84 a5 01 00 00 je 28d6 2731: 41 8b 84 24 58 01 00 mov 0x158(%r12),%eax 2738: 00 int notify = 0; f = __vxlan_find_mac(vxlan, mac); if (f) { if (flags & NLM_F_EXCL) { netdev_dbg(vxlan->dev, 2739: 85 c0 test %eax,%eax 273b: 74 0e je 274b 273d: 41 3b 84 24 ec 00 00 cmp 0xec(%r12),%eax 2744: 00 2745: 0f 86 95 01 00 00 jbe 28e0 274b: 41 81 e5 00 01 00 00 and $0x100,%r13d "lost race to create %pM\n", mac); return -EEXIST; 2752: 74 18 je 276c if (rc < 0) return rc; notify |= rc; } } else { if (!(flags & NLM_F_CREATE)) 2754: 41 8b 07 mov (%r15),%eax 2757: a8 01 test $0x1,%al 2759: 0f 85 f3 00 00 00 jne 2852 275f: 41 0f b7 57 04 movzwl 0x4(%r15),%edx return -ENOENT; if (vxlan->cfg.addrmax && 2764: 09 c2 or %eax,%edx 2766: 0f 84 e6 00 00 00 je 2852 276c: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 2771: 48 8b 3d 00 00 00 00 mov 0x0(%rip),%rdi # 2778 2778: ba 50 00 00 00 mov $0x50,%edx vxlan->addrcnt >= vxlan->cfg.addrmax) return -ENOSPC; /* Disallow replace to add a multicast entry */ if ((flags & NLM_F_REPLACE) && 277d: be 20 00 08 02 mov $0x2080020,%esi 2782: e8 00 00 00 00 callq 2787 2787: 48 85 c0 test %rax,%rax 278a: 48 89 c3 mov %rax,%rbx 278d: 0f 84 57 01 00 00 je 28ea (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac))) 2793: 0f b7 45 c4 movzwl -0x3c(%rbp),%eax 2797: 0f b7 55 c0 movzwl -0x40(%rbp),%edx 279b: 4c 8d 4d c8 lea -0x38(%rbp),%r9 279f: 44 8b 45 18 mov 0x18(%rbp),%r8d 27a3: 8b 4d 10 mov 0x10(%rbp),%ecx 27a6: 48 89 df mov %rbx,%rdi 27a9: 48 8b 75 b8 mov -0x48(%rbp),%rsi 27ad: 44 88 73 48 mov %r14b,0x48(%rbx) 27b1: 66 89 43 46 mov %ax,0x46(%rbx) 27b5: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 27bc 27bc: 48 89 43 28 mov %rax,0x28(%rbx) return -EOPNOTSUPP; netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); f = kmalloc(sizeof(*f), GFP_ATOMIC); if (!f) 27c0: 48 89 43 20 mov %rax,0x20(%rbx) return -ENOMEM; notify = 1; f->state = state; 27c4: 48 8d 43 30 lea 0x30(%rbx),%rax f->flags = ndm_flags; f->updated = f->used = jiffies; INIT_LIST_HEAD(&f->remotes); memcpy(f->eth_addr, mac, ETH_ALEN); vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); 27c8: 48 89 43 30 mov %rax,0x30(%rbx) 27cc: 48 89 43 38 mov %rax,0x38(%rbx) 27d0: 41 8b 07 mov (%r15),%eax 27d3: 89 43 40 mov %eax,0x40(%rbx) 27d6: 41 0f b7 47 04 movzwl 0x4(%r15),%eax 27db: 66 89 43 44 mov %ax,0x44(%rbx) if (!f) return -ENOMEM; notify = 1; f->state = state; f->flags = ndm_flags; 27df: e8 bc fc ff ff callq 24a0 f = kmalloc(sizeof(*f), GFP_ATOMIC); if (!f) return -ENOMEM; notify = 1; f->state = state; 27e4: 41 83 84 24 ec 00 00 addl $0x1,0xec(%r12) 27eb: 00 01 f->flags = ndm_flags; f->updated = f->used = jiffies; 27ed: 48 ba eb 83 b5 80 46 movabs $0x61c8864680b583eb,%rdx 27f4: 86 c8 61 INIT_LIST_HEAD(&f->remotes); 27f7: 49 8b 07 mov (%r15),%rax 27fa: 48 c1 e0 10 shl $0x10,%rax struct list_head name = LIST_HEAD_INIT(name) static inline void INIT_LIST_HEAD(struct list_head *list) { WRITE_ONCE(list->next, list); list->prev = list; 27fe: 48 0f af c2 imul %rdx,%rax memcpy(f->eth_addr, mac, ETH_ALEN); 2802: 48 c1 e8 38 shr $0x38,%rax 2806: 48 83 c0 2c add $0x2c,%rax 280a: 49 8d 14 c4 lea (%r12,%rax,8),%rdx 280e: 49 8b 04 c4 mov (%r12,%rax,8),%rax vxlan_fdb_append(f, ip, port, vni, ifindex, &rd); 2812: 48 89 53 08 mov %rdx,0x8(%rbx) ++vxlan->addrcnt; 2816: 48 89 03 mov %rax,(%rbx) 2819: 48 85 c0 test %rax,%rax 281c: 48 89 1a mov %rbx,(%rdx) #endif static __always_inline u32 hash_64_generic(u64 val, unsigned int bits) { #if BITS_PER_LONG == 64 /* 64x64-bit multiply is efficient on all 64-bit processors */ return val * GOLDEN_RATIO_64 >> (64 - bits); 281f: 0f 84 90 fe ff ff je 26b5 2825: 48 89 58 08 mov %rbx,0x8(%rax) 2829: e9 87 fe ff ff jmpq 26b5 282e: 49 8b 74 24 30 mov 0x30(%r12),%rsi /* Hash chain to use given mac address */ static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan, const u8 *mac) { return &vxlan->fdb_head[eth_hash(mac)]; 2833: 4c 8b 45 b8 mov -0x48(%rbp),%r8 2837: 4c 89 f9 mov %r15,%rcx 283a: 48 c7 c2 00 00 00 00 mov $0x0,%rdx * list-traversal primitive must be guarded by rcu_read_lock(). */ static inline void hlist_add_head_rcu(struct hlist_node *n, struct hlist_head *h) { struct hlist_node *first = h->first; 2841: 48 c7 c7 00 00 00 00 mov $0x0,%rdi n->next = first; 2848: e8 00 00 00 00 callq 284d 284d: e9 1f ff ff ff jmpq 2771 n->pprev = &h->first; rcu_assign_pointer(hlist_first_rcu(h), n); if (first) 2852: b8 a1 ff ff ff mov $0xffffffa1,%eax first->pprev = &n->next; 2857: e9 84 fe ff ff jmpq 26e0 285c: 48 8b 43 30 mov 0x30(%rbx),%rax /* Disallow replace to add a multicast entry */ if ((flags & NLM_F_REPLACE) && (is_multicast_ether_addr(mac) || is_zero_ether_addr(mac))) return -EOPNOTSUPP; netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); 2860: 48 8d 50 d8 lea -0x28(%rax),%rdx 2864: 48 89 55 c8 mov %rdx,-0x38(%rbp) 2868: e9 55 fe ff ff jmpq 26c2 286d: 48 8b 43 30 mov 0x30(%rbx),%rax 2871: 48 8d 4b 30 lea 0x30(%rbx),%rcx 2875: 48 39 c1 cmp %rax,%rcx 2878: 0f 84 f3 fd ff ff je 2671 287e: 48 8b 43 30 mov 0x30(%rbx),%rax if (!(is_multicast_ether_addr(f->eth_addr) || is_zero_ether_addr(f->eth_addr))) { notify |= vxlan_fdb_replace(f, ip, port, vni, ifindex); } else return -EOPNOTSUPP; 2882: 48 83 f8 28 cmp $0x28,%rax 2886: 0f 84 e5 fd ff ff je 2671 return list_entry_rcu(fdb->remotes.next, struct vxlan_rdst, list); } static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb) { return list_first_entry(&fdb->remotes, struct vxlan_rdst, list); 288c: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # 2893 2893: 48 8b 7d b8 mov -0x48(%rbp),%rdi vxlan_fdb_head(vxlan, mac)); } if (notify) { if (rd == NULL) rd = first_remote_rtnl(f); 2897: 0f b7 75 c0 movzwl -0x40(%rbp),%esi 289b: 48 89 50 28 mov %rdx,0x28(%rax) }) static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; 289f: 48 8b 17 mov (%rdi),%rdx rd = vxlan_fdb_find_rdst(f, ip, port, vni, ifindex); if (rd) return 0; rd = list_first_entry_or_null(&f->remotes, struct vxlan_rdst, list); 28a2: 48 89 50 d8 mov %rdx,-0x28(%rax) 28a6: 48 8b 57 08 mov 0x8(%rdi),%rdx 28aa: 48 89 50 e0 mov %rdx,-0x20(%rax) 28ae: 48 8b 57 10 mov 0x10(%rdi),%rdx if (!rd) 28b2: 48 89 50 e8 mov %rdx,-0x18(%rax) 28b6: 8b 57 18 mov 0x18(%rdi),%edx 28b9: 66 89 70 f4 mov %si,-0xc(%rax) * This do not free the cached dst to avoid races and contentions. * the dst will be freed on later cache lookup. */ static inline void dst_cache_reset(struct dst_cache *dst_cache) { dst_cache->reset_ts = jiffies; 28bd: 8b 7d 10 mov 0x10(%rbp),%edi 28c0: 8b 75 18 mov 0x18(%rbp),%esi return 0; dst_cache_reset(&rd->dst_cache); rd->remote_ip = *ip; 28c3: 89 50 f0 mov %edx,-0x10(%rax) 28c6: ba 01 00 00 00 mov $0x1,%edx 28cb: 89 78 f8 mov %edi,-0x8(%rax) 28ce: 89 70 fc mov %esi,-0x4(%rax) 28d1: e9 9b fd ff ff jmpq 2671 28d6: b8 fe ff ff ff mov $0xfffffffe,%eax 28db: e9 00 fe ff ff jmpq 26e0 28e0: b8 e4 ff ff ff mov $0xffffffe4,%eax 28e5: e9 f6 fd ff ff jmpq 26e0 rd->remote_port = port; 28ea: b8 f4 ff ff ff mov $0xfffffff4,%eax rd->remote_vni = vni; 28ef: e9 ec fd ff ff jmpq 26e0 rd = list_first_entry_or_null(&f->remotes, struct vxlan_rdst, list); if (!rd) return 0; dst_cache_reset(&rd->dst_cache); rd->remote_ip = *ip; 28f4: e8 00 00 00 00 callq 28f9 rd->remote_port = port; rd->remote_vni = vni; rd->remote_ifindex = ifindex; return 1; 28f9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000002900 : dst_cache_reset(&rd->dst_cache); rd->remote_ip = *ip; rd->remote_port = port; rd->remote_vni = vni; rd->remote_ifindex = ifindex; 2900: e8 00 00 00 00 callq 2905 2905: 55 push %rbp return rc; notify |= rc; } } else { if (!(flags & NLM_F_CREATE)) return -ENOENT; 2906: 48 89 e5 mov %rsp,%rbp 2909: 41 57 push %r15 290b: 41 56 push %r14 290d: 41 55 push %r13 290f: 41 54 push %r12 if (vxlan->cfg.addrmax && vxlan->addrcnt >= vxlan->cfg.addrmax) return -ENOSPC; 2911: 49 89 d4 mov %rdx,%r12 2914: 53 push %rbx 2915: 48 89 f3 mov %rsi,%rbx 2918: 4c 8d ae 40 08 00 00 lea 0x840(%rsi),%r13 return -EOPNOTSUPP; netdev_dbg(vxlan->dev, "add %pM -> %pIS\n", mac, ip); f = kmalloc(sizeof(*f), GFP_ATOMIC); if (!f) return -ENOMEM; 291f: 48 83 ec 20 sub $0x20,%rsp 2923: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 2929 rd = first_remote_rtnl(f); vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH); } return 0; } 2929: 48 8b 97 88 14 00 00 mov 0x1488(%rdi),%rdx return ret; } static int vxlan_dev_configure(struct net *src_net, struct net_device *dev, struct vxlan_config *conf) { 2930: 0f b7 8e 7c 09 00 00 movzwl 0x97c(%rsi),%ecx 2937: 83 e8 01 sub $0x1,%eax 293a: 48 98 cltq 293c: 4c 8b 74 c2 18 mov 0x18(%rdx,%rax,8),%r14 2941: 41 8b 44 24 50 mov 0x50(%r12),%eax 2946: f6 c4 40 test $0x40,%ah 2949: 0f 84 82 02 00 00 je 2bd1 294f: 25 1f be ff ff and $0xffffbe1f,%eax 2954: 3d 00 20 00 00 cmp $0x2000,%eax 2959: 0f 85 0a 05 00 00 jne 2e69 295f: 41 b9 fe ff ff ff mov $0xfffffffe,%r9d struct vxlan_dev *vxlan = netdev_priv(dev), *tmp; struct vxlan_rdst *dst = &vxlan->default_dst; unsigned short needed_headroom = ETH_HLEN; int err; bool use_ipv6 = false; __be16 default_port = vxlan->cfg.dst_port; 2965: 45 31 d2 xor %r10d,%r10d 2968: 48 c7 86 30 02 00 00 movq $0x0,0x230(%rsi) 296f: 00 00 00 00 struct net_device *lowerdev = NULL; if (conf->flags & VXLAN_F_GPE) { 2973: 66 44 89 8e 4c 02 00 mov %r9w,0x24c(%rsi) 297a: 00 297b: 66 44 89 96 4e 02 00 mov %r10w,0x24e(%rsi) 2982: 00 /* For now, allow GPE only together with COLLECT_METADATA. * This can be relaxed later; in such case, the other side * of the PtP link will have to be provided. */ if ((conf->flags & ~VXLAN_F_ALLOWED_GPE) || 2983: c6 86 75 02 00 00 00 movb $0x0,0x275(%rsi) 298a: c7 86 38 02 00 00 90 movl $0x1090,0x238(%rsi) 2991: 10 00 00 } static void vxlan_raw_setup(struct net_device *dev) { dev->header_ops = NULL; dev->type = ARPHRD_NONE; 2994: 48 c7 86 10 02 00 00 movq $0x0,0x210(%rsi) 299b: 00 00 00 00 dev->netdev_ops = &vxlan_netdev_ether_ops; } static void vxlan_raw_setup(struct net_device *dev) { dev->header_ops = NULL; 299f: 48 89 bb 78 08 00 00 mov %rdi,0x878(%rbx) dev->type = ARPHRD_NONE; 29a6: 41 8b 44 24 38 mov 0x38(%r12),%eax dev->hard_header_len = 0; 29ab: 4c 8d bb 80 08 00 00 lea 0x880(%rbx),%r15 29b2: 89 83 a0 08 00 00 mov %eax,0x8a0(%rbx) dev->addr_len = 0; 29b8: 49 8b 04 24 mov (%r12),%rax dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; 29bc: 48 89 83 80 08 00 00 mov %rax,0x880(%rbx) 29c3: 49 8b 44 24 08 mov 0x8(%r12),%rax dev->netdev_ops = &vxlan_netdev_raw_ops; 29c8: 49 89 47 08 mov %rax,0x8(%r15) 29cc: 49 8b 44 24 10 mov 0x10(%r12),%rax vxlan_raw_setup(dev); } else { vxlan_ether_setup(dev); } vxlan->net = src_net; 29d1: 49 89 47 10 mov %rax,0x10(%r15) 29d5: 41 8b 44 24 18 mov 0x18(%r12),%eax dst->remote_vni = conf->vni; 29da: 41 89 47 18 mov %eax,0x18(%r15) memcpy(&dst->remote_ip, &conf->remote_ip, sizeof(conf->remote_ip)); 29de: 0f b7 83 80 08 00 00 movzwl 0x880(%rbx),%eax vxlan_ether_setup(dev); } vxlan->net = src_net; dst->remote_vni = conf->vni; 29e5: 66 85 c0 test %ax,%ax memcpy(&dst->remote_ip, &conf->remote_ip, sizeof(conf->remote_ip)); 29e8: 0f 85 b1 02 00 00 jne 2c9f 29ee: 41 b8 02 00 00 00 mov $0x2,%r8d 29f4: 66 44 89 83 80 08 00 mov %r8w,0x880(%rbx) 29fb: 00 29fc: 66 83 bb 54 09 00 00 cmpw $0xa,0x954(%rbx) 2a03: 0a 2a04: 0f 84 e2 02 00 00 je 2cec 2a0a: 41 8b 44 24 4c mov 0x4c(%r12),%eax /* Unless IPv6 is explicitly requested, assume IPv4 */ if (!dst->remote_ip.sa.sa_family) 2a0f: 85 c0 test %eax,%eax 2a11: 0f 85 26 04 00 00 jne 2e3d 2a17: 41 8b 74 24 3c mov 0x3c(%r12),%esi 2a1c: 85 f6 test %esi,%esi dst->remote_ip.sa.sa_family = AF_INET; 2a1e: 0f 85 e6 02 00 00 jne 2d0a 2a24: 31 ff xor %edi,%edi 2a26: 8b 83 84 08 00 00 mov 0x884(%rbx),%eax if (dst->remote_ip.sa.sa_family == AF_INET6 || 2a2c: 25 f0 00 00 00 and $0xf0,%eax 2a31: 3d e0 00 00 00 cmp $0xe0,%eax 2a36: 0f 94 c0 sete %al 2a39: 84 c0 test %al,%al return -EPFNOSUPPORT; use_ipv6 = true; vxlan->flags |= VXLAN_F_IPV6; } if (conf->label && !use_ipv6) { 2a3b: 0f 85 12 04 00 00 jne 2e53 2a41: 41 8b 74 24 40 mov 0x40(%r12),%esi 2a46: 41 b8 0e 00 00 00 mov $0xe,%r8d pr_info("label only supported in use with IPv6\n"); return -EINVAL; } if (conf->remote_ifindex) { 2a4c: 85 f6 test %esi,%esi 2a4e: 0f 85 c9 03 00 00 jne 2e1d struct vxlan_net *vn = net_generic(src_net, vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev), *tmp; struct vxlan_rdst *dst = &vxlan->default_dst; unsigned short needed_headroom = ETH_HLEN; int err; bool use_ipv6 = false; 2a54: 40 84 ff test %dil,%dil static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr); else return IN_MULTICAST(ntohl(ipa->sin.sin_addr.s_addr)); 2a57: 75 0c jne 2a65 2a59: 41 f6 44 24 51 20 testb $0x20,0x51(%r12) 2a5f: 41 8d 40 32 lea 0x32(%r8),%eax 2a63: 74 04 je 2a69 2a65: 41 8d 40 46 lea 0x46(%r8),%eax if (!conf->mtu) dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); needed_headroom = lowerdev->hard_header_len; } else if (vxlan_addr_multicast(&dst->remote_ip)) { 2a69: 66 89 83 50 02 00 00 mov %ax,0x250(%rbx) 2a70: 49 8b 14 24 mov (%r12),%rdx pr_info("multicast destination requires interface to be specified\n"); return -EINVAL; } if (conf->mtu) { 2a74: 48 89 93 38 09 00 00 mov %rdx,0x938(%rbx) struct vxlan_config *conf) { struct vxlan_net *vn = net_generic(src_net, vxlan_net_id); struct vxlan_dev *vxlan = netdev_priv(dev), *tmp; struct vxlan_rdst *dst = &vxlan->default_dst; unsigned short needed_headroom = ETH_HLEN; 2a7b: 49 8b 54 24 08 mov 0x8(%r12),%rdx } else if (vxlan_addr_multicast(&dst->remote_ip)) { pr_info("multicast destination requires interface to be specified\n"); return -EINVAL; } if (conf->mtu) { 2a80: 48 89 93 40 09 00 00 mov %rdx,0x940(%rbx) err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false); if (err) return err; } if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) 2a87: 49 8b 54 24 10 mov 0x10(%r12),%rdx 2a8c: 48 89 93 48 09 00 00 mov %rdx,0x948(%rbx) 2a93: 49 8b 54 24 18 mov 0x18(%r12),%rdx needed_headroom += VXLAN6_HEADROOM; 2a98: 48 89 93 50 09 00 00 mov %rdx,0x950(%rbx) else needed_headroom += VXLAN_HEADROOM; dev->needed_headroom = needed_headroom; 2a9f: 49 8b 54 24 20 mov 0x20(%r12),%rdx memcpy(&vxlan->cfg, conf, sizeof(*conf)); 2aa4: 48 89 93 58 09 00 00 mov %rdx,0x958(%rbx) 2aab: 49 8b 54 24 28 mov 0x28(%r12),%rdx 2ab0: 48 89 93 60 09 00 00 mov %rdx,0x960(%rbx) 2ab7: 49 8b 54 24 30 mov 0x30(%r12),%rdx 2abc: 48 89 93 68 09 00 00 mov %rdx,0x968(%rbx) 2ac3: 49 8b 54 24 38 mov 0x38(%r12),%rdx 2ac8: 48 89 93 70 09 00 00 mov %rdx,0x970(%rbx) 2acf: 49 8b 54 24 40 mov 0x40(%r12),%rdx 2ad4: 48 89 93 78 09 00 00 mov %rdx,0x978(%rbx) 2adb: 49 8b 54 24 48 mov 0x48(%r12),%rdx 2ae0: 66 83 bb 7c 09 00 00 cmpw $0x0,0x97c(%rbx) 2ae7: 00 2ae8: 48 89 93 80 09 00 00 mov %rdx,0x980(%rbx) 2aef: 49 8b 54 24 50 mov 0x50(%r12),%rdx 2af4: 48 89 93 88 09 00 00 mov %rdx,0x988(%rbx) 2afb: 49 8b 54 24 58 mov 0x58(%r12),%rdx 2b00: 48 89 93 90 09 00 00 mov %rdx,0x990(%rbx) 2b07: 49 8b 54 24 60 mov 0x60(%r12),%rdx 2b0c: 48 89 93 98 09 00 00 mov %rdx,0x998(%rbx) if (!vxlan->cfg.dst_port) { 2b13: 75 15 jne 2b2a 2b15: 41 f6 44 24 51 40 testb $0x40,0x51(%r12) needed_headroom += VXLAN6_HEADROOM; else needed_headroom += VXLAN_HEADROOM; dev->needed_headroom = needed_headroom; memcpy(&vxlan->cfg, conf, sizeof(*conf)); 2b1b: b8 b6 12 00 00 mov $0x12b6,%eax 2b20: 0f 45 c8 cmovne %eax,%ecx 2b23: 66 89 8b 7c 09 00 00 mov %cx,0x97c(%rbx) 2b2a: 44 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%r8d 2b31: 45 0b 44 24 50 or 0x50(%r12),%r8d 2b36: 48 83 bb 90 09 00 00 cmpq $0x0,0x990(%rbx) 2b3d: 00 2b3e: 44 89 83 d8 08 00 00 mov %r8d,0x8d8(%rbx) if (!vxlan->cfg.dst_port) { if (conf->flags & VXLAN_F_GPE) vxlan->cfg.dst_port = 4790; /* IANA assigned VXLAN-GPE port */ 2b45: 75 0b jne 2b52 2b47: 48 c7 83 90 09 00 00 movq $0x12c,0x990(%rbx) 2b4e: 2c 01 00 00 2b52: 49 8b 16 mov (%r14),%rdx 2b55: 49 39 d6 cmp %rdx,%r14 2b58: 48 8d 42 f0 lea -0x10(%rdx),%rax else vxlan->cfg.dst_port = default_port; } vxlan->flags |= conf->flags; 2b5c: 0f 84 91 00 00 00 je 2bf3 2b62: 41 8b 74 24 38 mov 0x38(%r12),%esi if (!vxlan->cfg.age_interval) 2b67: eb 0d jmp 2b76 2b69: 48 8b 48 10 mov 0x10(%rax),%rcx 2b6d: 49 39 ce cmp %rcx,%r14 if (conf->flags & VXLAN_F_GPE) vxlan->cfg.dst_port = 4790; /* IANA assigned VXLAN-GPE port */ else vxlan->cfg.dst_port = default_port; } vxlan->flags |= conf->flags; 2b70: 48 8d 41 f0 lea -0x10(%rcx),%rax 2b74: 74 7d je 2bf3 if (!vxlan->cfg.age_interval) 2b76: 39 b0 30 01 00 00 cmp %esi,0x130(%rax) vxlan->cfg.age_interval = FDB_AGE_DEFAULT; 2b7c: 75 eb jne 2b69 2b7e: 66 83 78 40 0a cmpw $0xa,0x40(%rax) list_for_each_entry(tmp, &vn->vxlan_list, next) { 2b83: ba 01 00 00 00 mov $0x1,%edx 2b88: 74 0d je 2b97 2b8a: 31 d2 xor %edx,%edx 2b8c: 66 83 b8 14 01 00 00 cmpw $0xa,0x114(%rax) 2b93: 0a 2b94: 0f 94 c2 sete %dl 2b97: 39 fa cmp %edi,%edx 2b99: 75 ce jne 2b69 2b9b: 0f b7 93 7c 09 00 00 movzwl 0x97c(%rbx),%edx 2ba2: 66 39 90 3c 01 00 00 cmp %dx,0x13c(%rax) if (tmp->cfg.vni == conf->vni && 2ba9: 75 be jne 2b69 2bab: 8b 90 98 00 00 00 mov 0x98(%rax),%edx (tmp->default_dst.remote_ip.sa.sa_family == AF_INET6 || 2bb1: 44 31 c2 xor %r8d,%edx 2bb4: 80 e6 7d and $0x7d,%dh 2bb7: 75 b0 jne 2b69 2bb9: 0f ce bswap %esi 2bbb: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 2bc2: e8 00 00 00 00 callq 2bc7 if (!vxlan->cfg.age_interval) vxlan->cfg.age_interval = FDB_AGE_DEFAULT; list_for_each_entry(tmp, &vn->vxlan_list, next) { if (tmp->cfg.vni == conf->vni && 2bc7: b8 ef ff ff ff mov $0xffffffef,%eax (tmp->default_dst.remote_ip.sa.sa_family == AF_INET6 || tmp->cfg.saddr.sa.sa_family == AF_INET6) == use_ipv6 && 2bcc: e9 bf 00 00 00 jmpq 2c90 2bd1: 8b 86 3c 02 00 00 mov 0x23c(%rsi),%eax 2bd7: 48 c7 86 10 02 00 00 movq $0x0,0x210(%rsi) 2bde: 00 00 00 00 tmp->cfg.dst_port == vxlan->cfg.dst_port && 2be2: 80 e4 f7 and $0xf7,%ah 2be5: 80 cc 80 or $0x80,%ah 2be8: 89 86 3c 02 00 00 mov %eax,0x23c(%rsi) (tmp->flags & VXLAN_F_RCV_FLAGS) == (vxlan->flags & VXLAN_F_RCV_FLAGS)) { pr_info("duplicate VNI %u\n", be32_to_cpu(conf->vni)); 2bee: e9 ac fd ff ff jmpq 299f 2bf3: 66 83 bb 80 08 00 00 cmpw $0xa,0x880(%rbx) 2bfa: 0a return -EEXIST; 2bfb: 48 c7 83 18 02 00 00 movq $0x0,0x218(%rbx) 2c02: 00 00 00 00 } static void vxlan_ether_setup(struct net_device *dev) { dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 2c06: 0f 84 ca 00 00 00 je 2cd6 dev->netdev_ops = &vxlan_netdev_ether_ops; 2c0c: 8b 93 84 08 00 00 mov 0x884(%rbx),%edx } static void vxlan_ether_setup(struct net_device *dev) { dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; 2c12: 85 d2 test %edx,%edx 2c14: 0f 94 c0 sete %al 2c17: 84 c0 test %al,%al 2c19: 75 44 jne 2c5f 2c1b: 8b 83 a4 08 00 00 mov 0x8a4(%rbx),%eax 2c21: 44 0f b7 8b 7c 09 00 movzwl 0x97c(%rbx),%r9d 2c28: 00 return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 2c29: 41 b8 00 06 00 00 mov $0x600,%r8d pr_info("duplicate VNI %u\n", be32_to_cpu(conf->vni)); return -EEXIST; } } dev->ethtool_ops = &vxlan_ethtool_ops; 2c2f: c7 44 24 10 02 00 00 movl $0x2,0x10(%rsp) 2c36: 00 return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 2c37: b9 82 00 00 00 mov $0x82,%ecx return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); 2c3c: 4c 89 fa mov %r15,%rdx 2c3f: 48 c7 c6 00 00 00 00 mov $0x0,%rsi 2c46: 4c 89 ef mov %r13,%rdi } dev->ethtool_ops = &vxlan_ethtool_ops; /* create an fdb entry for a valid default destination */ if (!vxlan_addr_any(&vxlan->default_dst.remote_ip)) { 2c49: 89 44 24 08 mov %eax,0x8(%rsp) err = vxlan_fdb_create(vxlan, all_zeros_mac, 2c4d: 8b 83 a0 08 00 00 mov 0x8a0(%rbx),%eax 2c53: 89 04 24 mov %eax,(%rsp) 2c56: e8 35 f9 ff ff callq 2590 2c5b: 85 c0 test %eax,%eax 2c5d: 75 31 jne 2c90 2c5f: 48 89 df mov %rbx,%rdi 2c62: e8 00 00 00 00 callq 2c67 2c67: 85 c0 test %eax,%eax 2c69: 0f 85 91 01 00 00 jne 2e00 2c6f: 49 8b 16 mov (%r14),%rdx 2c72: 48 8d 83 50 08 00 00 lea 0x850(%rbx),%rax 2c79: 48 89 42 08 mov %rax,0x8(%rdx) 2c7d: 48 89 93 50 08 00 00 mov %rdx,0x850(%rbx) 2c84: 4c 89 b3 58 08 00 00 mov %r14,0x858(%rbx) NLM_F_EXCL|NLM_F_CREATE, vxlan->cfg.dst_port, vxlan->default_dst.remote_vni, vxlan->default_dst.remote_ifindex, NTF_SELF); if (err) 2c8b: 49 89 06 mov %rax,(%r14) 2c8e: 31 c0 xor %eax,%eax return err; } err = register_netdevice(dev); 2c90: 48 83 c4 20 add $0x20,%rsp 2c94: 5b pop %rbx 2c95: 41 5c pop %r12 if (err) { 2c97: 41 5d pop %r13 2c99: 41 5e pop %r14 2c9b: 41 5f pop %r15 2c9d: 5d pop %rbp 2c9e: c3 retq * Insert a new entry after the specified head. * This is good for implementing stacks. */ static inline void list_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); 2c9f: 66 83 f8 0a cmp $0xa,%ax vxlan_fdb_delete_default(vxlan); return err; } list_add(&vxlan->next, &vn->vxlan_list); 2ca3: 0f 85 53 fd ff ff jne 29fc #ifndef CONFIG_DEBUG_LIST static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { next->prev = new; 2ca9: 83 8b d8 08 00 00 20 orl $0x20,0x8d8(%rbx) new->next = next; 2cb0: 41 8b 74 24 3c mov 0x3c(%r12),%esi new->prev = prev; 2cb5: 85 f6 test %esi,%esi 2cb7: 0f 85 dc 00 00 00 jne 2d99 { switch (size) { case 1: *(volatile __u8 *)p = *(__u8 *)res; break; case 2: *(volatile __u16 *)p = *(__u16 *)res; break; case 4: *(volatile __u32 *)p = *(__u32 *)res; break; case 8: *(volatile __u64 *)p = *(__u64 *)res; break; 2cbd: 0f b6 83 88 08 00 00 movzbl 0x888(%rbx),%eax return 0; } 2cc4: bf 01 00 00 00 mov $0x1,%edi 2cc9: 3d ff 00 00 00 cmp $0xff,%eax 2cce: 0f 94 c0 sete %al /* Unless IPv6 is explicitly requested, assume IPv4 */ if (!dst->remote_ip.sa.sa_family) dst->remote_ip.sa.sa_family = AF_INET; if (dst->remote_ip.sa.sa_family == AF_INET6 || 2cd1: e9 63 fd ff ff jmpq 2a39 2cd6: 48 8b 83 88 08 00 00 mov 0x888(%rbx),%rax vxlan->cfg.saddr.sa.sa_family == AF_INET6) { if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; use_ipv6 = true; vxlan->flags |= VXLAN_F_IPV6; 2cdd: 48 0b 83 90 08 00 00 or 0x890(%rbx),%rax if (conf->label && !use_ipv6) { pr_info("label only supported in use with IPv6\n"); return -EINVAL; } if (conf->remote_ifindex) { 2ce4: 0f 94 c0 sete %al 2ce7: e9 2b ff ff ff jmpq 2c17 2cec: 83 8b d8 08 00 00 20 orl $0x20,0x8d8(%rbx) return (a->s6_addr32[0] & htonl(0xfffffff0)) == htonl(0x20010010); } static inline bool ipv6_addr_is_multicast(const struct in6_addr *addr) { return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000); 2cf3: 41 8b 74 24 3c mov 0x3c(%r12),%esi if (dst->remote_ip.sa.sa_family == AF_INET6 || vxlan->cfg.saddr.sa.sa_family == AF_INET6) { if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; use_ipv6 = true; 2cf8: 85 f6 test %esi,%esi 2cfa: 0f 85 99 00 00 00 jne 2d99 2d00: bf 01 00 00 00 mov $0x1,%edi 2d05: e9 1c fd ff ff jmpq 2a26 static inline bool ipv6_addr_any(const struct in6_addr *a) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 const unsigned long *ul = (const unsigned long *)a; return (ul[0] | ul[1]) == 0UL; 2d0a: 89 4d d4 mov %ecx,-0x2c(%rbp) 2d0d: e8 00 00 00 00 callq 2d12 2d12: 41 8b 74 24 3c mov 0x3c(%r12),%esi 2d17: 48 85 c0 test %rax,%rax 2d1a: 8b 4d d4 mov -0x2c(%rbp),%ecx vxlan->flags |= VXLAN_F_IPV6; 2d1d: 89 b3 a4 08 00 00 mov %esi,0x8a4(%rbx) if (conf->label && !use_ipv6) { pr_info("label only supported in use with IPv6\n"); return -EINVAL; } if (conf->remote_ifindex) { 2d23: 0f 84 fe 00 00 00 je 2e27 2d29: 41 8b 54 24 40 mov 0x40(%r12),%edx 2d2e: 31 ff xor %edi,%edi if (dst->remote_ip.sa.sa_family == AF_INET6 || vxlan->cfg.saddr.sa.sa_family == AF_INET6) { if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; use_ipv6 = true; 2d30: 85 d2 test %edx,%edx 2d32: 0f 85 b9 00 00 00 jne 2df1 2d38: 8b 90 48 02 00 00 mov 0x248(%rax),%edx pr_info("label only supported in use with IPv6\n"); return -EINVAL; } if (conf->remote_ifindex) { lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); 2d3e: 31 ff xor %edi,%edi 2d40: be 32 00 00 00 mov $0x32,%esi dst->remote_ifindex = conf->remote_ifindex; 2d45: 29 f2 sub %esi,%edx if (!lowerdev) { 2d47: 89 93 48 02 00 00 mov %edx,0x248(%rbx) return -EINVAL; } if (conf->remote_ifindex) { lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); dst->remote_ifindex = conf->remote_ifindex; 2d4d: 41 8b 54 24 40 mov 0x40(%r12),%edx 2d52: 44 0f b7 80 4e 02 00 movzwl 0x24e(%rax),%r8d 2d59: 00 return -EPERM; } } #endif if (!conf->mtu) 2d5a: 85 d2 test %edx,%edx 2d5c: 0f 84 f2 fc ff ff je 2a54 2d62: 89 d6 mov %edx,%esi 2d64: 8b 80 48 02 00 00 mov 0x248(%rax),%eax dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); 2d6a: 8d 50 ba lea -0x46(%rax),%edx 2d6d: 83 e8 32 sub $0x32,%eax 2d70: 66 83 bb 80 08 00 00 cmpw $0xa,0x880(%rbx) 2d77: 0a 2d78: 0f 45 d0 cmovne %eax,%edx 2d7b: 83 fe 43 cmp $0x43,%esi 2d7e: b8 ea ff ff ff mov $0xffffffea,%eax needed_headroom = lowerdev->hard_header_len; 2d83: 0f 8e 07 ff ff ff jle 2c90 2d89: 39 f2 cmp %esi,%edx } else if (vxlan_addr_multicast(&dst->remote_ip)) { pr_info("multicast destination requires interface to be specified\n"); return -EINVAL; } if (conf->mtu) { 2d8b: 0f 4f d6 cmovg %esi,%edx 2d8e: 89 93 48 02 00 00 mov %edx,0x248(%rbx) struct vxlan_rdst *dst, int new_mtu, bool strict) { int max_mtu = IP_MAX_MTU; if (lowerdev) max_mtu = lowerdev->mtu; 2d94: e9 bb fc ff ff jmpq 2a54 2d99: 89 4d d4 mov %ecx,-0x2c(%rbp) if (dst->remote_ip.sa.sa_family == AF_INET6) max_mtu -= VXLAN6_HEADROOM; 2d9c: e8 00 00 00 00 callq 2da1 2da1: 41 8b 74 24 3c mov 0x3c(%r12),%esi 2da6: 48 85 c0 test %rax,%rax 2da9: 8b 4d d4 mov -0x2c(%rbp),%ecx else max_mtu -= VXLAN_HEADROOM; if (new_mtu < 68) 2dac: 89 b3 a4 08 00 00 mov %esi,0x8a4(%rbx) return -EINVAL; 2db2: 74 73 je 2e27 if (dst->remote_ip.sa.sa_family == AF_INET6) max_mtu -= VXLAN6_HEADROOM; else max_mtu -= VXLAN_HEADROOM; if (new_mtu < 68) 2db4: 48 8b 90 08 03 00 00 mov 0x308(%rax),%rdx return -EINVAL; new_mtu = max_mtu; } dev->mtu = new_mtu; 2dbb: 48 85 d2 test %rdx,%rdx 2dbe: 74 0e je 2dce 2dc0: 8b b2 38 02 00 00 mov 0x238(%rdx),%esi 2dc6: 85 f6 test %esi,%esi 2dc8: 0f 85 b1 00 00 00 jne 2e7f pr_info("label only supported in use with IPv6\n"); return -EINVAL; } if (conf->remote_ifindex) { lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); 2dce: 41 8b 54 24 40 mov 0x40(%r12),%edx dst->remote_ifindex = conf->remote_ifindex; 2dd3: bf 01 00 00 00 mov $0x1,%edi if (!lowerdev) { 2dd8: 85 d2 test %edx,%edx 2dda: 75 15 jne 2df1 return -EINVAL; } if (conf->remote_ifindex) { lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); dst->remote_ifindex = conf->remote_ifindex; 2ddc: 8b 90 48 02 00 00 mov 0x248(%rax),%edx if (!lowerdev) { 2de2: bf 01 00 00 00 mov $0x1,%edi }) static __always_inline void __read_once_size(const volatile void *p, void *res, int size) { __READ_ONCE_SIZE; 2de7: be 46 00 00 00 mov $0x46,%esi } #if IS_ENABLED(CONFIG_IPV6) if (use_ipv6) { struct inet6_dev *idev = __in6_dev_get(lowerdev); if (idev && idev->cnf.disable_ipv6) { 2dec: e9 54 ff ff ff jmpq 2d45 2df1: 44 0f b7 80 4e 02 00 movzwl 0x24e(%rax),%r8d 2df8: 00 2df9: 89 d6 mov %edx,%esi 2dfb: e9 64 ff ff ff jmpq 2d64 return -EPERM; } } #endif if (!conf->mtu) 2e00: 4c 89 ef mov %r13,%rdi 2e03: 89 45 d4 mov %eax,-0x2c(%rbp) 2e06: e8 c5 f1 ff ff callq 1fd0 2e0b: 8b 45 d4 mov -0x2c(%rbp),%eax dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); 2e0e: 48 83 c4 20 add $0x20,%rsp 2e12: 5b pop %rbx 2e13: 41 5c pop %r12 2e15: 41 5d pop %r13 2e17: 41 5e pop %r14 2e19: 41 5f pop %r15 2e1b: 5d pop %rbp 2e1c: c3 retq 2e1d: b8 ff ff 00 00 mov $0xffff,%eax needed_headroom = lowerdev->hard_header_len; 2e22: e9 43 ff ff ff jmpq 2d6a 2e27: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 2e2e: e8 00 00 00 00 callq 2e33 return err; } err = register_netdevice(dev); if (err) { vxlan_fdb_delete_default(vxlan); 2e33: b8 ed ff ff ff mov $0xffffffed,%eax 2e38: e9 53 fe ff ff jmpq 2c90 return err; 2e3d: 48 c7 c7 00 00 00 00 mov $0x0,%rdi } list_add(&vxlan->next, &vn->vxlan_list); return 0; } 2e44: e8 00 00 00 00 callq 2e49 2e49: b8 ea ff ff ff mov $0xffffffea,%eax static int __vxlan_change_mtu(struct net_device *dev, struct net_device *lowerdev, struct vxlan_rdst *dst, int new_mtu, bool strict) { int max_mtu = IP_MAX_MTU; 2e4e: e9 3d fe ff ff jmpq 2c90 2e53: 48 c7 c7 00 00 00 00 mov $0x0,%rdi if (conf->remote_ifindex) { lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex); dst->remote_ifindex = conf->remote_ifindex; if (!lowerdev) { pr_info("ifindex %d does not exist\n", dst->remote_ifindex); 2e5a: e8 00 00 00 00 callq 2e5f 2e5f: b8 ea ff ff ff mov $0xffffffea,%eax return -ENODEV; 2e64: e9 27 fe ff ff jmpq 2c90 2e69: 48 c7 c7 00 00 00 00 mov $0x0,%rdi use_ipv6 = true; vxlan->flags |= VXLAN_F_IPV6; } if (conf->label && !use_ipv6) { pr_info("label only supported in use with IPv6\n"); 2e70: e8 00 00 00 00 callq 2e75 2e75: b8 ea ff ff ff mov $0xffffffea,%eax return -EINVAL; 2e7a: e9 11 fe ff ff jmpq 2c90 2e7f: 48 c7 c7 00 00 00 00 mov $0x0,%rdi if (!conf->mtu) dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); needed_headroom = lowerdev->hard_header_len; } else if (vxlan_addr_multicast(&dst->remote_ip)) { pr_info("multicast destination requires interface to be specified\n"); 2e86: e8 00 00 00 00 callq 2e8b 2e8b: b8 ff ff ff ff mov $0xffffffff,%eax return -EINVAL; 2e90: e9 fb fd ff ff jmpq 2c90 2e95: 90 nop 2e96: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 2e9d: 00 00 00 0000000000002ea0 : * This can be relaxed later; in such case, the other side * of the PtP link will have to be provided. */ if ((conf->flags & ~VXLAN_F_ALLOWED_GPE) || !(conf->flags & VXLAN_F_COLLECT_METADATA)) { pr_info("unsupported combination of extensions\n"); 2ea0: e8 00 00 00 00 callq 2ea5 return -EINVAL; 2ea5: 55 push %rbp 2ea6: 48 89 e5 mov %rsp,%rbp 2ea9: 41 57 push %r15 2eab: 41 56 push %r14 2ead: 41 55 push %r13 #if IS_ENABLED(CONFIG_IPV6) if (use_ipv6) { struct inet6_dev *idev = __in6_dev_get(lowerdev); if (idev && idev->cnf.disable_ipv6) { pr_info("IPv6 is disabled via sysctl\n"); 2eaf: 41 54 push %r12 2eb1: 49 89 fd mov %rdi,%r13 2eb4: 53 push %rbx 2eb5: 48 89 cb mov %rcx,%rbx 2eb8: b9 0d 00 00 00 mov $0xd,%ecx return -EPERM; 2ebd: 49 89 f6 mov %rsi,%r14 2ec0: 49 89 d7 mov %rdx,%r15 2ec3: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 2ec7: 48 83 c4 80 add $0xffffffffffffff80,%rsp 2ecb: 4c 8d 64 24 10 lea 0x10(%rsp),%r12 return 0; } static int vxlan_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { 2ed0: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 2ed7: 00 00 2ed9: 48 89 44 24 78 mov %rax,0x78(%rsp) 2ede: 31 c0 xor %eax,%eax 2ee0: 4c 89 e7 mov %r12,%rdi 2ee3: f3 48 ab rep stos %rax,%es:(%rdi) 2ee6: 48 8b 43 08 mov 0x8(%rbx),%rax struct vxlan_config conf; memset(&conf, 0, sizeof(conf)); 2eea: 48 85 c0 test %rax,%rax return 0; } static int vxlan_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { 2eed: 74 09 je 2ef8 2eef: 8b 40 04 mov 0x4(%rax),%eax 2ef2: 0f c8 bswap %eax 2ef4: 89 44 24 48 mov %eax,0x48(%rsp) 2ef8: 48 8b 43 10 mov 0x10(%rbx),%rax struct vxlan_config conf; memset(&conf, 0, sizeof(conf)); 2efc: 48 85 c0 test %rax,%rax 2eff: 0f 84 df 02 00 00 je 31e4 return 0; } static int vxlan_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { 2f05: 8b 40 04 mov 0x4(%rax),%eax 2f08: 89 44 24 14 mov %eax,0x14(%rsp) 2f0c: 48 8b 43 20 mov 0x20(%rbx),%rax struct vxlan_config conf; memset(&conf, 0, sizeof(conf)); 2f10: 48 85 c0 test %rax,%rax 2f13: 0f 84 8c 02 00 00 je 31a5 if (data[IFLA_VXLAN_ID]) 2f19: 8b 40 04 mov 0x4(%rax),%eax 2f1c: ba 02 00 00 00 mov $0x2,%edx conf.vni = cpu_to_be32(nla_get_u32(data[IFLA_VXLAN_ID])); 2f21: 66 89 54 24 2c mov %dx,0x2c(%rsp) 2f26: 89 44 24 30 mov %eax,0x30(%rsp) if (data[IFLA_VXLAN_GROUP]) { 2f2a: 48 8b 43 18 mov 0x18(%rbx),%rax 2f2e: 48 85 c0 test %rax,%rax 2f31: 74 07 je 2f3a 2f33: 8b 40 04 mov 0x4(%rax),%eax * nla_get_in_addr - return payload of IPv4 address attribute * @nla: IPv4 address netlink attribute */ static inline __be32 nla_get_in_addr(const struct nlattr *nla) { return *(__be32 *) nla_data(nla); 2f36: 89 44 24 4c mov %eax,0x4c(%rsp) conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]); 2f3a: 48 8b 43 30 mov 0x30(%rbx),%rax conf.remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]); conf.remote_ip.sa.sa_family = AF_INET6; } if (data[IFLA_VXLAN_LOCAL]) { 2f3e: 48 85 c0 test %rax,%rax 2f41: 74 08 je 2f4b 2f43: 0f b6 40 04 movzbl 0x4(%rax),%eax 2f47: 88 44 24 5a mov %al,0x5a(%rsp) 2f4b: 48 8b 43 28 mov 0x28(%rbx),%rax conf.saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]); conf.saddr.sa.sa_family = AF_INET; 2f4f: 48 85 c0 test %rax,%rax 2f52: 74 08 je 2f5c 2f54: 0f b6 40 04 movzbl 0x4(%rax),%eax conf.remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]); conf.remote_ip.sa.sa_family = AF_INET6; } if (data[IFLA_VXLAN_LOCAL]) { conf.saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]); 2f58: 88 44 24 5b mov %al,0x5b(%rsp) /* TODO: respect scope id */ conf.saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]); conf.saddr.sa.sa_family = AF_INET6; } if (data[IFLA_VXLAN_LINK]) 2f5c: 48 8b 83 d0 00 00 00 mov 0xd0(%rbx),%rax conf.remote_ifindex = nla_get_u32(data[IFLA_VXLAN_LINK]); 2f63: 48 85 c0 test %rax,%rax 2f66: 74 0c je 2f74 2f68: 8b 40 04 mov 0x4(%rax),%eax if (data[IFLA_VXLAN_TOS]) 2f6b: 25 00 0f ff ff and $0xffff0f00,%eax 2f70: 89 44 24 5c mov %eax,0x5c(%rsp) * nla_get_u8 - return payload of u8 attribute * @nla: u8 netlink attribute */ static inline u8 nla_get_u8(const struct nlattr *nla) { return *(u8 *) nla_data(nla); 2f74: 48 8b 43 38 mov 0x38(%rbx),%rax conf.tos = nla_get_u8(data[IFLA_VXLAN_TOS]); 2f78: 48 85 c0 test %rax,%rax if (data[IFLA_VXLAN_TTL]) 2f7b: 0f 84 a7 01 00 00 je 3128 2f81: 80 78 04 00 cmpb $0x0,0x4(%rax) 2f85: 0f 85 9d 01 00 00 jne 3128 conf.ttl = nla_get_u8(data[IFLA_VXLAN_TTL]); 2f8b: 48 8b 43 40 mov 0x40(%rbx),%rax if (data[IFLA_VXLAN_LABEL]) 2f8f: 48 85 c0 test %rax,%rax 2f92: 74 08 je 2f9c 2f94: 8b 40 04 mov 0x4(%rax),%eax 2f97: 48 89 44 24 68 mov %rax,0x68(%rsp) conf.label = nla_get_be32(data[IFLA_VXLAN_LABEL]) & 2f9c: 48 8b 43 58 mov 0x58(%rbx),%rax 2fa0: 48 85 c0 test %rax,%rax 2fa3: 74 0a je 2faf IPV6_FLOWLABEL_MASK; if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING])) 2fa5: 80 78 04 00 cmpb $0x0,0x4(%rax) 2fa9: 0f 85 ec 01 00 00 jne 319b 2faf: 48 8b 43 60 mov 0x60(%rbx),%rax 2fb3: 48 85 c0 test %rax,%rax 2fb6: 74 0a je 2fc2 2fb8: 80 78 04 00 cmpb $0x0,0x4(%rax) conf.flags |= VXLAN_F_LEARN; if (data[IFLA_VXLAN_AGEING]) 2fbc: 0f 85 cf 01 00 00 jne 3191 2fc2: 48 8b 43 68 mov 0x68(%rbx),%rax conf.age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]); 2fc6: 48 85 c0 test %rax,%rax 2fc9: 74 0a je 2fd5 2fcb: 80 78 04 00 cmpb $0x0,0x4(%rax) if (data[IFLA_VXLAN_PROXY] && nla_get_u8(data[IFLA_VXLAN_PROXY])) 2fcf: 0f 85 b2 01 00 00 jne 3187 2fd5: 48 8b 43 70 mov 0x70(%rbx),%rax 2fd9: 48 85 c0 test %rax,%rax 2fdc: 74 0a je 2fe8 2fde: 80 78 04 00 cmpb $0x0,0x4(%rax) conf.flags |= VXLAN_F_PROXY; if (data[IFLA_VXLAN_RSC] && nla_get_u8(data[IFLA_VXLAN_RSC])) 2fe2: 0f 85 95 01 00 00 jne 317d 2fe8: 48 8b 43 48 mov 0x48(%rbx),%rax 2fec: 48 85 c0 test %rax,%rax 2fef: 74 07 je 2ff8 2ff1: 8b 40 04 mov 0x4(%rax),%eax conf.flags |= VXLAN_F_RSC; if (data[IFLA_VXLAN_L2MISS] && nla_get_u8(data[IFLA_VXLAN_L2MISS])) 2ff4: 89 44 24 70 mov %eax,0x70(%rsp) 2ff8: 48 8b 83 c8 00 00 00 mov 0xc8(%rbx),%rax 2fff: 48 85 c0 test %rax,%rax 3002: 74 0a je 300e 3004: 80 78 04 00 cmpb $0x0,0x4(%rax) conf.flags |= VXLAN_F_L2MISS; if (data[IFLA_VXLAN_L3MISS] && nla_get_u8(data[IFLA_VXLAN_L3MISS])) 3008: 0f 85 62 01 00 00 jne 3170 300e: 48 8b 43 50 mov 0x50(%rbx),%rax 3012: 48 85 c0 test %rax,%rax 3015: 74 1a je 3031 3017: 0f b7 50 04 movzwl 0x4(%rax),%edx conf.flags |= VXLAN_F_L3MISS; if (data[IFLA_VXLAN_LIMIT]) 301b: 66 c1 c2 08 rol $0x8,%dx 301f: 66 89 54 24 56 mov %dx,0x56(%rsp) conf.addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]); 3024: 0f b7 40 06 movzwl 0x6(%rax),%eax if (data[IFLA_VXLAN_COLLECT_METADATA] && 3028: 66 c1 c0 08 rol $0x8,%ax 302c: 66 89 44 24 58 mov %ax,0x58(%rsp) 3031: 48 8b 43 78 mov 0x78(%rbx),%rax 3035: 48 85 c0 test %rax,%rax 3038: 74 09 je 3043 303a: 0f b7 40 04 movzwl 0x4(%rax),%eax nla_get_u8(data[IFLA_VXLAN_COLLECT_METADATA])) conf.flags |= VXLAN_F_COLLECT_METADATA; if (data[IFLA_VXLAN_PORT_RANGE]) { 303e: 66 89 44 24 54 mov %ax,0x54(%rsp) 3043: 48 8b 83 90 00 00 00 mov 0x90(%rbx),%rax const struct ifla_vxlan_port_range *p = nla_data(data[IFLA_VXLAN_PORT_RANGE]); conf.port_min = ntohs(p->low); 304a: 48 85 c0 test %rax,%rax 304d: 74 0a je 3059 304f: 80 78 04 00 cmpb $0x0,0x4(%rax) 3053: 0f 84 0d 01 00 00 je 3166 conf.port_max = ntohs(p->high); 3059: 48 8b 83 98 00 00 00 mov 0x98(%rbx),%rax 3060: 48 85 c0 test %rax,%rax } if (data[IFLA_VXLAN_PORT]) 3063: 74 0a je 306f 3065: 80 78 04 00 cmpb $0x0,0x4(%rax) 3069: 0f 85 ea 00 00 00 jne 3159 conf.dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); 306f: 48 8b 83 a0 00 00 00 mov 0xa0(%rbx),%rax if (data[IFLA_VXLAN_UDP_CSUM] && 3076: 48 85 c0 test %rax,%rax 3079: 74 0a je 3085 307b: 80 78 04 00 cmpb $0x0,0x4(%rax) 307f: 0f 85 c7 00 00 00 jne 314c 3085: 48 8b 83 a8 00 00 00 mov 0xa8(%rbx),%rax !nla_get_u8(data[IFLA_VXLAN_UDP_CSUM])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM_TX; if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX] && 308c: 48 85 c0 test %rax,%rax 308f: 74 0a je 309b 3091: 80 78 04 00 cmpb $0x0,0x4(%rax) 3095: 0f 85 a4 00 00 00 jne 313f 309b: 48 8b 83 b0 00 00 00 mov 0xb0(%rbx),%rax nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX] && 30a2: 48 85 c0 test %rax,%rax 30a5: 74 0a je 30b1 30a7: 80 78 04 00 cmpb $0x0,0x4(%rax) 30ab: 0f 85 81 00 00 00 jne 3132 30b1: 48 83 bb b8 00 00 00 cmpq $0x0,0xb8(%rbx) 30b8: 00 nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM6_RX; if (data[IFLA_VXLAN_REMCSUM_TX] && 30b9: 74 08 je 30c3 30bb: 81 4c 24 60 00 08 00 orl $0x800,0x60(%rsp) 30c2: 00 30c3: 48 83 bb d8 00 00 00 cmpq $0x0,0xd8(%rbx) 30ca: 00 nla_get_u8(data[IFLA_VXLAN_REMCSUM_TX])) conf.flags |= VXLAN_F_REMCSUM_TX; if (data[IFLA_VXLAN_REMCSUM_RX] && 30cb: 74 08 je 30d5 30cd: 81 4c 24 60 00 40 00 orl $0x4000,0x60(%rsp) 30d4: 00 30d5: 48 83 bb c0 00 00 00 cmpq $0x0,0xc0(%rbx) 30dc: 00 30dd: 74 08 je 30e7 30df: 81 4c 24 60 00 10 00 orl $0x1000,0x60(%rsp) 30e6: 00 nla_get_u8(data[IFLA_VXLAN_REMCSUM_RX])) conf.flags |= VXLAN_F_REMCSUM_RX; if (data[IFLA_VXLAN_GBP]) 30e7: 49 8b 47 20 mov 0x20(%r15),%rax conf.flags |= VXLAN_F_GBP; 30eb: 48 85 c0 test %rax,%rax 30ee: 74 07 je 30f7 30f0: 8b 40 04 mov 0x4(%rax),%eax if (data[IFLA_VXLAN_GPE]) 30f3: 89 44 24 50 mov %eax,0x50(%rsp) 30f7: 4c 89 e2 mov %r12,%rdx 30fa: 4c 89 f6 mov %r14,%rsi conf.flags |= VXLAN_F_GPE; 30fd: 4c 89 ef mov %r13,%rdi 3100: e8 fb f7 ff ff callq 2900 if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) 3105: 48 8b 4c 24 78 mov 0x78(%rsp),%rcx 310a: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx 3111: 00 00 conf.flags |= VXLAN_F_REMCSUM_NOPARTIAL; 3113: 0f 85 0a 01 00 00 jne 3223 if (tb[IFLA_MTU]) 3119: 48 8d 65 d8 lea -0x28(%rbp),%rsp 311d: 5b pop %rbx 311e: 41 5c pop %r12 conf.mtu = nla_get_u32(tb[IFLA_MTU]); 3120: 41 5d pop %r13 3122: 41 5e pop %r14 3124: 41 5f pop %r15 3126: 5d pop %rbp return vxlan_dev_configure(src_net, dev, &conf); 3127: c3 retq 3128: 83 4c 24 60 01 orl $0x1,0x60(%rsp) 312d: e9 59 fe ff ff jmpq 2f8b 3132: 81 4c 24 60 00 04 00 orl $0x400,0x60(%rsp) 3139: 00 } 313a: e9 72 ff ff ff jmpq 30b1 313f: 81 4c 24 60 00 02 00 orl $0x200,0x60(%rsp) 3146: 00 3147: e9 4f ff ff ff jmpq 309b 314c: 81 4c 24 60 00 01 00 orl $0x100,0x60(%rsp) 3153: 00 3154: e9 2c ff ff ff jmpq 3085 if (data[IFLA_VXLAN_LABEL]) conf.label = nla_get_be32(data[IFLA_VXLAN_LABEL]) & IPV6_FLOWLABEL_MASK; if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING])) conf.flags |= VXLAN_F_LEARN; 3159: 81 4c 24 60 80 00 00 orl $0x80,0x60(%rsp) 3160: 00 3161: e9 09 ff ff ff jmpq 306f nla_get_u8(data[IFLA_VXLAN_REMCSUM_TX])) conf.flags |= VXLAN_F_REMCSUM_TX; if (data[IFLA_VXLAN_REMCSUM_RX] && nla_get_u8(data[IFLA_VXLAN_REMCSUM_RX])) conf.flags |= VXLAN_F_REMCSUM_RX; 3166: 83 4c 24 60 40 orl $0x40,0x60(%rsp) 316b: e9 e9 fe ff ff jmpq 3059 nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM6_RX; if (data[IFLA_VXLAN_REMCSUM_TX] && nla_get_u8(data[IFLA_VXLAN_REMCSUM_TX])) conf.flags |= VXLAN_F_REMCSUM_TX; 3170: 81 4c 24 60 00 20 00 orl $0x2000,0x60(%rsp) 3177: 00 3178: e9 91 fe ff ff jmpq 300e nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX] && nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM6_RX; 317d: 83 4c 24 60 10 orl $0x10,0x60(%rsp) 3182: e9 61 fe ff ff jmpq 2fe8 3187: 83 4c 24 60 08 orl $0x8,0x60(%rsp) !nla_get_u8(data[IFLA_VXLAN_UDP_CSUM])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM_TX; if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX] && nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; 318c: e9 44 fe ff ff jmpq 2fd5 3191: 83 4c 24 60 04 orl $0x4,0x60(%rsp) if (data[IFLA_VXLAN_PORT]) conf.dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); if (data[IFLA_VXLAN_UDP_CSUM] && !nla_get_u8(data[IFLA_VXLAN_UDP_CSUM])) conf.flags |= VXLAN_F_UDP_ZERO_CSUM_TX; 3196: e9 27 fe ff ff jmpq 2fc2 319b: 83 4c 24 60 02 orl $0x2,0x60(%rsp) if (data[IFLA_VXLAN_LIMIT]) conf.addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]); if (data[IFLA_VXLAN_COLLECT_METADATA] && nla_get_u8(data[IFLA_VXLAN_COLLECT_METADATA])) conf.flags |= VXLAN_F_COLLECT_METADATA; 31a0: e9 0a fe ff ff jmpq 2faf 31a5: 48 8b b3 88 00 00 00 mov 0x88(%rbx),%rsi 31ac: 48 85 f6 test %rsi,%rsi if (data[IFLA_VXLAN_L2MISS] && nla_get_u8(data[IFLA_VXLAN_L2MISS])) conf.flags |= VXLAN_F_L2MISS; if (data[IFLA_VXLAN_L3MISS] && nla_get_u8(data[IFLA_VXLAN_L3MISS])) conf.flags |= VXLAN_F_L3MISS; 31af: 0f 84 75 fd ff ff je 2f2a 31b5: ba 10 00 00 00 mov $0x10,%edx if (data[IFLA_VXLAN_RSC] && nla_get_u8(data[IFLA_VXLAN_RSC])) conf.flags |= VXLAN_F_RSC; if (data[IFLA_VXLAN_L2MISS] && nla_get_u8(data[IFLA_VXLAN_L2MISS])) conf.flags |= VXLAN_F_L2MISS; 31ba: 48 89 e7 mov %rsp,%rdi 31bd: e8 00 00 00 00 callq 31c2 if (data[IFLA_VXLAN_PROXY] && nla_get_u8(data[IFLA_VXLAN_PROXY])) conf.flags |= VXLAN_F_PROXY; if (data[IFLA_VXLAN_RSC] && nla_get_u8(data[IFLA_VXLAN_RSC])) conf.flags |= VXLAN_F_RSC; 31c2: 48 8b 04 24 mov (%rsp),%rax 31c6: 48 8b 54 24 08 mov 0x8(%rsp),%rdx if (data[IFLA_VXLAN_AGEING]) conf.age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]); if (data[IFLA_VXLAN_PROXY] && nla_get_u8(data[IFLA_VXLAN_PROXY])) conf.flags |= VXLAN_F_PROXY; 31cb: 48 89 44 24 34 mov %rax,0x34(%rsp) 31d0: b8 0a 00 00 00 mov $0xa,%eax } if (data[IFLA_VXLAN_LOCAL]) { conf.saddr.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_LOCAL]); conf.saddr.sa.sa_family = AF_INET; } else if (data[IFLA_VXLAN_LOCAL6]) { 31d5: 48 89 54 24 3c mov %rdx,0x3c(%rsp) 31da: 66 89 44 24 2c mov %ax,0x2c(%rsp) 31df: e9 46 fd ff ff jmpq 2f2a 31e4: 48 8b b3 80 00 00 00 mov 0x80(%rbx),%rsi */ static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla) { struct in6_addr tmp; nla_memcpy(&tmp, nla, sizeof(tmp)); 31eb: 48 85 f6 test %rsi,%rsi 31ee: 0f 84 18 fd ff ff je 2f0c return tmp; 31f4: ba 10 00 00 00 mov $0x10,%edx 31f9: 48 89 e7 mov %rsp,%rdi if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; /* TODO: respect scope id */ conf.saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]); 31fc: e8 00 00 00 00 callq 3201 conf.saddr.sa.sa_family = AF_INET6; 3201: 48 8b 04 24 mov (%rsp),%rax } else if (data[IFLA_VXLAN_LOCAL6]) { if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; /* TODO: respect scope id */ conf.saddr.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_LOCAL6]); 3205: 48 8b 54 24 08 mov 0x8(%rsp),%rdx conf.saddr.sa.sa_family = AF_INET6; 320a: b9 0a 00 00 00 mov $0xa,%ecx 320f: 66 89 4c 24 10 mov %cx,0x10(%rsp) if (data[IFLA_VXLAN_ID]) conf.vni = cpu_to_be32(nla_get_u32(data[IFLA_VXLAN_ID])); if (data[IFLA_VXLAN_GROUP]) { conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]); } else if (data[IFLA_VXLAN_GROUP6]) { 3214: 48 89 44 24 18 mov %rax,0x18(%rsp) 3219: 48 89 54 24 20 mov %rdx,0x20(%rsp) 321e: e9 e9 fc ff ff jmpq 2f0c 3223: e8 00 00 00 00 callq 3228 */ static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla) { struct in6_addr tmp; nla_memcpy(&tmp, nla, sizeof(tmp)); 3228: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1) 322f: 00 0000000000003230 : 3230: e8 00 00 00 00 callq 3235 return tmp; 3235: 55 push %rbp 3236: 0f b6 d2 movzbl %dl,%edx 3239: 48 89 e5 mov %rsp,%rbp if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; conf.remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]); conf.remote_ip.sa.sa_family = AF_INET6; 323c: 41 55 push %r13 323e: 41 54 push %r12 3240: 53 push %rbx 3241: 4c 8d 85 80 fe ff ff lea -0x180(%rbp),%r8 conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]); } else if (data[IFLA_VXLAN_GROUP6]) { if (!IS_ENABLED(CONFIG_IPV6)) return -EPFNOSUPPORT; conf.remote_ip.sin6.sin6_addr = nla_get_in6_addr(data[IFLA_VXLAN_GROUP6]); 3248: 49 89 fd mov %rdi,%r13 324b: 49 89 cc mov %rcx,%r12 324e: b9 2c 00 00 00 mov $0x2c,%ecx if (tb[IFLA_MTU]) conf.mtu = nla_get_u32(tb[IFLA_MTU]); return vxlan_dev_configure(src_net, dev, &conf); } 3253: 48 81 ec 80 01 00 00 sub $0x180,%rsp 325a: 4c 89 c7 mov %r8,%rdi 325d: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 3264: 00 00 struct net_device *dev; int err; memset(&tb, 0, sizeof(tb)); dev = rtnl_create_link(net, name, name_assign_type, 3266: 48 89 45 e0 mov %rax,-0x20(%rbp) }; struct net_device *vxlan_dev_create(struct net *net, const char *name, u8 name_assign_type, struct vxlan_config *conf) { 326a: 31 c0 xor %eax,%eax 326c: f3 48 ab rep stos %rax,%es:(%rdi) 326f: 48 c7 c1 00 00 00 00 mov $0x0,%rcx struct nlattr *tb[IFLA_MAX + 1]; struct net_device *dev; int err; memset(&tb, 0, sizeof(tb)); 3276: 4c 89 ef mov %r13,%rdi }; struct net_device *vxlan_dev_create(struct net *net, const char *name, u8 name_assign_type, struct vxlan_config *conf) { 3279: e8 00 00 00 00 callq 327e struct nlattr *tb[IFLA_MAX + 1]; struct net_device *dev; int err; memset(&tb, 0, sizeof(tb)); 327e: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax }; struct net_device *vxlan_dev_create(struct net *net, const char *name, u8 name_assign_type, struct vxlan_config *conf) { 3284: 48 89 c3 mov %rax,%rbx 3287: 0f 87 8e 00 00 00 ja 331b 328d: 4c 89 e2 mov %r12,%rdx 3290: 48 89 c6 mov %rax,%rsi 3293: 4c 89 ef mov %r13,%rdi 3296: e8 65 f6 ff ff callq 2900 329b: 85 c0 test %eax,%eax struct nlattr *tb[IFLA_MAX + 1]; struct net_device *dev; int err; memset(&tb, 0, sizeof(tb)); 329d: 78 31 js 32d0 dev = rtnl_create_link(net, name, name_assign_type, 329f: 31 f6 xor %esi,%esi 32a1: 48 89 df mov %rbx,%rdi 32a4: e8 00 00 00 00 callq 32a9 32a9: 85 c0 test %eax,%eax 32ab: 48 89 df mov %rbx,%rdi &vxlan_link_ops, tb); if (IS_ERR(dev)) 32ae: 78 37 js 32e7 32b0: 48 8b 4d e0 mov -0x20(%rbp),%rcx struct net_device *dev; int err; memset(&tb, 0, sizeof(tb)); dev = rtnl_create_link(net, name, name_assign_type, 32b4: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx 32bb: 00 00 &vxlan_link_ops, tb); if (IS_ERR(dev)) return dev; err = vxlan_dev_configure(net, dev, conf); 32bd: 48 89 f8 mov %rdi,%rax 32c0: 75 5e jne 3320 32c2: 48 81 c4 80 01 00 00 add $0x180,%rsp 32c9: 5b pop %rbx 32ca: 41 5c pop %r12 if (err < 0) { 32cc: 41 5d pop %r13 32ce: 5d pop %rbp free_netdev(dev); return ERR_PTR(err); } err = rtnl_configure_link(dev, NULL); 32cf: c3 retq 32d0: 48 89 df mov %rbx,%rdi 32d3: 89 85 6c fe ff ff mov %eax,-0x194(%rbp) if (err < 0) { 32d9: e8 00 00 00 00 callq 32de 32de: 48 63 bd 6c fe ff ff movslq -0x194(%rbp),%rdi unregister_netdevice_many(&list_kill); return ERR_PTR(err); } return dev; } 32e5: eb c9 jmp 32b0 32e7: 4c 8d a5 70 fe ff ff lea -0x190(%rbp),%r12 32ee: 89 85 6c fe ff ff mov %eax,-0x194(%rbp) 32f4: 4c 89 e6 mov %r12,%rsi 32f7: 4c 89 a5 70 fe ff ff mov %r12,-0x190(%rbp) 32fe: 4c 89 a5 78 fe ff ff mov %r12,-0x188(%rbp) if (IS_ERR(dev)) return dev; err = vxlan_dev_configure(net, dev, conf); if (err < 0) { free_netdev(dev); 3305: e8 f6 d5 ff ff callq 900 330a: 4c 89 e7 mov %r12,%rdi 330d: e8 00 00 00 00 callq 3312 3312: 48 63 bd 6c fe ff ff movslq -0x194(%rbp),%rdi return ERR_PTR(err); } err = rtnl_configure_link(dev, NULL); if (err < 0) { LIST_HEAD(list_kill); 3319: eb 95 jmp 32b0 331b: 48 89 c7 mov %rax,%rdi 331e: eb 90 jmp 32b0 3320: e8 00 00 00 00 callq 3325 vxlan_dellink(dev, &list_kill); 3325: 90 nop 3326: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 332d: 00 00 00 0000000000003330 : return ERR_PTR(err); } err = rtnl_configure_link(dev, NULL); if (err < 0) { LIST_HEAD(list_kill); 3330: e8 00 00 00 00 callq 3335 vxlan_dellink(dev, &list_kill); 3335: 55 push %rbp 3336: 48 89 e5 mov %rsp,%rbp 3339: 41 57 push %r15 unregister_netdevice_many(&list_kill); 333b: 41 56 push %r14 333d: 4c 8d b7 40 08 00 00 lea 0x840(%rdi),%r14 3344: 41 55 push %r13 3346: 41 54 push %r12 3348: 53 push %rbx 3349: 49 89 fd mov %rdi,%r13 memset(&tb, 0, sizeof(tb)); dev = rtnl_create_link(net, name, name_assign_type, &vxlan_link_ops, tb); if (IS_ERR(dev)) return dev; 334c: 49 89 f4 mov %rsi,%r12 334f: 4c 89 f7 mov %r14,%rdi unregister_netdevice_many(&list_kill); return ERR_PTR(err); } return dev; } 3352: 48 89 d6 mov %rdx,%rsi 3355: 49 89 d7 mov %rdx,%r15 3358: 48 83 ec 28 sub $0x28,%rsp 335c: e8 9f cc ff ff callq 0 <__vxlan_find_mac> * and Tunnel endpoint. * Return true if packet is bogus and should be dropped. */ static bool vxlan_snoop(struct net_device *dev, union vxlan_addr *src_ip, const u8 *src_mac) { 3361: 48 85 c0 test %rax,%rax 3364: 74 7d je 33e3 3366: 48 89 c3 mov %rax,%rbx 3369: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 3370 3370: 4c 8b 4b 30 mov 0x30(%rbx),%r9 3374: 48 89 43 28 mov %rax,0x28(%rbx) 3378: 41 0f b7 41 d8 movzwl -0x28(%r9),%eax 337d: 66 41 3b 04 24 cmp (%r12),%ax static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 3382: 74 1e je 33a2 3384: f6 43 46 40 testb $0x40,0x46(%rbx) * and Tunnel endpoint. * Return true if packet is bogus and should be dropped. */ static bool vxlan_snoop(struct net_device *dev, union vxlan_addr *src_ip, const u8 *src_mac) { 3388: b8 01 00 00 00 mov $0x1,%eax static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 338d: 0f 84 86 00 00 00 je 3419 if (f) 3393: 48 83 c4 28 add $0x28,%rsp 3397: 5b pop %rbx 3398: 41 5c pop %r12 f->used = jiffies; 339a: 41 5d pop %r13 339c: 41 5e pop %r14 339e: 41 5f pop %r15 33a0: 5d pop %rbp 33a1: c3 retq 33a2: 66 83 f8 0a cmp $0xa,%ax 33a6: 74 21 je 33c9 #if IS_ENABLED(CONFIG_IPV6) static inline bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b) { if (a->sa.sa_family != b->sa.sa_family) 33a8: 41 8b 44 24 04 mov 0x4(%r12),%eax 33ad: 41 39 41 dc cmp %eax,-0x24(%r9) 33b1: 0f 94 c0 sete %al if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip))) return false; /* Don't migrate static entries, drop packets */ if (f->state & NUD_NOARP) 33b4: 84 c0 test %al,%al 33b6: 74 cc je 3384 return true; 33b8: 48 83 c4 28 add $0x28,%rsp 33bc: 31 c0 xor %eax,%eax if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip))) return false; /* Don't migrate static entries, drop packets */ if (f->state & NUD_NOARP) 33be: 5b pop %rbx 33bf: 41 5c pop %r12 33c1: 41 5d pop %r13 0, NTF_SELF); spin_unlock(&vxlan->hash_lock); } return false; } 33c3: 41 5e pop %r14 33c5: 41 5f pop %r15 33c7: 5d pop %rbp 33c8: c3 retq 33c9: 49 8b 51 e0 mov -0x20(%r9),%rdx 33cd: 49 8b 41 e8 mov -0x18(%r9),%rax 33d1: 49 33 54 24 08 xor 0x8(%r12),%rdx static inline bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b) { if (a->sa.sa_family != b->sa.sa_family) return false; if (a->sa.sa_family == AF_INET6) 33d6: 49 33 44 24 10 xor 0x10(%r12),%rax return ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr); else return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; 33db: 48 09 c2 or %rax,%rdx 33de: 0f 94 c0 sete %al 33e1: eb d1 jmp 33b4 33e3: 49 8d 9d 28 09 00 00 lea 0x928(%r13),%rbx 0, NTF_SELF); spin_unlock(&vxlan->hash_lock); } return false; } 33ea: 48 89 df mov %rbx,%rdi f = vxlan_find_mac(vxlan, src_mac); if (likely(f)) { struct vxlan_rdst *rdst = first_remote_rcu(f); if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip))) return false; 33ed: e8 00 00 00 00 callq 33f2 0, NTF_SELF); spin_unlock(&vxlan->hash_lock); } return false; } 33f2: 49 8b 45 48 mov 0x48(%r13),%rax 33f6: a8 01 test $0x1,%al 33f8: 0f 85 a0 00 00 00 jne 349e { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 const unsigned long *ul1 = (const unsigned long *)a1; const unsigned long *ul2 = (const unsigned long *)a2; return ((ul1[0] ^ ul2[0]) | (ul1[1] ^ ul2[1])) == 0UL; 33fe: 48 89 df mov %rbx,%rdi 3401: ff 14 25 00 00 00 00 callq *0x0 3408: 48 83 c4 28 add $0x28,%rsp 340c: 31 c0 xor %eax,%eax 340e: 5b pop %rbx 340f: 41 5c pop %r12 3411: 41 5d pop %r13 raw_spin_lock_init(&(_lock)->rlock); \ } while (0) static __always_inline void spin_lock(spinlock_t *lock) { raw_spin_lock(&lock->rlock); 3413: 41 5e pop %r14 3415: 41 5f pop %r15 3417: 5d pop %rbp 3418: c3 retq 3419: 4c 89 4d d0 mov %r9,-0x30(%rbp) 341d: e8 00 00 00 00 callq 3422 3422: 4c 8b 4d d0 mov -0x30(%rbp),%r9 } else { /* learned new entry */ spin_lock(&vxlan->hash_lock); /* close off race between vxlan_flush and incoming packets */ if (netif_running(dev)) 3426: 85 c0 test %eax,%eax 3428: 4d 8d 51 d8 lea -0x28(%r9),%r10 342c: 74 28 je 3456 342e: 4c 89 d1 mov %r10,%rcx 3431: 4d 89 e0 mov %r12,%r8 3434: 4c 89 fa mov %r15,%rdx 3437: 48 c7 c6 00 00 00 00 mov $0x0,%rsi 0, NTF_SELF); spin_unlock(&vxlan->hash_lock); } return false; } 343e: 4c 89 ef mov %r13,%rdi 3441: 4c 89 4d c8 mov %r9,-0x38(%rbp) 3445: 4c 89 55 d0 mov %r10,-0x30(%rbp) 3449: e8 00 00 00 00 callq 344e /* Don't migrate static entries, drop packets */ if (f->state & NUD_NOARP) return true; if (net_ratelimit()) 344e: 4c 8b 4d c8 mov -0x38(%rbp),%r9 3452: 4c 8b 55 d0 mov -0x30(%rbp),%r10 3456: 49 8b 04 24 mov (%r12),%rax 345a: b9 1c 00 00 00 mov $0x1c,%ecx netdev_info(dev, 345f: 4c 89 d2 mov %r10,%rdx 3462: 48 89 de mov %rbx,%rsi 3465: 4c 89 f7 mov %r14,%rdi 3468: 49 89 41 d8 mov %rax,-0x28(%r9) 346c: 49 8b 44 24 08 mov 0x8(%r12),%rax 3471: 49 89 41 e0 mov %rax,-0x20(%r9) 3475: 49 8b 44 24 10 mov 0x10(%r12),%rax 347a: 49 89 41 e8 mov %rax,-0x18(%r9) 347e: 41 8b 44 24 18 mov 0x18(%r12),%eax 3483: 41 89 41 f0 mov %eax,-0x10(%r9) "%pM migrated from %pIS to %pIS\n", src_mac, &rdst->remote_ip.sa, &src_ip->sa); rdst->remote_ip = *src_ip; 3487: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 348e f->updated = jiffies; vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH); 348e: 48 89 43 20 mov %rax,0x20(%rbx) 3492: e8 a9 e8 ff ff callq 1d40 3497: 31 c0 xor %eax,%eax if (net_ratelimit()) netdev_info(dev, "%pM migrated from %pIS to %pIS\n", src_mac, &rdst->remote_ip.sa, &src_ip->sa); rdst->remote_ip = *src_ip; 3499: e9 f5 fe ff ff jmpq 3393 349e: 45 0f b7 8d 7c 09 00 movzwl 0x97c(%r13),%r9d 34a5: 00 34a6: c7 44 24 10 02 00 00 movl $0x2,0x10(%rsp) 34ad: 00 34ae: 41 b8 00 06 00 00 mov $0x600,%r8d 34b4: c7 44 24 08 00 00 00 movl $0x0,0x8(%rsp) 34bb: 00 f->updated = jiffies; 34bc: 41 8b 85 a0 08 00 00 mov 0x8a0(%r13),%eax vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH); 34c3: b9 02 00 00 00 mov $0x2,%ecx vxlan->default_dst.remote_vni, 0, NTF_SELF); spin_unlock(&vxlan->hash_lock); } return false; 34c8: 4c 89 e2 mov %r12,%rdx 34cb: 4c 89 fe mov %r15,%rsi /* learned new entry */ spin_lock(&vxlan->hash_lock); /* close off race between vxlan_flush and incoming packets */ if (netif_running(dev)) vxlan_fdb_create(vxlan, src_mac, src_ip, 34ce: 4c 89 f7 mov %r14,%rdi 34d1: 89 04 24 mov %eax,(%rsp) 34d4: e8 b7 f0 ff ff callq 2590 34d9: e9 20 ff ff ff jmpq 33fe 34de: 66 90 xchg %ax,%ax 00000000000034e0 : 34e0: e8 00 00 00 00 callq 34e5 34e5: 55 push %rbp 34e6: 48 89 e5 mov %rsp,%rbp 34e9: 41 57 push %r15 34eb: 41 56 push %r14 34ed: 41 55 push %r13 34ef: 41 54 push %r12 34f1: 49 89 ff mov %rdi,%r15 34f4: 53 push %rbx 34f5: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 34f9: 48 83 ec 58 sub $0x58,%rsp 34fd: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 3504: 00 00 3506: 48 89 44 24 50 mov %rax,0x50(%rsp) 350b: 31 c0 xor %eax,%eax 350d: 0f b7 47 08 movzwl 0x8(%rdi),%eax /* Add static entry (via netlink) */ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *dev, const unsigned char *addr, u16 vid, u16 flags) { 3511: a8 82 test $0x82,%al 3513: 0f 84 cb 00 00 00 je 35e4 3519: 48 83 7e 08 00 cmpq $0x0,0x8(%rsi) 351e: 48 89 f7 mov %rsi,%rdi 3521: 0f 84 b6 00 00 00 je 35dd 3527: 4c 8d a2 40 08 00 00 lea 0x840(%rdx),%r12 352e: 48 89 d3 mov %rdx,%rbx 3531: 49 89 cd mov %rcx,%r13 3534: 45 89 ce mov %r9d,%r14d 3537: 4c 8d 44 24 20 lea 0x20(%rsp),%r8 353c: 4c 8d 4c 24 24 lea 0x24(%rsp),%r9 __be16 port; __be32 vni; u32 ifindex; int err; if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) { 3541: 48 8d 4c 24 1e lea 0x1e(%rsp),%rcx 3546: 48 8d 54 24 28 lea 0x28(%rsp),%rdx pr_info("RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state); return -EINVAL; } if (tb[NDA_DST] == NULL) 354b: 4c 89 e6 mov %r12,%rsi 354e: e8 cd d0 ff ff callq 620 3553: 85 c0 test %eax,%eax 3555: 75 67 jne 35be 3557: 0f b7 74 24 28 movzwl 0x28(%rsp),%esi 355c: b8 9f ff ff ff mov $0xffffff9f,%eax 3561: 66 39 b3 80 08 00 00 cmp %si,0x880(%rbx) return -EINVAL; err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &vni, &ifindex); 3568: 75 54 jne 35be 356a: 48 81 c3 28 09 00 00 add $0x928,%rbx 3571: 48 89 df mov %rbx,%rdi 3574: e8 00 00 00 00 callq 3579 3579: 41 0f b6 47 0a movzbl 0xa(%r15),%eax 357e: 44 0f b7 4c 24 1e movzwl 0x1e(%rsp),%r9d if (err) 3584: 48 8d 54 24 28 lea 0x28(%rsp),%rdx return err; if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family) 3589: 41 0f b7 4f 08 movzwl 0x8(%r15),%ecx return -EAFNOSUPPORT; 358e: 4c 89 e7 mov %r12,%rdi err = vxlan_fdb_parse(tb, vxlan, &ip, &port, &vni, &ifindex); if (err) return err; if (vxlan->default_dst.remote_ip.sa.sa_family != ip.sa.sa_family) 3591: 45 0f b7 c6 movzwl %r14w,%r8d 3595: 4c 89 ee mov %r13,%rsi 3598: 89 44 24 10 mov %eax,0x10(%rsp) } static __always_inline void spin_lock_bh(spinlock_t *lock) { raw_spin_lock_bh(&lock->rlock); 359c: 8b 44 24 24 mov 0x24(%rsp),%eax 35a0: 89 44 24 08 mov %eax,0x8(%rsp) 35a4: 8b 44 24 20 mov 0x20(%rsp),%eax 35a8: 89 04 24 mov %eax,(%rsp) return -EAFNOSUPPORT; spin_lock_bh(&vxlan->hash_lock); err = vxlan_fdb_create(vxlan, addr, &ip, ndm->ndm_state, flags, 35ab: e8 e0 ef ff ff callq 2590 35b0: 48 89 df mov %rbx,%rdi 35b3: 41 89 c4 mov %eax,%r12d 35b6: e8 00 00 00 00 callq 35bb 35bb: 44 89 e0 mov %r12d,%eax 35be: 48 8b 74 24 50 mov 0x50(%rsp),%rsi 35c3: 65 48 33 34 25 28 00 xor %gs:0x28,%rsi 35ca: 00 00 35cc: 75 2c jne 35fa 35ce: 48 8d 65 d8 lea -0x28(%rbp),%rsp 35d2: 5b pop %rbx 35d3: 41 5c pop %r12 35d5: 41 5d pop %r13 35d7: 41 5e pop %r14 35d9: 41 5f pop %r15 35db: 5d pop %rbp 35dc: c3 retq 35dd: b8 ea ff ff ff mov $0xffffffea,%eax raw_spin_unlock(&lock->rlock); } static __always_inline void spin_unlock_bh(spinlock_t *lock) { raw_spin_unlock_bh(&lock->rlock); 35e2: eb da jmp 35be 35e4: 0f b7 f0 movzwl %ax,%esi 35e7: 48 c7 c7 00 00 00 00 mov $0x0,%rdi port, vni, ifindex, ndm->ndm_flags); spin_unlock_bh(&vxlan->hash_lock); return err; } 35ee: e8 00 00 00 00 callq 35f3 35f3: b8 ea ff ff ff mov $0xffffffea,%eax 35f8: eb c4 jmp 35be 35fa: e8 00 00 00 00 callq 35ff 35ff: 90 nop 0000000000003600 : 3600: e8 00 00 00 00 callq 3605 3605: 55 push %rbp 3606: 48 89 e5 mov %rsp,%rbp 3609: 41 57 push %r15 360b: 41 56 push %r14 ndm->ndm_state); return -EINVAL; } if (tb[NDA_DST] == NULL) return -EINVAL; 360d: 41 55 push %r13 360f: 41 54 push %r12 3611: 4d 89 cc mov %r9,%r12 __be32 vni; u32 ifindex; int err; if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_REACHABLE))) { pr_info("RTM_NEWNEIGH with invalid state %#x\n", 3614: 53 push %rbx 3615: 89 cb mov %ecx,%ebx 3617: 49 89 ff mov %rdi,%r15 361a: 48 83 ec 48 sub $0x48,%rsp 361e: 44 8b 8e b4 00 00 00 mov 0xb4(%rsi),%r9d ndm->ndm_state); return -EINVAL; 3625: 4c 8b 6d 10 mov 0x10(%rbp),%r13 3629: 65 48 8b 0c 25 28 00 mov %gs:0x28,%rcx 3630: 00 00 static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct sk_buff *skb, int oif, u8 tos, __be32 daddr, __be32 *saddr, struct dst_cache *dst_cache, const struct ip_tunnel_info *info) { 3632: 48 89 4d d0 mov %rcx,-0x30(%rbp) 3636: 31 c9 xor %ecx,%ecx 3638: 48 8b 45 18 mov 0x18(%rbp),%rax 363c: 45 85 c9 test %r9d,%r9d 363f: 75 56 jne 3697 3641: 48 85 c0 test %rax,%rax 3644: 49 89 f6 mov %rsi,%r14 3647: 74 4a je 3693 3649: f6 40 28 20 testb $0x20,0x28(%rax) 364d: 75 48 jne 3697 364f: 4c 89 e6 mov %r12,%rsi 3652: 4c 89 ef mov %r13,%rdi 3655: 44 89 45 94 mov %r8d,-0x6c(%rbp) 3659: 89 55 98 mov %edx,-0x68(%rbp) 365c: e8 00 00 00 00 callq 3661 3661: 48 85 c0 test %rax,%rax 3664: 8b 55 98 mov -0x68(%rbp),%edx 3667: 44 8b 45 94 mov -0x6c(%rbp),%r8d 366b: 0f 84 8d 00 00 00 je 36fe ip_tunnel_dst_cache_usable(const struct sk_buff *skb, const struct ip_tunnel_info *info) { if (skb->mark) return false; if (!info) 3671: 48 8b 5d d0 mov -0x30(%rbp),%rbx 3675: 65 48 33 1c 25 28 00 xor %gs:0x28,%rbx 367c: 00 00 return true; if (info->key.tun_flags & TUNNEL_NOCACHE) 367e: 0f 85 89 00 00 00 jne 370d struct flowi4 fl4; if (tos && !info) use_cache = false; if (use_cache) { rt = dst_cache_get_ip4(dst_cache, saddr); 3684: 48 83 c4 48 add $0x48,%rsp 3688: 5b pop %rbx 3689: 41 5c pop %r12 368b: 41 5d pop %r13 368d: 41 5e pop %r14 368f: 41 5f pop %r15 if (rt) 3691: 5d pop %rbp 3692: c3 retq 3693: 84 db test %bl,%bl 3695: 74 b8 je 364f 3697: 45 31 f6 xor %r14d,%r14d 369a: 48 8d 75 a0 lea -0x60(%rbp),%rsi 369e: 31 c0 xor %eax,%eax 36a0: b9 06 00 00 00 mov $0x6,%ecx *saddr = fl4.saddr; if (use_cache) dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr); } return rt; } 36a5: 83 e3 1e and $0x1e,%ebx 36a8: 48 89 f7 mov %rsi,%rdi 36ab: f3 48 ab rep stos %rax,%es:(%rdi) 36ae: 41 8b 04 24 mov (%r12),%eax 36b2: 49 8b 7f 38 mov 0x38(%r15),%rdi 36b6: 89 55 a0 mov %edx,-0x60(%rbp) 36b9: 31 d2 xor %edx,%edx 36bb: 88 5d ac mov %bl,-0x54(%rbp) 36be: 44 89 4d a8 mov %r9d,-0x58(%rbp) 36c2: c6 45 ae 11 movb $0x11,-0x52(%rbp) { bool use_cache = ip_tunnel_dst_cache_usable(skb, info); struct rtable *rt = NULL; struct flowi4 fl4; if (tos && !info) 36c6: 44 89 45 c4 mov %r8d,-0x3c(%rbp) rt = dst_cache_get_ip4(dst_cache, saddr); if (rt) return rt; } memset(&fl4, 0, sizeof(fl4)); 36ca: 89 45 c0 mov %eax,-0x40(%rbp) 36cd: e8 00 00 00 00 callq 36d2 36d2: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax 36d8: 77 97 ja 3671 36da: 8b 55 c0 mov -0x40(%rbp),%edx 36dd: 45 84 f6 test %r14b,%r14b fl4.flowi4_oif = oif; fl4.flowi4_tos = RT_TOS(tos); fl4.flowi4_mark = skb->mark; fl4.flowi4_proto = IPPROTO_UDP; fl4.daddr = daddr; fl4.saddr = *saddr; 36e0: 41 89 14 24 mov %edx,(%r12) struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig); static inline struct rtable *ip_route_output_key(struct net *net, struct flowi4 *flp) { return ip_route_output_flow(net, flp, NULL); 36e4: 74 8b je 3671 if (rt) return rt; } memset(&fl4, 0, sizeof(fl4)); fl4.flowi4_oif = oif; 36e6: 48 89 c6 mov %rax,%rsi 36e9: 4c 89 ef mov %r13,%rdi fl4.flowi4_tos = RT_TOS(tos); 36ec: 48 89 45 98 mov %rax,-0x68(%rbp) fl4.flowi4_mark = skb->mark; 36f0: e8 00 00 00 00 callq 36f5 fl4.flowi4_proto = IPPROTO_UDP; 36f5: 48 8b 45 98 mov -0x68(%rbp),%rax fl4.daddr = daddr; 36f9: e9 73 ff ff ff jmpq 3671 36fe: 45 8b 8e b4 00 00 00 mov 0xb4(%r14),%r9d fl4.saddr = *saddr; rt = ip_route_output_key(vxlan->net, &fl4); if (!IS_ERR(rt)) { 3705: 41 be 01 00 00 00 mov $0x1,%r14d *saddr = fl4.saddr; 370b: eb 8d jmp 369a if (use_cache) 370d: e8 00 00 00 00 callq 3712 fl4.daddr = daddr; fl4.saddr = *saddr; rt = ip_route_output_key(vxlan->net, &fl4); if (!IS_ERR(rt)) { *saddr = fl4.saddr; 3712: 0f 1f 40 00 nopl 0x0(%rax) if (use_cache) dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr); 3716: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 371d: 00 00 00 0000000000003720 : 3720: e8 00 00 00 00 callq 3725 3725: 55 push %rbp 3726: 48 89 e5 mov %rsp,%rbp 3729: 41 57 push %r15 372b: 41 56 push %r14 372d: 41 55 push %r13 372f: 41 54 push %r12 3731: 49 89 fe mov %rdi,%r14 3734: 53 push %rbx if (tos && !info) use_cache = false; if (use_cache) { rt = dst_cache_get_ip4(dst_cache, saddr); if (rt) 3735: 4c 8d a7 40 08 00 00 lea 0x840(%rdi),%r12 373c: 48 83 ec 28 sub $0x28,%rsp *saddr = fl4.saddr; if (use_cache) dst_cache_set_ip4(dst_cache, &rt->dst, fl4.saddr); } return rt; } 3740: 0f b7 b7 80 08 00 00 movzwl 0x880(%rdi),%esi 3747: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 374e: 00 00 spin_unlock_bh(&vxlan->hash_lock); } /* Cleanup timer and forwarding table on shutdown */ static int vxlan_stop(struct net_device *dev) { 3750: 48 89 45 d0 mov %rax,-0x30(%rbp) 3754: 31 c0 xor %eax,%eax 3756: 48 8b 87 78 08 00 00 mov 0x878(%rdi),%rax 375d: 48 8b 90 88 14 00 00 mov 0x1488(%rax),%rdx 3764: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 376a 376a: 83 e8 01 sub $0x1,%eax 376d: 66 83 fe 0a cmp $0xa,%si return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); } static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 3771: 48 98 cltq 3773: 48 8b 4c c2 18 mov 0x18(%rdx,%rax,8),%rcx spin_unlock_bh(&vxlan->hash_lock); } /* Cleanup timer and forwarding table on shutdown */ static int vxlan_stop(struct net_device *dev) { 3778: 0f 84 c4 00 00 00 je 3842 377e: 8b bf 84 08 00 00 mov 0x884(%rdi),%edi 3784: c7 45 bc 00 00 00 00 movl $0x0,-0x44(%rbp) struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); 378b: 89 f8 mov %edi,%eax 378d: 25 f0 00 00 00 and $0xf0,%eax 3792: 3d e0 00 00 00 cmp $0xe0,%eax 3797: 0f 84 c3 00 00 00 je 3860 return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); } static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 379d: 49 8d be e0 08 00 00 lea 0x8e0(%r14),%rdi 37a4: 49 8d 9e a0 09 00 00 lea 0x9a0(%r14),%rbx 37ab: 4d 8d ae a0 11 00 00 lea 0x11a0(%r14),%r13 return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr); else return IN_MULTICAST(ntohl(ipa->sin.sin_addr.s_addr)); 37b2: e8 00 00 00 00 callq 37b7 /* Cleanup timer and forwarding table on shutdown */ static int vxlan_stop(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); int ret = 0; 37b7: 49 8d 86 28 09 00 00 lea 0x928(%r14),%rax if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && 37be: 48 89 c7 mov %rax,%rdi 37c1: 48 89 45 b0 mov %rax,-0x50(%rbp) 37c5: e8 00 00 00 00 callq 37ca 37ca: 48 8b 33 mov (%rbx),%rsi !vxlan_group_used(vn, vxlan)) ret = vxlan_igmp_leave(vxlan); del_timer_sync(&vxlan->age_timer); 37cd: 48 85 f6 test %rsi,%rsi 37d0: 75 0a jne 37dc 37d2: eb 24 jmp 37f8 37d4: 4d 85 ff test %r15,%r15 37d7: 4c 89 fe mov %r15,%rsi 37da: 74 1c je 37f8 37dc: 0f b7 56 44 movzwl 0x44(%rsi),%edx 37e0: 4c 8b 3e mov (%rsi),%r15 37e3: 0b 56 40 or 0x40(%rsi),%edx 37e6: 74 ec je 37d4 raw_spin_lock(&lock->rlock); } static __always_inline void spin_lock_bh(spinlock_t *lock) { raw_spin_lock_bh(&lock->rlock); 37e8: 4c 89 e7 mov %r12,%rdi 37eb: e8 40 e6 ff ff callq 1e30 37f0: 4d 85 ff test %r15,%r15 37f3: 4c 89 fe mov %r15,%rsi 37f6: 75 e4 jne 37dc 37f8: 48 83 c3 08 add $0x8,%rbx unsigned int h; spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n; hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { 37fc: 4c 39 eb cmp %r13,%rbx 37ff: 75 c9 jne 37ca 3801: 48 8b 7d b0 mov -0x50(%rbp),%rdi 3805: e8 00 00 00 00 callq 380a 380a: 49 8d b6 68 08 00 00 lea 0x868(%r14),%rsi 3811: 49 8d be 60 08 00 00 lea 0x860(%r14),%rdi struct vxlan_fdb *f = container_of(p, struct vxlan_fdb, hlist); /* the all_zeros_mac entry is deleted at vxlan_uninit */ if (!is_zero_ether_addr(f->eth_addr)) vxlan_fdb_destroy(vxlan, f); 3818: e8 73 d4 ff ff callq c90 381d: 48 8b 4d d0 mov -0x30(%rbp),%rcx unsigned int h; spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { struct hlist_node *p, *n; hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) { 3821: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx 3828: 00 00 382a: 8b 45 bc mov -0x44(%rbp),%eax static void vxlan_flush(struct vxlan_dev *vxlan) { unsigned int h; spin_lock_bh(&vxlan->hash_lock); for (h = 0; h < FDB_HASH_SIZE; ++h) { 382d: 0f 85 f0 01 00 00 jne 3a23 raw_spin_unlock(&lock->rlock); } static __always_inline void spin_unlock_bh(spinlock_t *lock) { raw_spin_unlock_bh(&lock->rlock); 3833: 48 83 c4 28 add $0x28,%rsp 3837: 5b pop %rbx 3838: 41 5c pop %r12 383a: 41 5d pop %r13 383c: 41 5e pop %r14 383e: 41 5f pop %r15 3840: 5d pop %rbp 3841: c3 retq 3842: 0f b6 87 88 08 00 00 movzbl 0x888(%rdi),%eax ret = vxlan_igmp_leave(vxlan); del_timer_sync(&vxlan->age_timer); vxlan_flush(vxlan); vxlan_sock_release(vxlan); 3849: 3d ff 00 00 00 cmp $0xff,%eax return ret; } 384e: 0f 84 92 01 00 00 je 39e6 3854: c7 45 bc 00 00 00 00 movl $0x0,-0x44(%rbp) 385b: e9 3d ff ff ff jmpq 379d 3860: 66 83 fe 02 cmp $0x2,%si 3864: 0f 84 12 01 00 00 je 397c 386a: 48 8b 11 mov (%rcx),%rdx 386d: 48 39 d1 cmp %rdx,%rcx 3870: 48 8d 42 f0 lea -0x10(%rdx),%rax { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); int ret = 0; if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) && 3874: 0f 84 96 01 00 00 je 3a10 387a: 41 8b 9e a4 08 00 00 mov 0x8a4(%r14),%ebx 3881: eb 21 jmp 38a4 3883: 66 83 fe 0a cmp $0xa,%si /* Cleanup timer and forwarding table on shutdown */ static int vxlan_stop(struct net_device *dev) { struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id); int ret = 0; 3887: 0f 84 92 00 00 00 je 391f 388d: 66 3b 70 40 cmp 0x40(%rax),%si unsigned short family = dev->default_dst.remote_ip.sa.sa_family; /* The vxlan_sock is only used by dev, leaving group has * no effect on other vxlan devices. */ if (family == AF_INET && dev->vn4_sock && 3891: 0f 84 c2 00 00 00 je 3959 3897: 48 8b 50 10 mov 0x10(%rax),%rdx if (family == AF_INET6 && dev->vn6_sock && atomic_read(&dev->vn6_sock->refcnt) == 1) return false; #endif list_for_each_entry(vxlan, &vn->vxlan_list, next) { 389b: 48 39 d1 cmp %rdx,%rcx 389e: 48 8d 42 f0 lea -0x10(%rdx),%rax 38a2: 74 32 je 38d6 38a4: 48 8b 50 30 mov 0x30(%rax),%rdx 38a8: 48 8b 52 48 mov 0x48(%rdx),%rdx 38ac: 83 e2 01 and $0x1,%edx 38af: 74 e6 je 3897 38b1: 49 39 c4 cmp %rax,%r12 continue; if (family == AF_INET && vxlan->vn4_sock != dev->vn4_sock) continue; #if IS_ENABLED(CONFIG_IPV6) if (family == AF_INET6 && vxlan->vn6_sock != dev->vn6_sock) 38b4: 74 e1 je 3897 38b6: 66 83 fe 02 cmp $0x2,%si 38ba: 75 c7 jne 3883 38bc: 49 8b be 60 08 00 00 mov 0x860(%r14),%rdi #if IS_ENABLED(CONFIG_IPV6) static inline bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b) { if (a->sa.sa_family != b->sa.sa_family) 38c3: 48 39 78 20 cmp %rdi,0x20(%rax) if (family == AF_INET6 && dev->vn6_sock && atomic_read(&dev->vn6_sock->refcnt) == 1) return false; #endif list_for_each_entry(vxlan, &vn->vxlan_list, next) { 38c7: 74 c4 je 388d 38c9: 48 8b 50 10 mov 0x10(%rax),%rdx 38cd: 48 39 d1 cmp %rdx,%rcx 38d0: 48 8d 42 f0 lea -0x10(%rdx),%rax if (!netif_running(vxlan->dev) || vxlan == dev) 38d4: 75 ce jne 38a4 38d6: 66 83 fe 02 cmp $0x2,%si 38da: 0f 84 48 01 00 00 je 3a28 38e0: 49 8b 86 68 08 00 00 mov 0x868(%r14),%rax continue; if (family == AF_INET && vxlan->vn4_sock != dev->vn4_sock) 38e7: 48 8b 40 10 mov 0x10(%rax),%rax 38eb: 31 f6 xor %esi,%esi 38ed: 4c 8b 68 20 mov 0x20(%rax),%r13 38f1: 4c 89 ef mov %r13,%rdi 38f4: e8 00 00 00 00 callq 38f9 if (family == AF_INET6 && dev->vn6_sock && atomic_read(&dev->vn6_sock->refcnt) == 1) return false; #endif list_for_each_entry(vxlan, &vn->vxlan_list, next) { 38f9: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 3900 3900: 4c 89 ef mov %r13,%rdi 3903: 49 8d 96 88 08 00 00 lea 0x888(%r14),%rdx struct sock *sk; union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; int ret = -EINVAL; if (ip->sa.sa_family == AF_INET) { 390a: 89 de mov %ebx,%esi 390c: ff 50 08 callq *0x8(%rax) 390f: 4c 89 ef mov %r13,%rdi 3912: 89 45 bc mov %eax,-0x44(%rbp) 3915: e8 00 00 00 00 callq 391a lock_sock(sk); ret = ip_mc_leave_group(sk, &mreq); release_sock(sk); #if IS_ENABLED(CONFIG_IPV6) } else { sk = vxlan->vn6_sock->sock->sk; 391a: e9 7e fe ff ff jmpq 379d 391f: 49 8b be 68 08 00 00 mov 0x868(%r14),%rdi 3926: 48 39 78 28 cmp %rdi,0x28(%rax) lock_sock(sk); ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex, 392a: 0f 85 67 ff ff ff jne 3897 3930: 66 83 78 40 0a cmpw $0xa,0x40(%rax) &ip->sin6.sin6_addr); 3935: 0f 85 5c ff ff ff jne 3897 release_sock(sk); #if IS_ENABLED(CONFIG_IPV6) } else { sk = vxlan->vn6_sock->sock->sk; lock_sock(sk); ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex, 393b: 48 8b 78 48 mov 0x48(%rax),%rdi &ip->sin6.sin6_addr); release_sock(sk); 393f: 48 8b 50 50 mov 0x50(%rax),%rdx release_sock(sk); #if IS_ENABLED(CONFIG_IPV6) } else { sk = vxlan->vn6_sock->sock->sk; lock_sock(sk); ret = ipv6_stub->ipv6_sock_mc_drop(sk, ifindex, 3943: 49 33 be 88 08 00 00 xor 0x888(%r14),%rdi &ip->sin6.sin6_addr); release_sock(sk); 394a: 49 33 96 90 08 00 00 xor 0x890(%r14),%rdx continue; if (family == AF_INET && vxlan->vn4_sock != dev->vn4_sock) continue; #if IS_ENABLED(CONFIG_IPV6) if (family == AF_INET6 && vxlan->vn6_sock != dev->vn6_sock) 3951: 48 09 d7 or %rdx,%rdi 3954: 0f 94 c2 sete %dl 3957: eb 0d jmp 3966 3959: 41 8b be 84 08 00 00 mov 0x884(%r14),%edi #if IS_ENABLED(CONFIG_IPV6) static inline bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b) { if (a->sa.sa_family != b->sa.sa_family) 3960: 39 78 44 cmp %edi,0x44(%rax) 3963: 0f 94 c2 sete %dl 3966: 84 d2 test %dl,%dl 3968: 0f 84 29 ff ff ff je 3897 396e: 39 58 64 cmp %ebx,0x64(%rax) 3971: 0f 85 20 ff ff ff jne 3897 3977: e9 d8 fe ff ff jmpq 3854 397c: 49 8b 96 60 08 00 00 mov 0x860(%r14),%rdx 3983: 48 85 d2 test %rdx,%rdx 3986: 74 0b je 3993 3988: 8b 82 18 20 00 00 mov 0x2018(%rdx),%eax return false; if (a->sa.sa_family == AF_INET6) return ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr); else return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; 398e: 83 f8 01 cmp $0x1,%eax 3991: 74 10 je 39a3 3993: 4c 8b 01 mov (%rcx),%r8 #if IS_ENABLED(CONFIG_IPV6) if (family == AF_INET6 && vxlan->vn6_sock != dev->vn6_sock) continue; #endif if (!vxlan_addr_equal(&vxlan->default_dst.remote_ip, 3996: 4c 39 c1 cmp %r8,%rcx 3999: 49 8d 40 f0 lea -0x10(%r8),%rax 399d: 0f 85 d7 fe ff ff jne 387a &dev->default_dst.remote_ip)) continue; if (vxlan->default_dst.remote_ifindex != 39a3: 41 8b 9e a4 08 00 00 mov 0x8a4(%r14),%ebx 39aa: 48 8b 42 10 mov 0x10(%rdx),%rax unsigned short family = dev->default_dst.remote_ip.sa.sa_family; /* The vxlan_sock is only used by dev, leaving group has * no effect on other vxlan devices. */ if (family == AF_INET && dev->vn4_sock && 39ae: 89 5d cc mov %ebx,-0x34(%rbp) 39b1: 31 f6 xor %esi,%esi 39b3: 48 c7 45 c4 00 00 00 movq $0x0,-0x3c(%rbp) 39ba: 00 39bb: 89 7d c4 mov %edi,-0x3c(%rbp) 39be: 48 8b 58 20 mov 0x20(%rax),%rbx 39c2: 48 89 df mov %rbx,%rdi if (family == AF_INET6 && dev->vn6_sock && atomic_read(&dev->vn6_sock->refcnt) == 1) return false; #endif list_for_each_entry(vxlan, &vn->vxlan_list, next) { 39c5: e8 00 00 00 00 callq 39ca 39ca: 48 8d 75 c4 lea -0x3c(%rbp),%rsi 39ce: 48 89 df mov %rbx,%rdi 39d1: e8 00 00 00 00 callq 39d6 /* Inverse of vxlan_igmp_join when last VNI is brought down */ static int vxlan_igmp_leave(struct vxlan_dev *vxlan) { struct sock *sk; union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; 39d6: 48 89 df mov %rbx,%rdi 39d9: 89 45 bc mov %eax,-0x44(%rbp) struct ip_mreqn mreq = { .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr, .imr_ifindex = ifindex, }; sk = vxlan->vn4_sock->sock->sk; 39dc: e8 00 00 00 00 callq 39e1 39e1: e9 b7 fd ff ff jmpq 379d union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; int ret = -EINVAL; if (ip->sa.sa_family == AF_INET) { struct ip_mreqn mreq = { 39e6: 48 8b 87 68 08 00 00 mov 0x868(%rdi),%rax 39ed: 48 85 c0 test %rax,%rax .imr_multiaddr.s_addr = ip->sin.sin_addr.s_addr, .imr_ifindex = ifindex, }; sk = vxlan->vn4_sock->sock->sk; 39f0: 0f 84 74 fe ff ff je 386a 39f6: 8b 90 18 20 00 00 mov 0x2018(%rax),%edx lock_sock(sk); ret = ip_mc_leave_group(sk, &mreq); 39fc: 83 fa 01 cmp $0x1,%edx 39ff: 0f 85 65 fe ff ff jne 386a 3a05: 8b 9f a4 08 00 00 mov 0x8a4(%rdi),%ebx 3a0b: e9 d7 fe ff ff jmpq 38e7 release_sock(sk); 3a10: 41 8b 9e a4 08 00 00 mov 0x8a4(%r14),%ebx */ if (family == AF_INET && dev->vn4_sock && atomic_read(&dev->vn4_sock->refcnt) == 1) return false; #if IS_ENABLED(CONFIG_IPV6) if (family == AF_INET6 && dev->vn6_sock && 3a17: 49 8b 86 68 08 00 00 mov 0x868(%r14),%rax 3a1e: e9 c4 fe ff ff jmpq 38e7 3a23: e8 00 00 00 00 callq 3a28 3a28: 41 8b be 84 08 00 00 mov 0x884(%r14),%edi 3a2f: 49 8b 96 60 08 00 00 mov 0x860(%r14),%rdx /* Inverse of vxlan_igmp_join when last VNI is brought down */ static int vxlan_igmp_leave(struct vxlan_dev *vxlan) { struct sock *sk; union vxlan_addr *ip = &vxlan->default_dst.remote_ip; int ifindex = vxlan->default_dst.remote_ifindex; 3a36: e9 6f ff ff ff jmpq 39aa 3a3b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 0000000000003a40 : 3a40: e8 00 00 00 00 callq 3a45 3a45: 55 push %rbp 3a46: 49 89 d0 mov %rdx,%r8 3a49: 48 89 e5 mov %rsp,%rbp 3a4c: 41 57 push %r15 3a4e: 41 56 push %r14 3a50: 41 55 push %r13 3a52: 41 54 push %r12 vxlan_flush(vxlan); vxlan_sock_release(vxlan); return ret; } 3a54: 53 push %rbx 3a55: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 3a59: 48 83 ec 30 sub $0x30,%rsp 3a5d: 48 8b 5f 20 mov 0x20(%rdi),%rbx 3a61: 4c 63 b7 80 00 00 00 movslq 0x80(%rdi),%r14 3a68: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 3a6f: 00 00 return ndst; } #endif /* Bypass encapsulation if the destination is local */ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, 3a71: 48 89 44 24 28 mov %rax,0x28(%rsp) 3a76: 31 c0 xor %eax,%eax 3a78: 4c 8b a6 88 04 00 00 mov 0x488(%rsi),%r12 3a7f: 65 4c 03 25 00 00 00 add %gs:0x0(%rip),%r12 # 3a87 3a86: 00 3a87: 48 8b 42 30 mov 0x30(%rdx),%rax 3a8b: 4c 8b a8 88 04 00 00 mov 0x488(%rax),%r13 { struct pcpu_sw_netstats *tx_stats, *rx_stats; union vxlan_addr loopback; union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip; struct net_device *dev = skb->dev; int len = skb->len; 3a92: 65 4c 03 2d 00 00 00 add %gs:0x0(%rip),%r13 # 3a9a 3a99: 00 return ndst; } #endif /* Bypass encapsulation if the destination is local */ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, 3a9a: 0f b7 87 c4 00 00 00 movzwl 0xc4(%rdi),%eax 3aa1: 48 8b b7 d0 00 00 00 mov 0xd0(%rdi),%rsi union vxlan_addr loopback; union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip; struct net_device *dev = skb->dev; int len = skb->len; tx_stats = this_cpu_ptr(src_vxlan->dev->tstats); 3aa8: 4c 8b 8f d8 00 00 00 mov 0xd8(%rdi),%r9 3aaf: 80 a7 90 00 00 00 f8 andb $0xf8,0x90(%rdi) 3ab6: 80 a7 92 00 00 00 fd andb $0xfd,0x92(%rdi) rx_stats = this_cpu_ptr(dst_vxlan->dev->tstats); 3abd: 48 8b 4a 30 mov 0x30(%rdx),%rcx 3ac1: 44 89 f2 mov %r14d,%edx 3ac4: 48 01 f0 add %rsi,%rax 3ac7: 4c 29 c8 sub %r9,%rax return skb->inner_transport_header - skb->inner_network_header; } static inline int skb_network_offset(const struct sk_buff *skb) { return skb_network_header(skb) - skb->data; 3aca: 29 c2 sub %eax,%edx 3acc: 3b 97 84 00 00 00 cmp 0x84(%rdi),%edx 3ad2: 48 89 4f 20 mov %rcx,0x20(%rdi) 3ad6: 89 97 80 00 00 00 mov %edx,0x80(%rdi) 3adc: 0f 82 be 00 00 00 jb 3ba0 skb->pkt_type = PACKET_HOST; 3ae2: 89 c0 mov %eax,%eax 3ae4: 4c 01 c8 add %r9,%rax skb->encapsulation = 0; 3ae7: 48 89 87 d8 00 00 00 mov %rax,0xd8(%rdi) skb->dev = dst_vxlan->dev; 3aee: 66 41 83 78 40 02 cmpw $0x2,0x40(%r8) 3af4: 0f 84 90 00 00 00 je 3b8a } unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) { skb->len -= len; 3afa: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 3b01 BUG_ON(skb->len < skb->data_len); 3b01: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # 3b08 } unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) { skb->len -= len; 3b08: 48 89 44 24 08 mov %rax,0x8(%rsp) BUG_ON(skb->len < skb->data_len); 3b0d: b8 0a 00 00 00 mov $0xa,%eax return skb->data += len; 3b12: 48 89 54 24 10 mov %rdx,0x10(%rsp) 3b17: 66 89 04 24 mov %ax,(%rsp) 3b1b: 41 f6 80 98 00 00 00 testb $0x1,0x98(%r8) 3b22: 01 __skb_pull(skb, skb_network_offset(skb)); if (remote_ip->sa.sa_family == AF_INET) { 3b23: 49 89 ff mov %rdi,%r15 3b26: 75 49 jne 3b71 3b28: 49 83 44 24 10 01 addq $0x1,0x10(%r12) loopback.sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); loopback.sa.sa_family = AF_INET; #if IS_ENABLED(CONFIG_IPV6) } else { loopback.sin6.sin6_addr = in6addr_loopback; 3b2e: 4d 01 74 24 18 add %r14,0x18(%r12) 3b33: 4c 89 ff mov %r15,%rdi 3b36: e8 00 00 00 00 callq 3b3b 3b3b: 85 c0 test %eax,%eax loopback.sa.sa_family = AF_INET6; 3b3d: 74 27 je 3b66 3b3f: 48 83 83 60 01 00 00 addq $0x1,0x160(%rbx) 3b46: 01 3b47: 48 8b 44 24 28 mov 0x28(%rsp),%rax #endif } if (dst_vxlan->flags & VXLAN_F_LEARN) 3b4c: 65 48 33 04 25 28 00 xor %gs:0x28,%rax 3b53: 00 00 3b55: 75 4b jne 3ba2 3b57: 48 8d 65 d8 lea -0x28(%rbp),%rsp vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source); u64_stats_update_begin(&tx_stats->syncp); tx_stats->tx_packets++; 3b5b: 5b pop %rbx 3b5c: 41 5c pop %r12 tx_stats->tx_bytes += len; 3b5e: 41 5d pop %r13 3b60: 41 5e pop %r14 3b62: 41 5f pop %r15 u64_stats_update_end(&tx_stats->syncp); if (netif_rx(skb) == NET_RX_SUCCESS) { 3b64: 5d pop %rbp 3b65: c3 retq 3b66: 49 83 45 00 01 addq $0x1,0x0(%r13) 3b6b: 4d 01 75 08 add %r14,0x8(%r13) u64_stats_update_begin(&rx_stats->syncp); rx_stats->rx_packets++; rx_stats->rx_bytes += len; u64_stats_update_end(&rx_stats->syncp); } else { dev->stats.rx_dropped++; 3b6f: eb d6 jmp 3b47 3b71: 0f b7 87 c6 00 00 00 movzwl 0xc6(%rdi),%eax } } 3b78: 48 89 cf mov %rcx,%rdi 3b7b: 48 8d 54 06 06 lea 0x6(%rsi,%rax,1),%rdx 3b80: 48 89 e6 mov %rsp,%rsi 3b83: e8 a8 f7 ff ff callq 3330 3b88: eb 9e jmp 3b28 3b8a: ba 02 00 00 00 mov $0x2,%edx 3b8f: c7 44 24 04 7f 00 00 movl $0x100007f,0x4(%rsp) 3b96: 01 tx_stats->tx_bytes += len; u64_stats_update_end(&tx_stats->syncp); if (netif_rx(skb) == NET_RX_SUCCESS) { u64_stats_update_begin(&rx_stats->syncp); rx_stats->rx_packets++; 3b97: 66 89 14 24 mov %dx,(%rsp) rx_stats->rx_bytes += len; 3b9b: e9 7b ff ff ff jmpq 3b1b 3ba0: 0f 0b ud2 loopback.sa.sa_family = AF_INET6; #endif } if (dst_vxlan->flags & VXLAN_F_LEARN) vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source); 3ba2: e8 00 00 00 00 callq 3ba7 3ba7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 3bae: 00 00 0000000000003bb0 : 3bb0: e8 00 00 00 00 callq 3bb5 3bb5: 55 push %rbp 3bb6: 48 89 e5 mov %rsp,%rbp 3bb9: 41 57 push %r15 skb->dev = dst_vxlan->dev; __skb_pull(skb, skb_network_offset(skb)); if (remote_ip->sa.sa_family == AF_INET) { loopback.sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); loopback.sa.sa_family = AF_INET; 3bbb: 41 56 push %r14 3bbd: 41 55 push %r13 skb->encapsulation = 0; skb->dev = dst_vxlan->dev; __skb_pull(skb, skb_network_offset(skb)); if (remote_ip->sa.sa_family == AF_INET) { loopback.sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 3bbf: 41 54 push %r12 3bc1: 49 89 fe mov %rdi,%r14 3bc4: 53 push %rbx 3bc5: 4d 8d a6 10 01 00 00 lea 0x110(%r14),%r12 loopback.sa.sa_family = AF_INET; 3bcc: 48 83 ec 20 sub $0x20,%rsp unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) { skb->len -= len; BUG_ON(skb->len < skb->data_len); 3bd0: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 3bd7: 00 00 rx_stats->rx_bytes += len; u64_stats_update_end(&rx_stats->syncp); } else { dev->stats.rx_dropped++; } } 3bd9: 48 89 45 d0 mov %rax,-0x30(%rbp) 3bdd: 31 c0 xor %eax,%eax 3bdf: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 3be5 return 0; } static void __net_exit vxlan_exit_net(struct net *net) { 3be5: 48 8b 97 88 14 00 00 mov 0x1488(%rdi),%rdx 3bec: 83 e8 01 sub $0x1,%eax 3bef: 48 98 cltq 3bf1: 48 8b 44 c2 18 mov 0x18(%rdx,%rax,8),%rax struct vxlan_dev *vxlan, *next; struct net_device *dev, *aux; LIST_HEAD(list); rtnl_lock(); for_each_netdev_safe(net, dev, aux) 3bf6: 48 89 45 b8 mov %rax,-0x48(%rbp) 3bfa: 48 8d 45 c0 lea -0x40(%rbp),%rax return 0; } static void __net_exit vxlan_exit_net(struct net *net) { 3bfe: 48 89 45 c0 mov %rax,-0x40(%rbp) 3c02: 48 89 45 c8 mov %rax,-0x38(%rbp) 3c06: e8 00 00 00 00 callq 3c0b 3c0b: 49 8b 86 10 01 00 00 mov 0x110(%r14),%rax 3c12: 48 8b 30 mov (%rax),%rsi 3c15: 49 39 c4 cmp %rax,%r12 3c18: 48 8d 78 b0 lea -0x50(%rax),%rdi 3c1c: 48 8d 5e b0 lea -0x50(%rsi),%rbx 3c20: 75 05 jne 3c27 3c22: eb 28 jmp 3c4c 3c24: 48 89 c3 mov %rax,%rbx 3c27: 48 81 bf 98 07 00 00 cmpq $0x0,0x798(%rdi) 3c2e: 00 00 00 00 struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_dev *vxlan, *next; struct net_device *dev, *aux; LIST_HEAD(list); 3c32: 0f 84 3a 01 00 00 je 3d72 rtnl_lock(); 3c38: 48 8b 43 50 mov 0x50(%rbx),%rax for_each_netdev_safe(net, dev, aux) 3c3c: 48 8d 53 50 lea 0x50(%rbx),%rdx 3c40: 48 89 df mov %rbx,%rdi 3c43: 48 83 e8 50 sub $0x50,%rax 3c47: 49 39 d4 cmp %rdx,%r12 3c4a: 75 d8 jne 3c24 3c4c: 48 8b 75 b8 mov -0x48(%rbp),%rsi 3c50: 48 8b 06 mov (%rsi),%rax 3c53: 48 8b 18 mov (%rax),%rbx 3c56: 48 39 c6 cmp %rax,%rsi if (dev->rtnl_link_ops == &vxlan_link_ops) 3c59: 4c 8d 60 f0 lea -0x10(%rax),%r12 3c5d: 4c 8d 6b f0 lea -0x10(%rbx),%r13 3c61: 0f 84 df 00 00 00 je 3d46 3c67: 49 8b 7c 24 30 mov 0x30(%r12),%rdi struct vxlan_dev *vxlan, *next; struct net_device *dev, *aux; LIST_HEAD(list); rtnl_lock(); for_each_netdev_safe(net, dev, aux) 3c6c: 4c 3b b7 80 04 00 00 cmp 0x480(%rdi),%r14 3c73: 0f 84 b0 00 00 00 je 3d29 3c79: 49 83 bc 24 f0 00 00 cmpq $0x0,0xf0(%r12) 3c80: 00 00 if (dev->rtnl_link_ops == &vxlan_link_ops) unregister_netdevice_queue(dev, &list); list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) { 3c82: bb ff ff ff ff mov $0xffffffff,%ebx 3c87: 0f 84 93 00 00 00 je 3d20 3c8d: 8d 53 01 lea 0x1(%rbx),%edx 3c90: be 00 01 00 00 mov $0x100,%esi 3c95: 48 c7 c7 00 00 00 00 mov $0x0,%rdi /* If vxlan->dev is in the same netns, it has already been added * to the list by the previous loop. */ if (!net_eq(dev_net(vxlan->dev), net)) { 3c9c: 48 63 d2 movslq %edx,%rdx 3c9f: e8 00 00 00 00 callq 3ca4 3ca4: 3b 05 00 00 00 00 cmp 0x0(%rip),%eax # 3caa static inline void gro_cells_destroy(struct gro_cells *gcells) { int i; if (!gcells->cells) 3caa: 89 c3 mov %eax,%ebx 3cac: 7d 54 jge 3d02 3cae: 48 98 cltq 3cb0: 49 8b 94 24 f0 00 00 mov 0xf0(%r12),%rdx 3cb7: 00 3cb8: 48 03 14 c5 00 00 00 add 0x0(,%rax,8),%rdx 3cbf: 00 3cc0: 48 8d 7a 18 lea 0x18(%rdx),%rdi 3cc4: 49 89 d7 mov %rdx,%r15 3cc7: e8 00 00 00 00 callq 3ccc 3ccc: 49 8b 3f mov (%r15),%rdi 3ccf: 49 39 ff cmp %rdi,%r15 3cd2: 74 b9 je 3c8d return; for_each_possible_cpu(i) { 3cd4: 48 85 ff test %rdi,%rdi 3cd7: 74 b4 je 3c8d 3cd9: 41 83 6f 10 01 subl $0x1,0x10(%r15) struct gro_cell *cell = per_cpu_ptr(gcells->cells, i); 3cde: 48 8b 0f mov (%rdi),%rcx 3ce1: 48 8b 57 08 mov 0x8(%rdi),%rdx 3ce5: 48 c7 07 00 00 00 00 movq $0x0,(%rdi) 3cec: 48 c7 47 08 00 00 00 movq $0x0,0x8(%rdi) 3cf3: 00 3cf4: 48 89 51 08 mov %rdx,0x8(%rcx) netif_napi_del(&cell->napi); 3cf8: 48 89 0a mov %rcx,(%rdx) 3cfb: e8 00 00 00 00 callq 3d00 */ static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_) { struct sk_buff *skb = list_->next; if (skb == (struct sk_buff *)list_) 3d00: eb ca jmp 3ccc 3d02: 49 8b bc 24 f0 00 00 mov 0xf0(%r12),%rdi 3d09: 00 void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list); static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) { struct sk_buff *next, *prev; list->qlen--; 3d0a: e8 00 00 00 00 callq 3d0f next = skb->next; 3d0f: 49 8b 7c 24 30 mov 0x30(%r12),%rdi prev = skb->prev; 3d14: 49 c7 84 24 f0 00 00 movq $0x0,0xf0(%r12) 3d1b: 00 00 00 00 00 skb->next = skb->prev = NULL; 3d20: 48 8d 75 c0 lea -0x40(%rbp),%rsi next->prev = prev; 3d24: e8 00 00 00 00 callq 3d29 prev->next = next; 3d29: 49 8b 45 10 mov 0x10(%r13),%rax void skb_queue_purge(struct sk_buff_head *list); static inline void __skb_queue_purge(struct sk_buff_head *list) { struct sk_buff *skb; while ((skb = __skb_dequeue(list)) != NULL) kfree_skb(skb); 3d2d: 49 8d 55 10 lea 0x10(%r13),%rdx 3d31: 4d 89 ec mov %r13,%r12 __skb_queue_purge(&cell->napi_skbs); } free_percpu(gcells->cells); 3d34: 48 83 e8 10 sub $0x10,%rax 3d38: 48 39 55 b8 cmp %rdx,-0x48(%rbp) 3d3c: 74 08 je 3d46 3d3e: 49 89 c5 mov %rax,%r13 3d41: e9 21 ff ff ff jmpq 3c67 gcells->cells = NULL; 3d46: 48 8d 7d c0 lea -0x40(%rbp),%rdi 3d4a: e8 00 00 00 00 callq 3d4f 3d4f: e8 00 00 00 00 callq 3d54 gro_cells_destroy(&vxlan->gro_cells); unregister_netdevice_queue(vxlan->dev, &list); 3d54: 48 8b 45 d0 mov -0x30(%rbp),%rax 3d58: 65 48 33 04 25 28 00 xor %gs:0x28,%rax 3d5f: 00 00 rtnl_lock(); for_each_netdev_safe(net, dev, aux) if (dev->rtnl_link_ops == &vxlan_link_ops) unregister_netdevice_queue(dev, &list); list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) { 3d61: 75 1d jne 3d80 3d63: 48 83 c4 20 add $0x20,%rsp 3d67: 5b pop %rbx 3d68: 41 5c pop %r12 3d6a: 41 5d pop %r13 3d6c: 41 5e pop %r14 3d6e: 41 5f pop %r15 3d70: 5d pop %rbp 3d71: c3 retq 3d72: 48 8d 75 c0 lea -0x40(%rbp),%rsi gro_cells_destroy(&vxlan->gro_cells); unregister_netdevice_queue(vxlan->dev, &list); } } unregister_netdevice_many(&list); 3d76: e8 00 00 00 00 callq 3d7b 3d7b: e9 b8 fe ff ff jmpq 3c38 rtnl_unlock(); 3d80: e8 00 00 00 00 callq 3d85 } 3d85: 90 nop 3d86: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 3d8d: 00 00 00 0000000000003d90 : 3d90: e8 00 00 00 00 callq 3d95 3d95: 55 push %rbp 3d96: 48 89 e5 mov %rsp,%rbp 3d99: 41 57 push %r15 3d9b: 41 56 push %r14 3d9d: 41 55 push %r13 3d9f: 41 54 push %r12 3da1: 45 89 ce mov %r9d,%r14d LIST_HEAD(list); rtnl_lock(); for_each_netdev_safe(net, dev, aux) if (dev->rtnl_link_ops == &vxlan_link_ops) unregister_netdevice_queue(dev, &list); 3da4: 53 push %rbx 3da5: 48 89 fb mov %rdi,%rbx 3da8: 41 89 cc mov %ecx,%r12d 3dab: 48 83 ec 18 sub $0x18,%rsp 3daf: 80 7d 10 01 cmpb $0x1,0x10(%rbp) } } unregister_netdevice_many(&list); rtnl_unlock(); } 3db3: 4c 89 45 d0 mov %r8,-0x30(%rbp) 3db7: 45 19 ed sbb %r13d,%r13d 3dba: 41 81 e5 00 f8 ff ff and $0xfffff800,%r13d static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst, int iphdr_len, __be32 vni, struct vxlan_metadata *md, u32 vxflags, bool udp_sum) { 3dc1: 41 81 c5 00 10 00 00 add $0x1000,%r13d 3dc8: 41 81 e1 00 02 00 00 and $0x200,%r9d 3dcf: 0f 85 d6 00 00 00 jne 3eab 3dd5: 48 8b 8f d0 00 00 00 mov 0xd0(%rdi),%rcx 3ddc: 48 8b bf d8 00 00 00 mov 0xd8(%rdi),%rdi 3de3: 41 89 f9 mov %edi,%r9d 3de6: 41 29 c9 sub %ecx,%r9d struct vxlanhdr *vxh; int min_headroom; int err; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; 3de9: 4c 8b 56 18 mov 0x18(%rsi),%r10 3ded: 44 0f b7 bb aa 00 00 movzwl 0xaa(%rbx),%r15d 3df4: 00 3df5: 0f b7 76 68 movzwl 0x68(%rsi),%esi __be16 inner_protocol = htons(ETH_P_TEB); if ((vxflags & VXLAN_F_REMCSUM_TX) && 3df9: 45 0f b7 9a 4e 02 00 movzwl 0x24e(%r10),%r11d 3e00: 00 3e01: 41 0f b7 82 50 02 00 movzwl 0x250(%r10),%eax 3e08: 00 3e09: 45 89 fa mov %r15d,%r10d 3e0c: 66 41 81 e2 00 10 and $0x1000,%r10w 3e12: 44 01 d8 add %r11d,%eax 3e15: 83 e0 f0 and $0xfffffff0,%eax 3e18: 66 41 83 fa 01 cmp $0x1,%r10w type |= SKB_GSO_TUNNEL_REMCSUM; } min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len + VXLAN_HLEN + iphdr_len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); 3e1d: 8d 74 30 10 lea 0x10(%rax,%rsi,1),%esi 3e21: 19 c0 sbb %eax,%eax 3e23: f7 d0 not %eax (skb->csum_offset == offsetof(struct udphdr, check) || skb->csum_offset == offsetof(struct tcphdr, check))) type |= SKB_GSO_TUNNEL_REMCSUM; } min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len 3e25: 8d 54 16 10 lea 0x10(%rsi,%rdx,1),%edx 3e29: 83 e0 04 and $0x4,%eax 3e2c: 01 d0 add %edx,%eax 3e2e: f6 83 8e 00 00 00 01 testb $0x1,0x8e(%rbx) 3e35: 0f 84 3e 02 00 00 je 4079 3e3b: 8b 93 cc 00 00 00 mov 0xcc(%rbx),%edx 3e41: 48 01 d1 add %rdx,%rcx 3e44: 8b 51 20 mov 0x20(%rcx),%edx 3e47: 0f b7 ca movzwl %dx,%ecx 3e4a: c1 fa 10 sar $0x10,%edx 3e4d: 29 d1 sub %edx,%ecx 3e4f: 83 f9 01 cmp $0x1,%ecx 3e52: 0f 95 c2 setne %dl 3e55: 31 f6 xor %esi,%esi 3e57: 41 39 c1 cmp %eax,%r9d 3e5a: 0f b6 d2 movzbl %dl,%edx 3e5d: 73 05 jae 3e64 */ static inline int skb_header_cloned(const struct sk_buff *skb) { int dataref; if (!skb->cloned) 3e5f: 44 29 c8 sub %r9d,%eax 3e62: 89 c6 mov %eax,%esi 3e64: 09 f2 or %esi,%edx 3e66: 0f 85 7d 01 00 00 jne 3fe9 }; #ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) { return skb->head + skb->end; 3e6c: 66 45 85 d2 test %r10w,%r10w 3e70: 0f 85 ae 01 00 00 jne 4024 3e76: 48 85 db test %rbx,%rbx if (!skb->cloned) return 0; dataref = atomic_read(&skb_shinfo(skb)->dataref); dataref = (dataref & SKB_DATAREF_MASK) - (dataref >> SKB_DATAREF_SHIFT); return dataref != 1; 3e79: 0f 84 69 03 00 00 je 41e8 3e7f: 44 89 ee mov %r13d,%esi 3e82: 48 89 df mov %rbx,%rdi } static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom, int cloned) { int delta = 0; 3e85: e8 00 00 00 00 callq 3e8a if (!skb->cloned) return 0; dataref = atomic_read(&skb_shinfo(skb)->dataref); dataref = (dataref & SKB_DATAREF_MASK) - (dataref >> SKB_DATAREF_SHIFT); return dataref != 1; 3e8a: 85 c0 test %eax,%eax 3e8c: 41 89 c7 mov %eax,%r15d int cloned) { int delta = 0; if (headroom > skb_headroom(skb)) delta = headroom - skb_headroom(skb); 3e8f: 74 45 je 3ed6 3e91: 48 89 df mov %rbx,%rdi if (delta || cloned) 3e94: e8 00 00 00 00 callq 3e99 3e99: 48 83 c4 18 add $0x18,%rsp * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. */ static inline struct sk_buff *vlan_hwaccel_push_inside(struct sk_buff *skb) { if (skb_vlan_tag_present(skb)) 3e9d: 44 89 f8 mov %r15d,%eax 3ea0: 5b pop %rbx 3ea1: 41 5c pop %r12 3ea3: 41 5d pop %r13 3ea5: 41 5e pop %r14 err = skb_cow_head(skb, min_headroom); if (unlikely(err)) goto out_free; skb = vlan_hwaccel_push_inside(skb); if (WARN_ON(!skb)) 3ea7: 41 5f pop %r15 3ea9: 5d pop %rbp 3eaa: c3 retq 3eab: 0f b6 87 91 00 00 00 movzbl 0x91(%rdi),%eax return -ENOMEM; err = iptunnel_handle_offloads(skb, type); 3eb2: 48 8b 8f d0 00 00 00 mov 0xd0(%rdi),%rcx 3eb9: 48 8b bf d8 00 00 00 mov 0xd8(%rdi),%rdi if (err) 3ec0: 83 e0 06 and $0x6,%eax skb_set_inner_protocol(skb, inner_protocol); return 0; out_free: kfree_skb(skb); 3ec3: 3c 06 cmp $0x6,%al 3ec5: 0f 84 83 02 00 00 je 414e return err; } 3ecb: 41 89 f9 mov %edi,%r9d skb_set_inner_protocol(skb, inner_protocol); return 0; out_free: kfree_skb(skb); return err; 3ece: 41 29 c9 sub %ecx,%r9d } 3ed1: e9 13 ff ff ff jmpq 3de9 3ed6: 48 8b 83 d8 00 00 00 mov 0xd8(%rbx),%rax int min_headroom; int err; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; __be16 inner_protocol = htons(ETH_P_TEB); if ((vxflags & VXLAN_F_REMCSUM_TX) && 3edd: 83 83 80 00 00 00 08 addl $0x8,0x80(%rbx) 3ee4: 41 c1 ec 08 shr $0x8,%r12d 3ee8: 41 81 e5 00 40 00 00 and $0x4000,%r13d * * Return the number of bytes of free space at the head of an &sk_buff. */ static inline unsigned int skb_headroom(const struct sk_buff *skb) { return skb->data - skb->head; 3eef: 48 8d 50 f8 lea -0x8(%rax),%rdx 3ef3: 48 89 93 d8 00 00 00 mov %rdx,0xd8(%rbx) 3efa: c7 40 f8 08 00 00 00 movl $0x8,-0x8(%rax) 3f01: 44 89 60 fc mov %r12d,-0x4(%rax) 3f05: 74 57 je 3f5e } unsigned char *skb_push(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len) { skb->data -= len; 3f07: 0f b7 8b 98 00 00 00 movzwl 0x98(%rbx),%ecx skb->len += len; 3f0e: 48 8b 93 d8 00 00 00 mov 0xd8(%rbx),%rdx static inline __be32 vxlan_vni_field(__be32 vni) { #if defined(__BIG_ENDIAN) return (__force __be32)((__force u32)vni << 8); #else return (__force __be32)((__force u32)vni >> 8); 3f15: 48 2b 93 d0 00 00 00 sub 0xd0(%rbx),%rdx vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = VXLAN_HF_VNI; vxh->vx_vni = vxlan_vni_field(vni); if (type & SKB_GSO_TUNNEL_REMCSUM) { 3f1c: 83 e9 08 sub $0x8,%ecx } unsigned char *skb_push(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len) { skb->data -= len; 3f1f: 29 d1 sub %edx,%ecx 3f21: d1 e9 shr %ecx 3f23: 0f c9 bswap %ecx 3f25: 89 ca mov %ecx,%edx 3f27: 81 c9 00 00 00 80 or $0x80000000,%ecx err = iptunnel_handle_offloads(skb, type); if (err) goto out_free; vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); vxh->vx_flags = VXLAN_HF_VNI; 3f2d: 66 83 bb 9a 00 00 00 cmpw $0x6,0x9a(%rbx) 3f34: 06 vxh->vx_vni = vxlan_vni_field(vni); if (type & SKB_GSO_TUNNEL_REMCSUM) { 3f35: c7 40 f8 08 20 00 00 movl $0x2008,-0x8(%rax) offsetof(struct tcphdr, check); } static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset) { __be32 vni_field = cpu_to_be32(start >> VXLAN_RCO_SHIFT); 3f3c: 0f 44 d1 cmove %ecx,%edx 3f3f: 44 09 e2 or %r12d,%edx 3f42: 89 50 fc mov %edx,-0x4(%rax) 3f45: 8b 93 cc 00 00 00 mov 0xcc(%rbx),%edx 3f4b: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx 3f52: 66 83 7c 11 02 00 cmpw $0x0,0x2(%rcx,%rdx,1) if (offset == offsetof(struct udphdr, check)) vni_field |= VXLAN_RCO_UDP; 3f58: 0f 84 39 02 00 00 je 4197 3f5e: 41 f7 c6 00 08 00 00 test $0x800,%r14d unsigned int start; start = skb_checksum_start_offset(skb) - sizeof(struct vxlanhdr); vxh->vx_vni |= vxlan_compute_rco(start, skb->csum_offset); vxh->vx_flags |= VXLAN_HF_RCO; 3f65: 74 3b je 3fa2 3f67: 48 8b 7d d0 mov -0x30(%rbp),%rdi 3f6b: 8b 17 mov (%rdi),%edx 3f6d: 85 d2 test %edx,%edx if (type & SKB_GSO_TUNNEL_REMCSUM) { unsigned int start; start = skb_checksum_start_offset(skb) - sizeof(struct vxlanhdr); vxh->vx_vni |= vxlan_compute_rco(start, skb->csum_offset); 3f6f: 74 31 je 3fa2 3f71: 81 48 f8 80 00 00 00 orl $0x80,-0x8(%rax) return csum_fold(csum_partial(csum_start, plen, partial)); } static inline bool skb_is_gso(const struct sk_buff *skb) { return skb_shinfo(skb)->gso_size; 3f78: 8b 17 mov (%rdi),%edx 3f7a: f7 c2 00 00 40 00 test $0x400000,%edx 3f80: 74 06 je 3f88 vxh->vx_flags |= VXLAN_HF_RCO; if (!skb_is_gso(skb)) { 3f82: 80 48 f9 40 orb $0x40,-0x7(%rax) 3f86: 8b 17 mov (%rdi),%edx 3f88: f7 c2 00 00 08 00 test $0x80000,%edx skb->ip_summed = CHECKSUM_NONE; skb->encapsulation = 0; } } if (vxflags & VXLAN_F_GBP) 3f8e: 74 0a je 3f9a 3f90: 48 8b 7d d0 mov -0x30(%rbp),%rdi 3f94: 80 48 f9 08 orb $0x8,-0x7(%rax) static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags, struct vxlan_metadata *md) { struct vxlanhdr_gbp *gbp; if (!md->gbp) 3f98: 8b 17 mov (%rdi),%edx 3f9a: 66 c1 c2 08 rol $0x8,%dx 3f9e: 66 89 50 fa mov %dx,-0x6(%rax) return; gbp = (struct vxlanhdr_gbp *)vxh; vxh->vx_flags |= VXLAN_HF_GBP; 3fa2: 41 81 e6 00 40 00 00 and $0x4000,%r14d if (md->gbp & VXLAN_GBP_DONT_LEARN) 3fa9: 0f 84 25 02 00 00 je 41d4 3faf: 0f b7 93 c0 00 00 00 movzwl 0xc0(%rbx),%edx gbp->dont_learn = 1; 3fb6: 80 48 f8 04 orb $0x4,-0x8(%rax) if (md->gbp & VXLAN_GBP_POLICY_APPLIED) 3fba: 66 81 fa 65 58 cmp $0x5865,%dx 3fbf: 0f 84 e5 01 00 00 je 41aa gbp->policy_applied = 1; 3fc5: 66 81 fa 86 dd cmp $0xdd86,%dx gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK); 3fca: 0f 84 3d 02 00 00 je 420d 3fd0: 66 83 fa 08 cmp $0x8,%dx } } if (vxflags & VXLAN_F_GBP) vxlan_build_gbp_hdr(vxh, vxflags, md); if (vxflags & VXLAN_F_GPE) { 3fd4: 41 bf a0 ff ff ff mov $0xffffffa0,%r15d 3fda: 0f 85 b1 fe ff ff jne 3e91 err = vxlan_build_gpe_hdr(vxh, vxflags, skb->protocol); 3fe0: c6 40 fb 01 movb $0x1,-0x5(%rax) 3fe4: e9 c5 01 00 00 jmpq 41ae static int vxlan_build_gpe_hdr(struct vxlanhdr *vxh, u32 vxflags, __be16 protocol) { struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)vxh; gpe->np_applied = 1; 3fe9: 83 c6 3f add $0x3f,%esi switch (protocol) { 3fec: 31 d2 xor %edx,%edx 3fee: b9 20 00 08 02 mov $0x2080020,%ecx 3ff3: 83 e6 c0 and $0xffffffc0,%esi 3ff6: 48 89 df mov %rbx,%rdi 3ff9: e8 00 00 00 00 callq 3ffe 3ffe: 85 c0 test %eax,%eax 4000: 41 89 c7 mov %eax,%r15d 4003: 0f 85 88 fe ff ff jne 3e91 return 0; case htons(ETH_P_TEB): gpe->next_protocol = VXLAN_GPE_NP_ETHERNET; return 0; } return -EPFNOSUPPORT; 4009: 44 0f b7 bb aa 00 00 movzwl 0xaa(%rbx),%r15d 4010: 00 gpe->np_applied = 1; switch (protocol) { case htons(ETH_P_IP): gpe->next_protocol = VXLAN_GPE_NP_IPV4; 4011: 45 89 fa mov %r15d,%r10d 4014: 66 41 81 e2 00 10 and $0x1000,%r10w if (headroom > skb_headroom(skb)) delta = headroom - skb_headroom(skb); if (delta || cloned) return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0, 401a: 66 45 85 d2 test %r10w,%r10w 401e: 0f 84 52 fe ff ff je 3e76 4024: 66 41 81 e7 ff ef and $0xefff,%r15w 402a: f6 83 8e 00 00 00 01 testb $0x1,0x8e(%rbx) 4031: 44 0f b7 8b a8 00 00 movzwl 0xa8(%rbx),%r9d 4038: 00 + VXLAN_HLEN + iphdr_len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0); /* Need space for new headers (invalidates iph ptr) */ err = skb_cow_head(skb, min_headroom); if (unlikely(err)) 4039: 0f 84 d4 01 00 00 je 4213 403f: 8b 83 cc 00 00 00 mov 0xcc(%rbx),%eax 4045: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx 404c: 48 01 c8 add %rcx,%rax 404f: 8b 40 20 mov 0x20(%rax),%eax 4052: 0f b7 d0 movzwl %ax,%edx 4055: c1 f8 10 sar $0x10,%eax 4058: 29 c2 sub %eax,%edx */ static inline int skb_header_cloned(const struct sk_buff *skb) { int dataref; if (!skb->cloned) 405a: 89 d0 mov %edx,%eax 405c: 31 d2 xor %edx,%edx 405e: 83 f8 01 cmp $0x1,%eax * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. */ static inline struct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb) { skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, 4061: 48 8b 83 d8 00 00 00 mov 0xd8(%rbx),%rax 4068: 0f 95 c2 setne %dl 406b: 31 f6 xor %esi,%esi 406d: 48 29 c8 sub %rcx,%rax }; #ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) { return skb->head + skb->end; 4070: 83 f8 03 cmp $0x3,%eax 4073: 89 c1 mov %eax,%ecx 4075: 77 3a ja 40b1 4077: eb 31 jmp 40aa 4079: 41 39 c1 cmp %eax,%r9d 407c: 0f 82 c0 00 00 00 jb 4142 if (!skb->cloned) return 0; dataref = atomic_read(&skb_shinfo(skb)->dataref); dataref = (dataref & SKB_DATAREF_MASK) - (dataref >> SKB_DATAREF_SHIFT); return dataref != 1; 4082: 66 45 85 d2 test %r10w,%r10w 4086: 0f 84 ea fd ff ff je 3e76 408c: 44 0f b7 8b a8 00 00 movzwl 0xa8(%rbx),%r9d 4093: 00 * * Return the number of bytes of free space at the head of an &sk_buff. */ static inline unsigned int skb_headroom(const struct sk_buff *skb) { return skb->data - skb->head; 4094: 66 41 81 e7 ff ef and $0xefff,%r15w if (!skb->cloned) return 0; dataref = atomic_read(&skb_shinfo(skb)->dataref); dataref = (dataref & SKB_DATAREF_MASK) - (dataref >> SKB_DATAREF_SHIFT); return dataref != 1; 409a: 48 2b bb d0 00 00 00 sub 0xd0(%rbx),%rdi static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom, int cloned) { int delta = 0; if (headroom > skb_headroom(skb)) 40a1: 83 ff 03 cmp $0x3,%edi * * Return the number of bytes of free space at the head of an &sk_buff. */ static inline unsigned int skb_headroom(const struct sk_buff *skb) { return skb->data - skb->head; 40a4: 89 f9 mov %edi,%ecx static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom, int cloned) { int delta = 0; if (headroom > skb_headroom(skb)) 40a6: 77 32 ja 40da 40a8: 31 d2 xor %edx,%edx 40aa: be 04 00 00 00 mov $0x4,%esi 40af: 29 ce sub %ecx,%esi 40b1: 09 f2 or %esi,%edx * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. */ static inline struct sk_buff *vlan_hwaccel_push_inside(struct sk_buff *skb) { if (skb_vlan_tag_present(skb)) 40b3: 74 25 je 40da 40b5: 83 c6 3f add $0x3f,%esi 40b8: 31 d2 xor %edx,%edx 40ba: b9 20 00 08 02 mov $0x2080020,%ecx * Following the skb_unshare() example, in case of error, the calling function * doesn't have to worry about freeing the original skb. */ static inline struct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb) { skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, 40bf: 83 e6 c0 and $0xffffffc0,%esi 40c2: 48 89 df mov %rbx,%rdi 40c5: 44 89 4d c8 mov %r9d,-0x38(%rbp) 40c9: e8 00 00 00 00 callq 40ce * * Return the number of bytes of free space at the head of an &sk_buff. */ static inline unsigned int skb_headroom(const struct sk_buff *skb) { return skb->data - skb->head; 40ce: 85 c0 test %eax,%eax 40d0: 44 8b 4d c8 mov -0x38(%rbp),%r9d 40d4: 0f 88 01 01 00 00 js 41db int cloned) { int delta = 0; if (headroom > skb_headroom(skb)) delta = headroom - skb_headroom(skb); 40da: be 04 00 00 00 mov $0x4,%esi 40df: 48 89 df mov %rbx,%rdi if (delta || cloned) 40e2: 44 89 4d c4 mov %r9d,-0x3c(%rbp) return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0, 40e6: e8 00 00 00 00 callq 40eb 40eb: 48 8b bb d8 00 00 00 mov 0xd8(%rbx),%rdi 40f2: ba 0c 00 00 00 mov $0xc,%edx 40f7: 48 89 45 c8 mov %rax,-0x38(%rbp) 40fb: 66 41 c1 c7 08 rol $0x8,%r15w static inline int __vlan_insert_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) { struct vlan_ethhdr *veth; if (skb_cow_head(skb, VLAN_HLEN) < 0) 4100: 48 8d 77 04 lea 0x4(%rdi),%rsi 4104: e8 00 00 00 00 callq 4109 4109: 48 8b 4d c8 mov -0x38(%rbp),%rcx return -ENOMEM; veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); 410d: 44 8b 4d c4 mov -0x3c(%rbp),%r9d 4111: 66 83 ab c6 00 00 00 subw $0x4,0xc6(%rbx) 4118: 04 4119: 48 85 db test %rbx,%rbx /* Move the mac addresses to the beginning of the new header. */ memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); 411c: 66 44 89 49 0c mov %r9w,0xc(%rcx) 4121: 66 44 89 79 0e mov %r15w,0xe(%rcx) 4126: 0f 84 bc 00 00 00 je 41e8 /* first, the ethernet type */ veth->h_vlan_proto = vlan_proto; /* now, the TCI */ veth->h_vlan_TCI = htons(vlan_tci); 412c: 31 c9 xor %ecx,%ecx 412e: 66 44 89 8b c0 00 00 mov %r9w,0xc0(%rbx) 4135: 00 return -ENOMEM; veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); /* Move the mac addresses to the beginning of the new header. */ memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); 4136: 66 89 8b aa 00 00 00 mov %cx,0xaa(%rbx) skb->mac_header -= VLAN_HLEN; /* first, the ethernet type */ veth->h_vlan_proto = vlan_proto; 413d: e9 3d fd ff ff jmpq 3e7f veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); /* Move the mac addresses to the beginning of the new header. */ memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); skb->mac_header -= VLAN_HLEN; 4142: 44 29 c8 sub %r9d,%eax 4145: 31 d2 xor %edx,%edx 4147: 89 c6 mov %eax,%esi static inline struct sk_buff *vlan_insert_tag_set_proto(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) { skb = vlan_insert_tag(skb, vlan_proto, vlan_tci); if (skb) 4149: e9 16 fd ff ff jmpq 3e64 /* Move the mac addresses to the beginning of the new header. */ memmove(skb->data, skb->data + VLAN_HLEN, 2 * ETH_ALEN); skb->mac_header -= VLAN_HLEN; /* first, the ethernet type */ veth->h_vlan_proto = vlan_proto; 414e: 0f b7 83 98 00 00 00 movzwl 0x98(%rbx),%eax /* now, the TCI */ veth->h_vlan_TCI = htons(vlan_tci); 4155: 49 89 fa mov %rdi,%r10 static inline struct sk_buff *vlan_insert_tag_set_proto(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci) { skb = vlan_insert_tag(skb, vlan_proto, vlan_tci); if (skb) 4158: 49 29 ca sub %rcx,%r10 415b: 45 89 d1 mov %r10d,%r9d skb->protocol = vlan_proto; 415e: 44 29 d0 sub %r10d,%eax 4161: 3d fe 00 00 00 cmp $0xfe,%eax static inline struct sk_buff *__vlan_hwaccel_push_inside(struct sk_buff *skb) { skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto, skb_vlan_tag_get(skb)); if (likely(skb)) skb->vlan_tci = 0; 4166: 0f 8f 7d fc ff ff jg 3de9 416c: a8 01 test $0x1,%al 416e: 0f 85 75 fc ff ff jne 3de9 int cloned) { int delta = 0; if (headroom > skb_headroom(skb)) delta = headroom - skb_headroom(skb); 4174: 0f b7 83 9a 00 00 00 movzwl 0x9a(%rbx),%eax 417b: 66 83 f8 06 cmp $0x6,%ax } } static inline int skb_checksum_start_offset(const struct sk_buff *skb) { return skb->csum_start - skb_headroom(skb); 417f: 74 0a je 418b 4181: 66 83 f8 10 cmp $0x10,%ax * * Return the number of bytes of free space at the head of an &sk_buff. */ static inline unsigned int skb_headroom(const struct sk_buff *skb) { return skb->data - skb->head; 4185: 0f 85 5e fc ff ff jne 3de9 418b: 41 81 cd 00 40 00 00 or $0x4000,%r13d if ((vxflags & VXLAN_F_REMCSUM_TX) && skb->ip_summed == CHECKSUM_PARTIAL) { int csum_start = skb_checksum_start_offset(skb); if (csum_start <= VXLAN_MAX_REMCSUM_START && 4192: e9 52 fc ff ff jmpq 3de9 4197: 80 a3 91 00 00 00 f9 andb $0xf9,0x91(%rbx) 419e: 80 a3 92 00 00 00 fd andb $0xfd,0x92(%rbx) !(csum_start & VXLAN_RCO_SHIFT_MASK) && (skb->csum_offset == offsetof(struct udphdr, check) || 41a5: e9 b4 fd ff ff jmpq 3f5e 41aa: c6 40 fb 03 movb $0x3,-0x5(%rax) if ((vxflags & VXLAN_F_REMCSUM_TX) && skb->ip_summed == CHECKSUM_PARTIAL) { int csum_start = skb_checksum_start_offset(skb); if (csum_start <= VXLAN_MAX_REMCSUM_START && !(csum_start & VXLAN_RCO_SHIFT_MASK) && 41ae: 0f b7 83 c0 00 00 00 movzwl 0xc0(%rbx),%eax 41b5: 66 89 83 b8 00 00 00 mov %ax,0xb8(%rbx) (skb->csum_offset == offsetof(struct udphdr, check) || skb->csum_offset == offsetof(struct tcphdr, check))) type |= SKB_GSO_TUNNEL_REMCSUM; 41bc: 80 a3 93 00 00 00 f7 andb $0xf7,0x93(%rbx) 41c3: 48 83 c4 18 add $0x18,%rsp start = skb_checksum_start_offset(skb) - sizeof(struct vxlanhdr); vxh->vx_vni |= vxlan_compute_rco(start, skb->csum_offset); vxh->vx_flags |= VXLAN_HF_RCO; if (!skb_is_gso(skb)) { skb->ip_summed = CHECKSUM_NONE; 41c7: 5b pop %rbx 41c8: 31 c0 xor %eax,%eax 41ca: 41 5c pop %r12 41cc: 41 5d pop %r13 skb->encapsulation = 0; 41ce: 41 5e pop %r14 41d0: 41 5f pop %r15 41d2: 5d pop %rbp 41d3: c3 retq 41d4: b8 65 58 00 00 mov $0x5865,%eax 41d9: eb da jmp 41b5 return 0; case htons(ETH_P_IPV6): gpe->next_protocol = VXLAN_GPE_NP_IPV6; return 0; case htons(ETH_P_TEB): gpe->next_protocol = VXLAN_GPE_NP_ETHERNET; 41db: be 01 00 00 00 mov $0x1,%esi vxlan_build_gbp_hdr(vxh, vxflags, md); if (vxflags & VXLAN_F_GPE) { err = vxlan_build_gpe_hdr(vxh, vxflags, skb->protocol); if (err < 0) goto out_free; inner_protocol = skb->protocol; 41e0: 48 89 df mov %rbx,%rdi 41e3: e8 00 00 00 00 callq 41e8 #define ENCAP_TYPE_IPPROTO 1 static inline void skb_set_inner_protocol(struct sk_buff *skb, __be16 protocol) { skb->inner_protocol = protocol; 41e8: be d5 06 00 00 mov $0x6d5,%esi skb->inner_protocol_type = ENCAP_TYPE_ETHER; 41ed: 48 c7 c7 00 00 00 00 mov $0x0,%rdi return 0; out_free: kfree_skb(skb); return err; } 41f4: e8 00 00 00 00 callq 41f9 goto out_free; inner_protocol = skb->protocol; } skb_set_inner_protocol(skb, inner_protocol); return 0; 41f9: 48 83 c4 18 add $0x18,%rsp out_free: kfree_skb(skb); return err; } 41fd: b8 f4 ff ff ff mov $0xfffffff4,%eax 4202: 5b pop %rbx 4203: 41 5c pop %r12 { struct vxlanhdr *vxh; int min_headroom; int err; int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; __be16 inner_protocol = htons(ETH_P_TEB); 4205: 41 5d pop %r13 4207: 41 5e pop %r14 4209: 41 5f pop %r15 __dev_kfree_skb_irq(skb, SKB_REASON_CONSUMED); } static inline void dev_kfree_skb_any(struct sk_buff *skb) { __dev_kfree_skb_any(skb, SKB_REASON_DROPPED); 420b: 5d pop %rbp 420c: c3 retq 420d: c6 40 fb 02 movb $0x2,-0x5(%rax) 4211: eb 9b jmp 41ae 4213: 48 8b bb d8 00 00 00 mov 0xd8(%rbx),%rdi err = skb_cow_head(skb, min_headroom); if (unlikely(err)) goto out_free; skb = vlan_hwaccel_push_inside(skb); if (WARN_ON(!skb)) 421a: e9 7b fe ff ff jmpq 409a 421f: 90 nop 0000000000004220 : 4220: e8 00 00 00 00 callq 4225 4225: 55 push %rbp 4226: 49 89 d3 mov %rdx,%r11 return 0; out_free: kfree_skb(skb); return err; } 4229: 4c 8d 96 40 08 00 00 lea 0x840(%rsi),%r10 if (unlikely(err)) goto out_free; skb = vlan_hwaccel_push_inside(skb); if (WARN_ON(!skb)) return -ENOMEM; 4230: 48 89 e5 mov %rsp,%rbp return 0; out_free: kfree_skb(skb); return err; } 4233: 41 57 push %r15 4235: 41 56 push %r14 4237: 41 55 push %r13 4239: 41 54 push %r12 423b: 49 89 fd mov %rdi,%r13 switch (protocol) { case htons(ETH_P_IP): gpe->next_protocol = VXLAN_GPE_NP_IPV4; return 0; case htons(ETH_P_IPV6): gpe->next_protocol = VXLAN_GPE_NP_IPV6; 423e: 53 push %rbx 423f: 48 89 f3 mov %rsi,%rbx 4242: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 4246: 48 81 ec f0 00 00 00 sub $0xf0,%rsp 424d: 4c 8b 67 58 mov 0x58(%rdi),%r12 } } static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, struct vxlan_rdst *rdst, bool did_rsc) { 4251: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 4258: 00 00 * * Get network device private data */ static inline void *netdev_priv(const struct net_device *dev) { return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); 425a: 48 89 84 24 e8 00 00 mov %rax,0xe8(%rsp) 4261: 00 4262: 31 c0 xor %eax,%eax 4264: 8b 86 d8 08 00 00 mov 0x8d8(%rsi),%eax 426a: 49 83 e4 fe and $0xfffffffffffffffe,%r12 426e: 89 44 24 64 mov %eax,0x64(%rsp) 4272: 48 8b 86 70 08 00 00 mov 0x870(%rsi),%rax 4279: 48 8b 80 80 04 00 00 mov 0x480(%rax),%rax static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb) { struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb); if (md_dst && md_dst->dst.flags & DST_METADATA) 4280: 48 89 44 24 70 mov %rax,0x70(%rsp) 4285: 48 8b 86 78 08 00 00 mov 0x878(%rsi),%rax 428c: 48 89 44 24 78 mov %rax,0x78(%rsp) 4291: 0f 84 99 08 00 00 je 4b30 __be16 src_port = 0, dst_port; __be32 vni, label; __be16 df = 0; __u8 tos, ttl; int err; u32 flags = vxlan->flags; 4297: 41 f6 44 24 61 02 testb $0x2,0x61(%r12) 429d: 0f 84 9b 03 00 00 je 463e 42a3: 49 81 c4 a0 00 00 00 add $0xa0,%r12 42aa: 4d 85 db test %r11,%r11 42ad: 0f 84 a9 03 00 00 je 465c 42b3: 41 0f b7 43 1c movzwl 0x1c(%r11),%eax bool udp_sum = false; bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); 42b8: 66 85 c0 test %ax,%ax 42bb: 66 89 84 24 84 00 00 mov %ax,0x84(%rsp) 42c2: 00 42c3: 0f 84 51 03 00 00 je 461a 42c9: 41 8b 43 20 mov 0x20(%r11),%eax 42cd: 4d 8d 73 48 lea 0x48(%r11),%r14 42d1: 4d 89 df mov %r11,%r15 { struct metadata_dst *md_dst = skb_metadata_dst(skb); struct dst_entry *dst; if (md_dst) return &md_dst->u.tun_info; 42d4: 89 44 24 50 mov %eax,0x50(%rsp) 42d8: 48 8d 83 54 09 00 00 lea 0x954(%rbx),%rax info = skb_tunnel_info(skb); if (rdst) { 42df: 48 89 44 24 68 mov %rax,0x68(%rsp) dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; 42e4: 41 0f b7 03 movzwl (%r11),%eax 42e8: 66 83 f8 0a cmp $0xa,%ax 42ec: 0f 84 3c 03 00 00 je 462e 42f2: 41 8b 77 04 mov 0x4(%r15),%esi 42f6: 85 f6 test %esi,%esi 42f8: 0f 94 c2 sete %dl vni = rdst->remote_vni; 42fb: 84 d2 test %dl,%dl dst = &rdst->remote_ip; src = &vxlan->cfg.saddr; dst_cache = &rdst->dst_cache; 42fd: 74 3e je 433d 42ff: 84 c9 test %cl,%cl info = skb_tunnel_info(skb); if (rdst) { dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; vni = rdst->remote_vni; dst = &rdst->remote_ip; 4301: 0f 85 d1 04 00 00 jne 47d8 info = skb_tunnel_info(skb); if (rdst) { dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; vni = rdst->remote_vni; 4307: 48 83 83 68 01 00 00 addq $0x1,0x168(%rbx) 430e: 01 dst = &rdst->remote_ip; src = &vxlan->cfg.saddr; 430f: 4c 89 ef mov %r13,%rdi 4312: e8 00 00 00 00 callq 4317 4317: 48 8b 84 24 e8 00 00 mov 0xe8(%rsp),%rax 431e: 00 return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 431f: 65 48 33 04 25 28 00 xor %gs:0x28,%rax 4326: 00 00 return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); 4328: 0f 85 da 09 00 00 jne 4d08 dst = &remote_ip; src = &local_ip; dst_cache = &info->dst_cache; } if (vxlan_addr_any(dst)) { 432e: 48 8d 65 d8 lea -0x28(%rbp),%rsp if (did_rsc) { 4332: 5b pop %rbx 4333: 41 5c pop %r12 4335: 41 5d pop %r13 } return; drop: dev->stats.tx_dropped++; 4337: 41 5e pop %r14 4339: 41 5f pop %r15 433b: 5d pop %rbp 433c: c3 retq 433d: 0f b6 bb 83 09 00 00 movzbl 0x983(%rbx),%edi rt_tx_error: ip_rt_put(rt); tx_error: dev->stats.tx_errors++; tx_free: dev_kfree_skb(skb); 4344: 41 0f b7 95 c4 00 00 movzwl 0xc4(%r13),%edx 434b: 00 } 434c: 49 03 95 d0 00 00 00 add 0xd0(%r13),%rdx 4353: 40 84 ff test %dil,%dil 4356: 40 88 bc 24 87 00 00 mov %dil,0x87(%rsp) 435d: 00 435e: 48 89 54 24 38 mov %rdx,0x38(%rsp) 4363: 75 22 jne 4387 4365: 66 83 f8 0a cmp $0xa,%ax 4369: 0f 84 71 03 00 00 je 46e0 goto drop; } old_iph = ip_hdr(skb); ttl = vxlan->cfg.ttl; 436f: 41 8b 47 04 mov 0x4(%r15),%eax 4373: 25 f0 00 00 00 and $0xf0,%eax skb->transport_header += offset; } static inline unsigned char *skb_network_header(const struct sk_buff *skb) { return skb->head + skb->network_header; 4378: 3d e0 00 00 00 cmp $0xe0,%eax 437d: 0f 94 c0 sete %al 4380: 88 84 24 87 00 00 00 mov %al,0x87(%rsp) 4387: 0f b6 83 82 09 00 00 movzbl 0x982(%rbx),%eax 438e: 3c 01 cmp $0x1,%al 4390: 88 84 24 88 00 00 00 mov %al,0x88(%rsp) return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); } static inline bool vxlan_addr_multicast(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 4397: 0f 84 a1 04 00 00 je 483e 439d: 8b 83 84 09 00 00 mov 0x984(%rbx),%eax return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr); else return IN_MULTICAST(ntohl(ipa->sin.sin_addr.s_addr)); 43a3: 0f b7 93 80 09 00 00 movzwl 0x980(%rbx),%edx 43aa: 48 8b bb 80 04 00 00 mov 0x480(%rbx),%rdi 43b1: 89 84 24 80 00 00 00 mov %eax,0x80(%rsp) ttl = vxlan->cfg.ttl; if (!ttl && vxlan_addr_multicast(dst)) ttl = 1; tos = vxlan->cfg.tos; 43b8: 0f b7 83 7e 09 00 00 movzwl 0x97e(%rbx),%eax if (tos == 1) 43bf: 89 94 24 9c 00 00 00 mov %edx,0x9c(%rsp) ttl = vxlan->cfg.ttl; if (!ttl && vxlan_addr_multicast(dst)) ttl = 1; tos = vxlan->cfg.tos; 43c6: 39 c2 cmp %eax,%edx if (tos == 1) 43c8: 89 84 24 98 00 00 00 mov %eax,0x98(%rsp) tos = ip_tunnel_get_dsfield(old_iph, skb); label = vxlan->cfg.label; 43cf: 0f 8e 3b 04 00 00 jle 4810 src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, 43d5: 41 f6 85 91 00 00 00 testb $0x30,0x91(%r13) 43dc: 30 43dd: 0f 84 0c 04 00 00 je 47ef tos = vxlan->cfg.tos; if (tos == 1) tos = ip_tunnel_get_dsfield(old_iph, skb); label = vxlan->cfg.label; 43e3: 41 8b 85 a4 00 00 00 mov 0xa4(%r13),%eax src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, 43ea: 85 c0 test %eax,%eax 43ec: 0f 85 c0 00 00 00 jne 44b2 43f2: 49 8b b5 d8 00 00 00 mov 0xd8(%r13),%rsi static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb, int min, int max, bool use_eth) { u32 hash; if (min >= max) { 43f9: 41 0f b7 8d c0 00 00 movzwl 0xc0(%r13),%ecx 4400: 00 4401: 0f b6 56 08 movzbl 0x8(%rsi),%edx data, proto, nhoff, hlen, flags); } static inline __u32 skb_get_hash(struct sk_buff *skb) { if (!skb->l4_hash && !skb->sw_hash) 4405: 0f b6 46 0b movzbl 0xb(%rsi),%eax 4409: 81 e9 05 41 52 21 sub $0x21524105,%ecx 440f: 44 0f b6 46 04 movzbl 0x4(%rsi),%r8d __skb_get_hash(skb); return skb->hash; 4414: 8d 3c 0a lea (%rdx,%rcx,1),%edi 4417: c1 e0 18 shl $0x18,%eax /* Use default range */ inet_get_local_port_range(net, &min, &max); } hash = skb_get_hash(skb); if (unlikely(!hash)) { 441a: 45 8d 0c 08 lea (%r8,%rcx,1),%r9d 441e: 8d 14 38 lea (%rax,%rdi,1),%edx 4421: 0f b6 46 0a movzbl 0xa(%rsi),%eax if (use_eth) { /* Can't find a normal hash, caller has indicated an * Ethernet packet so use that to compute a hash. */ hash = jhash(skb->data, 2 * ETH_ALEN, 4425: 0f b6 7e 07 movzbl 0x7(%rsi),%edi { u32 a, b, c; const u8 *k = key; /* Set up the internal state */ a = b = c = JHASH_INITVAL + length + initval; 4429: c1 e0 10 shl $0x10,%eax 442c: c1 e7 18 shl $0x18,%edi 442f: 01 d0 add %edx,%eax 4431: 0f b6 56 06 movzbl 0x6(%rsi),%edx 4435: 46 8d 04 0f lea (%rdi,%r9,1),%r8d 4439: c1 e2 10 shl $0x10,%edx 443c: 41 8d 3c 10 lea (%r8,%rdx,1),%edi 4440: 0f b6 56 05 movzbl 0x5(%rsi),%edx 4444: 44 0f b6 06 movzbl (%rsi),%r8d 4448: c1 e2 08 shl $0x8,%edx 444b: 44 01 c1 add %r8d,%ecx 444e: 01 fa add %edi,%edx 4450: 0f b6 7e 03 movzbl 0x3(%rsi),%edi 4454: c1 e7 18 shl $0x18,%edi 4457: 44 8d 04 39 lea (%rcx,%rdi,1),%r8d 445b: 0f b6 7e 02 movzbl 0x2(%rsi),%edi 445f: 0f b6 4e 01 movzbl 0x1(%rsi),%ecx 4463: 0f b6 76 09 movzbl 0x9(%rsi),%esi 4467: c1 e7 10 shl $0x10,%edi 446a: c1 e1 08 shl $0x8,%ecx 446d: c1 e6 08 shl $0x8,%esi case 10: c += (u32)k[9]<<8; case 9: c += k[8]; case 8: b += (u32)k[7]<<24; case 7: b += (u32)k[6]<<16; case 6: b += (u32)k[5]<<8; case 5: b += k[4]; 4470: 44 01 c7 add %r8d,%edi 4473: 01 f0 add %esi,%eax case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4475: 89 d6 mov %edx,%esi 4477: 01 f9 add %edi,%ecx case 10: c += (u32)k[9]<<8; case 9: c += k[8]; case 8: b += (u32)k[7]<<24; case 7: b += (u32)k[6]<<16; case 6: b += (u32)k[5]<<8; case 5: b += k[4]; 4479: 31 d0 xor %edx,%eax case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 447b: c1 c6 0e rol $0xe,%esi case 10: c += (u32)k[9]<<8; case 9: c += k[8]; case 8: b += (u32)k[7]<<24; case 7: b += (u32)k[6]<<16; case 6: b += (u32)k[5]<<8; case 5: b += k[4]; 447e: 29 f0 sub %esi,%eax case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4480: 89 c6 mov %eax,%esi 4482: 31 c1 xor %eax,%ecx 4484: c1 c6 0b rol $0xb,%esi 4487: 29 f1 sub %esi,%ecx 4489: 89 ce mov %ecx,%esi 448b: 31 ca xor %ecx,%edx 448d: c1 ce 07 ror $0x7,%esi 4490: 29 f2 sub %esi,%edx 4492: 89 d6 mov %edx,%esi __jhash_final(a, b, c); 4494: 31 d0 xor %edx,%eax 4496: c1 c6 10 rol $0x10,%esi case 6: b += (u32)k[5]<<8; case 5: b += k[4]; case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4499: 29 f0 sub %esi,%eax 449b: 89 c6 mov %eax,%esi __jhash_final(a, b, c); 449d: 31 c1 xor %eax,%ecx 449f: c1 c6 04 rol $0x4,%esi case 6: b += (u32)k[5]<<8; case 5: b += k[4]; case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 44a2: 29 f1 sub %esi,%ecx __jhash_final(a, b, c); 44a4: 31 ca xor %ecx,%edx 44a6: c1 c1 0e rol $0xe,%ecx 44a9: 29 ca sub %ecx,%edx 44ab: 31 d0 xor %edx,%eax 44ad: c1 ca 08 ror $0x8,%edx 44b0: 29 d0 sub %edx,%eax 44b2: 8b b4 24 98 00 00 00 mov 0x98(%rsp),%esi 44b9: 8b 8c 24 9c 00 00 00 mov 0x9c(%rsp),%ecx 44c0: 89 c2 mov %eax,%edx 44c2: c1 e2 10 shl $0x10,%edx 44c5: 31 d0 xor %edx,%eax 44c7: 29 f1 sub %esi,%ecx 44c9: 48 63 c9 movslq %ecx,%rcx 44cc: 48 0f af c8 imul %rax,%rcx 44d0: 48 c1 e9 20 shr $0x20,%rcx 44d4: 01 ce add %ecx,%esi 44d6: 66 c1 c6 08 rol $0x8,%si 44da: 4d 85 e4 test %r12,%r12 44dd: 66 89 74 24 62 mov %si,0x62(%rsp) * attacker is leaked. Only upper 16 bits are relevant in the * computation for 16 bit port value. */ hash ^= hash << 16; return htons((((u64) hash * (max - min)) >> 32) + min); 44e2: 0f 84 7a 05 00 00 je 4a62 44e8: 41 0f b6 44 24 2b movzbl 0x2b(%r12),%eax 44ee: 48 8d 94 24 94 00 00 lea 0x94(%rsp),%rdx 44f5: 00 44f6: 88 84 24 87 00 00 00 mov %al,0x87(%rsp) 44fd: 41 0f b6 44 24 2a movzbl 0x2a(%r12),%eax 4503: 88 84 24 88 00 00 00 mov %al,0x88(%rsp) vxlan->cfg.port_max, true); if (info) { 450a: 41 8b 44 24 2c mov 0x2c(%r12),%eax 450f: 89 84 24 80 00 00 00 mov %eax,0x80(%rsp) 4516: 41 0f b6 44 24 29 movzbl 0x29(%r12),%eax ttl = info->key.ttl; 451c: 83 e0 01 and $0x1,%eax } } static inline void *ip_tunnel_info_opts(struct ip_tunnel_info *info) { return info + 1; 451f: 41 80 7c 24 48 00 cmpb $0x0,0x48(%r12) 4525: 88 44 24 48 mov %al,0x48(%rsp) 4529: 49 8d 44 24 50 lea 0x50(%r12),%rax tos = info->key.tos; 452e: 48 0f 44 c2 cmove %rdx,%rax 4532: 48 89 44 24 40 mov %rax,0x40(%rsp) 4537: 48 8b 7c 24 70 mov 0x70(%rsp),%rdi label = info->key.label; 453c: 48 39 7c 24 78 cmp %rdi,0x78(%rsp) 4541: 0f 95 44 24 70 setne 0x70(%rsp) udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); 4546: 66 41 83 3f 02 cmpw $0x2,(%r15) 454b: 0f 84 2e 03 00 00 je 487f 4551: 48 8b 83 68 08 00 00 mov 0x868(%rbx),%rax 4558: 48 85 c0 test %rax,%rax 455b: 0f 84 a6 fd ff ff je 4307 4561: 48 8b 40 10 mov 0x10(%rax),%rax 4565: 0f b6 8c 24 88 00 00 movzbl 0x88(%rsp),%ecx 456c: 00 __be16 df = 0; __u8 tos, ttl; int err; u32 flags = vxlan->flags; bool udp_sum = false; bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); 456d: 48 8b 40 20 mov 0x20(%rax),%rax 4571: 48 89 44 24 30 mov %rax,0x30(%rsp) md = ip_tunnel_info_opts(info); } else { md->gbp = skb->mark; } if (dst->sa.sa_family == AF_INET) { 4576: 48 8b 44 24 68 mov 0x68(%rsp),%rax 457b: 48 83 c0 08 add $0x8,%rax 457f: 4d 85 db test %r11,%r11 #if IS_ENABLED(CONFIG_IPV6) } else { struct dst_entry *ndst; u32 rt6i_flags; if (!vxlan->vn6_sock) 4582: 48 89 44 24 78 mov %rax,0x78(%rsp) 4587: 49 8d 47 08 lea 0x8(%r15),%rax 458b: 48 89 44 24 68 mov %rax,0x68(%rsp) 4590: 0f 84 93 05 00 00 je 4b29 goto drop; sk = vxlan->vn6_sock->sock->sk; ndst = vxlan6_get_route(vxlan, skb, 4596: 41 8b 53 24 mov 0x24(%r11),%edx 459a: 48 8b 44 24 78 mov 0x78(%rsp),%rax struct dst_entry *ndst; u32 rt6i_flags; if (!vxlan->vn6_sock) goto drop; sk = vxlan->vn6_sock->sock->sk; 459f: 44 8b 84 24 80 00 00 mov 0x80(%rsp),%r8d 45a6: 00 ndst = vxlan6_get_route(vxlan, skb, 45a7: 4d 8d 4f 08 lea 0x8(%r15),%r9 45ab: 4c 89 74 24 08 mov %r14,0x8(%rsp) 45b0: 4c 89 64 24 10 mov %r12,0x10(%rsp) 45b5: 4c 89 ee mov %r13,%rsi rdst ? rdst->remote_ifindex : 0, tos, label, &dst->sin6.sin6_addr, 45b8: 4c 89 d7 mov %r10,%rdi 45bb: 48 89 04 24 mov %rax,(%rsp) 45bf: e8 ac c4 ff ff callq a70 if (!vxlan->vn6_sock) goto drop; sk = vxlan->vn6_sock->sock->sk; ndst = vxlan6_get_route(vxlan, skb, 45c4: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax 45ca: 49 89 c6 mov %rax,%r14 45cd: 0f 87 2c 06 00 00 ja 4bff 45d3: 48 3b 58 18 cmp 0x18(%rax),%rbx 45d7: 0f 84 90 05 00 00 je 4b6d 45dd: 4d 85 e4 test %r12,%r12 45e0: 8b 80 14 01 00 00 mov 0x114(%rax),%eax 45e6: 0f 85 06 01 00 00 jne 46f2 45ec: 89 c2 mov %eax,%edx 45ee: c1 ea 1f shr $0x1f,%edx 45f1: 84 d2 test %dl,%dl 45f3: 0f 84 f9 00 00 00 je 46f2 rdst ? rdst->remote_ifindex : 0, tos, label, &dst->sin6.sin6_addr, &src->sin6.sin6_addr, dst_cache, info); if (IS_ERR(ndst)) { 45f9: a9 00 00 00 30 test $0x30000000,%eax 45fe: 0f 84 b0 05 00 00 je 4bb4 &dst->sin6.sin6_addr); dev->stats.tx_carrier_errors++; goto tx_error; } if (ndst->dev == dev) { 4604: 8b 44 24 64 mov 0x64(%rsp),%eax 4608: c1 e8 07 shr $0x7,%eax 460b: 83 f0 01 xor $0x1,%eax goto tx_error; } /* Bypass encapsulation if the destination is local */ rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags; if (!info && rt6i_flags & RTF_LOCAL && 460e: 83 e0 01 and $0x1,%eax dev->stats.collisions++; goto tx_error; } /* Bypass encapsulation if the destination is local */ rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags; 4611: 88 44 24 48 mov %al,0x48(%rsp) 4615: e9 e1 00 00 00 jmpq 46fb if (!info && rt6i_flags & RTF_LOCAL && 461a: 0f b7 83 7c 09 00 00 movzwl 0x97c(%rbx),%eax 4621: 66 89 84 24 84 00 00 mov %ax,0x84(%rsp) 4628: 00 4629: e9 9b fc ff ff jmpq 42c9 462e: 49 8b 57 08 mov 0x8(%r15),%rdx 4632: 49 0b 57 10 or 0x10(%r15),%rdx vxlan_encap_bypass(skb, vxlan, dst_vxlan); return; } if (!info) udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); 4636: 0f 94 c2 sete %dl 4639: e9 bd fc ff ff jmpq 42fb 463e: 4d 8b a4 24 90 00 00 mov 0x90(%r12),%r12 4645: 00 4646: 4d 85 e4 test %r12,%r12 4649: 0f 84 e1 04 00 00 je 4b30 bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); info = skb_tunnel_info(skb); if (rdst) { dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; 464f: 49 83 c4 1c add $0x1c,%r12 4653: 4d 85 db test %r11,%r11 4656: 0f 85 57 fc ff ff jne 42b3 465c: 41 0f b7 44 24 32 movzwl 0x32(%r12),%eax static inline bool ipv6_addr_any(const struct in6_addr *a) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 const unsigned long *ul = (const unsigned long *)a; return (ul[0] | ul[1]) == 0UL; 4662: 66 85 c0 test %ax,%ax 4665: 66 89 84 24 84 00 00 mov %ax,0x84(%rsp) 466c: 00 466d: 75 0f jne 467e dst = skb_dst(skb); if (dst && dst->lwtstate) 466f: 0f b7 83 7c 09 00 00 movzwl 0x97c(%rbx),%eax 4676: 66 89 84 24 84 00 00 mov %ax,0x84(%rsp) 467d: 00 467e: 49 8b 04 24 mov (%r12),%rax info->options_len = len; } static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate) { return (struct ip_tunnel_info *)lwtstate->data; 4682: 48 c1 e8 20 shr $0x20,%rax bool udp_sum = false; bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); info = skb_tunnel_info(skb); if (rdst) { 4686: 41 f6 44 24 49 02 testb $0x2,0x49(%r12) if (!info) { WARN_ONCE(1, "%s: Missing encapsulation instructions\n", dev->name); goto drop; } dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; 468c: 48 89 44 24 50 mov %rax,0x50(%rsp) 4691: 0f 85 80 03 00 00 jne 4a17 4697: 41 8b 44 24 0c mov 0xc(%r12),%eax 469c: ba 02 00 00 00 mov $0x2,%edx 46a1: 66 89 94 24 a0 00 00 mov %dx,0xa0(%rsp) 46a8: 00 46a9: 89 84 24 a4 00 00 00 mov %eax,0xa4(%rsp) static inline __be32 vxlan_tun_id_to_vni(__be64 tun_id) { #if defined(__BIG_ENDIAN) return (__force __be32)tun_id; #else return (__force __be32)((__force u64)tun_id >> 32); 46b0: 41 8b 44 24 08 mov 0x8(%r12),%eax 46b5: 89 84 24 c4 00 00 00 mov %eax,0xc4(%rsp) 46bc: b8 02 00 00 00 mov $0x2,%eax } static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info *tun_info) { return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET; 46c1: 48 8d bc 24 c0 00 00 lea 0xc0(%rsp),%rdi 46c8: 00 vni = vxlan_tun_id_to_vni(info->key.tun_id); remote_ip.sa.sa_family = ip_tunnel_info_af(info); if (remote_ip.sa.sa_family == AF_INET) { remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; 46c9: 4d 8d 74 24 38 lea 0x38(%r12),%r14 dev->name); goto drop; } dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni = vxlan_tun_id_to_vni(info->key.tun_id); remote_ip.sa.sa_family = ip_tunnel_info_af(info); 46ce: 4c 8d bc 24 a0 00 00 lea 0xa0(%rsp),%r15 46d5: 00 46d6: 48 89 7c 24 68 mov %rdi,0x68(%rsp) if (remote_ip.sa.sa_family == AF_INET) { remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; 46db: e9 08 fc ff ff jmpq 42e8 local_ip.sin.sin_addr.s_addr = info->key.u.ipv4.src; 46e0: 41 0f b6 47 08 movzbl 0x8(%r15),%eax 46e5: 3d ff 00 00 00 cmp $0xff,%eax 46ea: 0f 94 c0 sete %al 46ed: e9 8e fc ff ff jmpq 4380 } else { remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst; local_ip.sin6.sin6_addr = info->key.u.ipv6.src; } dst = &remote_ip; src = &local_ip; 46f2: 4d 85 e4 test %r12,%r12 46f5: 0f 84 09 ff ff ff je 4604 dst_cache = &info->dst_cache; 46fb: 41 0f b7 85 c0 00 00 movzwl 0xc0(%r13),%eax 4702: 00 local_ip.sin.sin_addr.s_addr = info->key.u.ipv4.src; } else { remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst; local_ip.sin6.sin6_addr = info->key.u.ipv6.src; } dst = &remote_ip; 4703: 66 83 f8 08 cmp $0x8,%ax src = &local_ip; 4707: 0f 84 8e 03 00 00 je 4a9b 470d: 44 0f b6 bc 24 88 00 movzbl 0x88(%rsp),%r15d 4714: 00 00 return (a->s6_addr32[0] & htonl(0xfffffff0)) == htonl(0x20010010); } static inline bool ipv6_addr_is_multicast(const struct in6_addr *addr) { return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000); 4716: 45 31 e4 xor %r12d,%r12d 4719: 41 83 e7 fc and $0xfffffffc,%r15d 471d: 66 3d 86 dd cmp $0xdd86,%ax 4721: 0f 84 60 04 00 00 je 4b87 goto tx_error; vxlan_encap_bypass(skb, vxlan, dst_vxlan); return; } if (!info) 4727: 80 bc 24 87 00 00 00 cmpb $0x0,0x87(%rsp) 472e: 00 472f: 0f 84 52 03 00 00 je 4a87 /* Extract dsfield from inner protocol */ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, const struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP)) 4735: 0f b6 74 24 70 movzbl 0x70(%rsp),%esi 473a: 4c 89 ef mov %r13,%rdi * ECN codepoint of the outside header to ECT(0) if the ECN codepoint of * the inside header is CE. */ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner) { outer &= ~INET_ECN_MASK; 473d: e8 00 00 00 00 callq 4742 4742: 0f b6 44 24 48 movzbl 0x48(%rsp),%eax 4747: 44 8b 4c 24 64 mov 0x64(%rsp),%r9d 474c: ba 28 00 00 00 mov $0x28,%edx return iph->tos; else if (skb->protocol == htons(ETH_P_IPV6)) 4751: 4c 8b 44 24 40 mov 0x40(%rsp),%r8 4756: 8b 4c 24 50 mov 0x50(%rsp),%ecx udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip6_dst_hoplimit(ndst); 475a: 4c 89 f6 mov %r14,%rsi 475d: 4c 89 ef mov %r13,%rdi 4760: 89 04 24 mov %eax,(%rsp) 4763: e8 28 f6 ff ff callq 3d90 skb_scrub_packet(skb, xnet); 4768: 85 c0 test %eax,%eax 476a: 0f 88 58 03 00 00 js 4ac8 4770: 0f b6 44 24 48 movzbl 0x48(%rsp),%eax err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr), 4775: 0f b7 74 24 62 movzwl 0x62(%rsp),%esi 477a: 45 09 fc or %r15d,%r12d 477d: 0f b7 8c 24 84 00 00 movzwl 0x84(%rsp),%ecx 4784: 00 4785: 4c 8b 4c 24 68 mov 0x68(%rsp),%r9 478a: 45 0f b6 e4 movzbl %r12b,%r12d 478e: 4c 8b 44 24 78 mov 0x78(%rsp),%r8 4793: 44 89 24 24 mov %r12d,(%rsp) 4797: 4c 89 ea mov %r13,%rdx vni, md, flags, udp_sum); if (err < 0) { 479a: 4c 89 f7 mov %r14,%rdi 479d: 83 f0 01 xor $0x1,%eax dst_release(ndst); return; } udp_tunnel6_xmit_skb(ndst, sk, skb, dev, 47a0: 89 74 24 18 mov %esi,0x18(%rsp) 47a4: 48 8b 74 24 30 mov 0x30(%rsp),%rsi 47a9: 0f b6 c0 movzbl %al,%eax 47ac: 89 4c 24 20 mov %ecx,0x20(%rsp) 47b0: 48 89 d9 mov %rbx,%rcx 47b3: 89 44 24 28 mov %eax,0x28(%rsp) 47b7: 8b 84 24 80 00 00 00 mov 0x80(%rsp),%eax 47be: 89 44 24 10 mov %eax,0x10(%rsp) 47c2: 0f b6 84 24 87 00 00 movzbl 0x87(%rsp),%eax 47c9: 00 47ca: 89 44 24 08 mov %eax,0x8(%rsp) 47ce: e8 00 00 00 00 callq 47d3 47d3: e9 3f fb ff ff jmpq 4317 47d8: 48 8b b3 70 08 00 00 mov 0x870(%rbx),%rsi 47df: 4c 89 d2 mov %r10,%rdx 47e2: 4c 89 ef mov %r13,%rdi 47e5: e8 56 f2 ff ff callq 3a40 47ea: e9 28 fb ff ff jmpq 4317 47ef: 4c 89 ef mov %r13,%rdi 47f2: 4c 89 5c 24 40 mov %r11,0x40(%rsp) 47f7: 4c 89 54 24 48 mov %r10,0x48(%rsp) 47fc: e8 00 00 00 00 callq 4801 4801: 4c 8b 5c 24 40 mov 0x40(%rsp),%r11 4806: 4c 8b 54 24 48 mov 0x48(%rsp),%r10 } if (vxlan_addr_any(dst)) { if (did_rsc) { /* short-circuited back to local bridge */ vxlan_encap_bypass(skb, vxlan, vxlan); 480b: e9 d3 fb ff ff jmpq 43e3 4810: 48 8d 94 24 9c 00 00 lea 0x9c(%rsp),%rdx 4817: 00 4818: 48 8d b4 24 98 00 00 lea 0x98(%rsp),%rsi 481f: 00 } static inline __u32 skb_get_hash(struct sk_buff *skb) { if (!skb->l4_hash && !skb->sw_hash) __skb_get_hash(skb); 4820: 4c 89 5c 24 40 mov %r11,0x40(%rsp) 4825: 4c 89 54 24 48 mov %r10,0x48(%rsp) 482a: e8 00 00 00 00 callq 482f 482f: 4c 8b 5c 24 40 mov 0x40(%rsp),%r11 4834: 4c 8b 54 24 48 mov 0x48(%rsp),%r10 4839: e9 97 fb ff ff jmpq 43d5 483e: 41 0f b7 85 c0 00 00 movzwl 0xc0(%r13),%eax 4845: 00 { u32 hash; if (min >= max) { /* Use default range */ inet_get_local_port_range(net, &min, &max); 4846: 66 83 f8 08 cmp $0x8,%ax 484a: 0f 84 4f 03 00 00 je 4b9f 4850: 66 3d 86 dd cmp $0xdd86,%ax 4854: c6 84 24 88 00 00 00 movb $0x0,0x88(%rsp) 485b: 00 485c: 0f 85 3b fb ff ff jne 439d 4862: 48 8b 44 24 38 mov 0x38(%rsp),%rax 4867: 0f b7 00 movzwl (%rax),%eax 486a: 66 c1 c0 08 rol $0x8,%ax 486e: 66 c1 e8 04 shr $0x4,%ax 4872: 66 89 84 24 88 00 00 mov %ax,0x88(%rsp) 4879: 00 /* Extract dsfield from inner protocol */ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, const struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP)) 487a: e9 1e fb ff ff jmpq 439d 487f: 48 8b 83 60 08 00 00 mov 0x860(%rbx),%rax return iph->tos; else if (skb->protocol == htons(ETH_P_IPV6)) return ipv6_get_dsfield((const struct ipv6hdr *)iph); else return 0; 4886: 48 85 c0 test %rax,%rax 4889: 0f 84 78 fa ff ff je 4307 static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, const struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP)) return iph->tos; else if (skb->protocol == htons(ETH_P_IPV6)) 488f: 48 8b 40 10 mov 0x10(%rax),%rax } static inline __u8 ipv6_get_dsfield(const struct ipv6hdr *ipv6h) { return ntohs(*(const __be16 *)ipv6h) >> 4; 4893: 4d 85 db test %r11,%r11 4896: 45 8b 47 04 mov 0x4(%r15),%r8d 489a: 0f b6 8c 24 88 00 00 movzbl 0x88(%rsp),%ecx 48a1: 00 48a2: 48 8b 40 20 mov 0x20(%rax),%rax 48a6: 48 89 44 24 78 mov %rax,0x78(%rsp) 48ab: 48 8b 44 24 68 mov 0x68(%rsp),%rax } else { md->gbp = skb->mark; } if (dst->sa.sa_family == AF_INET) { if (!vxlan->vn4_sock) 48b0: 4c 8d 48 04 lea 0x4(%rax),%r9 48b4: 0f 84 ab 03 00 00 je 4c65 48ba: 41 8b 53 24 mov 0x24(%r11),%edx 48be: 4c 89 d7 mov %r10,%rdi goto drop; sk = vxlan->vn4_sock->sock->sk; 48c1: 4c 89 64 24 08 mov %r12,0x8(%rsp) rt = vxlan_get_route(vxlan, skb, 48c6: 4c 89 34 24 mov %r14,(%rsp) 48ca: 4c 89 ee mov %r13,%rsi 48cd: e8 2e ed ff ff callq 3600 } if (dst->sa.sa_family == AF_INET) { if (!vxlan->vn4_sock) goto drop; sk = vxlan->vn4_sock->sock->sk; 48d2: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax 48d8: 49 89 c2 mov %rax,%r10 rt = vxlan_get_route(vxlan, skb, 48db: 0f 87 c0 03 00 00 ja 4ca1 48e1: 48 8b 50 18 mov 0x18(%rax),%rdx 48e5: 48 39 d3 cmp %rdx,%rbx 48e8: 0f 84 7e 03 00 00 je 4c6c 48ee: 4d 85 e4 test %r12,%r12 48f1: 0f 84 87 03 00 00 je 4c7e 48f7: 45 0f b7 74 24 28 movzwl 0x28(%r12),%r14d 48fd: 41 83 e6 01 and $0x1,%r14d 4901: 41 f7 de neg %r14d rdst ? rdst->remote_ifindex : 0, tos, dst->sin.sin_addr.s_addr, &src->sin.sin_addr.s_addr, dst_cache, info); if (IS_ERR(rt)) { 4904: 41 83 e6 40 and $0x40,%r14d if (dst->sa.sa_family == AF_INET) { if (!vxlan->vn4_sock) goto drop; sk = vxlan->vn4_sock->sock->sk; rt = vxlan_get_route(vxlan, skb, 4908: 41 0f b7 85 c0 00 00 movzwl 0xc0(%r13),%eax 490f: 00 rdst ? rdst->remote_ifindex : 0, tos, dst->sin.sin_addr.s_addr, &src->sin.sin_addr.s_addr, dst_cache, info); if (IS_ERR(rt)) { 4910: 66 83 f8 08 cmp $0x8,%ax &dst->sin.sin_addr.s_addr); dev->stats.tx_carrier_errors++; goto tx_error; } if (rt->dst.dev == dev) { 4914: 0f 84 14 03 00 00 je 4c2e 491a: 0f b6 bc 24 88 00 00 movzbl 0x88(%rsp),%edi 4921: 00 dev->stats.collisions++; goto rt_tx_error; } /* Bypass encapsulation if the destination is local */ if (!info && rt->rt_flags & RTCF_LOCAL && 4922: 45 31 e4 xor %r12d,%r12d 4925: 83 e7 fc and $0xfffffffc,%edi return; } if (!info) udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX); else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) 4928: 66 3d 86 dd cmp $0xdd86,%ax 492c: 40 88 bc 24 80 00 00 mov %dil,0x80(%rsp) 4933: 00 union vxlan_addr *src; struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; __be16 src_port = 0, dst_port; __be32 vni, label; __be16 df = 0; 4934: 0f 84 b3 01 00 00 je 4aed 493a: 80 bc 24 87 00 00 00 cmpb $0x0,0x87(%rsp) 4941: 00 /* Extract dsfield from inner protocol */ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, const struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP)) 4942: 75 23 jne 4967 4944: 49 8b 42 28 mov 0x28(%r10),%rax 4948: 48 83 e0 fc and $0xfffffffffffffffc,%rax 494c: 8b 40 24 mov 0x24(%rax),%eax 494f: 85 c0 test %eax,%eax 4951: 75 0d jne 4960 4953: 48 8b 82 80 04 00 00 mov 0x480(%rdx),%rax return iph->tos; else if (skb->protocol == htons(ETH_P_IPV6)) 495a: 8b 80 a4 03 00 00 mov 0x3a4(%rax),%eax 4960: 88 84 24 87 00 00 00 mov %al,0x87(%rsp) 4967: 0f b6 44 24 48 movzbl 0x48(%rsp),%eax udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX); else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) df = htons(IP_DF); tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); 496c: 44 8b 4c 24 64 mov 0x64(%rsp),%r9d 4971: 4c 89 d6 mov %r10,%rsi static inline u32 dst_metric_raw(const struct dst_entry *dst, const int metric) { u32 *p = DST_METRICS_PTR(dst); return p[metric-1]; 4974: 4c 8b 44 24 40 mov 0x40(%rsp),%r8 4979: 8b 4c 24 50 mov 0x50(%rsp),%ecx return skb->skb_iif; } static inline int ip4_dst_hoplimit(const struct dst_entry *dst) { int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT); 497d: ba 14 00 00 00 mov $0x14,%edx struct net *net = dev_net(dst->dev); if (hoplimit == 0) 4982: 4c 89 ef mov %r13,%rdi hoplimit = net->ipv4.sysctl_ip_default_ttl; 4985: 4c 89 94 24 88 00 00 mov %r10,0x88(%rsp) 498c: 00 498d: 89 04 24 mov %eax,(%rsp) 4990: e8 fb f3 ff ff callq 3d90 4995: 85 c0 test %eax,%eax err = vxlan_build_skb(skb, &rt->dst, sizeof(struct iphdr), 4997: 4c 8b 94 24 88 00 00 mov 0x88(%rsp),%r10 499e: 00 499f: 0f 88 30 01 00 00 js 4ad5 49a5: 0f b6 44 24 48 movzbl 0x48(%rsp),%eax 49aa: 48 8b 5c 24 68 mov 0x68(%rsp),%rbx 49af: 45 0f b7 f6 movzwl %r14w,%r14d 49b3: 0f b6 74 24 70 movzbl 0x70(%rsp),%esi 49b8: 45 8b 47 04 mov 0x4(%r15),%r8d 49bc: 4c 89 ea mov %r13,%rdx 49bf: 44 0f b6 8c 24 80 00 movzbl 0x80(%rsp),%r9d 49c6: 00 00 vni, md, flags, udp_sum); if (err < 0) 49c8: 4c 89 d7 mov %r10,%rdi 49cb: 8b 4b 04 mov 0x4(%rbx),%ecx 49ce: 44 89 74 24 08 mov %r14d,0x8(%rsp) 49d3: 83 f0 01 xor $0x1,%eax goto xmit_tx_error; udp_tunnel_xmit_skb(rt, sk, skb, src->sin.sin_addr.s_addr, 49d6: 0f b6 c0 movzbl %al,%eax 49d9: 89 74 24 20 mov %esi,0x20(%rsp) 49dd: 0f b7 74 24 62 movzwl 0x62(%rsp),%esi 49e2: 89 44 24 28 mov %eax,0x28(%rsp) 49e6: 0f b7 84 24 84 00 00 movzwl 0x84(%rsp),%eax 49ed: 00 49ee: 45 09 e1 or %r12d,%r9d 49f1: 45 0f b6 c9 movzbl %r9b,%r9d 49f5: 89 74 24 10 mov %esi,0x10(%rsp) 49f9: 48 8b 74 24 78 mov 0x78(%rsp),%rsi 49fe: 89 44 24 18 mov %eax,0x18(%rsp) 4a02: 0f b6 84 24 87 00 00 movzbl 0x87(%rsp),%eax 4a09: 00 4a0a: 89 04 24 mov %eax,(%rsp) 4a0d: e8 00 00 00 00 callq 4a12 4a12: e9 00 f9 ff ff jmpq 4317 4a17: b8 0a 00 00 00 mov $0xa,%eax 4a1c: 49 8b 54 24 20 mov 0x20(%r12),%rdx 4a21: 66 89 84 24 a0 00 00 mov %ax,0xa0(%rsp) 4a28: 00 4a29: 49 8b 44 24 18 mov 0x18(%r12),%rax 4a2e: 48 89 94 24 b0 00 00 mov %rdx,0xb0(%rsp) 4a35: 00 4a36: 48 89 84 24 a8 00 00 mov %rax,0xa8(%rsp) 4a3d: 00 4a3e: 49 8b 44 24 08 mov 0x8(%r12),%rax 4a43: 49 8b 54 24 10 mov 0x10(%r12),%rdx dev->name); goto drop; } dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni = vxlan_tun_id_to_vni(info->key.tun_id); remote_ip.sa.sa_family = ip_tunnel_info_af(info); 4a48: 48 89 84 24 c8 00 00 mov %rax,0xc8(%rsp) 4a4f: 00 if (remote_ip.sa.sa_family == AF_INET) { remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; local_ip.sin.sin_addr.s_addr = info->key.u.ipv4.src; } else { remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst; 4a50: b8 0a 00 00 00 mov $0xa,%eax dev->name); goto drop; } dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; vni = vxlan_tun_id_to_vni(info->key.tun_id); remote_ip.sa.sa_family = ip_tunnel_info_af(info); 4a55: 48 89 94 24 d0 00 00 mov %rdx,0xd0(%rsp) 4a5c: 00 if (remote_ip.sa.sa_family == AF_INET) { remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; local_ip.sin.sin_addr.s_addr = info->key.u.ipv4.src; } else { remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst; 4a5d: e9 5f fc ff ff jmpq 46c1 4a62: 41 8b 85 b4 00 00 00 mov 0xb4(%r13),%eax 4a69: c6 44 24 48 00 movb $0x0,0x48(%rsp) local_ip.sin6.sin6_addr = info->key.u.ipv6.src; 4a6e: 89 84 24 94 00 00 00 mov %eax,0x94(%rsp) 4a75: 48 8d 84 24 94 00 00 lea 0x94(%rsp),%rax 4a7c: 00 4a7d: 48 89 44 24 40 mov %rax,0x40(%rsp) 4a82: e9 b0 fa ff ff jmpq 4537 4a87: 4c 89 f7 mov %r14,%rdi 4a8a: e8 00 00 00 00 callq 4a8f 4a8f: 88 84 24 87 00 00 00 mov %al,0x87(%rsp) udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); if (info->options_len) md = ip_tunnel_info_opts(info); } else { md->gbp = skb->mark; 4a96: e9 9a fc ff ff jmpq 4735 __be32 vni, label; __be16 df = 0; __u8 tos, ttl; int err; u32 flags = vxlan->flags; bool udp_sum = false; 4a9b: 48 8b 44 24 38 mov 0x38(%rsp),%rax udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); if (info->options_len) md = ip_tunnel_info_opts(info); } else { md->gbp = skb->mark; 4aa0: 44 0f b6 60 01 movzbl 0x1(%rax),%r12d const struct iphdr *old_iph; union vxlan_addr *dst; union vxlan_addr remote_ip, local_ip; union vxlan_addr *src; struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; 4aa5: 44 0f b6 bc 24 88 00 movzbl 0x88(%rsp),%r15d 4aac: 00 00 4aae: 41 83 e4 03 and $0x3,%r12d 4ab2: b8 02 00 00 00 mov $0x2,%eax if (!info) udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip6_dst_hoplimit(ndst); 4ab7: 41 83 e7 fc and $0xfffffffc,%r15d 4abb: 41 80 fc 03 cmp $0x3,%r12b 4abf: 44 0f 44 e0 cmove %eax,%r12d 4ac3: e9 5f fc ff ff jmpq 4727 4ac8: 4c 89 f7 mov %r14,%rdi /* Extract dsfield from inner protocol */ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph, const struct sk_buff *skb) { if (skb->protocol == htons(ETH_P_IP)) return iph->tos; 4acb: e8 00 00 00 00 callq 4ad0 4ad0: e9 42 f8 ff ff jmpq 4317 4ad5: 45 31 ed xor %r13d,%r13d 4ad8: 4c 89 d7 mov %r10,%rdi 4adb: e8 00 00 00 00 callq 4ae0 4ae0: 48 83 83 58 01 00 00 addq $0x1,0x158(%rbx) 4ae7: 01 4ae8: e9 22 f8 ff ff jmpq 430f 4aed: 48 8b 44 24 38 mov 0x38(%rsp),%rax 4af2: 44 0f b7 20 movzwl (%rax),%r12d 4af6: 66 41 c1 c4 08 rol $0x8,%r12w skb_scrub_packet(skb, xnet); err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr), vni, md, flags, udp_sum); if (err < 0) { dst_release(ndst); 4afb: 66 41 c1 ec 04 shr $0x4,%r12w return; 4b00: 0f b6 84 24 88 00 00 movzbl 0x88(%rsp),%eax 4b07: 00 { /* dst_release() accepts a NULL parameter. * We rely on dst being first structure in struct rtable */ BUILD_BUG_ON(offsetof(struct rtable, dst) != 0); dst_release(&rt->dst); 4b08: 41 83 e4 03 and $0x3,%r12d 4b0c: 41 b9 02 00 00 00 mov $0x2,%r9d /* skb is already freed. */ skb = NULL; rt_tx_error: ip_rt_put(rt); tx_error: dev->stats.tx_errors++; 4b12: 83 e0 fc and $0xfffffffc,%eax 4b15: 41 80 fc 03 cmp $0x3,%r12b 4b19: 88 84 24 80 00 00 00 mov %al,0x80(%rsp) 4b20: 45 0f 44 e1 cmove %r9d,%r12d 4b24: e9 11 fe ff ff jmpq 493a 4b29: 31 d2 xor %edx,%edx 4b2b: e9 6a fa ff ff jmpq 459a 4b30: 4d 85 db test %r11,%r11 4b33: 0f 85 24 01 00 00 jne 4c5d 4b39: 80 3d 00 00 00 00 00 cmpb $0x0,0x0(%rip) # 4b40 4b40: 0f 85 c1 f7 ff ff jne 4307 4b46: 48 89 d9 mov %rbx,%rcx 4b49: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 4b50: be 9b 07 00 00 mov $0x79b,%esi 4b55: 48 c7 c7 00 00 00 00 mov $0x0,%rdi if (!vxlan->vn6_sock) goto drop; sk = vxlan->vn6_sock->sock->sk; ndst = vxlan6_get_route(vxlan, skb, 4b5c: c6 05 00 00 00 00 01 movb $0x1,0x0(%rip) # 4b63 bool udp_sum = false; bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); info = skb_tunnel_info(skb); if (rdst) { 4b63: e8 00 00 00 00 callq 4b68 4b68: e9 9a f7 ff ff jmpq 4307 dst = &rdst->remote_ip; src = &vxlan->cfg.saddr; dst_cache = &rdst->dst_cache; } else { if (!info) { WARN_ONCE(1, "%s: Missing encapsulation instructions\n", 4b6d: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 4b72: 4c 89 f7 mov %r14,%rdi 4b75: e8 00 00 00 00 callq 4b7a 4b7a: 48 83 83 78 01 00 00 addq $0x1,0x178(%rbx) 4b81: 01 4b82: e9 59 ff ff ff jmpq 4ae0 4b87: 48 8b 44 24 38 mov 0x38(%rsp),%rax 4b8c: 44 0f b7 20 movzwl (%rax),%r12d 4b90: 66 41 c1 c4 08 rol $0x8,%r12w 4b95: 66 41 c1 ec 04 shr $0x4,%r12w 4b9a: e9 06 ff ff ff jmpq 4aa5 4b9f: 48 8b 44 24 38 mov 0x38(%rsp),%rax } if (ndst->dev == dev) { netdev_dbg(dev, "circular route to %pI6\n", &dst->sin6.sin6_addr); dst_release(ndst); 4ba4: 0f b6 40 01 movzbl 0x1(%rax),%eax 4ba8: 88 84 24 88 00 00 00 mov %al,0x88(%rsp) dev->stats.collisions++; 4baf: e9 e9 f7 ff ff jmpq 439d goto tx_error; 4bb4: 4c 89 f7 mov %r14,%rdi 4bb7: e8 00 00 00 00 callq 4bbc 4bbc: 0f b7 8c 24 84 00 00 movzwl 0x84(%rsp),%ecx 4bc3: 00 4bc4: 41 0f b7 17 movzwl (%r15),%edx 4bc8: 48 8b bb 78 08 00 00 mov 0x878(%rbx),%rdi 4bcf: 44 8b 83 d8 08 00 00 mov 0x8d8(%rbx),%r8d 4bd6: 8b 74 24 50 mov 0x50(%rsp),%esi 4bda: e8 91 b5 ff ff callq 170 4bdf: 48 85 c0 test %rax,%rax 4be2: 0f 84 f8 fe ff ff je 4ae0 rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags; if (!info && rt6i_flags & RTF_LOCAL && !(rt6i_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) { struct vxlan_dev *dst_vxlan; dst_release(ndst); 4be8: 48 8b b3 70 08 00 00 mov 0x870(%rbx),%rsi dst_vxlan = vxlan_find_vni(vxlan->net, vni, 4bef: 48 89 c2 mov %rax,%rdx 4bf2: 4c 89 ef mov %r13,%rdi 4bf5: e8 46 ee ff ff callq 3a40 4bfa: e9 18 f7 ff ff jmpq 4317 4bff: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 4c04: 48 83 83 b8 01 00 00 addq $0x1,0x1b8(%rbx) 4c0b: 01 4c0c: e9 cf fe ff ff jmpq 4ae0 dst->sa.sa_family, dst_port, vxlan->flags); if (!dst_vxlan) 4c11: 48 8b 4c 24 68 mov 0x68(%rsp),%rcx 4c16: 48 c7 c2 00 00 00 00 mov $0x0,%rdx goto tx_error; vxlan_encap_bypass(skb, vxlan, dst_vxlan); 4c1d: 48 89 de mov %rbx,%rsi 4c20: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 4c27: e8 00 00 00 00 callq 4c2c return; 4c2c: eb d6 jmp 4c04 4c2e: 48 8b 44 24 38 mov 0x38(%rsp),%rax 4c33: 44 0f b6 60 01 movzbl 0x1(%rax),%r12d &src->sin6.sin6_addr, dst_cache, info); if (IS_ERR(ndst)) { netdev_dbg(dev, "no route to %pI6\n", &dst->sin6.sin6_addr); dev->stats.tx_carrier_errors++; 4c38: e9 c3 fe ff ff jmpq 4b00 goto tx_error; 4c3d: 48 8b 4c 24 68 mov 0x68(%rsp),%rcx rdst ? rdst->remote_ifindex : 0, tos, label, &dst->sin6.sin6_addr, &src->sin6.sin6_addr, dst_cache, info); if (IS_ERR(ndst)) { netdev_dbg(dev, "no route to %pI6\n", 4c42: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 4c49: 48 89 de mov %rbx,%rsi 4c4c: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 4c53: e8 00 00 00 00 callq 4c58 4c58: e9 15 ff ff ff jmpq 4b72 4c5d: 45 31 e4 xor %r12d,%r12d 4c60: e9 4e f6 ff ff jmpq 42b3 4c65: 31 d2 xor %edx,%edx 4c67: e9 52 fc ff ff jmpq 48be 4c6c: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) dev->stats.tx_carrier_errors++; goto tx_error; } if (ndst->dev == dev) { netdev_dbg(dev, "circular route to %pI6\n", 4c71: 48 83 83 78 01 00 00 addq $0x1,0x178(%rbx) 4c78: 01 4c79: e9 5a fe ff ff jmpq 4ad8 4c7e: 8b 80 a4 00 00 00 mov 0xa4(%rax),%eax 4c84: 85 c0 test %eax,%eax 4c86: 78 71 js 4cf9 4c88: 8b 44 24 64 mov 0x64(%rsp),%eax 4c8c: 45 31 f6 xor %r14d,%r14d bool udp_sum = false; bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); info = skb_tunnel_info(skb); if (rdst) { 4c8f: c1 e8 06 shr $0x6,%eax 4c92: 83 f0 01 xor $0x1,%eax if (dst->sa.sa_family == AF_INET) { if (!vxlan->vn4_sock) goto drop; sk = vxlan->vn4_sock->sock->sk; rt = vxlan_get_route(vxlan, skb, 4c95: 83 e0 01 and $0x1,%eax 4c98: 88 44 24 48 mov %al,0x48(%rsp) 4c9c: e9 67 fc ff ff jmpq 4908 } if (rt->dst.dev == dev) { netdev_dbg(dev, "circular route to %pI4\n", &dst->sin.sin_addr.s_addr); dev->stats.collisions++; 4ca1: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 4ca6: e9 59 ff ff ff jmpq 4c04 goto rt_tx_error; 4cab: 49 8d 4f 04 lea 0x4(%r15),%rcx } /* Bypass encapsulation if the destination is local */ if (!info && rt->rt_flags & RTCF_LOCAL && 4caf: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 4cb6: 48 89 de mov %rbx,%rsi vxlan_encap_bypass(skb, vxlan, dst_vxlan); return; } if (!info) udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX); 4cb9: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 4cc0: e8 00 00 00 00 callq 4cc5 4cc5: e9 3a ff ff ff jmpq 4c04 4cca: 49 8d 4f 04 lea 0x4(%r15),%rcx 4cce: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 4cd5: 48 89 de mov %rbx,%rsi 4cd8: 48 c7 c7 00 00 00 00 mov $0x0,%rdi rdst ? rdst->remote_ifindex : 0, tos, dst->sin.sin_addr.s_addr, &src->sin.sin_addr.s_addr, dst_cache, info); if (IS_ERR(rt)) { netdev_dbg(dev, "no route to %pI4\n", 4cdf: 48 89 84 24 88 00 00 mov %rax,0x88(%rsp) 4ce6: 00 4ce7: e8 00 00 00 00 callq 4cec 4cec: 4c 8b 94 24 88 00 00 mov 0x88(%rsp),%r10 4cf3: 00 4cf4: e9 78 ff ff ff jmpq 4c71 4cf9: a9 00 00 00 30 test $0x30000000,%eax dev->stats.tx_carrier_errors++; goto tx_error; } if (rt->dst.dev == dev) { netdev_dbg(dev, "circular route to %pI4\n", 4cfe: 4c 89 d7 mov %r10,%rdi 4d01: 75 85 jne 4c88 4d03: e9 af fe ff ff jmpq 4bb7 4d08: e8 00 00 00 00 callq 4d0d 4d0d: 0f 1f 00 nopl (%rax) 0000000000004d10 : 4d10: e8 00 00 00 00 callq 4d15 4d15: 55 push %rbp 4d16: 48 89 f9 mov %rdi,%rcx 4d19: 48 89 e5 mov %rsp,%rbp 4d1c: 41 57 push %r15 4d1e: 41 56 push %r14 4d20: 41 55 push %r13 4d22: 41 54 push %r12 4d24: 49 89 f4 mov %rsi,%r12 4d27: 53 push %rbx 4d28: 4c 8d af 40 08 00 00 lea 0x840(%rdi),%r13 4d2f: 48 83 ec 30 sub $0x30,%rsp dev->stats.collisions++; goto rt_tx_error; } /* Bypass encapsulation if the destination is local */ if (!info && rt->rt_flags & RTCF_LOCAL && 4d33: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 4d3a: 00 00 ip_rt_put(rt); tx_error: dev->stats.tx_errors++; tx_free: dev_kfree_skb(skb); } 4d3c: 48 89 45 d0 mov %rax,-0x30(%rbp) dst->remote_ifindex); return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true); } static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) { 4d40: 31 c0 xor %eax,%eax 4d42: 48 8b 46 58 mov 0x58(%rsi),%rax 4d46: 48 83 e0 fe and $0xfffffffffffffffe,%rax 4d4a: 0f 84 6c 02 00 00 je 4fbc 4d50: f6 40 61 02 testb $0x2,0x61(%rax) 4d54: 48 8d 98 a0 00 00 00 lea 0xa0(%rax),%rbx 4d5b: 0f 84 3f 02 00 00 je 4fa0 4d61: 0f b7 91 80 09 00 00 movzwl 0x980(%rcx),%edx 4d68: 0f b7 81 7e 09 00 00 movzwl 0x97e(%rcx),%eax 4d6f: 48 8b b9 80 04 00 00 mov 0x480(%rcx),%rdi static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb) { struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb); if (md_dst && md_dst->dst.flags & DST_METADATA) 4d76: 39 c2 cmp %eax,%edx 4d78: 89 45 c8 mov %eax,-0x38(%rbp) 4d7b: 89 55 cc mov %edx,-0x34(%rbp) 4d7e: 0f 8e e3 01 00 00 jle 4f67 { struct metadata_dst *md_dst = skb_metadata_dst(skb); struct dst_entry *dst; if (md_dst) return &md_dst->u.tun_info; 4d84: 41 f6 84 24 91 00 00 testb $0x30,0x91(%r12) 4d8b: 00 30 static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb) { struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb); if (md_dst && md_dst->dst.flags & DST_METADATA) 4d8d: 0f 84 f8 01 00 00 je 4f8b struct vxlan_dev *vxlan = netdev_priv(dev); struct ip_tunnel_info *info = skb_tunnel_info(skb); __be16 sport, dport; sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, 4d93: 41 8b 84 24 a4 00 00 mov 0xa4(%r12),%eax 4d9a: 00 4d9b: 85 c0 test %eax,%eax 4d9d: 0f 85 d1 00 00 00 jne 4e74 4da3: 4d 8b 84 24 d8 00 00 mov 0xd8(%r12),%r8 4daa: 00 static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb, int min, int max, bool use_eth) { u32 hash; if (min >= max) { 4dab: 45 0f b7 8c 24 c0 00 movzwl 0xc0(%r12),%r9d 4db2: 00 00 data, proto, nhoff, hlen, flags); } static inline __u32 skb_get_hash(struct sk_buff *skb) { if (!skb->l4_hash && !skb->sw_hash) 4db4: 41 0f b6 50 0b movzbl 0xb(%r8),%edx 4db9: 41 0f b6 78 08 movzbl 0x8(%r8),%edi 4dbe: 41 0f b6 40 0a movzbl 0xa(%r8),%eax __skb_get_hash(skb); return skb->hash; 4dc3: 41 81 e9 05 41 52 21 sub $0x21524105,%r9d 4dca: 44 01 cf add %r9d,%edi /* Use default range */ inet_get_local_port_range(net, &min, &max); } hash = skb_get_hash(skb); if (unlikely(!hash)) { 4dcd: c1 e2 18 shl $0x18,%edx 4dd0: 8d 34 3a lea (%rdx,%rdi,1),%esi if (use_eth) { /* Can't find a normal hash, caller has indicated an * Ethernet packet so use that to compute a hash. */ hash = jhash(skb->data, 2 * ETH_ALEN, 4dd3: c1 e0 10 shl $0x10,%eax 4dd6: 41 0f b6 78 06 movzbl 0x6(%r8),%edi { u32 a, b, c; const u8 *k = key; /* Set up the internal state */ a = b = c = JHASH_INITVAL + length + initval; 4ddb: 8d 14 06 lea (%rsi,%rax,1),%edx 4dde: 41 0f b6 40 07 movzbl 0x7(%r8),%eax 4de3: 41 0f b6 70 04 movzbl 0x4(%r8),%esi 4de8: c1 e7 10 shl $0x10,%edi 4deb: 44 01 ce add %r9d,%esi 4dee: c1 e0 18 shl $0x18,%eax 4df1: 01 f0 add %esi,%eax 4df3: 41 0f b6 30 movzbl (%r8),%esi 4df7: 01 f8 add %edi,%eax 4df9: 41 0f b6 78 05 movzbl 0x5(%r8),%edi 4dfe: 44 01 ce add %r9d,%esi 4e01: 45 0f b6 48 03 movzbl 0x3(%r8),%r9d 4e06: c1 e7 08 shl $0x8,%edi 4e09: 01 c7 add %eax,%edi 4e0b: 44 89 c8 mov %r9d,%eax 4e0e: c1 e0 18 shl $0x18,%eax 4e11: 44 8d 0c 06 lea (%rsi,%rax,1),%r9d 4e15: 41 0f b6 70 02 movzbl 0x2(%r8),%esi 4e1a: 41 0f b6 40 09 movzbl 0x9(%r8),%eax 4e1f: c1 e6 10 shl $0x10,%esi 4e22: c1 e0 08 shl $0x8,%eax case 6: b += (u32)k[5]<<8; case 5: b += k[4]; case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4e25: 41 01 f1 add %esi,%r9d 4e28: 41 0f b6 70 01 movzbl 0x1(%r8),%esi case 10: c += (u32)k[9]<<8; case 9: c += k[8]; case 8: b += (u32)k[7]<<24; case 7: b += (u32)k[6]<<16; case 6: b += (u32)k[5]<<8; case 5: b += k[4]; 4e2d: 01 d0 add %edx,%eax case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4e2f: 89 fa mov %edi,%edx 4e31: 31 f8 xor %edi,%eax 4e33: c1 c2 0e rol $0xe,%edx case 10: c += (u32)k[9]<<8; case 9: c += k[8]; case 8: b += (u32)k[7]<<24; case 7: b += (u32)k[6]<<16; case 6: b += (u32)k[5]<<8; case 5: b += k[4]; 4e36: 29 d0 sub %edx,%eax 4e38: c1 e6 08 shl $0x8,%esi case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4e3b: 44 01 ce add %r9d,%esi 4e3e: 89 f2 mov %esi,%edx 4e40: 89 c6 mov %eax,%esi 4e42: 31 c2 xor %eax,%edx 4e44: c1 c6 0b rol $0xb,%esi 4e47: 29 f2 sub %esi,%edx 4e49: 31 d7 xor %edx,%edi __jhash_final(a, b, c); 4e4b: 89 fe mov %edi,%esi 4e4d: 89 d7 mov %edx,%edi case 6: b += (u32)k[5]<<8; case 5: b += k[4]; case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4e4f: c1 cf 07 ror $0x7,%edi __jhash_final(a, b, c); 4e52: 29 fe sub %edi,%esi 4e54: 89 f7 mov %esi,%edi case 6: b += (u32)k[5]<<8; case 5: b += k[4]; case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4e56: 31 f0 xor %esi,%eax 4e58: c1 c7 10 rol $0x10,%edi 4e5b: 29 f8 sub %edi,%eax __jhash_final(a, b, c); 4e5d: 89 c7 mov %eax,%edi 4e5f: 31 c2 xor %eax,%edx 4e61: c1 c7 04 rol $0x4,%edi 4e64: 29 fa sub %edi,%edx 4e66: 31 d6 xor %edx,%esi case 6: b += (u32)k[5]<<8; case 5: b += k[4]; case 4: a += (u32)k[3]<<24; case 3: a += (u32)k[2]<<16; case 2: a += (u32)k[1]<<8; case 1: a += k[0]; 4e68: c1 c2 0e rol $0xe,%edx 4e6b: 29 d6 sub %edx,%esi 4e6d: 31 f0 xor %esi,%eax __jhash_final(a, b, c); 4e6f: c1 ce 08 ror $0x8,%esi 4e72: 29 f0 sub %esi,%eax 4e74: 8b 75 c8 mov -0x38(%rbp),%esi 4e77: 44 8b 75 cc mov -0x34(%rbp),%r14d 4e7b: 89 c2 mov %eax,%edx 4e7d: c1 e2 10 shl $0x10,%edx 4e80: 44 0f b7 7b 32 movzwl 0x32(%rbx),%r15d 4e85: 31 d0 xor %edx,%eax 4e87: 41 29 f6 sub %esi,%r14d 4e8a: 4d 63 f6 movslq %r14d,%r14 4e8d: 49 0f af c6 imul %r14,%rax 4e91: 48 c1 e8 20 shr $0x20,%rax 4e95: 44 8d 34 30 lea (%rax,%rsi,1),%r14d 4e99: 66 41 c1 c6 08 rol $0x8,%r14w 4e9e: 66 45 85 ff test %r15w,%r15w 4ea2: 75 08 jne 4eac * attacker is leaked. Only upper 16 bits are relevant in the * computation for 16 bit port value. */ hash ^= hash << 16; return htons((((u64) hash * (max - min)) >> 32) + min); 4ea4: 44 0f b7 b9 7c 09 00 movzwl 0x97c(%rcx),%r15d 4eab: 00 /* Since this is being sent on the wire obfuscate hash a bit * to minimize possbility that any useful information to an * attacker is leaked. Only upper 16 bits are relevant in the * computation for 16 bit port value. */ hash ^= hash << 16; 4eac: f6 43 49 02 testb $0x2,0x49(%rbx) vxlan->cfg.port_max, true); dport = info->key.tp_dst ? : vxlan->cfg.dst_port; 4eb0: 75 3e jne 4ef0 4eb2: 48 83 b9 60 08 00 00 cmpq $0x0,0x860(%rcx) 4eb9: 00 return htons((((u64) hash * (max - min)) >> 32) + min); 4eba: 0f 84 03 01 00 00 je 4fc3 4ec0: 0f b6 4b 2a movzbl 0x2a(%rbx),%ecx 4ec4: 44 8b 43 0c mov 0xc(%rbx),%r8d 4ec8: 4c 8d 4b 08 lea 0x8(%rbx),%r9 4ecc: 31 d2 xor %edx,%edx 4ece: 48 89 5c 24 08 mov %rbx,0x8(%rsp) 4ed3: 48 c7 04 24 00 00 00 movq $0x0,(%rsp) 4eda: 00 4edb: 4c 89 e6 mov %r12,%rsi } static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info *tun_info) { return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET; 4ede: 4c 89 ef mov %r13,%rdi 4ee1: e8 1a e7 ff ff callq 3600 if (ip_tunnel_info_af(info) == AF_INET) { struct rtable *rt; if (!vxlan->vn4_sock) 4ee6: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax 4eec: 76 47 jbe 4f35 4eee: eb 59 jmp 4f49 return -EINVAL; rt = vxlan_get_route(vxlan, skb, 0, info->key.tos, 4ef0: 48 83 b9 68 08 00 00 cmpq $0x0,0x868(%rcx) 4ef7: 00 4ef8: 0f 84 c5 00 00 00 je 4fc3 4efe: 0f b6 4b 2a movzbl 0x2a(%rbx),%ecx 4f02: 44 8b 43 2c mov 0x2c(%rbx),%r8d 4f06: 48 8d 43 08 lea 0x8(%rbx),%rax 4f0a: 4c 8d 4b 18 lea 0x18(%rbx),%r9 4f0e: 31 d2 xor %edx,%edx 4f10: 48 89 5c 24 10 mov %rbx,0x10(%rsp) 4f15: 48 c7 44 24 08 00 00 movq $0x0,0x8(%rsp) 4f1c: 00 00 info->key.u.ipv4.dst, &info->key.u.ipv4.src, NULL, info); if (IS_ERR(rt)) 4f1e: 48 89 04 24 mov %rax,(%rsp) ip_rt_put(rt); } else { #if IS_ENABLED(CONFIG_IPV6) struct dst_entry *ndst; if (!vxlan->vn6_sock) 4f22: 4c 89 e6 mov %r12,%rsi 4f25: 4c 89 ef mov %r13,%rdi 4f28: e8 43 bb ff ff callq a70 4f2d: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax return -EINVAL; ndst = vxlan6_get_route(vxlan, skb, 0, info->key.tos, 4f33: 77 14 ja 4f49 4f35: 48 89 c7 mov %rax,%rdi 4f38: e8 00 00 00 00 callq 4f3d 4f3d: 66 44 89 73 30 mov %r14w,0x30(%rbx) 4f42: 66 44 89 7b 32 mov %r15w,0x32(%rbx) 4f47: 31 c0 xor %eax,%eax 4f49: 48 8b 5d d0 mov -0x30(%rbp),%rbx 4f4d: 65 48 33 1c 25 28 00 xor %gs:0x28,%rbx 4f54: 00 00 4f56: 75 75 jne 4fcd 4f58: 48 83 c4 30 add $0x30,%rsp 4f5c: 5b pop %rbx info->key.label, &info->key.u.ipv6.dst, &info->key.u.ipv6.src, NULL, info); if (IS_ERR(ndst)) 4f5d: 41 5c pop %r12 4f5f: 41 5d pop %r13 4f61: 41 5e pop %r14 4f63: 41 5f pop %r15 return PTR_ERR(ndst); dst_release(ndst); 4f65: 5d pop %rbp 4f66: c3 retq 4f67: 48 8d 55 cc lea -0x34(%rbp),%rdx 4f6b: 48 8d 75 c8 lea -0x38(%rbp),%rsi #else /* !CONFIG_IPV6 */ return -EPFNOSUPPORT; #endif } info->key.tp_src = sport; 4f6f: 48 89 4d c0 mov %rcx,-0x40(%rbp) info->key.tp_dst = dport; 4f73: e8 00 00 00 00 callq 4f78 return 0; 4f78: 41 f6 84 24 91 00 00 testb $0x30,0x91(%r12) 4f7f: 00 30 } 4f81: 48 8b 4d c0 mov -0x40(%rbp),%rcx 4f85: 0f 85 08 fe ff ff jne 4d93 4f8b: 4c 89 e7 mov %r12,%rdi 4f8e: 48 89 4d c0 mov %rcx,-0x40(%rbp) 4f92: e8 00 00 00 00 callq 4f97 { u32 hash; if (min >= max) { /* Use default range */ inet_get_local_port_range(net, &min, &max); 4f97: 48 8b 4d c0 mov -0x40(%rbp),%rcx 4f9b: e9 f3 fd ff ff jmpq 4d93 4fa0: 48 8b 80 90 00 00 00 mov 0x90(%rax),%rax 4fa7: 48 8d 58 1c lea 0x1c(%rax),%rbx data, proto, nhoff, hlen, flags); } static inline __u32 skb_get_hash(struct sk_buff *skb) { if (!skb->l4_hash && !skb->sw_hash) 4fab: 48 85 c0 test %rax,%rax 4fae: b8 00 00 00 00 mov $0x0,%eax 4fb3: 48 0f 44 d8 cmove %rax,%rbx 4fb7: e9 a5 fd ff ff jmpq 4d61 __skb_get_hash(skb); 4fbc: 31 db xor %ebx,%ebx 4fbe: e9 9e fd ff ff jmpq 4d61 4fc3: b8 ea ff ff ff mov $0xffffffea,%eax 4fc8: e9 7c ff ff ff jmpq 4f49 4fcd: e8 00 00 00 00 callq 4fd2 if (md_dst) return &md_dst->u.tun_info; dst = skb_dst(skb); if (dst && dst->lwtstate) 4fd2: 0f 1f 40 00 nopl 0x0(%rax) 4fd6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 4fdd: 00 00 00 0000000000004fe0 : info->options_len = len; } static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate) { return (struct ip_tunnel_info *)lwtstate->data; 4fe0: e8 00 00 00 00 callq 4fe5 4fe5: 55 push %rbp 4fe6: 49 89 f0 mov %rsi,%r8 4fe9: 48 89 e5 mov %rsp,%rbp return lwt_tun_info(dst->lwtstate); return NULL; 4fec: 41 57 push %r15 4fee: 41 56 push %r14 4ff0: 41 55 push %r13 4ff2: 41 54 push %r12 if (ip_tunnel_info_af(info) == AF_INET) { struct rtable *rt; if (!vxlan->vn4_sock) return -EINVAL; 4ff4: 53 push %rbx 4ff5: 48 89 d3 mov %rdx,%rbx 4ff8: 48 83 ec 20 sub $0x20,%rsp 4ffc: 8b 4a 34 mov 0x34(%rdx),%ecx #endif } info->key.tp_src = sport; info->key.tp_dst = dport; return 0; } 4fff: 4c 8b b7 48 02 00 00 mov 0x248(%rdi),%r14 5006: 44 8d 61 08 lea 0x8(%rcx),%r12d 500a: 44 39 62 30 cmp %r12d,0x30(%rdx) 500e: 49 89 cd mov %rcx,%r13 } static struct sk_buff **vxlan_gro_receive(struct sock *sk, struct sk_buff **head, struct sk_buff *skb) { 5011: 73 50 jae 5063 5013: 8b 92 80 00 00 00 mov 0x80(%rdx),%edx 5019: 89 d0 mov %edx,%eax 501b: 2b 83 84 00 00 00 sub 0x84(%rbx),%eax 5021: 41 39 c4 cmp %eax,%r12d 5024: 0f 87 ab 02 00 00 ja 52d5 502a: 49 89 cf mov %rcx,%r15 int dev_restart(struct net_device *dev); int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb); static inline unsigned int skb_gro_offset(const struct sk_buff *skb) { return NAPI_GRO_CB(skb)->data_offset; 502d: 4c 03 bb d8 00 00 00 add 0xd8(%rbx),%r15 5034: 48 c7 43 28 00 00 00 movq $0x0,0x28(%rbx) 503b: 00 skb_gro_remcsum_init(&grc); off_vx = skb_gro_offset(skb); hlen = off_vx + sizeof(*vh); vh = skb_gro_header_fast(skb, off_vx); if (skb_gro_header_hard(skb, hlen)) { 503c: c7 43 30 00 00 00 00 movl $0x0,0x30(%rbx) 5043: 75 25 jne 506a 5045: ba 01 00 00 00 mov $0x1,%edx return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 504a: 45 31 ff xor %r15d,%r15d 504d: 66 09 53 38 or %dx,0x38(%rbx) return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 5051: 48 83 c4 20 add $0x20,%rsp 5055: 4c 89 f8 mov %r15,%rax 5058: 5b pop %rbx 5059: 41 5c pop %r12 vh = skb_gro_header_slow(skb, hlen, off_vx); if (unlikely(!vh)) 505b: 41 5d pop %r13 505d: 41 5e pop %r14 505f: 41 5f pop %r15 5061: 5d pop %rbp 5062: c3 retq 5063: 49 89 cf mov %rcx,%r15 unsigned int offset) { if (!pskb_may_pull(skb, hlen)) return NULL; NAPI_GRO_CB(skb)->frag0 = NULL; 5066: 4c 03 7a 28 add 0x28(%rdx),%r15 506a: f6 43 4a 04 testb $0x4,0x4a(%rbx) NAPI_GRO_CB(skb)->frag0_len = 0; 506e: 74 2c je 509c 5070: 31 d2 xor %edx,%edx 5072: be 08 00 00 00 mov $0x8,%esi static struct sk_buff **vxlan_gro_receive(struct sock *sk, struct sk_buff **head, struct sk_buff *skb) { struct sk_buff *p, **pp = NULL; 5077: 4c 89 ff mov %r15,%rdi 507a: 4c 89 45 c8 mov %r8,-0x38(%rbp) pp = eth_gro_receive(head, skb); flush = 0; out: skb_gro_remcsum_cleanup(skb, &grc); NAPI_GRO_CB(skb)->flush |= flush; 507e: 48 89 4d d0 mov %rcx,-0x30(%rbp) return pp; } 5082: e8 00 00 00 00 callq 5087 5087: 4c 8b 45 c8 mov -0x38(%rbp),%r8 508b: 48 8b 4d d0 mov -0x30(%rbp),%rcx 508f: f7 d0 not %eax 5091: 8b 53 4c mov 0x4c(%rbx),%edx } static inline void *skb_gro_header_fast(struct sk_buff *skb, unsigned int offset) { return NAPI_GRO_CB(skb)->frag0 + offset; 5094: 01 c2 add %eax,%edx 5096: 83 d2 00 adc $0x0,%edx 5099: 89 53 4c mov %edx,0x4c(%rbx) } static inline void skb_gro_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len) { if (NAPI_GRO_CB(skb)->csum_valid) 509c: 41 f7 07 00 20 00 00 testl $0x2000,(%r15) NAPI_GRO_CB(skb)->csum = csum_sub(NAPI_GRO_CB(skb)->csum, 50a3: 0f 85 a5 00 00 00 jne 514e 50a9: 41 bd 02 00 00 00 mov $0x2,%r13d 50af: 45 31 f6 xor %r14d,%r14d 50b2: 45 31 e4 xor %r12d,%r12d 50b5: 83 43 34 08 addl $0x8,0x34(%rbx) 50b9: 49 8b 00 mov (%r8),%rax 50bc: 48 85 c0 test %rax,%rax csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len, __u8 proto, __wsum sum); static inline unsigned add32_with_carry(unsigned a, unsigned b) { asm("addl %2,%0\n\t" 50bf: 75 0e jne 50cf 50c1: eb 34 jmp 50f7 50c3: 80 60 4a fe andb $0xfe,0x4a(%rax) 50c7: 48 8b 00 mov (%rax),%rax 50ca: 48 85 c0 test %rax,%rax skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr)); flags = vh->vx_flags; if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { 50cd: 74 28 je 50f7 50cf: f6 40 4a 01 testb $0x1,0x4a(%rax) 50d3: 74 f2 je 50c7 50d5: 48 89 ca mov %rcx,%rdx 50d8: 48 03 90 d8 00 00 00 add 0xd8(%rax),%rdx }; static inline void skb_gro_remcsum_init(struct gro_remcsum *grc) { grc->offset = 0; grc->delta = 0; 50df: 8b 3a mov (%rdx),%edi 50e1: 41 39 3f cmp %edi,(%r15) __wsum delta; }; static inline void skb_gro_remcsum_init(struct gro_remcsum *grc) { grc->offset = 0; 50e4: 75 dd jne 50c3 return skb->len - NAPI_GRO_CB(skb)->data_offset; } static inline void skb_gro_pull(struct sk_buff *skb, unsigned int len) { NAPI_GRO_CB(skb)->data_offset += len; 50e6: 8b 72 04 mov 0x4(%rdx),%esi goto out; } skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */ for (p = *head; p; p = p->next) { 50e9: 41 39 77 04 cmp %esi,0x4(%r15) 50ed: 75 d4 jne 50c3 50ef: 48 8b 00 mov (%rax),%rax 50f2: 48 85 c0 test %rax,%rax continue; vh2 = (struct vxlanhdr *)(p->data + off_vx); if (vh->vx_flags != vh2->vx_flags || vh->vx_vni != vh2->vx_vni) { NAPI_GRO_CB(p)->same_flow = 0; 50f5: 75 d8 jne 50cf goto out; } skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */ for (p = *head; p; p = p->next) { 50f7: 48 89 de mov %rbx,%rsi 50fa: 4c 89 c7 mov %r8,%rdi 50fd: e8 00 00 00 00 callq 5102 if (!NAPI_GRO_CB(p)->same_flow) 5102: 31 d2 xor %edx,%edx 5104: 49 89 c7 mov %rax,%r15 continue; vh2 = (struct vxlanhdr *)(p->data + off_vx); 5107: 45 85 f6 test %r14d,%r14d 510a: 0f 84 3d ff ff ff je 504d if (vh->vx_flags != vh2->vx_flags || 5110: 44 89 e1 mov %r12d,%ecx 5113: 41 83 c4 02 add $0x2,%r12d 5117: 44 3b 63 30 cmp 0x30(%rbx),%r12d 511b: 0f 87 7c 01 00 00 ja 529d goto out; } skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */ for (p = *head; p; p = p->next) { 5121: 48 03 4b 28 add 0x28(%rbx),%rcx 5125: 0f b7 31 movzwl (%rcx),%esi NAPI_GRO_CB(p)->same_flow = 0; continue; } } pp = eth_gro_receive(head, skb); 5128: 44 89 f0 mov %r14d,%eax 512b: f7 d6 not %esi 512d: 01 f0 add %esi,%eax 512f: 83 d0 00 adc $0x0,%eax 5132: 89 c6 mov %eax,%esi 5134: 66 31 c0 xor %ax,%ax struct gro_remcsum *grc) { void *ptr; size_t plen = grc->offset + sizeof(u16); if (!grc->delta) 5137: c1 e6 10 shl $0x10,%esi 513a: 01 f0 add %esi,%eax 513c: 15 ff ff 00 00 adc $0xffff,%eax } static inline void *skb_gro_header_fast(struct sk_buff *skb, unsigned int offset) { return NAPI_GRO_CB(skb)->frag0 + offset; 5141: f7 d0 not %eax if (!grc->delta) return; ptr = skb_gro_header_fast(skb, grc->offset); if (skb_gro_header_hard(skb, grc->offset + sizeof(u16))) { 5143: c1 e8 10 shr $0x10,%eax 5146: 66 89 01 mov %ax,(%rcx) 5149: e9 ff fe ff ff jmpq 504d 514e: 41 8b 86 1c 20 00 00 mov 0x201c(%r14),%eax 5155: f6 c4 04 test $0x4,%ah 5158: 0f 84 4b ff ff ff je 50a9 515e: 0f b6 b3 93 00 00 00 movzbl 0x93(%rbx),%esi * the last step before putting a checksum into a packet. * Make sure not to mix with 64bit checksums. */ static inline __sum16 csum_fold(__wsum sum) { asm(" addl %1,%0\n" 5165: 40 f6 c6 10 test $0x10,%sil 5169: 0f 85 9a 01 00 00 jne 5309 516f: f6 43 4a 04 testb $0x4,0x4a(%rbx) return delta; } static inline void remcsum_unadjust(__sum16 *psum, __wsum delta) { *psum = csum_fold(csum_sub(delta, *psum)); 5173: 0f 84 cc fe ff ff je 5045 5179: 49 63 57 04 movslq 0x4(%r15),%rdx 517d: 41 89 d6 mov %edx,%r14d skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr)); flags = vh->vx_flags; if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { 5180: 48 c1 fa 3f sar $0x3f,%rdx 5184: 41 81 e6 00 00 00 7f and $0x7f000000,%r14d 518b: 48 83 e2 f6 and $0xfffffffffffffff6,%rdx struct gro_remcsum *grc, bool nopartial) { size_t start, offset; if (skb->remcsum_offload) 518f: 41 0f ce bswap %r14d 5192: 48 83 c2 10 add $0x10,%rdx 5196: 45 01 f6 add %r14d,%r14d 5199: f6 c4 10 test $0x10,%ah 519c: 0f 84 75 01 00 00 je 5317 return vh; if (!NAPI_GRO_CB(skb)->csum_valid) 51a2: 45 89 f1 mov %r14d,%r9d 51a5: 49 01 d1 add %rdx,%r9 51a8: 49 63 d6 movslq %r14d,%rdx skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr)); flags = vh->vx_flags; if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) { vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), 51ab: 4d 63 d1 movslq %r9d,%r10 #endif } static inline size_t vxlan_rco_start(__be32 vni_field) { return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT; 51ae: 49 8d 42 02 lea 0x2(%r10),%rax } static inline size_t vxlan_rco_offset(__be32 vni_field) { return (vni_field & VXLAN_RCO_UDP) ? offsetof(struct udphdr, check) : 51b2: 48 39 d0 cmp %rdx,%rax #endif } static inline size_t vxlan_rco_start(__be32 vni_field) { return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT; 51b5: 48 0f 42 c2 cmovb %rdx,%rax 51b9: 41 8d 44 05 08 lea 0x8(%r13,%rax,1),%eax } static inline size_t vxlan_rco_offset(__be32 vni_field) { return (vni_field & VXLAN_RCO_UDP) ? offsetof(struct udphdr, check) : 51be: 3b 43 30 cmp 0x30(%rbx),%eax #endif } static inline size_t vxlan_rco_start(__be32 vni_field) { return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT; 51c1: 0f 86 72 01 00 00 jbe 5339 51c7: 8b b3 80 00 00 00 mov 0x80(%rbx),%esi __wsum delta; size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); BUG_ON(!NAPI_GRO_CB(skb)->csum_valid); if (!nopartial) { 51cd: 89 f2 mov %esi,%edx 51cf: 2b 93 84 00 00 00 sub 0x84(%rbx),%edx if (!NAPI_GRO_CB(skb)->csum_valid) return NULL; start = vxlan_rco_start(vni_field); offset = start + vxlan_rco_offset(vni_field); 51d5: 39 d0 cmp %edx,%eax 51d7: 0f 87 9a 01 00 00 ja 5377 int start, int offset, struct gro_remcsum *grc, bool nopartial) { __wsum delta; size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); 51dd: 49 89 cf mov %rcx,%r15 NAPI_GRO_CB(skb)->gro_remcsum_start = off + hdrlen + start; return ptr; } ptr = skb_gro_header_fast(skb, off); if (skb_gro_header_hard(skb, off + plen)) { 51e0: 4c 03 bb d8 00 00 00 add 0xd8(%rbx),%r15 51e7: 48 c7 43 28 00 00 00 movq $0x0,0x28(%rbx) 51ee: 00 51ef: c7 43 30 00 00 00 00 movl $0x0,0x30(%rbx) 51f6: 0f 84 b4 01 00 00 je 53b0 51fc: 49 8d 7f 08 lea 0x8(%r15),%rdi return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 5200: 31 d2 xor %edx,%edx 5202: 44 89 f6 mov %r14d,%esi return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 5205: 4c 89 45 b8 mov %r8,-0x48(%rbp) 5209: 4c 89 4d c0 mov %r9,-0x40(%rbp) ptr = skb_gro_header_slow(skb, off + plen, off); if (!ptr) 520d: 49 01 fa add %rdi,%r10 5210: 48 89 4d c8 mov %rcx,-0x38(%rbp) 5214: 44 8b 6b 4c mov 0x4c(%rbx),%r13d unsigned int offset) { if (!pskb_may_pull(skb, hlen)) return NULL; NAPI_GRO_CB(skb)->frag0 = NULL; 5218: 4c 89 55 d0 mov %r10,-0x30(%rbp) 521c: e8 00 00 00 00 callq 5221 NAPI_GRO_CB(skb)->frag0_len = 0; 5221: 4c 8b 55 d0 mov -0x30(%rbp),%r10 5225: 4c 8b 4d c0 mov -0x40(%rbp),%r9 } ptr = skb_gro_header_fast(skb, off); if (skb_gro_header_hard(skb, off + plen)) { ptr = skb_gro_header_slow(skb, off + plen, off); if (!ptr) 5229: f7 d0 not %eax 522b: 41 01 c5 add %eax,%r13d return NULL; } delta = remcsum_adjust(ptr + hdrlen, NAPI_GRO_CB(skb)->csum, 522e: 41 83 d5 00 adc $0x0,%r13d { __sum16 *psum = (__sum16 *)(ptr + offset); __wsum delta; /* Subtract out checksum up to start */ csum = csum_sub(csum, csum_partial(ptr, start, 0)); 5232: 44 89 e8 mov %r13d,%eax 5235: 66 45 31 ed xor %r13w,%r13w 5239: 48 8b 4d c8 mov -0x38(%rbp),%rcx } static inline __wsum remcsum_adjust(void *ptr, __wsum csum, int start, int offset) { __sum16 *psum = (__sum16 *)(ptr + offset); 523d: 41 0f b7 12 movzwl (%r10),%edx 5241: c1 e0 10 shl $0x10,%eax 5244: 45 01 cc add %r9d,%r12d 5247: 41 01 c5 add %eax,%r13d 524a: 41 81 d5 ff ff 00 00 adc $0xffff,%r13d csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len, __u8 proto, __wsum sum); static inline unsigned add32_with_carry(unsigned a, unsigned b) { asm("addl %2,%0\n\t" 5251: 41 f7 d5 not %r13d 5254: 4c 8b 45 b8 mov -0x48(%rbp),%r8 start, offset); /* Adjust skb->csum since we changed the packet */ NAPI_GRO_CB(skb)->csum = csum_add(NAPI_GRO_CB(skb)->csum, delta); grc->offset = off + hdrlen + offset; 5258: 41 c1 ed 10 shr $0x10,%r13d 525c: 66 45 89 2a mov %r13w,(%r10) 5260: 44 89 e8 mov %r13d,%eax static inline __sum16 csum_fold(__wsum sum) { asm(" addl %1,%0\n" " adcl $0xffff,%0" : "=r" (sum) : "r" ((__force u32)sum << 16), 5263: 4d 63 ec movslq %r12d,%r13 "0" ((__force u32)sum & 0xffff0000)); 5266: f7 d2 not %edx 5268: 49 83 c5 02 add $0x2,%r13 vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), vh->vx_vni, &grc, !!(vs->flags & VXLAN_F_REMCSUM_NOPARTIAL)); if (!vh) 526c: 80 8b 93 00 00 00 10 orb $0x10,0x93(%rbx) static inline __sum16 csum_fold(__wsum sum) { asm(" addl %1,%0\n" " adcl $0xffff,%0" : "=r" (sum) : "r" ((__force u32)sum << 16), 5273: 01 d0 add %edx,%eax 5275: 83 d0 00 adc $0x0,%eax * the last step before putting a checksum into a packet. * Make sure not to mix with 64bit checksums. */ static inline __sum16 csum_fold(__wsum sum) { asm(" addl %1,%0\n" 5278: 41 89 c6 mov %eax,%r14d 527b: 8b 43 4c mov 0x4c(%rbx),%eax 527e: 44 01 f0 add %r14d,%eax csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len, __u8 proto, __wsum sum); static inline unsigned add32_with_carry(unsigned a, unsigned b) { asm("addl %2,%0\n\t" 5281: 83 d0 00 adc $0x0,%eax 5284: 4d 85 ff test %r15,%r15 5287: 89 43 4c mov %eax,0x4c(%rbx) 528a: 0f 85 25 fe ff ff jne 50b5 5290: ba 01 00 00 00 mov $0x1,%edx 5295: 45 31 ff xor %r15d,%r15d 5298: e9 6a fe ff ff jmpq 5107 offset = start + vxlan_rco_offset(vni_field); vh = skb_gro_remcsum_process(skb, (void *)vh, off, hdrlen, start, offset, grc, nopartial); skb->remcsum_offload = 1; 529d: 8b b3 80 00 00 00 mov 0x80(%rbx),%esi 52a3: 89 f0 mov %esi,%eax 52a5: 2b 83 84 00 00 00 sub 0x84(%rbx),%eax 52ab: 41 39 c5 cmp %eax,%r13d 52ae: 0f 87 91 00 00 00 ja 5345 vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), vh->vx_vni, &grc, !!(vs->flags & VXLAN_F_REMCSUM_NOPARTIAL)); if (!vh) 52b4: 48 03 8b d8 00 00 00 add 0xd8(%rbx),%rcx 52bb: 48 c7 43 28 00 00 00 movq $0x0,0x28(%rbx) 52c2: 00 52c3: c7 43 30 00 00 00 00 movl $0x0,0x30(%rbx) static struct sk_buff **vxlan_gro_receive(struct sock *sk, struct sk_buff **head, struct sk_buff *skb) { struct sk_buff *p, **pp = NULL; 52ca: 0f 85 55 fe ff ff jne 5125 52d0: e9 78 fd ff ff jmpq 504d return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 52d5: 41 39 d4 cmp %edx,%r12d 52d8: 48 89 75 c8 mov %rsi,-0x38(%rbp) return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 52dc: 48 89 4d d0 mov %rcx,-0x30(%rbp) 52e0: 0f 87 5f fd ff ff ja 5045 return; ptr = skb_gro_header_fast(skb, grc->offset); if (skb_gro_header_hard(skb, grc->offset + sizeof(u16))) { ptr = skb_gro_header_slow(skb, plen, grc->offset); if (!ptr) 52e6: 44 89 e6 mov %r12d,%esi 52e9: 48 89 df mov %rbx,%rdi unsigned int offset) { if (!pskb_may_pull(skb, hlen)) return NULL; NAPI_GRO_CB(skb)->frag0 = NULL; 52ec: 29 c6 sub %eax,%esi 52ee: e8 00 00 00 00 callq 52f3 NAPI_GRO_CB(skb)->frag0_len = 0; 52f3: 48 85 c0 test %rax,%rax 52f6: 48 8b 4d d0 mov -0x30(%rbp),%rcx return; ptr = skb_gro_header_fast(skb, grc->offset); if (skb_gro_header_hard(skb, grc->offset + sizeof(u16))) { ptr = skb_gro_header_slow(skb, plen, grc->offset); if (!ptr) 52fa: 4c 8b 45 c8 mov -0x38(%rbp),%r8 52fe: 0f 84 41 fd ff ff je 5045 5304: e9 21 fd ff ff jmpq 502a return 1; if (unlikely(len > skb->len)) 5309: 4d 85 ff test %r15,%r15 530c: 0f 85 97 fd ff ff jne 50a9 5312: e9 2e fd ff ff jmpq 5045 return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 5317: 47 8d 6c 35 08 lea 0x8(%r13,%r14,1),%r13d 531c: 83 ce 10 or $0x10,%esi 531f: 4d 85 ff test %r15,%r15 5322: 40 88 b3 93 00 00 00 mov %sil,0x93(%rbx) } static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, unsigned int offset) { if (!pskb_may_pull(skb, hlen)) 5329: 66 44 89 6b 3e mov %r13w,0x3e(%rbx) 532e: 0f 85 75 fd ff ff jne 50a9 5334: e9 0c fd ff ff jmpq 5045 vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), vh->vx_vni, &grc, !!(vs->flags & VXLAN_F_REMCSUM_NOPARTIAL)); if (!vh) 5339: 49 89 cf mov %rcx,%r15 533c: 4c 03 7b 28 add 0x28(%rbx),%r15 5340: e9 b7 fe ff ff jmpq 51fc 5345: 44 39 ee cmp %r13d,%esi size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start); BUG_ON(!NAPI_GRO_CB(skb)->csum_valid); if (!nopartial) { NAPI_GRO_CB(skb)->gro_remcsum_start = off + hdrlen + start; 5348: 48 89 4d c8 mov %rcx,-0x38(%rbp) offset = start + vxlan_rco_offset(vni_field); vh = skb_gro_remcsum_process(skb, (void *)vh, off, hdrlen, start, offset, grc, nopartial); skb->remcsum_offload = 1; 534c: 0f 82 fb fc ff ff jb 504d 5352: 44 89 ee mov %r13d,%esi 5355: 48 89 df mov %rbx,%rdi 5358: 89 55 d0 mov %edx,-0x30(%rbp) 535b: 29 c6 sub %eax,%esi 535d: e8 00 00 00 00 callq 5362 vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr), vh->vx_vni, &grc, !!(vs->flags & VXLAN_F_REMCSUM_NOPARTIAL)); if (!vh) 5362: 48 85 c0 test %rax,%rax 5365: 8b 55 d0 mov -0x30(%rbp),%edx 5368: 48 8b 4d c8 mov -0x38(%rbp),%rcx } static inline void *skb_gro_header_fast(struct sk_buff *skb, unsigned int offset) { return NAPI_GRO_CB(skb)->frag0 + offset; 536c: 0f 84 db fc ff ff je 504d 5372: e9 3d ff ff ff jmpq 52b4 static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) return 1; if (unlikely(len > skb->len)) 5377: 39 f0 cmp %esi,%eax 5379: 77 35 ja 53b0 537b: 29 d0 sub %edx,%eax 537d: 48 89 df mov %rbx,%rdi 5380: 4c 89 45 b8 mov %r8,-0x48(%rbp) return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 5384: 89 c6 mov %eax,%esi 5386: 4c 89 55 c0 mov %r10,-0x40(%rbp) 538a: 4c 89 4d c8 mov %r9,-0x38(%rbp) 538e: 48 89 4d d0 mov %rcx,-0x30(%rbp) } static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, unsigned int offset) { if (!pskb_may_pull(skb, hlen)) 5392: e8 00 00 00 00 callq 5397 5397: 48 85 c0 test %rax,%rax 539a: 48 8b 4d d0 mov -0x30(%rbp),%rcx 539e: 4c 8b 4d c8 mov -0x38(%rbp),%r9 53a2: 4c 8b 55 c0 mov -0x40(%rbp),%r10 53a6: 4c 8b 45 b8 mov -0x48(%rbp),%r8 static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) return 1; if (unlikely(len > skb->len)) 53aa: 0f 85 2d fe ff ff jne 51dd return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 53b0: 80 8b 93 00 00 00 10 orb $0x10,0x93(%rbx) 53b7: ba 01 00 00 00 mov $0x1,%edx 53bc: 45 31 ff xor %r15d,%r15d 53bf: e9 89 fc ff ff jmpq 504d 53c4: 66 90 xchg %ax,%ax 53c6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 53cd: 00 00 00 00000000000053d0 : 53d0: e8 00 00 00 00 callq 53d5 53d5: 55 push %rbp 53d6: 48 89 e5 mov %rsp,%rbp 53d9: 41 57 push %r15 53db: 41 56 push %r14 53dd: 41 55 push %r13 53df: 41 54 push %r12 offset = start + vxlan_rco_offset(vni_field); vh = skb_gro_remcsum_process(skb, (void *)vh, off, hdrlen, start, offset, grc, nopartial); skb->remcsum_offload = 1; 53e1: 49 89 f4 mov %rsi,%r12 53e4: 53 push %rbx 53e5: 48 89 fb mov %rdi,%rbx 53e8: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp static struct sk_buff **vxlan_gro_receive(struct sock *sk, struct sk_buff **head, struct sk_buff *skb) { struct sk_buff *p, **pp = NULL; 53ec: 48 83 ec 60 sub $0x60,%rsp 53f0: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 53f7: 00 00 53f9: 48 89 44 24 58 mov %rax,0x58(%rsp) 53fe: 31 c0 xor %eax,%eax return err <= 1; } /* Callback from net/ipv4/udp.c to receive packets */ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb) { 5400: 8b 86 80 00 00 00 mov 0x80(%rsi),%eax 5406: 89 c2 mov %eax,%edx 5408: 2b 96 84 00 00 00 sub 0x84(%rsi),%edx 540e: 83 fa 0f cmp $0xf,%edx 5411: 0f 86 b9 02 00 00 jbe 56d0 5417: 41 0f b7 84 24 c2 00 movzwl 0xc2(%r12),%eax 541e: 00 00 5420: 49 03 84 24 d0 00 00 add 0xd0(%r12),%rax 5427: 00 5428: 4c 8b 68 08 mov 0x8(%rax),%r13 542c: 44 8b 70 0c mov 0xc(%rax),%r14d 5430: 41 f6 c5 08 test $0x8,%r13b 5434: 44 89 e9 mov %r13d,%ecx return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 5437: 0f 84 80 00 00 00 je 54bd 543d: 4c 8b bb 48 02 00 00 mov 0x248(%rbx),%r15 return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 5444: 4c 89 ee mov %r13,%rsi return skb->transport_header != (typeof(skb->transport_header))~0U; } static inline unsigned char *skb_transport_header(const struct sk_buff *skb) { return skb->head + skb->transport_header; 5447: 48 83 e6 f7 and $0xfffffffffffffff7,%rsi 544b: 49 89 f5 mov %rsi,%r13 544e: 4d 85 ff test %r15,%r15 5451: 74 3d je 5490 5453: 41 8b bf 1c 20 00 00 mov 0x201c(%r15),%edi /* Need UDP and VXLAN header to be present */ if (!pskb_may_pull(skb, VXLAN_HLEN)) goto drop; unparsed = *vxlan_hdr(skb); 545a: f7 c7 00 20 00 00 test $0x2000,%edi /* VNI flag always required to be set */ if (!(unparsed.vx_flags & VXLAN_HF_VNI)) { 5460: 0f 85 83 00 00 00 jne 54e9 5466: 44 89 f0 mov %r14d,%eax 5469: c1 e0 08 shl $0x8,%eax 546c: 69 d0 47 86 c8 61 imul $0x61c88647,%eax,%edx 5472: c1 ea 16 shr $0x16,%edx ntohl(vxlan_hdr(skb)->vx_flags), ntohl(vxlan_hdr(skb)->vx_vni)); /* Return non vxlan pkt */ goto drop; } unparsed.vx_flags &= ~VXLAN_HF_VNI; 5475: 49 8d 54 d7 10 lea 0x10(%r15,%rdx,8),%rdx 547a: 48 8b 5a 08 mov 0x8(%rdx),%rbx unparsed.vx_vni &= ~VXLAN_VNI_MASK; vs = rcu_dereference_sk_user_data(sk); if (!vs) 547e: 48 85 db test %rbx,%rbx 5481: 74 0d je 5490 static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, __be32 vni) { struct vxlan_dev *vxlan; /* For flow based devices, map all packets to VNI 0 */ if (vs->flags & VXLAN_F_COLLECT_METADATA) 5483: 3b 43 60 cmp 0x60(%rbx),%eax 5486: 74 67 je 54ef 5488: 48 8b 1b mov (%rbx),%rbx 548b: 48 85 db test %rbx,%rbx 548e: 75 f3 jne 5483 5490: 4c 89 e7 mov %r12,%rdi 5493: e8 00 00 00 00 callq 5498 static inline __be32 vxlan_vni(__be32 vni_field) { #if defined(__BIG_ENDIAN) return (__force __be32)((__force u32)vni_field >> 8); #else return (__force __be32)((__force u32)(vni_field & VXLAN_VNI_MASK) << 8); 5498: 31 c0 xor %eax,%eax 549a: 48 8b 4c 24 58 mov 0x58(%rsp),%rcx 549f: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx 54a6: 00 00 vni = 0; hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) { 54a8: 0f 85 e7 08 00 00 jne 5d95 54ae: 48 8d 65 d8 lea -0x28(%rbp),%rsp 54b2: 5b pop %rbx if (vxlan->default_dst.remote_vni == vni) 54b3: 41 5c pop %r12 54b5: 41 5d pop %r13 54b7: 41 5e pop %r14 54b9: 41 5f pop %r15 /* For flow based devices, map all packets to VNI 0 */ if (vs->flags & VXLAN_F_COLLECT_METADATA) vni = 0; hlist_for_each_entry_rcu(vxlan, vni_head(vs, vni), hlist) { 54bb: 5d pop %rbp 54bc: c3 retq 54bd: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) gro_cells_receive(&vxlan->gro_cells, skb); return 0; drop: /* Consume bad packet */ kfree_skb(skb); 54c2: eb cc jmp 5490 54c4: 8b 48 08 mov 0x8(%rax),%ecx 54c7: 49 8b 74 24 20 mov 0x20(%r12),%rsi return 0; } 54cc: 45 89 f0 mov %r14d,%r8d 54cf: 41 0f c8 bswap %r8d 54d2: 48 c7 c2 00 00 00 00 mov $0x0,%rdx 54d9: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 54e0: 0f c9 bswap %ecx 54e2: e8 00 00 00 00 callq 54e7 54e7: eb a7 jmp 5490 54e9: 31 d2 xor %edx,%edx 54eb: 31 c0 xor %eax,%eax 54ed: eb 86 jmp 5475 54ef: 81 e7 00 40 00 00 and $0x4000,%edi goto drop; unparsed = *vxlan_hdr(skb); /* VNI flag always required to be set */ if (!(unparsed.vx_flags & VXLAN_HF_VNI)) { netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n", 54f5: 0f 85 74 01 00 00 jne 566f 54fb: ba 65 58 00 00 mov $0x5865,%edx 5500: 31 c9 xor %ecx,%ecx 5502: c6 44 24 27 00 movb $0x0,0x27(%rsp) 5507: 48 8b 43 30 mov 0x30(%rbx),%rax 550b: 48 8b 7b 38 mov 0x38(%rbx),%rdi 550f: 45 31 c0 xor %r8d,%r8d 5512: be 10 00 00 00 mov $0x10,%esi 5517: 48 39 b8 80 04 00 00 cmp %rdi,0x480(%rax) { struct vxlan_dev *vxlan; /* For flow based devices, map all packets to VNI 0 */ if (vs->flags & VXLAN_F_COLLECT_METADATA) vni = 0; 551e: 4c 89 e7 mov %r12,%rdi goto drop; /* For backwards compatibility, only allow reserved fields to be * used by VXLAN extensions if explicitly requested. */ if (vs->flags & VXLAN_F_GPE) { 5521: 41 0f 95 c0 setne %r8b 5525: e8 00 00 00 00 callq 552a 552a: 85 c0 test %eax,%eax 552c: 0f 85 5e ff ff ff jne 5490 struct vxlan_sock *vs; struct vxlanhdr unparsed; struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; __be16 protocol = htons(ETH_P_TEB); bool raw_proto = false; 5532: 41 8b 97 1c 20 00 00 mov 0x201c(%r15),%edx 5539: f6 c6 20 test $0x20,%dh if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags)) goto drop; raw_proto = true; } if (__iptunnel_pull_header(skb, VXLAN_HLEN, protocol, raw_proto, 553c: 0f 85 b4 01 00 00 jne 56f6 5542: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) 5547: 4c 8d 44 24 2c lea 0x2c(%rsp),%r8 554c: c7 44 24 2c 00 00 00 movl $0x0,0x2c(%rsp) 5553: 00 5554: 44 89 f0 mov %r14d,%eax 5557: 44 89 e9 mov %r13d,%ecx 555a: 25 00 00 00 ff and $0xff000000,%eax 555f: f6 c6 04 test $0x4,%dh 5562: 89 c7 mov %eax,%edi 5564: 0f 85 e8 01 00 00 jne 5752 /* salt for hash table */ static u32 vxlan_salt __read_mostly; static inline bool vxlan_collect_metadata(struct vxlan_sock *vs) { return vs->flags & VXLAN_F_COLLECT_METADATA || 556a: f6 c6 08 test $0x8,%dh 556d: 0f 85 25 03 00 00 jne 5898 5573: 85 c9 test %ecx,%ecx 5575: 0f 85 15 ff ff ff jne 5490 struct pcpu_sw_netstats *stats; struct vxlan_dev *vxlan; struct vxlan_sock *vs; struct vxlanhdr unparsed; struct vxlan_metadata _md; struct vxlan_metadata *md = &_md; 557b: 85 ff test %edi,%edi md = ip_tunnel_info_opts(&tun_dst->u.tun_info); skb_dst_set(skb, (struct dst_entry *)tun_dst); } else { memset(md, 0, sizeof(*md)); 557d: 0f 85 0d ff ff ff jne 5490 5583: 80 7c 24 27 00 cmpb $0x0,0x27(%rsp) ntohl(vxlan_hdr(skb)->vx_vni)); /* Return non vxlan pkt */ goto drop; } unparsed.vx_flags &= ~VXLAN_HF_VNI; unparsed.vx_vni &= ~VXLAN_VNI_MASK; 5588: 0f 84 85 03 00 00 je 5913 558e: 49 8b 8c 24 d0 00 00 mov 0xd0(%r12),%rcx 5595: 00 skb_dst_set(skb, (struct dst_entry *)tun_dst); } else { memset(md, 0, sizeof(*md)); } if (vs->flags & VXLAN_F_REMCSUM_RX) 5596: 49 8b 84 24 d8 00 00 mov 0xd8(%r12),%rax 559d: 00 if (!vxlan_remcsum(&unparsed, skb, vs->flags)) goto drop; if (vs->flags & VXLAN_F_GBP) 559e: 45 0f b7 ac 24 c4 00 movzwl 0xc4(%r12),%r13d 55a5: 00 00 vxlan_parse_gbp_hdr(&unparsed, skb, vs->flags, md); /* Note that GBP and GPE can never be active together. This is * ensured in vxlan_dev_configure. */ if (unparsed.vx_flags || unparsed.vx_vni) { 55a7: 48 29 c8 sub %rcx,%rax 55aa: 66 41 89 84 24 c6 00 mov %ax,0xc6(%r12) 55b1: 00 00 * adding extensions to VXLAN. */ goto drop; } if (!raw_proto) { 55b3: 48 8b 73 30 mov 0x30(%rbx),%rsi 55b7: 89 c2 mov %eax,%edx 55b9: 41 80 a4 24 90 00 00 andb $0xf8,0x90(%r12) 55c0: 00 f8 return skb->mac_header != (typeof(skb->mac_header))~0U; } static inline void skb_reset_mac_header(struct sk_buff *skb) { skb->mac_header = skb->data - skb->head; 55c2: 49 89 74 24 20 mov %rsi,0x20(%r12) 55c7: 66 41 89 94 24 c4 00 mov %dx,0xc4(%r12) 55ce: 00 00 55d0: 49 01 cd add %rcx,%r13 55d3: 49 8b 57 10 mov 0x10(%r15),%rdx 55d7: 48 8b 52 20 mov 0x20(%rdx),%rdx 55db: 0f b7 72 10 movzwl 0x10(%rdx),%esi 55df: 66 83 fe 02 cmp $0x2,%si if (!vxlan_set_mac(vxlan, vs, skb)) goto drop; } else { skb_reset_mac_header(skb); skb->dev = vxlan->dev; 55e3: 0f 84 0b 04 00 00 je 59f4 skb->pkt_type = PACKET_HOST; 55e9: 41 0f b7 bc 24 c0 00 movzwl 0xc0(%r12),%edi 55f0: 00 00 if (!raw_proto) { if (!vxlan_set_mac(vxlan, vs, skb)) goto drop; } else { skb_reset_mac_header(skb); skb->dev = vxlan->dev; 55f2: 66 83 ff 08 cmp $0x8,%di 55f6: 0f 84 84 05 00 00 je 5b80 return skb->head + skb->network_header; } static inline void skb_reset_network_header(struct sk_buff *skb) { skb->network_header = skb->data - skb->head; 55fc: 66 81 ff 86 dd cmp $0xdd86,%di skb->transport_header += offset; } static inline unsigned char *skb_network_header(const struct sk_buff *skb) { return skb->head + skb->network_header; 5601: 0f 84 78 04 00 00 je 5a7f return vni_field; } static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs) { return vs->sock->sk->sk_family; 5607: 48 8b 43 30 mov 0x30(%rbx),%rax 560b: 48 8b 80 88 04 00 00 mov 0x488(%rax),%rax static bool vxlan_ecn_decapsulate(struct vxlan_sock *vs, void *oiph, struct sk_buff *skb) { int err = 0; if (vxlan_get_sk_family(vs) == AF_INET) 5612: 65 48 03 05 00 00 00 add %gs:0x0(%rip),%rax # 561a 5619: 00 static inline int IP6_ECN_decapsulate(const struct ipv6hdr *oipv6h, struct sk_buff *skb) { __u8 inner; if (skb->protocol == htons(ETH_P_IP)) 561a: 48 83 00 01 addq $0x1,(%rax) 561e: 41 8b 94 24 80 00 00 mov 0x80(%r12),%edx 5625: 00 5626: 48 01 50 08 add %rdx,0x8(%rax) 562a: 48 8b 83 f0 00 00 00 mov 0xf0(%rbx),%rax inner = ip_hdr(skb)->tos; else if (skb->protocol == htons(ETH_P_IPV6)) 5631: 48 85 c0 test %rax,%rax 5634: 74 2c je 5662 5636: 41 f6 84 24 8e 00 00 testb $0x1,0x8e(%r12) 563d: 00 01 ++vxlan->dev->stats.rx_frame_errors; ++vxlan->dev->stats.rx_errors; goto drop; } stats = this_cpu_ptr(vxlan->dev->tstats); 563f: 0f 84 72 05 00 00 je 5bb7 5645: 41 8b 94 24 cc 00 00 mov 0xcc(%r12),%edx 564c: 00 u64_stats_update_begin(&stats->syncp); stats->rx_packets++; 564d: 49 03 94 24 d0 00 00 add 0xd0(%r12),%rdx 5654: 00 stats->rx_bytes += skb->len; 5655: 8b 52 20 mov 0x20(%rdx),%edx 5658: 66 83 fa 01 cmp $0x1,%dx static inline int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb) { struct gro_cell *cell; struct net_device *dev = skb->dev; if (!gcells->cells || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) 565c: 0f 84 55 05 00 00 je 5bb7 5662: 4c 89 e7 mov %r12,%rdi 5665: e8 00 00 00 00 callq 566a * one of multiple shared copies of the buffer. Cloned buffers are * shared data so must not be written to under normal circumstances. */ static inline int skb_cloned(const struct sk_buff *skb) { return skb->cloned && 566a: e9 29 fe ff ff jmpq 5498 566f: 40 f6 c6 04 test $0x4,%sil 5673: 0f 84 17 fe ff ff je 5490 }; #ifdef NET_SKBUFF_DATA_USES_OFFSET static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) { return skb->head + skb->end; 5679: 40 f6 c6 31 test $0x31,%sil 567d: 0f 85 0d fe ff ff jne 5490 5683: 48 89 f0 mov %rsi,%rax 5686: 48 c1 e8 18 shr $0x18,%rax * one of multiple shared copies of the buffer. Cloned buffers are * shared data so must not be written to under normal circumstances. */ static inline int skb_cloned(const struct sk_buff *skb) { return skb->cloned && 568a: 3c 02 cmp $0x2,%al 568c: 0f 84 77 02 00 00 je 5909 return netif_rx(skb); 5692: 3c 03 cmp $0x3,%al 5694: 0f 84 65 02 00 00 je 58ff 569a: 3c 01 cmp $0x1,%al 569c: ba 08 00 00 00 mov $0x8,%edx struct sk_buff *skb, u32 vxflags) { struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed; /* Need to have Next Protocol set for interfaces in GPE mode. */ if (!gpe->np_applied) 56a1: 0f 85 e9 fd ff ff jne 5490 56a7: 41 89 cd mov %ecx,%r13d return false; /* "When the O bit is set to 1, the packet is an OAM packet and OAM * processing MUST occur." However, we don't implement OAM * processing, thus drop the packet. */ if (gpe->oam_flag) 56aa: 48 b8 00 00 00 00 ff movabs $0xffffffff00000000,%rax 56b1: ff ff ff return false; switch (gpe->next_protocol) { 56b4: b9 01 00 00 00 mov $0x1,%ecx 56b9: 41 81 e5 c2 ff ff 00 and $0xffffc2,%r13d 56c0: 48 21 c6 and %rax,%rsi 56c3: c6 44 24 27 01 movb $0x1,0x27(%rsp) 56c8: 49 09 f5 or %rsi,%r13 56cb: e9 37 fe ff ff jmpq 5507 56d0: 83 f8 0f cmp $0xf,%eax 56d3: 0f 86 b7 fd ff ff jbe 5490 break; default: return false; } unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS; 56d9: be 10 00 00 00 mov $0x10,%esi 56de: 4c 89 e7 mov %r12,%rdi 56e1: 29 d6 sub %edx,%esi 56e3: e8 00 00 00 00 callq 56e8 56e8: 48 85 c0 test %rax,%rax 56eb: 0f 84 9f fd ff ff je 5490 56f1: e9 21 fd ff ff jmpq 5417 * used by VXLAN extensions if explicitly requested. */ if (vs->flags & VXLAN_F_GPE) { if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags)) goto drop; raw_proto = true; 56f6: 41 0f b7 84 24 c2 00 movzwl 0xc2(%r12),%eax 56fd: 00 00 break; default: return false; } unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS; 56ff: 49 8b 94 24 d0 00 00 mov 0xd0(%r12),%rdx 5706: 00 static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) return 1; if (unlikely(len > skb->len)) 5707: 41 b8 04 00 00 00 mov $0x4,%r8d return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 570d: 4c 89 e7 mov %r12,%rdi 5710: 8b 4c 02 0c mov 0xc(%rdx,%rax,1),%ecx 5714: 49 8b 47 10 mov 0x10(%r15),%rax __be16 protocol = htons(ETH_P_TEB); bool raw_proto = false; void *oiph; /* Need UDP and VXLAN header to be present */ if (!pskb_may_pull(skb, VXLAN_HLEN)) 5718: ba 00 04 00 00 mov $0x400,%edx 571d: 48 8b 40 20 mov 0x20(%rax),%rax 5721: c1 e1 08 shl $0x8,%ecx 5724: 48 c1 e1 20 shl $0x20,%rcx if (__iptunnel_pull_header(skb, VXLAN_HLEN, protocol, raw_proto, !net_eq(vxlan->net, dev_net(vxlan->dev)))) goto drop; if (vxlan_collect_metadata(vs)) { __be32 vni = vxlan_vni(vxlan_hdr(skb)->vx_vni); 5728: 0f b7 70 10 movzwl 0x10(%rax),%esi 572c: e8 00 00 00 00 callq 5731 5731: 48 85 c0 test %rax,%rax 5734: 0f 84 56 fd ff ff je 5490 struct metadata_dst *tun_dst; tun_dst = udp_tun_rx_dst(skb, vxlan_get_sk_family(vs), TUNNEL_KEY, 573a: 49 89 44 24 58 mov %rax,0x58(%r12) 573f: 4c 8d 80 f0 00 00 00 lea 0xf0(%rax),%r8 5746: 41 8b 97 1c 20 00 00 mov 0x201c(%r15),%edx 574d: e9 02 fe ff ff jmpq 5554 5752: 41 f7 c5 00 20 00 00 test $0x2000,%r13d 5759: 45 89 e9 mov %r13d,%r9d 575c: 0f 84 17 01 00 00 je 5879 vxlan_vni_to_tun_id(vni), sizeof(*md)); if (!tun_dst) 5762: 41 f6 84 24 93 00 00 testb $0x10,0x93(%r12) 5769: 00 10 * Sets skb dst, assuming a reference was taken on dst and should * be released by skb_dst_drop() */ static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst) { skb->_skb_refdst = (unsigned long)dst; 576b: 0f 85 08 01 00 00 jne 5879 } } static inline void *ip_tunnel_info_opts(struct ip_tunnel_info *info) { return info + 1; 5771: 41 81 e6 00 00 00 7f and $0x7f000000,%r14d 5778: 48 98 cltq 577a: 41 8b bc 24 80 00 00 mov 0x80(%r12),%edi 5781: 00 static bool vxlan_remcsum(struct vxlanhdr *unparsed, struct sk_buff *skb, u32 vxflags) { size_t start, offset; if (!(unparsed->vx_flags & VXLAN_HF_RCO) || skb->remcsum_offload) 5782: 41 0f ce bswap %r14d 5785: 48 c1 f8 3f sar $0x3f,%rax 5789: 43 8d 34 36 lea (%r14,%r14,1),%esi 578d: 48 83 e0 f6 and $0xfffffffffffffff6,%rax 5791: 48 8d 44 06 10 lea 0x10(%rsi,%rax,1),%rax 5796: 49 89 f6 mov %rsi,%r14 5799: 89 fe mov %edi,%esi 579b: 41 2b b4 24 84 00 00 sub 0x84(%r12),%esi 57a2: 00 #endif } static inline size_t vxlan_rco_start(__be32 vni_field) { return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT; 57a3: 48 89 44 24 18 mov %rax,0x18(%rsp) } static inline size_t vxlan_rco_offset(__be32 vni_field) { return (vni_field & VXLAN_RCO_UDP) ? offsetof(struct udphdr, check) : 57a8: 83 c0 02 add $0x2,%eax 57ab: 39 f0 cmp %esi,%eax 57ad: 0f 87 65 05 00 00 ja 5d18 #endif } static inline size_t vxlan_rco_start(__be32 vni_field) { return be32_to_cpu(vni_field & VXLAN_RCO_MASK) << VXLAN_RCO_SHIFT; 57b3: 41 0f b7 84 24 c2 00 movzwl 0xc2(%r12),%eax 57ba: 00 00 57bc: 49 8b b4 24 d0 00 00 mov 0xd0(%r12),%rsi 57c3: 00 goto out; start = vxlan_rco_start(unparsed->vx_vni); offset = start + vxlan_rco_offset(unparsed->vx_vni); 57c4: 80 e6 10 and $0x10,%dh 57c7: 4c 8d 54 06 10 lea 0x10(%rsi,%rax,1),%r10 return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 57cc: 0f 84 09 05 00 00 je 5cdb 57d2: 41 0f b6 84 24 91 00 movzbl 0x91(%r12),%eax 57d9: 00 00 return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 57db: 83 e0 06 and $0x6,%eax 57de: 3c 04 cmp $0x4,%al 57e0: 0f 85 58 06 00 00 jne 5e3e if (!pskb_may_pull(skb, offset + sizeof(u16))) return false; skb_remcsum_process(skb, (void *)(vxlan_hdr(skb) + 1), start, offset, 57e6: 45 8b 9c 24 98 00 00 mov 0x98(%r12),%r11d 57ed: 00 57ee: 48 63 44 24 18 movslq 0x18(%rsp),%rax 57f3: 31 d2 xor %edx,%edx static inline void skb_remcsum_process(struct sk_buff *skb, void *ptr, int start, int offset, bool nopartial) { __wsum delta; if (!nopartial) { 57f5: 44 89 f6 mov %r14d,%esi 57f8: 4c 89 d7 mov %r10,%rdi 57fb: 44 89 5c 24 08 mov %r11d,0x8(%rsp) 5800: 44 89 4c 24 20 mov %r9d,0x20(%rsp) skb_remcsum_adjust_partial(skb, ptr, start, offset); return; } if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { 5805: 4c 89 44 24 10 mov %r8,0x10(%rsp) 580a: 49 8d 0c 02 lea (%r10,%rax,1),%rcx 580e: 48 89 4c 24 18 mov %rcx,0x18(%rsp) 5813: e8 00 00 00 00 callq 5818 5818: 48 8b 4c 24 18 mov 0x18(%rsp),%rcx 581d: f7 d0 not %eax 581f: 44 8b 5c 24 08 mov 0x8(%rsp),%r11d __wsum delta; /* Subtract out checksum up to start */ csum = csum_sub(csum, csum_partial(ptr, start, 0)); 5824: 41 01 c3 add %eax,%r11d 5827: 41 83 d3 00 adc $0x0,%r11d 582b: 44 89 da mov %r11d,%edx 582e: 66 45 31 db xor %r11w,%r11w 5832: 44 8b 4c 24 20 mov 0x20(%rsp),%r9d 5837: 0f b7 31 movzwl (%rcx),%esi } static inline __wsum remcsum_adjust(void *ptr, __wsum csum, int start, int offset) { __sum16 *psum = (__sum16 *)(ptr + offset); 583a: c1 e2 10 shl $0x10,%edx 583d: 44 89 d8 mov %r11d,%eax 5840: 01 d0 add %edx,%eax 5842: 15 ff ff 00 00 adc $0xffff,%eax __wsum delta; /* Subtract out checksum up to start */ csum = csum_sub(csum, csum_partial(ptr, start, 0)); 5847: f7 d0 not %eax 5849: 4c 8b 44 24 10 mov 0x10(%rsp),%r8 584e: c1 e8 10 shr $0x10,%eax 5851: 66 89 01 mov %ax,(%rcx) 5854: 89 c2 mov %eax,%edx 5856: f7 d6 not %esi 5858: 41 8b 84 24 98 00 00 mov 0x98(%r12),%eax 585f: 00 { asm(" addl %1,%0\n" " adcl $0xffff,%0" : "=r" (sum) : "r" ((__force u32)sum << 16), "0" ((__force u32)sum & 0xffff0000)); 5860: 01 f2 add %esi,%edx 5862: 83 d2 00 adc $0x0,%edx 5865: 01 d0 add %edx,%eax csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len, __u8 proto, __wsum sum); static inline unsigned add32_with_carry(unsigned a, unsigned b) { asm("addl %2,%0\n\t" 5867: 83 d0 00 adc $0x0,%eax static inline __sum16 csum_fold(__wsum sum) { asm(" addl %1,%0\n" " adcl $0xffff,%0" : "=r" (sum) : "r" ((__force u32)sum << 16), 586a: 41 89 84 24 98 00 00 mov %eax,0x98(%r12) 5871: 00 * the last step before putting a checksum into a packet. * Make sure not to mix with 64bit checksums. */ static inline __sum16 csum_fold(__wsum sum) { asm(" addl %1,%0\n" 5872: 41 8b 97 1c 20 00 00 mov 0x201c(%r15),%edx csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, __u32 len, __u8 proto, __wsum sum); static inline unsigned add32_with_carry(unsigned a, unsigned b) { asm("addl %2,%0\n\t" 5879: 44 89 c9 mov %r9d,%ecx 587c: 48 b8 00 00 00 00 ff movabs $0xffffffff00000000,%rax 5883: ff ff ff 5886: 31 ff xor %edi,%edi 5888: 80 e5 df and $0xdf,%ch 588b: 49 21 c5 and %rax,%r13 588e: 89 ce mov %ecx,%esi 5890: 49 09 f5 or %rsi,%r13 5893: e9 d2 fc ff ff jmpq 556a 5898: f6 c1 80 test $0x80,%cl } delta = remcsum_adjust(ptr, skb->csum, start, offset); /* Adjust skb->csum since we changed the packet */ skb->csum = csum_add(skb->csum, delta); 589b: 74 5a je 58f7 589d: 4c 89 ee mov %r13,%rsi 58a0: 48 c1 ee 10 shr $0x10,%rsi 58a4: 66 c1 c6 08 rol $0x8,%si 58a8: 0f b7 f6 movzwl %si,%esi !!(vxflags & VXLAN_F_REMCSUM_NOPARTIAL)); out: unparsed->vx_flags &= ~VXLAN_HF_RCO; 58ab: 41 89 30 mov %esi,(%r8) 58ae: 49 8b 74 24 58 mov 0x58(%r12),%rsi 58b3: 48 83 e6 fe and $0xfffffffffffffffe,%rsi unparsed->vx_vni &= VXLAN_VNI_MASK; 58b7: 74 0f je 58c8 return false; skb_remcsum_process(skb, (void *)(vxlan_hdr(skb) + 1), start, offset, !!(vxflags & VXLAN_F_REMCSUM_NOPARTIAL)); out: unparsed->vx_flags &= ~VXLAN_HF_RCO; 58b9: 66 83 8e c8 00 00 00 orw $0x10,0xc8(%rsi) 58c0: 10 58c1: c6 86 e8 00 00 00 04 movb $0x4,0xe8(%rsi) struct vxlan_metadata *md) { struct vxlanhdr_gbp *gbp = (struct vxlanhdr_gbp *)unparsed; struct metadata_dst *tun_dst; if (!(unparsed->vx_flags & VXLAN_HF_GBP)) 58c8: 44 89 e8 mov %r13d,%eax 58cb: 0f b6 f4 movzbl %ah,%esi goto out; md->gbp = ntohs(gbp->policy_id); 58ce: 40 f6 c6 40 test $0x40,%sil 58d2: 74 07 je 58db 58d4: 41 81 08 00 00 40 00 orl $0x400000,(%r8) 58db: 83 e6 08 and $0x8,%esi tun_dst = (struct metadata_dst *)skb_dst(skb); if (tun_dst) { 58de: 74 07 je 58e7 58e0: 41 81 08 00 00 08 00 orl $0x80000,(%r8) 58e7: 80 e6 20 and $0x20,%dh tun_dst->u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT; 58ea: 75 0b jne 58f7 58ec: 41 8b 10 mov (%r8),%edx 58ef: 41 89 94 24 b4 00 00 mov %edx,0xb4(%r12) 58f6: 00 tun_dst->u.tun_info.options_len = sizeof(*md); 58f7: 83 e1 7f and $0x7f,%ecx } if (gbp->dont_learn) 58fa: e9 74 fc ff ff jmpq 5573 58ff: ba 65 58 00 00 mov $0x5865,%edx md->gbp |= VXLAN_GBP_DONT_LEARN; 5904: e9 9e fd ff ff jmpq 56a7 5909: ba 86 dd 00 00 mov $0xdd86,%edx if (gbp->policy_applied) 590e: e9 94 fd ff ff jmpq 56a7 md->gbp |= VXLAN_GBP_POLICY_APPLIED; 5913: 49 8b 84 24 d8 00 00 mov 0xd8(%r12),%rax 591a: 00 /* In flow-based mode, GBP is carried in dst_metadata */ if (!(vxflags & VXLAN_F_COLLECT_METADATA)) 591b: 49 2b 84 24 d0 00 00 sub 0xd0(%r12),%rax 5922: 00 skb->mark = md->gbp; 5923: 4c 89 e7 mov %r12,%rdi 5926: 66 41 89 84 24 c6 00 mov %ax,0xc6(%r12) 592d: 00 00 out: unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS; 592f: 48 8b 73 30 mov 0x30(%rbx),%rsi 5933: e8 00 00 00 00 callq 5938 5938: 66 41 89 84 24 c0 00 mov %ax,0xc0(%r12) 593f: 00 00 * processing, thus drop the packet. */ if (gpe->oam_flag) return false; switch (gpe->next_protocol) { 5941: 41 0f b6 84 24 91 00 movzbl 0x91(%r12),%eax 5948: 00 00 return skb->mac_header != (typeof(skb->mac_header))~0U; } static inline void skb_reset_mac_header(struct sk_buff *skb) { skb->mac_header = skb->data - skb->head; 594a: 41 0f b7 b4 24 c6 00 movzwl 0xc6(%r12),%esi 5951: 00 00 struct sk_buff *skb) { union vxlan_addr saddr; skb_reset_mac_header(skb); skb->protocol = eth_type_trans(skb, vxlan->dev); 5953: 49 8b 8c 24 d0 00 00 mov 0xd0(%r12),%rcx 595a: 00 595b: 89 c2 mov %eax,%edx 595d: 83 e2 06 and $0x6,%edx 5960: 48 8d 3c 31 lea (%rcx,%rsi,1),%rdi 5964: 80 fa 04 cmp $0x4,%dl 5967: 0f 84 e9 03 00 00 je 5d56 596d: 80 fa 06 cmp $0x6,%dl 5970: 0f 84 18 02 00 00 je 5b8e static __always_inline void __skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len, unsigned int off) { if (skb->ip_summed == CHECKSUM_COMPLETE) 5976: 48 8b 43 30 mov 0x30(%rbx),%rax skb->network_header += offset; } static inline unsigned char *skb_mac_header(const struct sk_buff *skb) { return skb->head + skb->mac_header; 597a: 8b 57 06 mov 0x6(%rdi),%edx 597d: 4c 8b 80 38 03 00 00 mov 0x338(%rax),%r8 5984: 0f b7 47 0a movzwl 0xa(%rdi),%eax 5988: 66 41 33 40 04 xor 0x4(%r8),%ax static __always_inline void __skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len, unsigned int off) { if (skb->ip_summed == CHECKSUM_COMPLETE) 598d: 41 33 10 xor (%r8),%edx skb->network_header += offset; } static inline unsigned char *skb_mac_header(const struct sk_buff *skb) { return skb->head + skb->mac_header; 5990: 0f b7 c0 movzwl %ax,%eax 5993: 09 c2 or %eax,%edx static __always_inline void __skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len, unsigned int off) { if (skb->ip_summed == CHECKSUM_COMPLETE) 5995: 0f 84 f5 fa ff ff je 5490 599b: 49 8b 47 10 mov 0x10(%r15),%rax skb->csum = csum_block_sub(skb->csum, csum_partial(start, len, 0), off); else if (skb->ip_summed == CHECKSUM_PARTIAL && 599f: 45 0f b7 ac 24 c4 00 movzwl 0xc4(%r12),%r13d 59a6: 00 00 skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); /* Ignore packet loops (and multicast echo) */ if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) 59a8: 48 8b 40 20 mov 0x20(%rax),%rax 59ac: 66 83 78 10 02 cmpw $0x2,0x10(%rax) 59b1: 0f 84 ff 02 00 00 je 5cb6 59b7: 4a 8b 44 29 08 mov 0x8(%rcx,%r13,1),%rax 59bc: 4a 8b 54 29 10 mov 0x10(%rcx,%r13,1),%rdx 59c1: 48 89 44 24 38 mov %rax,0x38(%rsp) 59c6: b8 0a 00 00 00 mov $0xa,%eax return vni_field; } static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs) { return vs->sock->sk->sk_family; 59cb: 48 89 54 24 40 mov %rdx,0x40(%rsp) return false; /* Get address from the outer IP header */ if (vxlan_get_sk_family(vs) == AF_INET) { saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; 59d0: 66 89 44 24 30 mov %ax,0x30(%rsp) 59d5: f6 83 98 00 00 00 01 testb $0x1,0x98(%rbx) /* Ignore packet loops (and multicast echo) */ if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) return false; /* Get address from the outer IP header */ if (vxlan_get_sk_family(vs) == AF_INET) { 59dc: 0f 85 a2 02 00 00 jne 5c84 59e2: 49 8b 84 24 d8 00 00 mov 0xd8(%r12),%rax 59e9: 00 saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; saddr.sa.sa_family = AF_INET; #if IS_ENABLED(CONFIG_IPV6) } else { saddr.sin6.sin6_addr = ipv6_hdr(skb)->saddr; 59ea: 48 29 c8 sub %rcx,%rax 59ed: 89 c2 mov %eax,%edx 59ef: e9 d3 fb ff ff jmpq 55c7 59f4: 45 0f b7 84 24 c0 00 movzwl 0xc0(%r12),%r8d 59fb: 00 00 59fd: 66 41 83 f8 08 cmp $0x8,%r8w saddr.sa.sa_family = AF_INET6; 5a02: 0f 84 c6 02 00 00 je 5cce #endif } if ((vxlan->flags & VXLAN_F_LEARN) && 5a08: 66 41 81 f8 86 dd cmp $0xdd86,%r8w 5a0e: 0f 85 f3 fb ff ff jne 5607 5a14: 0f b7 c0 movzwl %ax,%eax 5a17: 0f b7 3c 01 movzwl (%rcx,%rax,1),%edi 5a1b: 66 c1 c7 08 rol $0x8,%di 5a1f: 66 c1 ef 04 shr $0x4,%di 5a23: 83 e7 03 and $0x3,%edi static inline int IP_ECN_decapsulate(const struct iphdr *oiph, struct sk_buff *skb) { __u8 inner; if (skb->protocol == htons(ETH_P_IP)) 5a26: 41 0f b6 55 01 movzbl 0x1(%r13),%edx 5a2b: 0f 85 2b 02 00 00 jne 5c5c 5a31: 83 e2 03 and $0x3,%edx 5a34: 0f 84 cd fb ff ff je 5607 inner = ip_hdr(skb)->tos; else if (skb->protocol == htons(ETH_P_IPV6)) 5a3a: 80 fa 02 cmp $0x2,%dl 5a3d: 0f 86 ea 01 00 00 jbe 5c2d 5a43: 80 fa 03 cmp $0x3,%dl 5a46: 0f 85 bb fb ff ff jne 5607 5a4c: 80 3d 00 00 00 00 00 cmpb $0x0,0x0(%rip) # 5a53 * 2 if packet should be dropped */ static inline int INET_ECN_decapsulate(struct sk_buff *skb, __u8 outer, __u8 inner) { if (INET_ECN_is_not_ect(inner)) { 5a53: 74 0d je 5a62 5a55: e8 00 00 00 00 callq 5a5a else if (skb->protocol == htons(ETH_P_IPV6)) inner = ipv6_get_dsfield(ipv6_hdr(skb)); else return 0; return INET_ECN_decapsulate(skb, oiph->tos, inner); 5a5a: 85 c0 test %eax,%eax * 2 if packet should be dropped */ static inline int INET_ECN_decapsulate(struct sk_buff *skb, __u8 outer, __u8 inner) { if (INET_ECN_is_not_ect(inner)) { 5a5c: 0f 85 55 04 00 00 jne 5eb7 switch (outer & INET_ECN_MASK) { 5a62: 48 8b 43 30 mov 0x30(%rbx),%rax 5a66: 48 83 80 98 01 00 00 addq $0x1,0x198(%rax) 5a6d: 01 5a6e: 48 8b 43 30 mov 0x30(%rbx),%rax 5a72: 48 83 80 50 01 00 00 addq $0x1,0x150(%rax) 5a79: 01 5a7a: e9 11 fa ff ff jmpq 5490 #if IS_ENABLED(CONFIG_IPV6) else err = IP6_ECN_decapsulate(oiph, skb); #endif if (unlikely(err) && log_ecn_error) { 5a7f: 0f b7 c0 movzwl %ax,%eax 5a82: 44 0f b7 04 01 movzwl (%rcx,%rax,1),%r8d if (vxlan_get_sk_family(vs) == AF_INET) net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", 5a87: 66 41 c1 c0 08 rol $0x8,%r8w 5a8c: 66 41 c1 e8 04 shr $0x4,%r8w 5a91: 41 0f b7 55 00 movzwl 0x0(%r13),%edx oiph = skb_network_header(skb); skb_reset_network_header(skb); if (!vxlan_ecn_decapsulate(vs, oiph, skb)) { ++vxlan->dev->stats.rx_frame_errors; 5a96: 66 c1 c2 08 rol $0x8,%dx 5a9a: 66 c1 ea 04 shr $0x4,%dx ++vxlan->dev->stats.rx_errors; 5a9e: 41 83 e0 03 and $0x3,%r8d 5aa2: 75 52 jne 5af6 5aa4: 83 e2 03 and $0x3,%edx 5aa7: 0f 84 5a fb ff ff je 5607 goto drop; 5aad: 80 fa 02 cmp $0x2,%dl 5ab0: 0f 86 77 01 00 00 jbe 5c2d 5ab6: 80 fa 03 cmp $0x3,%dl 5ab9: 0f 85 48 fb ff ff jne 5607 5abf: 80 3d 00 00 00 00 00 cmpb $0x0,0x0(%rip) # 5ac6 5ac6: 74 9a je 5a62 5ac8: e8 00 00 00 00 callq 5acd 5acd: 85 c0 test %eax,%eax * 2 if packet should be dropped */ static inline int INET_ECN_decapsulate(struct sk_buff *skb, __u8 outer, __u8 inner) { if (INET_ECN_is_not_ect(inner)) { 5acf: 74 91 je 5a62 5ad1: 41 be 02 00 00 00 mov $0x2,%r14d switch (outer & INET_ECN_MASK) { 5ad7: 49 8d 75 08 lea 0x8(%r13),%rsi 5adb: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 5ae2: e8 00 00 00 00 callq 5ae7 5ae7: 41 83 fe 02 cmp $0x2,%r14d 5aeb: 0f 84 71 ff ff ff je 5a62 #if IS_ENABLED(CONFIG_IPV6) else err = IP6_ECN_decapsulate(oiph, skb); #endif if (unlikely(err) && log_ecn_error) { 5af1: e9 11 fb ff ff jmpq 5607 5af6: 83 e2 03 and $0x3,%edx if (vxlan_get_sk_family(vs) == AF_INET) net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", &((struct iphdr *)oiph)->saddr, ((struct iphdr *)oiph)->tos); else net_info_ratelimited("non-ECT from %pI6\n", 5af9: 80 fa 03 cmp $0x3,%dl 5afc: 0f 85 05 fb ff ff jne 5607 return 0; case INET_ECN_ECT_0: case INET_ECN_ECT_1: return 1; case INET_ECN_CE: return 2; 5b02: 66 83 ff 08 cmp $0x8,%di 5b06: 0f 84 8e 02 00 00 je 5d9a 5b0c: 66 81 ff 86 dd cmp $0xdd86,%di 5b11: 0f 85 f0 fa ff ff jne 5607 } oiph = skb_network_header(skb); skb_reset_network_header(skb); if (!vxlan_ecn_decapsulate(vs, oiph, skb)) { 5b17: 41 8b 94 24 c8 00 00 mov 0xc8(%r12),%edx 5b1e: 00 5b1f: 48 01 c8 add %rcx,%rax 5b22: 48 8d 70 28 lea 0x28(%rax),%rsi } } if (INET_ECN_is_ce(outer)) 5b26: 48 01 d1 add %rdx,%rcx 5b29: 48 39 ce cmp %rcx,%rsi 5b2c: 0f 87 d5 fa ff ff ja 5607 ipv6_change_dsfield(inner, INET_ECN_MASK, dscp); } static inline int INET_ECN_set_ce(struct sk_buff *skb) { switch (skb->protocol) { 5b32: 0f b7 10 movzwl (%rax),%edx 5b35: 66 c1 c2 08 rol $0x8,%dx 5b39: 80 e2 30 and $0x30,%dl 5b3c: 0f 84 c5 fa ff ff je 5607 5b42: 8b 10 mov (%rax),%edx 5b44: 89 d1 mov %edx,%ecx 5b46: 80 cd 30 or $0x30,%ch skb_tail_pointer(skb)) return IP_ECN_set_ce(ip_hdr(skb)); break; case cpu_to_be16(ETH_P_IPV6): if (skb_network_header(skb) + sizeof(struct ipv6hdr) <= 5b49: 89 08 mov %ecx,(%rax) 5b4b: 41 0f b6 84 24 91 00 movzbl 0x91(%r12),%eax 5b52: 00 00 5b54: 83 e0 06 and $0x6,%eax 5b57: 3c 04 cmp $0x4,%al 5b59: 0f 85 a8 fa ff ff jne 5607 5b5f: 41 8b 84 24 98 00 00 mov 0x98(%r12),%eax 5b66: 00 5b67: f7 d2 not %edx */ static inline int IP6_ECN_set_ce(struct sk_buff *skb, struct ipv6hdr *iph) { __be32 from, to; if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) 5b69: 01 d0 add %edx,%eax 5b6b: 83 d0 00 adc $0x0,%eax 5b6e: 01 c8 add %ecx,%eax 5b70: 83 d0 00 adc $0x0,%eax return 0; from = *(__be32 *)iph; 5b73: 41 89 84 24 98 00 00 mov %eax,0x98(%r12) 5b7a: 00 to = from | htonl(INET_ECN_CE << 20); *(__be32 *)iph = to; if (skb->ip_summed == CHECKSUM_COMPLETE) 5b7b: e9 87 fa ff ff jmpq 5607 5b80: 0f b7 c0 movzwl %ax,%eax 5b83: 44 0f b6 44 01 01 movzbl 0x1(%rcx,%rax,1),%r8d 5b89: e9 03 ff ff ff jmpq 5a91 5b8e: 41 0f b7 94 24 98 00 movzwl 0x98(%r12),%edx 5b95: 00 00 5b97: 41 2b 94 24 d8 00 00 sub 0xd8(%r12),%edx 5b9e: 00 5b9f: 01 ca add %ecx,%edx 5ba1: 0f 89 cf fd ff ff jns 5976 skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from), 5ba7: 83 e0 f9 and $0xfffffff9,%eax 5baa: 41 88 84 24 91 00 00 mov %al,0x91(%r12) 5bb1: 00 struct sk_buff *skb) { __u8 inner; if (skb->protocol == htons(ETH_P_IP)) inner = ip_hdr(skb)->tos; 5bb2: e9 bf fd ff ff jmpq 5976 5bb7: 49 8b 54 24 20 mov 0x20(%r12),%rdx 5bbc: f6 82 f1 00 00 00 40 testb $0x40,0xf1(%rdx) 5bc3: 0f 84 99 fa ff ff je 5662 5bc9: 65 48 03 05 00 00 00 add %gs:0x0(%rip),%rax # 5bd1 5bd0: 00 5bd1: 8b 3d 00 00 00 00 mov 0x0(%rip),%edi # 5bd7 skb_checksum_start_offset(skb) < 0) skb->ip_summed = CHECKSUM_NONE; 5bd7: 39 78 10 cmp %edi,0x10(%rax) 5bda: 0f 87 49 02 00 00 ja 5e29 5be0: 48 8b 50 08 mov 0x8(%rax),%rdx 5be4: 49 89 04 24 mov %rax,(%r12) }; static inline int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb) { struct gro_cell *cell; struct net_device *dev = skb->dev; 5be8: 49 89 54 24 08 mov %rdx,0x8(%r12) if (!gcells->cells || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) 5bed: 4c 89 22 mov %r12,(%rdx) 5bf0: 8b 78 10 mov 0x10(%rax),%edi 5bf3: 4c 89 60 08 mov %r12,0x8(%rax) 5bf7: 8d 57 01 lea 0x1(%rdi),%edx return netif_rx(skb); cell = this_cpu_ptr(gcells->cells); 5bfa: 83 fa 01 cmp $0x1,%edx 5bfd: 89 50 10 mov %edx,0x10(%rax) 5c00: 0f 85 92 f8 ff ff jne 5498 if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) { 5c06: 48 8b 50 28 mov 0x28(%rax),%rdx 5c0a: 48 8d 78 18 lea 0x18(%rax),%rdi 5c0e: 80 e2 02 and $0x2,%dl static inline void __skb_queue_before(struct sk_buff_head *list, struct sk_buff *next, struct sk_buff *newsk) { __skb_insert(newsk, next->prev, next, list); 5c11: 0f 85 81 f8 ff ff jne 5498 struct sk_buff_head *list); static inline void __skb_insert(struct sk_buff *newsk, struct sk_buff *prev, struct sk_buff *next, struct sk_buff_head *list) { newsk->next = next; 5c17: f0 0f ba 68 28 00 lock btsl $0x0,0x28(%rax) newsk->prev = prev; next->prev = prev->next = newsk; 5c1d: 0f 82 75 f8 ff ff jb 5498 5c23: e8 00 00 00 00 callq 5c28 list->qlen++; 5c28: e9 6b f8 ff ff jmpq 5498 5c2d: 80 3d 00 00 00 00 00 cmpb $0x0,0x0(%rip) # 5c34 kfree_skb(skb); return NET_RX_DROP; } __skb_queue_tail(&cell->napi_skbs, skb); if (skb_queue_len(&cell->napi_skbs) == 1) 5c34: 0f 84 cd f9 ff ff je 5607 napi_schedule(&cell->napi); 5c3a: 66 83 fe 02 cmp $0x2,%si * insure only one NAPI poll instance runs. We also make * sure there is no pending NAPI disable. */ static inline bool napi_schedule_prep(struct napi_struct *n) { return !napi_disable_pending(n) && 5c3e: 0f 84 b8 01 00 00 je 5dfc 5c44: e8 00 00 00 00 callq 5c49 * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ static __always_inline bool test_and_set_bit(long nr, volatile unsigned long *addr) { GEN_BINARY_RMWcc(LOCK_PREFIX "bts", *addr, "Ir", nr, "%0", c); 5c49: 85 c0 test %eax,%eax 5c4b: 0f 84 b6 f9 ff ff je 5607 5c51: 41 be 01 00 00 00 mov $0x1,%r14d * running. */ static inline void napi_schedule(struct napi_struct *n) { if (napi_schedule_prep(n)) __napi_schedule(n); 5c57: e9 7b fe ff ff jmpq 5ad7 5c5c: 83 e2 03 and $0x3,%edx #if IS_ENABLED(CONFIG_IPV6) else err = IP6_ECN_decapsulate(oiph, skb); #endif if (unlikely(err) && log_ecn_error) { 5c5f: 80 fa 03 cmp $0x3,%dl 5c62: 0f 85 9f f9 ff ff jne 5607 5c68: 66 41 83 f8 08 cmp $0x8,%r8w if (vxlan_get_sk_family(vs) == AF_INET) 5c6d: 0f 84 27 01 00 00 je 5d9a 5c73: 66 41 81 f8 86 dd cmp $0xdd86,%r8w net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", &((struct iphdr *)oiph)->saddr, ((struct iphdr *)oiph)->tos); else net_info_ratelimited("non-ECT from %pI6\n", 5c79: 0f 84 98 fe ff ff je 5b17 5c7f: e9 83 f9 ff ff jmpq 5607 5c84: 49 8b 7c 24 20 mov 0x20(%r12),%rdi 5c89: 48 8d 54 31 06 lea 0x6(%rcx,%rsi,1),%rdx case INET_ECN_CE: return 2; } } if (INET_ECN_is_ce(outer)) 5c8e: 48 8d 74 24 30 lea 0x30(%rsp),%rsi 5c93: e8 98 d6 ff ff callq 3330 ipv6_change_dsfield(inner, INET_ECN_MASK, dscp); } static inline int INET_ECN_set_ce(struct sk_buff *skb) { switch (skb->protocol) { 5c98: 84 c0 test %al,%al 5c9a: 0f 85 f0 f7 ff ff jne 5490 5ca0: 49 8b 8c 24 d0 00 00 mov 0xd0(%r12),%rcx 5ca7: 00 5ca8: 45 0f b7 ac 24 c4 00 movzwl 0xc4(%r12),%r13d 5caf: 00 00 5cb1: e9 2c fd ff ff jmpq 59e2 saddr.sa.sa_family = AF_INET6; #endif } if ((vxlan->flags & VXLAN_F_LEARN) && vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source)) 5cb6: 42 8b 44 29 0c mov 0xc(%rcx,%r13,1),%eax 5cbb: ba 02 00 00 00 mov $0x2,%edx 5cc0: 66 89 54 24 30 mov %dx,0x30(%rsp) 5cc5: 89 44 24 34 mov %eax,0x34(%rsp) saddr.sin6.sin6_addr = ipv6_hdr(skb)->saddr; saddr.sa.sa_family = AF_INET6; #endif } if ((vxlan->flags & VXLAN_F_LEARN) && 5cc9: e9 07 fd ff ff jmpq 59d5 5cce: 0f b7 c0 movzwl %ax,%eax 5cd1: 0f b6 7c 01 01 movzbl 0x1(%rcx,%rax,1),%edi 5cd6: e9 48 fd ff ff jmpq 5a23 5cdb: 44 89 f0 mov %r14d,%eax 5cde: 41 80 8c 24 91 00 00 orb $0x6,0x91(%r12) 5ce5: 00 06 if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) return false; /* Get address from the outer IP header */ if (vxlan_get_sk_family(vs) == AF_INET) { saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; 5ce7: 25 fe ff 00 00 and $0xfffe,%eax saddr.sa.sa_family = AF_INET; 5cec: 4c 01 d0 add %r10,%rax 5cef: 48 29 f0 sub %rsi,%rax 5cf2: 66 41 89 84 24 98 00 mov %ax,0x98(%r12) 5cf9: 00 00 if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) return false; /* Get address from the outer IP header */ if (vxlan_get_sk_family(vs) == AF_INET) { saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; 5cfb: 0f b7 44 24 18 movzwl 0x18(%rsp),%eax struct sk_buff *skb) { __u8 inner; if (skb->protocol == htons(ETH_P_IP)) inner = ip_hdr(skb)->tos; 5d00: 44 29 f0 sub %r14d,%eax 5d03: 66 41 89 84 24 9a 00 mov %ax,0x9a(%r12) 5d0a: 00 00 static inline void skb_remcsum_adjust_partial(struct sk_buff *skb, void *ptr, u16 start, u16 offset) { skb->ip_summed = CHECKSUM_PARTIAL; skb->csum_start = ((unsigned char *)ptr + start) - skb->head; 5d0c: 41 8b 97 1c 20 00 00 mov 0x201c(%r15),%edx } while (0) static inline void skb_remcsum_adjust_partial(struct sk_buff *skb, void *ptr, u16 start, u16 offset) { skb->ip_summed = CHECKSUM_PARTIAL; 5d13: e9 61 fb ff ff jmpq 5879 skb->csum_start = ((unsigned char *)ptr + start) - skb->head; 5d18: 39 c7 cmp %eax,%edi 5d1a: 89 54 24 08 mov %edx,0x8(%rsp) 5d1e: 44 89 6c 24 20 mov %r13d,0x20(%rsp) 5d23: 4c 89 44 24 10 mov %r8,0x10(%rsp) 5d28: 0f 82 62 f7 ff ff jb 5490 skb->csum_offset = offset - start; 5d2e: 29 f0 sub %esi,%eax 5d30: 4c 89 e7 mov %r12,%rdi 5d33: 89 c6 mov %eax,%esi 5d35: e8 00 00 00 00 callq 5d3a 5d3a: 48 85 c0 test %rax,%rax 5d3d: 4c 8b 44 24 10 mov 0x10(%rsp),%r8 5d42: 44 8b 4c 24 20 mov 0x20(%rsp),%r9d 5d47: 8b 54 24 08 mov 0x8(%rsp),%edx static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) return 1; if (unlikely(len > skb->len)) 5d4b: 0f 84 3f f7 ff ff je 5490 5d51: e9 5d fa ff ff jmpq 57b3 5d56: 31 d2 xor %edx,%edx 5d58: be 0e 00 00 00 mov $0xe,%esi 5d5d: e8 00 00 00 00 callq 5d62 return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 5d62: 41 0f b7 b4 24 c6 00 movzwl 0xc6(%r12),%esi 5d69: 00 00 goto out; start = vxlan_rco_start(unparsed->vx_vni); offset = start + vxlan_rco_offset(unparsed->vx_vni); if (!pskb_may_pull(skb, offset + sizeof(u16))) 5d6b: 49 8b 8c 24 d0 00 00 mov 0xd0(%r12),%rcx 5d72: 00 5d73: f7 d0 not %eax 5d75: 89 c2 mov %eax,%edx 5d77: 41 8b 84 24 98 00 00 mov 0x98(%r12),%eax 5d7e: 00 5d7f: 01 d0 add %edx,%eax 5d81: 83 d0 00 adc $0x0,%eax 5d84: 41 89 84 24 98 00 00 mov %eax,0x98(%r12) 5d8b: 00 static __always_inline void __skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len, unsigned int off) { if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_block_sub(skb->csum, 5d8c: 48 8d 3c 31 lea (%rcx,%rsi,1),%rdi 5d90: e9 e1 fb ff ff jmpq 5976 5d95: e8 00 00 00 00 callq 5d9a 5d9a: 41 8b 94 24 c8 00 00 mov 0xc8(%r12),%edx 5da1: 00 5da2: 48 01 c8 add %rcx,%rax 5da5: 48 8d 70 14 lea 0x14(%rax),%rsi 5da9: 48 01 d1 add %rdx,%rcx 5dac: 48 39 ce cmp %rcx,%rsi 5daf: 0f 87 52 f8 ff ff ja 5607 5db5: 0f b6 70 01 movzbl 0x1(%rax),%esi 5db9: 0f b7 78 0a movzwl 0xa(%rax),%edi 5dbd: 89 f1 mov %esi,%ecx 5dbf: 83 c6 01 add $0x1,%esi 5dc2: 89 f2 mov %esi,%edx 5dc4: 83 e2 03 and $0x3,%edx drop: /* Consume bad packet */ kfree_skb(skb); return 0; } 5dc7: 40 80 e6 02 and $0x2,%sil static inline int INET_ECN_set_ce(struct sk_buff *skb) { switch (skb->protocol) { case cpu_to_be16(ETH_P_IP): if (skb_network_header(skb) + sizeof(struct iphdr) <= 5dcb: 0f 84 36 f8 ff ff je 5607 5dd1: 66 c1 c2 08 rol $0x8,%dx 5dd5: 31 f6 xor %esi,%esi 5dd7: 0f b7 d2 movzwl %dx,%edx 5dda: 8d 94 17 ff fb 00 00 lea 0xfbff(%rdi,%rdx,1),%edx 5de1: 81 fa fe ff 00 00 cmp $0xfffe,%edx } while (0) static inline int IP_ECN_set_ce(struct iphdr *iph) { u32 check = (__force u32)iph->check; u32 ecn = (iph->tos + 1) & INET_ECN_MASK; 5de7: 40 0f 97 c6 seta %sil (label) |= htonl(INET_ECN_ECT_0 << 20); \ } while (0) static inline int IP_ECN_set_ce(struct iphdr *iph) { u32 check = (__force u32)iph->check; 5deb: 83 c9 03 or $0x3,%ecx u32 ecn = (iph->tos + 1) & INET_ECN_MASK; 5dee: 01 f2 add %esi,%edx 5df0: 88 48 01 mov %cl,0x1(%rax) 5df3: 66 89 50 0a mov %dx,0xa(%rax) * INET_ECN_NOT_ECT => 01 * INET_ECN_ECT_1 => 10 * INET_ECN_ECT_0 => 11 * INET_ECN_CE => 00 */ if (!(ecn & 2)) 5df7: e9 0b f8 ff ff jmpq 5607 5dfc: e8 00 00 00 00 callq 5e01 /* * The following gives us: * INET_ECN_ECT_1 => check += htons(0xFFFD) * INET_ECN_ECT_0 => check += htons(0xFFFE) */ check += (__force u16)htons(0xFFFB) + (__force u16)htons(ecn); 5e01: 85 c0 test %eax,%eax 5e03: 0f 84 fe f7 ff ff je 5607 5e09: 41 be 01 00 00 00 mov $0x1,%r14d 5e0f: 41 0f b6 55 01 movzbl 0x1(%r13),%edx iph->check = (__force __sum16)(check + (check>=0xFFFF)); 5e14: 49 8d 75 0c lea 0xc(%r13),%rsi 5e18: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 5e1f: e8 00 00 00 00 callq 5e24 5e24: e9 be fc ff ff jmpq 5ae7 5e29: f0 48 ff 82 e8 01 00 lock incq 0x1e8(%rdx) 5e30: 00 err = IP6_ECN_decapsulate(oiph, skb); #endif if (unlikely(err) && log_ecn_error) { if (vxlan_get_sk_family(vs) == AF_INET) net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", 5e31: 4c 89 e7 mov %r12,%rdi 5e34: e8 00 00 00 00 callq 5e39 5e39: e9 5a f6 ff ff jmpq 5498 5e3e: 4c 89 e7 mov %r12,%rdi 5e41: 4c 89 54 24 08 mov %r10,0x8(%rsp) 5e46: 44 89 4c 24 20 mov %r9d,0x20(%rsp) 5e4b: 4c 89 44 24 10 mov %r8,0x10(%rsp) 5e50: e8 00 00 00 00 callq 5e55 5e55: 41 0f b6 84 24 91 00 movzbl 0x91(%r12),%eax 5e5c: 00 00 * * Atomically increments @v by 1. */ static __always_inline void atomic64_inc(atomic64_t *v) { asm volatile(LOCK_PREFIX "incq %0" 5e5e: 4c 8b 54 24 08 mov 0x8(%rsp),%r10 cell = this_cpu_ptr(gcells->cells); if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) { atomic_long_inc(&dev->rx_dropped); kfree_skb(skb); 5e63: 49 8b bc 24 d8 00 00 mov 0xd8(%r12),%rdi 5e6a: 00 5e6b: 4c 8b 44 24 10 mov 0x10(%rsp),%r8 skb_remcsum_adjust_partial(skb, ptr, start, offset); return; } if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { __skb_checksum_complete(skb); 5e70: 44 8b 4c 24 20 mov 0x20(%rsp),%r9d 5e75: 4c 89 d6 mov %r10,%rsi 5e78: 89 c2 mov %eax,%edx 5e7a: 48 29 fe sub %rdi,%rsi 5e7d: 83 e2 06 and $0x6,%edx 5e80: 80 fa 04 cmp $0x4,%dl 5e83: 74 3d je 5ec2 static __always_inline void __skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len, unsigned int off) { if (skb->ip_summed == CHECKSUM_COMPLETE) 5e85: 80 fa 06 cmp $0x6,%dl 5e88: 0f 85 58 f9 ff ff jne 57e6 return; } if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { __skb_checksum_complete(skb); skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data); 5e8e: 41 0f b7 94 24 98 00 movzwl 0x98(%r12),%edx 5e95: 00 00 5e97: 49 2b bc 24 d0 00 00 sub 0xd0(%r12),%rdi 5e9e: 00 static __always_inline void __skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len, unsigned int off) { if (skb->ip_summed == CHECKSUM_COMPLETE) 5e9f: 39 fa cmp %edi,%edx 5ea1: 0f 89 3f f9 ff ff jns 57e6 return; } if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE)) { __skb_checksum_complete(skb); skb_postpull_rcsum(skb, skb->data, ptr - (void *)skb->data); 5ea7: 83 e0 f9 and $0xfffffff9,%eax 5eaa: 41 88 84 24 91 00 00 mov %al,0x91(%r12) 5eb1: 00 static __always_inline void __skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len, unsigned int off) { if (skb->ip_summed == CHECKSUM_COMPLETE) 5eb2: e9 2f f9 ff ff jmpq 57e6 skb->csum = csum_block_sub(skb->csum, csum_partial(start, len, 0), off); else if (skb->ip_summed == CHECKSUM_PARTIAL && 5eb7: 41 be 02 00 00 00 mov $0x2,%r14d 5ebd: e9 4d ff ff ff jmpq 5e0f 5ec2: 31 d2 xor %edx,%edx 5ec4: e8 00 00 00 00 callq 5ec9 5ec9: 45 8b 9c 24 98 00 00 mov 0x98(%r12),%r11d 5ed0: 00 5ed1: f7 d0 not %eax 5ed3: 4c 8b 44 24 10 mov 0x10(%rsp),%r8 skb_checksum_start_offset(skb) < 0) skb->ip_summed = CHECKSUM_NONE; 5ed8: 41 01 c3 add %eax,%r11d 5edb: 41 83 d3 00 adc $0x0,%r11d 5edf: 44 8b 4c 24 20 mov 0x20(%rsp),%r9d 5ee4: 45 89 9c 24 98 00 00 mov %r11d,0x98(%r12) 5eeb: 00 return 0; case INET_ECN_ECT_0: case INET_ECN_ECT_1: return 1; case INET_ECN_CE: return 2; 5eec: 4c 8b 54 24 08 mov 0x8(%rsp),%r10 5ef1: e9 f8 f8 ff ff jmpq 57ee static __always_inline void __skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len, unsigned int off) { if (skb->ip_summed == CHECKSUM_COMPLETE) skb->csum = csum_block_sub(skb->csum, 5ef6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 5efd: 00 00 00 0000000000005f00 : 5f00: e8 00 00 00 00 callq 5f05 5f05: 55 push %rbp 5f06: 48 89 e5 mov %rsp,%rbp 5f09: 41 57 push %r15 5f0b: 41 56 push %r14 5f0d: 41 55 push %r13 5f0f: 41 54 push %r12 5f11: 49 89 f6 mov %rsi,%r14 5f14: 53 push %rbx 5f15: 48 89 fb mov %rdi,%rbx 5f18: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp 5f1c: 48 83 ec 60 sub $0x60,%rsp 5f20: 65 48 8b 04 25 28 00 mov %gs:0x28,%rax 5f27: 00 00 5f29: 48 89 44 24 58 mov %rax,0x58(%rsp) 5f2e: 31 c0 xor %eax,%eax * Outer IP header inherits ECN and DF from inner header. * Outer UDP destination is the VXLAN assigned port. * source port is based on hash of flow */ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) { 5f30: 48 8b 47 58 mov 0x58(%rdi),%rax 5f34: 48 83 e0 fe and $0xfffffffffffffffe,%rax 5f38: 0f 84 fc 04 00 00 je 643a 5f3e: f6 40 61 02 testb $0x2,0x61(%rax) 5f42: 0f 84 52 01 00 00 je 609a 5f48: 48 05 a0 00 00 00 add $0xa0,%rax 5f4e: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx 5f55: 48 8b 93 d8 00 00 00 mov 0xd8(%rbx),%rdx 5f5c: 48 29 ca sub %rcx,%rdx 5f5f: 66 89 93 c6 00 00 00 mov %dx,0xc6(%rbx) static inline struct metadata_dst *skb_metadata_dst(struct sk_buff *skb) { struct metadata_dst *md_dst = (struct metadata_dst *) skb_dst(skb); if (md_dst && md_dst->dst.flags & DST_METADATA) 5f66: 41 8b b6 d8 08 00 00 mov 0x8d8(%r14),%esi 5f6d: f7 c6 00 20 00 00 test $0x2000,%esi 5f73: 0f 85 e6 00 00 00 jne 605f { struct metadata_dst *md_dst = skb_metadata_dst(skb); struct dst_entry *dst; if (md_dst) return &md_dst->u.tun_info; 5f79: 83 e6 02 and $0x2,%esi 5f7c: 4d 8d ae 40 08 00 00 lea 0x840(%r14),%r13 return skb->mac_header != (typeof(skb->mac_header))~0U; } static inline void skb_reset_mac_header(struct sk_buff *skb) { skb->mac_header = skb->data - skb->head; 5f83: 74 20 je 5fa5 5f85: 0f b7 d2 movzwl %dx,%edx 5f88: 0f b7 44 11 0c movzwl 0xc(%rcx,%rdx,1),%eax 5f8d: 66 c1 c0 08 rol $0x8,%ax 5f91: 66 3d 06 08 cmp $0x806,%ax 5f95: 0f 84 cf 04 00 00 je 646a info = skb_tunnel_info(skb); skb_reset_mac_header(skb); if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { 5f9b: 66 3d dd 86 cmp $0x86dd,%ax 5f9f: 0f 84 77 02 00 00 je 621c 5fa5: 44 0f b7 bb c6 00 00 movzwl 0xc6(%rbx),%r15d 5fac: 00 * * Get network device private data */ static inline void *netdev_priv(const struct net_device *dev) { return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); 5fad: 4c 89 ef mov %r13,%rdi 5fb0: 49 01 cf add %rcx,%r15 else kfree_skb(skb); return NETDEV_TX_OK; } if (vxlan->flags & VXLAN_F_PROXY) { 5fb3: 4c 89 fe mov %r15,%rsi eth = eth_hdr(skb); if (ntohs(eth->h_proto) == ETH_P_ARP) 5fb6: e8 45 a0 ff ff callq 0 <__vxlan_find_mac> 5fbb: 48 85 c0 test %rax,%rax 5fbe: 49 89 c4 mov %rax,%r12 5fc1: 0f 84 24 02 00 00 je 61eb 5fc7: 41 80 7c 24 48 00 cmpb $0x0,0x48(%r12) return arp_reduce(dev, skb); #if IS_ENABLED(CONFIG_IPV6) else if (ntohs(eth->h_proto) == ETH_P_IPV6 && 5fcd: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 5fd4 5fd4: c6 44 24 18 00 movb $0x0,0x18(%rsp) skb->network_header += offset; } static inline unsigned char *skb_mac_header(const struct sk_buff *skb) { return skb->head + skb->mac_header; 5fd9: 49 89 44 24 28 mov %rax,0x28(%r12) static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 5fde: 0f 88 e0 00 00 00 js 60c4 5fe4: 49 8b 44 24 30 mov 0x30(%r12),%rax 5fe9: 49 83 c4 30 add $0x30,%r12 if (f) 5fed: 49 39 c4 cmp %rax,%r12 static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 5ff0: 4c 8d 78 d8 lea -0x28(%rax),%r15 if (f) 5ff4: 74 6f je 6065 5ff6: 0f b6 44 24 18 movzbl 0x18(%rsp),%eax eth = eth_hdr(skb); f = vxlan_find_mac(vxlan, eth->h_dest); did_rsc = false; if (f && (f->flags & NTF_ROUTER) && (vxlan->flags & VXLAN_F_RSC) && 5ffb: 4d 89 fd mov %r15,%r13 { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); if (f) f->used = jiffies; 5ffe: 89 44 24 20 mov %eax,0x20(%rsp) 6002: 49 8b 47 28 mov 0x28(%r15),%rax #endif } eth = eth_hdr(skb); f = vxlan_find_mac(vxlan, eth->h_dest); did_rsc = false; 6006: 49 39 c4 cmp %rax,%r12 { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); if (f) f->used = jiffies; 6009: 4c 8d 78 d8 lea -0x28(%rax),%r15 600d: 74 36 je 6045 eth = eth_hdr(skb); f = vxlan_find_mac(vxlan, eth->h_dest); did_rsc = false; if (f && (f->flags & NTF_ROUTER) && (vxlan->flags & VXLAN_F_RSC) && 600f: 4d 85 ed test %r13,%r13 6012: 74 7e je 6092 6014: be 20 00 08 02 mov $0x2080020,%esi kfree_skb(skb); return NETDEV_TX_OK; } } list_for_each_entry_rcu(rdst, &f->remotes, list) { 6019: 48 89 df mov %rbx,%rdi 601c: e8 00 00 00 00 callq 6021 6021: 48 85 c0 test %rax,%rax 6024: 74 dc je 6002 fdst = rdst; continue; } skb1 = skb_clone(skb, GFP_ATOMIC); if (skb1) vxlan_xmit_one(skb1, dev, rdst, did_rsc); 6026: 8b 4c 24 20 mov 0x20(%rsp),%ecx 602a: 4c 89 fa mov %r15,%rdx kfree_skb(skb); return NETDEV_TX_OK; } } list_for_each_entry_rcu(rdst, &f->remotes, list) { 602d: 48 89 c7 mov %rax,%rdi fdst = rdst; continue; } skb1 = skb_clone(skb, GFP_ATOMIC); if (skb1) vxlan_xmit_one(skb1, dev, rdst, did_rsc); 6030: 4c 89 f6 mov %r14,%rsi 6033: e8 e8 e1 ff ff callq 4220 kfree_skb(skb); return NETDEV_TX_OK; } } list_for_each_entry_rcu(rdst, &f->remotes, list) { 6038: 49 8b 47 28 mov 0x28(%r15),%rax 603c: 49 39 c4 cmp %rax,%r12 struct sk_buff *skb1; if (!fdst) { 603f: 4c 8d 78 d8 lea -0x28(%rax),%r15 6043: 75 ca jne 600f fdst = rdst; continue; } skb1 = skb_clone(skb, GFP_ATOMIC); 6045: 4d 85 ed test %r13,%r13 6048: 74 1b je 6065 604a: 0f b6 4c 24 18 movzbl 0x18(%rsp),%ecx 604f: 4c 89 ea mov %r13,%rdx if (skb1) 6052: 4c 89 f6 mov %r14,%rsi 6055: 48 89 df mov %rbx,%rdi vxlan_xmit_one(skb1, dev, rdst, did_rsc); 6058: e8 c3 e1 ff ff callq 4220 605d: eb 0e jmp 606d 605f: f6 40 49 01 testb $0x1,0x49(%rax) 6063: 75 4e jne 60b3 6065: 48 89 df mov %rbx,%rdi 6068: e8 00 00 00 00 callq 606d kfree_skb(skb); return NETDEV_TX_OK; } } list_for_each_entry_rcu(rdst, &f->remotes, list) { 606d: 31 c0 xor %eax,%eax 606f: 48 8b 4c 24 58 mov 0x58(%rsp),%rcx 6074: 65 48 33 0c 25 28 00 xor %gs:0x28,%rcx 607b: 00 00 if (skb1) vxlan_xmit_one(skb1, dev, rdst, did_rsc); } if (fdst) vxlan_xmit_one(skb, dev, fdst, did_rsc); 607d: 0f 85 52 08 00 00 jne 68d5 6083: 48 8d 65 d8 lea -0x28(%rbp),%rsp 6087: 5b pop %rbx 6088: 41 5c pop %r12 608a: 41 5d pop %r13 608c: 41 5e pop %r14 608e: 41 5f pop %r15 info = skb_tunnel_info(skb); skb_reset_mac_header(skb); if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { if (info && info->mode & IP_TUNNEL_INFO_TX) 6090: 5d pop %rbp 6091: c3 retq 6092: 4d 89 fd mov %r15,%r13 if ((vxlan->flags & VXLAN_F_L2MISS) && !is_multicast_ether_addr(eth->h_dest)) vxlan_fdb_miss(vxlan, eth->h_dest); dev->stats.tx_dropped++; kfree_skb(skb); 6095: e9 68 ff ff ff jmpq 6002 609a: 48 8b 80 90 00 00 00 mov 0x90(%rax),%rax if (fdst) vxlan_xmit_one(skb, dev, fdst, did_rsc); else kfree_skb(skb); return NETDEV_TX_OK; } 60a1: 48 85 c0 test %rax,%rax 60a4: 0f 84 90 03 00 00 je 643a 60aa: 48 83 c0 1c add $0x1c,%rax 60ae: e9 9b fe ff ff jmpq 5f4e 60b3: 31 c9 xor %ecx,%ecx 60b5: 31 d2 xor %edx,%edx 60b7: 4c 89 f6 mov %r14,%rsi 60ba: 48 89 df mov %rbx,%rdi 60bd: e8 5e e1 ff ff callq 4220 kfree_skb(skb); return NETDEV_TX_OK; } } list_for_each_entry_rcu(rdst, &f->remotes, list) { 60c2: eb a9 jmp 606d 60c4: 41 f6 86 d8 08 00 00 testb $0x4,0x8d8(%r14) 60cb: 04 dst = skb_dst(skb); if (dst && dst->lwtstate) 60cc: 0f 84 12 ff ff ff je 5fe4 60d2: 41 0f b7 47 0c movzwl 0xc(%r15),%eax 60d7: 66 c1 c0 08 rol $0x8,%ax info->options_len = len; } static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate) { return (struct ip_tunnel_info *)lwtstate->data; 60db: 66 3d 00 08 cmp $0x800,%ax 60df: 74 0a je 60eb 60e1: 66 3d dd 86 cmp $0x86dd,%ax skb_reset_mac_header(skb); if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { if (info && info->mode & IP_TUNNEL_INFO_TX) vxlan_xmit_one(skb, dev, NULL, false); 60e5: 0f 85 f9 fe ff ff jne 5fe4 60eb: 0f b7 83 c6 00 00 00 movzwl 0xc6(%rbx),%eax 60f2: 48 8b 93 d0 00 00 00 mov 0xd0(%rbx),%rdx eth = eth_hdr(skb); f = vxlan_find_mac(vxlan, eth->h_dest); did_rsc = false; if (f && (f->flags & NTF_ROUTER) && (vxlan->flags & VXLAN_F_RSC) && 60f9: 48 01 d0 add %rdx,%rax 60fc: f6 00 01 testb $0x1,(%rax) 60ff: 0f 85 f2 05 00 00 jne 66f7 (ntohs(eth->h_proto) == ETH_P_IP || 6105: 0f b7 40 0c movzwl 0xc(%rax),%eax 6109: 66 c1 c0 08 rol $0x8,%ax eth = eth_hdr(skb); f = vxlan_find_mac(vxlan, eth->h_dest); did_rsc = false; if (f && (f->flags & NTF_ROUTER) && (vxlan->flags & VXLAN_F_RSC) && 610d: 66 3d 00 08 cmp $0x800,%ax 6111: 0f 84 66 05 00 00 je 667d 6117: 66 3d dd 86 cmp $0x86dd,%ax 611b: 0f 85 d6 05 00 00 jne 66f7 6121: 8b 8b 80 00 00 00 mov 0x80(%rbx),%ecx 6127: 89 c8 mov %ecx,%eax 6129: 2b 83 84 00 00 00 sub 0x84(%rbx),%eax static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb) { struct vxlan_dev *vxlan = netdev_priv(dev); struct neighbour *n; if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) 612f: 83 f8 27 cmp $0x27,%eax 6132: 0f 86 39 07 00 00 jbe 6871 return false; n = NULL; switch (ntohs(eth_hdr(skb)->h_proto)) { 6138: 44 0f b7 83 c4 00 00 movzwl 0xc4(%rbx),%r8d 613f: 00 6140: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 6147 6147: 48 8b 78 28 mov 0x28(%rax),%rdi 614b: 49 01 d0 add %rdx,%r8 614e: 4c 89 f2 mov %r14,%rdx 6151: 49 8d 70 18 lea 0x18(%r8),%rsi 6155: 4c 89 44 24 20 mov %r8,0x20(%rsp) return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 615a: e8 00 00 00 00 callq 615f return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 615f: 48 85 c0 test %rax,%rax 6162: 4c 8b 44 24 20 mov 0x20(%rsp),%r8 6167: 0f 84 8a 0a 00 00 je 6bf7 skb->transport_header += offset; } static inline unsigned char *skb_network_header(const struct sk_buff *skb) { return skb->head + skb->network_header; 616d: 0f b7 bb c6 00 00 00 movzwl 0xc6(%rbx),%edi struct ipv6hdr *pip6; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) return false; pip6 = ipv6_hdr(skb); n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev); 6174: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx 617b: 44 8b 80 b8 00 00 00 mov 0xb8(%rax),%r8d 6182: 48 8d 34 39 lea (%rcx,%rdi,1),%rsi 6186: 0f b7 56 04 movzwl 0x4(%rsi),%edx 618a: 44 8b 0e mov (%rsi),%r9d 618d: 66 33 90 bc 00 00 00 xor 0xbc(%rax),%dx if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { 6194: 45 31 c8 xor %r9d,%r8d 6197: 0f b7 d2 movzwl %dx,%edx 619a: 41 09 d0 or %edx,%r8d skb->network_header += offset; } static inline unsigned char *skb_mac_header(const struct sk_buff *skb) { return skb->head + skb->mac_header; 619d: 44 89 44 24 20 mov %r8d,0x20(%rsp) 61a2: 0f 85 e1 05 00 00 jne 6789 61a8: f0 ff 48 30 lock decl 0x30(%rax) * Please note: addr1 & addr2 must both be aligned to u16. */ static inline bool ether_addr_equal(const u8 *addr1, const u8 *addr2) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) u32 fold = ((*(const u32 *)addr1) ^ (*(const u32 *)addr2)) | 61ac: 0f 84 ca 05 00 00 je 677c 61b2: 8b 44 24 20 mov 0x20(%rsp),%eax 61b6: 85 c0 test %eax,%eax 61b8: 0f 84 39 05 00 00 je 66f7 61be: 4c 89 fe mov %r15,%rsi 61c1: 4c 89 ef mov %r13,%rdi 61c4: e8 37 9e ff ff callq 0 <__vxlan_find_mac> 61c9: 48 85 c0 test %rax,%rax if (n) { bool diff; diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha); if (diff) { 61cc: 49 89 c4 mov %rax,%r12 61cf: 0f 84 f6 06 00 00 je 68cb 61d5: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 61dc * returns true if the result is 0, or false for all other * cases. */ static __always_inline bool atomic_dec_and_test(atomic_t *v) { GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", e); 61dc: c6 44 24 18 01 movb $0x1,0x18(%rsp) 61e1: 49 89 44 24 28 mov %rax,0x28(%r12) if (f && (f->flags & NTF_ROUTER) && (vxlan->flags & VXLAN_F_RSC) && (ntohs(eth->h_proto) == ETH_P_IP || ntohs(eth->h_proto) == ETH_P_IPV6)) { did_rsc = route_shortcircuit(dev, skb); if (did_rsc) 61e6: e9 f9 fd ff ff jmpq 5fe4 61eb: c6 44 24 18 00 movb $0x0,0x18(%rsp) static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 61f0: 48 c7 c6 00 00 00 00 mov $0x0,%rsi 61f7: 4c 89 ef mov %r13,%rdi if (f) 61fa: e8 01 9e ff ff callq 0 <__vxlan_find_mac> 61ff: 48 85 c0 test %rax,%rax 6202: 49 89 c4 mov %rax,%r12 f->used = jiffies; 6205: 0f 84 f6 04 00 00 je 6701 620b: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 6212 6212: 49 89 44 24 28 mov %rax,0x28(%r12) 6217: e9 c8 fd ff ff jmpq 5fe4 #endif } eth = eth_hdr(skb); f = vxlan_find_mac(vxlan, eth->h_dest); did_rsc = false; 621c: 8b 93 80 00 00 00 mov 0x80(%rbx),%edx static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 6222: 89 d0 mov %edx,%eax 6224: 2b 83 84 00 00 00 sub 0x84(%rbx),%eax 622a: 83 f8 3f cmp $0x3f,%eax 622d: 0f 86 f6 04 00 00 jbe 6729 6233: 0f b7 83 c4 00 00 00 movzwl 0xc4(%rbx),%eax if (f) 623a: 48 01 c8 add %rcx,%rax f->used = jiffies; 623d: 80 78 06 3a cmpb $0x3a,0x6(%rax) 6241: 0f 85 5e fd ff ff jne 5fa5 6247: 44 0f b7 a3 c2 00 00 movzwl 0xc2(%rbx),%r12d 624e: 00 624f: 49 01 cc add %rcx,%r12 return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 6252: 66 41 81 3c 24 87 00 cmpw $0x87,(%r12) 6259: 0f 85 46 fd ff ff jne 5fa5 return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 625f: 49 8b 96 08 03 00 00 mov 0x308(%r14),%rdx skb->transport_header += offset; } static inline unsigned char *skb_network_header(const struct sk_buff *skb) { return skb->head + skb->network_header; 6266: 48 85 d2 test %rdx,%rdx 6269: 0f 84 f8 03 00 00 je 6667 if (ntohs(eth->h_proto) == ETH_P_ARP) return arp_reduce(dev, skb); #if IS_ENABLED(CONFIG_IPV6) else if (ntohs(eth->h_proto) == ETH_P_IPV6 && pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg)) && 626f: 48 ba 00 00 00 00 00 movabs $0x100000000000000,%rdx 6276: 00 00 01 return skb->transport_header != (typeof(skb->transport_header))~0U; } static inline unsigned char *skb_transport_header(const struct sk_buff *skb) { return skb->head + skb->transport_header; 6279: 48 33 50 20 xor 0x20(%rax),%rdx 627d: 48 0b 50 18 or 0x18(%rax),%rdx 6281: 0f 84 e0 03 00 00 je 6667 ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) { struct nd_msg *msg; msg = (struct nd_msg *)skb_transport_header(skb); if (msg->icmph.icmp6_code == 0 && 6287: 41 0f b6 44 24 08 movzbl 0x8(%r12),%eax 628d: 3d ff 00 00 00 cmp $0xff,%eax 6292: 0f 84 cf 03 00 00 je 6667 const struct in6_addr *saddr, *daddr; struct neighbour *n; struct inet6_dev *in6_dev; in6_dev = __in6_dev_get(dev); if (!in6_dev) 6298: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # 629f msg = (struct nd_msg *)skb_transport_header(skb); if (msg->icmph.icmp6_code != 0 || msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) goto out; if (ipv6_addr_loopback(daddr) || 629f: 49 8d 74 24 08 lea 0x8(%r12),%rsi 62a4: 4c 89 f2 mov %r14,%rdx 62a7: 48 8b 78 28 mov 0x28(%rax),%rdi 62ab: e8 00 00 00 00 callq 62b0 62b0: 48 85 c0 test %rax,%rax 62b3: 49 89 c7 mov %rax,%r15 62b6: 0f 84 3b 06 00 00 je 68f7 62bc: f6 80 ad 00 00 00 c2 testb $0xc2,0xad(%rax) 62c3: 0f 84 21 06 00 00 je 68ea ipv6_addr_is_multicast(&msg->target)) goto out; n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev); 62c9: 48 8d b0 b8 00 00 00 lea 0xb8(%rax),%rsi 62d0: 4c 89 ef mov %r13,%rdi 62d3: e8 28 9d ff ff callq 0 <__vxlan_find_mac> 62d8: 48 85 c0 test %rax,%rax 62db: 0f 84 e7 08 00 00 je 6bc8 if (n) { 62e1: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # 62e8 62e8: 48 89 50 28 mov %rdx,0x28(%rax) struct vxlan_fdb *f; struct sk_buff *reply; if (!(n->nud_state & NUD_CONNECTED)) { 62ec: 48 8b 50 30 mov 0x30(%rax),%rdx 62f0: 66 83 7a d8 0a cmpw $0xa,-0x28(%rdx) 62f5: 0f 84 bd 08 00 00 je 6bb8 neigh_release(n); goto out; } f = vxlan_find_mac(vxlan, n->ha); 62fb: 83 7a dc 00 cmpl $0x0,-0x24(%rdx) 62ff: 0f 94 c2 sete %dl static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 6302: 84 d2 test %dl,%dl 6304: 0f 85 e0 05 00 00 jne 68ea if (f) 630a: 0f be 40 48 movsbl 0x48(%rax),%eax 630e: c1 e8 1f shr $0x1f,%eax f->used = jiffies; 6311: 4c 8b 6b 20 mov 0x20(%rbx),%r13 6315: 83 e0 01 and $0x1,%eax 6318: 88 44 24 20 mov %al,0x20(%rsp) 631c: 4d 85 ed test %r13,%r13 631f: 0f 84 c5 05 00 00 je 68ea return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 6325: 41 0f b7 95 4e 02 00 movzwl 0x24e(%r13),%edx 632c: 00 return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); 632d: 41 0f b7 85 50 02 00 movzwl 0x250(%r13),%eax 6334: 00 neigh_release(n); goto out; } f = vxlan_find_mac(vxlan, n->ha); if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) { 6335: 83 c9 ff or $0xffffffff,%ecx 6338: be 20 00 08 02 mov $0x2080020,%esi neigh_release(n); goto out; } reply = vxlan_na_create(skb, n, !!(f ? f->flags & NTF_ROUTER : 0)); 633d: 01 d0 add %edx,%eax 633f: 41 0f b7 95 52 02 00 movzwl 0x252(%r13),%edx 6346: 00 #if IS_ENABLED(CONFIG_IPV6) static struct sk_buff *vxlan_na_create(struct sk_buff *request, struct neighbour *n, bool isrouter) { struct net_device *dev = request->dev; 6347: 83 e0 f0 and $0xfffffff0,%eax 634a: 8d 7c 10 58 lea 0x58(%rax,%rdx,1),%edi u8 *daddr; int na_olen = 8; /* opt hdr + ETH_ALEN for target */ int ns_olen; int i, len; if (dev == NULL) 634e: 31 d2 xor %edx,%edx 6350: e8 00 00 00 00 callq 6355 struct sk_buff *__build_skb(void *data, unsigned int frag_size); struct sk_buff *build_skb(void *data, unsigned int frag_size); static inline struct sk_buff *alloc_skb(unsigned int size, gfp_t priority) { return __alloc_skb(size, priority, 0, NUMA_NO_NODE); 6355: 48 85 c0 test %rax,%rax 6358: 49 89 c4 mov %rax,%r12 635b: 0f 84 89 05 00 00 je 68ea 6361: 66 c7 80 c0 00 00 00 movw $0xdd86,0xc0(%rax) 6368: 86 dd 636a: 4c 89 68 20 mov %r13,0x20(%rax) 636e: be 0e 00 00 00 mov $0xe,%esi 6373: 48 8b 53 20 mov 0x20(%rbx),%rdx 6377: 4c 89 e7 mov %r12,%rdi 637a: 0f b7 8a 4e 02 00 00 movzwl 0x24e(%rdx),%ecx 6381: 0f b7 82 50 02 00 00 movzwl 0x250(%rdx),%eax 6388: 01 c8 add %ecx,%eax 638a: 83 e0 f0 and $0xfffffff0,%eax return NULL; len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) + sizeof(*na) + na_olen + dev->needed_tailroom; reply = alloc_skb(len, GFP_ATOMIC); if (reply == NULL) 638d: 83 c0 10 add $0x10,%eax 6390: 41 01 84 24 c8 00 00 add %eax,0xc8(%r12) 6397: 00 return NULL; reply->protocol = htons(ETH_P_IPV6); 6398: 48 63 d0 movslq %eax,%rdx reply->dev = dev; 639b: 49 01 94 24 d8 00 00 add %rdx,0xd8(%r12) 63a2: 00 skb_reserve(reply, LL_RESERVED_SPACE(request->dev)); 63a3: e8 00 00 00 00 callq 63a8 skb_push(reply, sizeof(struct ethhdr)); 63a8: 49 8b 84 24 d0 00 00 mov 0xd0(%r12),%rax 63af: 00 if (reply == NULL) return NULL; reply->protocol = htons(ETH_P_IPV6); reply->dev = dev; skb_reserve(reply, LL_RESERVED_SPACE(request->dev)); 63b0: 49 8b 8c 24 d8 00 00 mov 0xd8(%r12),%rcx 63b7: 00 63b8: 48 29 c1 sub %rax,%rcx 63bb: 66 41 89 8c 24 c6 00 mov %cx,0xc6(%r12) 63c2: 00 00 * room. This is only allowed for an empty buffer. */ static inline void skb_reserve(struct sk_buff *skb, int len) { skb->data += len; skb->tail += len; 63c4: 0f b7 93 c2 00 00 00 movzwl 0xc2(%rbx),%edx * Increase the headroom of an empty &sk_buff by reducing the tail * room. This is only allowed for an empty buffer. */ static inline void skb_reserve(struct sk_buff *skb, int len) { skb->data += len; 63cb: 48 8b b3 d0 00 00 00 mov 0xd0(%rbx),%rsi 63d2: 0f b7 bb c6 00 00 00 movzwl 0xc6(%rbx),%edi return skb->mac_header != (typeof(skb->mac_header))~0U; } static inline void skb_reset_mac_header(struct sk_buff *skb) { skb->mac_header = skb->data - skb->head; 63d9: 44 8b 9b 80 00 00 00 mov 0x80(%rbx),%r11d 63e0: 48 01 f2 add %rsi,%rdx 63e3: 48 8d 7c 3e 06 lea 0x6(%rsi,%rdi,1),%rdi 63e8: 48 89 d6 mov %rdx,%rsi 63eb: 48 2b b3 d8 00 00 00 sub 0xd8(%rbx),%rsi 63f2: 41 29 f3 sub %esi,%r11d return skb->transport_header != (typeof(skb->transport_header))~0U; } static inline unsigned char *skb_transport_header(const struct sk_buff *skb) { return skb->head + skb->transport_header; 63f5: 45 8d 53 e7 lea -0x19(%r11),%r10d 63f9: 45 85 d2 test %r10d,%r10d 63fc: 0f 8e 46 05 00 00 jle 6948 skb_push(reply, sizeof(struct ethhdr)); skb_reset_mac_header(reply); ns = (struct nd_msg *)skb_transport_header(request); daddr = eth_hdr(request)->h_source; 6402: 80 7a 18 01 cmpb $0x1,0x18(%rdx) 6406: 0f 84 34 05 00 00 je 6940 ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns); for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) { 640c: 31 f6 xor %esi,%esi 640e: eb 0f jmp 641f 6410: 4c 63 c6 movslq %esi,%r8 skb_push(reply, sizeof(struct ethhdr)); skb_reset_mac_header(reply); ns = (struct nd_msg *)skb_transport_header(request); daddr = eth_hdr(request)->h_source; 6413: 42 80 7c 02 18 01 cmpb $0x1,0x18(%rdx,%r8,1) ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns); for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) { 6419: 0f 84 24 05 00 00 je 6943 641f: 44 8d 46 01 lea 0x1(%rsi),%r8d 6423: 4d 63 c0 movslq %r8d,%r8 6426: 46 0f b6 44 02 18 movzbl 0x18(%rdx,%r8,1),%r8d 642c: 42 8d 34 c6 lea (%rsi,%r8,8),%esi 6430: 44 39 d6 cmp %r10d,%esi if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) { 6433: 7c db jl 6410 6435: e9 0e 05 00 00 jmpq 6948 643a: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx 6441: 48 8b 93 d8 00 00 00 mov 0xd8(%rbx),%rdx 6448: 48 29 ca sub %rcx,%rdx 644b: 66 89 93 c6 00 00 00 mov %dx,0xc6(%rbx) ns = (struct nd_msg *)skb_transport_header(request); daddr = eth_hdr(request)->h_source; ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns); for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) { 6452: 41 8b b6 d8 08 00 00 mov 0x8d8(%r14),%esi 6459: f7 c6 00 20 00 00 test $0x2000,%esi 645f: 0f 85 00 fc ff ff jne 6065 6465: e9 0f fb ff ff jmpq 5f79 return skb->mac_header != (typeof(skb->mac_header))~0U; } static inline void skb_reset_mac_header(struct sk_buff *skb) { skb->mac_header = skb->data - skb->head; 646a: 41 f6 86 38 02 00 00 testb $0x80,0x238(%r14) 6471: 80 6472: 0f 85 ef 01 00 00 jne 6667 6478: 66 41 83 be 4c 02 00 cmpw $0x18,0x24c(%r14) 647f: 00 18 6481: 41 0f b6 86 75 02 00 movzbl 0x275(%r14),%eax 6488: 00 info = skb_tunnel_info(skb); skb_reset_mac_header(skb); if (vxlan->flags & VXLAN_F_COLLECT_METADATA) { 6489: 0f 85 e5 01 00 00 jne 6674 648f: 83 c0 10 add $0x10,%eax 6492: 8b b3 80 00 00 00 mov 0x80(%rbx),%esi 6498: 89 f2 mov %esi,%edx struct arphdr *parp; u8 *arpptr, *sha; __be32 sip, tip; struct neighbour *n; if (dev->flags & IFF_NOARP) 649a: 2b 93 84 00 00 00 sub 0x84(%rbx),%edx 64a0: 39 d0 cmp %edx,%eax 64a2: 0f 87 ae 02 00 00 ja 6756 return (struct arphdr *)skb_network_header(skb); } static inline int arp_hdr_len(struct net_device *dev) { switch (dev->type) { 64a8: 0f b7 83 c4 00 00 00 movzwl 0xc4(%rbx),%eax 64af: 48 01 c1 add %rax,%rcx 64b2: 0f b7 01 movzwl (%rcx),%eax 64b5: 66 3d 00 01 cmp $0x100,%ax 64b9: 74 0a je 64c5 64bb: 66 3d 00 06 cmp $0x600,%ax #if IS_ENABLED(CONFIG_FIREWIRE_NET) case ARPHRD_IEEE1394: /* ARP header, device address and 2 IP addresses */ return sizeof(struct arphdr) + dev->addr_len + sizeof(u32) * 2; 64bf: 0f 85 a2 01 00 00 jne 6667 64c5: 66 83 79 02 08 cmpw $0x8,0x2(%rcx) return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 64ca: 0f 85 97 01 00 00 jne 6667 return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 64d0: 66 81 79 06 00 01 cmpw $0x100,0x6(%rcx) 64d6: 0f 85 8b 01 00 00 jne 6667 skb->transport_header += offset; } static inline unsigned char *skb_network_header(const struct sk_buff *skb) { return skb->head + skb->network_header; 64dc: 0f b6 41 04 movzbl 0x4(%rcx),%eax 64e0: 41 3a 86 75 02 00 00 cmp 0x275(%r14),%al dev->stats.tx_dropped++; goto out; } parp = arp_hdr(skb); if ((parp->ar_hrd != htons(ARPHRD_ETHER) && 64e7: 0f 85 7a 01 00 00 jne 6667 64ed: 80 79 05 04 cmpb $0x4,0x5(%rcx) 64f1: 0f 85 70 01 00 00 jne 6667 parp->ar_hrd != htons(ARPHRD_IEEE802)) || 64f7: 4c 8d 61 08 lea 0x8(%rcx),%r12 64fb: 49 8d 14 04 lea (%r12,%rax,1),%rdx 64ff: 8b 44 02 04 mov 0x4(%rdx,%rax,1),%eax parp->ar_pro != htons(ETH_P_IP) || 6503: 8b 0a mov (%rdx),%ecx 6505: 3c 7f cmp $0x7f,%al 6507: 89 4c 24 20 mov %ecx,0x20(%rsp) 650b: 89 44 24 2c mov %eax,0x2c(%rsp) parp->ar_op != htons(ARPOP_REQUEST) || parp->ar_hln != dev->addr_len || 650f: 0f 84 52 01 00 00 je 6667 parp = arp_hdr(skb); if ((parp->ar_hrd != htons(ARPHRD_ETHER) && parp->ar_hrd != htons(ARPHRD_IEEE802)) || parp->ar_pro != htons(ETH_P_IP) || parp->ar_op != htons(ARPOP_REQUEST) || 6515: 25 f0 00 00 00 and $0xf0,%eax 651a: 3d e0 00 00 00 cmp $0xe0,%eax parp->ar_hln != dev->addr_len || 651f: 0f 84 42 01 00 00 je 6667 6525: 48 8d 74 24 2c lea 0x2c(%rsp),%rsi parp->ar_pln != 4) goto out; arpptr = (u8 *)parp + sizeof(struct arphdr); 652a: 4c 89 f2 mov %r14,%rdx sha = arpptr; arpptr += dev->addr_len; /* sha */ 652d: 48 c7 c7 00 00 00 00 mov $0x0,%rdi memcpy(&sip, arpptr, sizeof(sip)); 6534: e8 00 00 00 00 callq 6539 6539: 48 85 c0 test %rax,%rax arpptr += sizeof(sip); arpptr += dev->addr_len; /* tha */ memcpy(&tip, arpptr, sizeof(tip)); 653c: 49 89 c7 mov %rax,%r15 if (ipv4_is_loopback(tip) || 653f: 0f 84 f7 06 00 00 je 6c3c 6545: f6 80 ad 00 00 00 c2 testb $0xc2,0xad(%rax) 654c: 0f 84 98 03 00 00 je 68ea 6552: 48 8d 90 b8 00 00 00 lea 0xb8(%rax),%rdx ipv4_is_multicast(tip)) goto out; n = neigh_lookup(&arp_tbl, &tip, dev); 6559: 4c 89 ef mov %r13,%rdi 655c: 48 89 d6 mov %rdx,%rsi 655f: 48 89 54 24 18 mov %rdx,0x18(%rsp) 6564: e8 97 9a ff ff callq 0 <__vxlan_find_mac> if (n) { 6569: 48 85 c0 test %rax,%rax if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) goto out; n = neigh_lookup(&arp_tbl, &tip, dev); 656c: 48 8b 54 24 18 mov 0x18(%rsp),%rdx if (n) { 6571: 74 29 je 659c 6573: 48 8b 0d 00 00 00 00 mov 0x0(%rip),%rcx # 657a struct vxlan_fdb *f; struct sk_buff *reply; if (!(n->nud_state & NUD_CONNECTED)) { 657a: 48 89 48 28 mov %rcx,0x28(%rax) 657e: 48 8b 40 30 mov 0x30(%rax),%rax neigh_release(n); goto out; } f = vxlan_find_mac(vxlan, n->ha); 6582: 66 83 78 d8 0a cmpw $0xa,-0x28(%rax) 6587: 0f 84 4d 03 00 00 je 68da static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); 658d: 83 78 dc 00 cmpl $0x0,-0x24(%rax) 6591: 0f 94 c0 sete %al 6594: 84 c0 test %al,%al 6596: 0f 85 4e 03 00 00 jne 68ea if (f) 659c: 48 89 14 24 mov %rdx,(%rsp) 65a0: 44 8b 44 24 2c mov 0x2c(%rsp),%r8d f->used = jiffies; 65a5: 4d 89 e1 mov %r12,%r9 65a8: 8b 54 24 20 mov 0x20(%rsp),%edx 65ac: 4c 89 64 24 08 mov %r12,0x8(%rsp) 65b1: 4c 89 f1 mov %r14,%rcx return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr; } static inline bool vxlan_addr_any(const union vxlan_addr *ipa) { if (ipa->sa.sa_family == AF_INET6) 65b4: be 06 08 00 00 mov $0x806,%esi 65b9: bf 02 00 00 00 mov $0x2,%edi return ipv6_addr_any(&ipa->sin6.sin6_addr); else return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY); 65be: e8 00 00 00 00 callq 65c3 65c3: 4c 89 ff mov %r15,%rdi neigh_release(n); goto out; } f = vxlan_find_mac(vxlan, n->ha); if (f && vxlan_addr_any(&(first_remote_rcu(f)->remote_ip))) { 65c6: 49 89 c4 mov %rax,%r12 65c9: e8 72 a2 ff ff callq 840 /* bridge-local neighbor */ neigh_release(n); goto out; } reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, 65ce: 4d 85 e4 test %r12,%r12 65d1: 0f 84 90 00 00 00 je 6667 65d7: 49 8b 8c 24 d8 00 00 mov 0xd8(%r12),%rcx 65de: 00 65df: 49 8b 84 24 d0 00 00 mov 0xd0(%r12),%rax 65e6: 00 65e7: 48 89 ca mov %rcx,%rdx 65ea: 48 29 c2 sub %rax,%rdx 65ed: 66 41 89 94 24 c6 00 mov %dx,0xc6(%r12) 65f4: 00 00 65f6: 41 0f b7 94 24 c4 00 movzwl 0xc4(%r12),%edx 65fd: 00 00 n->ha, sha); neigh_release(n); if (reply == NULL) 65ff: 48 01 d0 add %rdx,%rax 6602: 41 8b 94 24 80 00 00 mov 0x80(%r12),%edx 6609: 00 return skb->mac_header != (typeof(skb->mac_header))~0U; } static inline void skb_reset_mac_header(struct sk_buff *skb) { skb->mac_header = skb->data - skb->head; 660a: 48 29 c8 sub %rcx,%rax 660d: 29 c2 sub %eax,%edx 660f: 41 3b 94 24 84 00 00 cmp 0x84(%r12),%edx 6616: 00 6617: 41 89 94 24 80 00 00 mov %edx,0x80(%r12) 661e: 00 661f: 0f 82 54 05 00 00 jb 6b79 6625: 89 c0 mov %eax,%eax return skb->inner_transport_header - skb->inner_network_header; } static inline int skb_network_offset(const struct sk_buff *skb) { return skb_network_header(skb) - skb->data; 6627: 41 80 a4 24 90 00 00 andb $0xf8,0x90(%r12) 662e: 00 f8 6630: 4c 89 e7 mov %r12,%rdi } unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) { skb->len -= len; 6633: 48 01 c8 add %rcx,%rax 6636: 49 89 84 24 d8 00 00 mov %rax,0xd8(%r12) 663d: 00 663e: 41 0f b6 84 24 91 00 movzbl 0x91(%r12),%eax 6645: 00 00 6647: 83 e0 f9 and $0xfffffff9,%eax 664a: 83 c8 02 or $0x2,%eax 664d: 41 88 84 24 91 00 00 mov %al,0x91(%r12) 6654: 00 BUG_ON(skb->len < skb->data_len); return skb->data += len; 6655: e8 00 00 00 00 callq 665a goto out; skb_reset_mac_header(reply); __skb_pull(reply, skb_network_offset(reply)); reply->ip_summed = CHECKSUM_UNNECESSARY; reply->pkt_type = PACKET_HOST; 665a: 83 e8 01 sub $0x1,%eax 665d: 75 08 jne 6667 665f: 49 83 86 60 01 00 00 addq $0x1,0x160(%r14) 6666: 01 6667: 48 89 df mov %rbx,%rdi 666a: e8 00 00 00 00 callq 666f if (reply == NULL) goto out; skb_reset_mac_header(reply); __skb_pull(reply, skb_network_offset(reply)); reply->ip_summed = CHECKSUM_UNNECESSARY; 666f: e9 f9 f9 ff ff jmpq 606d 6674: 8d 44 00 10 lea 0x10(%rax,%rax,1),%eax 6678: e9 15 fe ff ff jmpq 6492 667d: 8b 8b 80 00 00 00 mov 0x80(%rbx),%ecx 6683: 89 c8 mov %ecx,%eax reply->pkt_type = PACKET_HOST; if (netif_rx_ni(reply) == NET_RX_DROP) 6685: 2b 83 84 00 00 00 sub 0x84(%rbx),%eax 668b: 83 f8 13 cmp $0x13,%eax 668e: 0f 86 0a 02 00 00 jbe 689e if (reply == NULL) goto out; if (netif_rx_ni(reply) == NET_RX_DROP) dev->stats.rx_dropped++; 6694: 44 0f b7 83 c4 00 00 movzwl 0xc4(%rbx),%r8d 669b: 00 vxlan_ip_miss(dev, &ipa); } out: consume_skb(skb); 669c: 48 c7 c7 00 00 00 00 mov $0x0,%rdi struct nd_msg *msg; msg = (struct nd_msg *)skb_transport_header(skb); if (msg->icmph.icmp6_code == 0 && msg->icmph.icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) return neigh_reduce(dev, skb); 66a3: 49 01 d0 add %rdx,%r8 #endif default: /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2; 66a6: 4c 89 f2 mov %r14,%rdx 66a9: 49 8d 70 10 lea 0x10(%r8),%rsi 66ad: 4c 89 44 24 20 mov %r8,0x20(%rsp) 66b2: e8 00 00 00 00 callq 66b7 return skb->data_len; } static inline unsigned int skb_headlen(const struct sk_buff *skb) { return skb->len - skb->data_len; 66b7: 48 85 c0 test %rax,%rax 66ba: 4c 8b 44 24 20 mov 0x20(%rsp),%r8 return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); } static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) 66bf: 0f 85 a8 fa ff ff jne 616d skb->transport_header += offset; } static inline unsigned char *skb_network_header(const struct sk_buff *skb) { return skb->head + skb->network_header; 66c5: 41 f6 86 d8 08 00 00 testb $0x10,0x8d8(%r14) 66cc: 10 struct iphdr *pip; if (!pskb_may_pull(skb, sizeof(struct iphdr))) return false; pip = ip_hdr(skb); n = neigh_lookup(&arp_tbl, &pip->daddr, dev); 66cd: 74 28 je 66f7 66cf: 48 8d 7c 24 30 lea 0x30(%rsp),%rdi 66d4: b9 07 00 00 00 mov $0x7,%ecx 66d9: 48 8d 74 24 30 lea 0x30(%rsp),%rsi 66de: f3 ab rep stos %eax,%es:(%rdi) 66e0: 66 c7 44 24 30 02 00 movw $0x2,0x30(%rsp) if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { 66e7: 4c 89 f7 mov %r14,%rdi 66ea: 41 8b 40 10 mov 0x10(%r8),%eax 66ee: 89 44 24 34 mov %eax,0x34(%rsp) 66f2: e8 59 b9 ff ff callq 2050 66f7: c6 44 24 18 00 movb $0x0,0x18(%rsp) 66fc: e9 e3 f8 ff ff jmpq 5fe4 union vxlan_addr ipa = { 6701: 41 f6 86 d8 08 00 00 testb $0x8,0x8d8(%r14) 6708: 08 .sin.sin_addr.s_addr = pip->daddr, .sin.sin_family = AF_INET, }; vxlan_ip_miss(dev, &ipa); 6709: 74 11 je 671c 670b: 41 f6 07 01 testb $0x1,(%r15) if (!pskb_may_pull(skb, sizeof(struct iphdr))) return false; pip = ip_hdr(skb); n = neigh_lookup(&arp_tbl, &pip->daddr, dev); if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { union vxlan_addr ipa = { 670f: 75 0b jne 671c 6711: 4c 89 fe mov %r15,%rsi 6714: 4c 89 ef mov %r13,%rdi .sin.sin_addr.s_addr = pip->daddr, .sin.sin_family = AF_INET, }; vxlan_ip_miss(dev, &ipa); 6717: e8 e4 b9 ff ff callq 2100 if (!pskb_may_pull(skb, sizeof(struct iphdr))) return false; pip = ip_hdr(skb); n = neigh_lookup(&arp_tbl, &pip->daddr, dev); if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { union vxlan_addr ipa = { 671c: 49 83 86 68 01 00 00 addq $0x1,0x168(%r14) 6723: 01 .sin.sin_addr.s_addr = pip->daddr, .sin.sin_family = AF_INET, }; vxlan_ip_miss(dev, &ipa); 6724: e9 3c f9 ff ff jmpq 6065 6729: 83 fa 3f cmp $0x3f,%edx 672c: 0f 86 73 f8 ff ff jbe 5fa5 } if (f == NULL) { f = vxlan_find_mac(vxlan, all_zeros_mac); if (f == NULL) { if ((vxlan->flags & VXLAN_F_L2MISS) && 6732: be 40 00 00 00 mov $0x40,%esi 6737: 48 89 df mov %rbx,%rdi 673a: 29 c6 sub %eax,%esi 673c: e8 00 00 00 00 callq 6741 !is_multicast_ether_addr(eth->h_dest)) vxlan_fdb_miss(vxlan, eth->h_dest); 6741: 48 85 c0 test %rax,%rax 6744: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx 674b: 0f 84 54 f8 ff ff je 5fa5 dev->stats.tx_dropped++; 6751: e9 dd fa ff ff jmpq 6233 6756: 39 c6 cmp %eax,%esi 6758: 72 15 jb 676f static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) return 1; if (unlikely(len > skb->len)) 675a: 29 d0 sub %edx,%eax 675c: 48 89 df mov %rbx,%rdi 675f: 89 c6 mov %eax,%esi 6761: e8 00 00 00 00 callq 6766 return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 6766: 48 85 c0 test %rax,%rax 6769: 0f 85 0a 05 00 00 jne 6c79 676f: 49 83 86 68 01 00 00 addq $0x1,0x168(%r14) 6776: 01 if (vxlan->flags & VXLAN_F_PROXY) { eth = eth_hdr(skb); if (ntohs(eth->h_proto) == ETH_P_ARP) return arp_reduce(dev, skb); #if IS_ENABLED(CONFIG_IPV6) else if (ntohs(eth->h_proto) == ETH_P_IPV6 && 6777: e9 eb fe ff ff jmpq 6667 677c: 48 89 c7 mov %rax,%rdi 677f: e8 00 00 00 00 callq 6784 6784: e9 29 fa ff ff jmpq 61b2 static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) return 1; if (unlikely(len > skb->len)) 6789: 41 0f b6 96 75 02 00 movzbl 0x275(%r14),%edx 6790: 00 return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 6791: 4c 8d 46 06 lea 0x6(%rsi),%r8 6795: 83 fa 08 cmp $0x8,%edx struct neighbour *n; if (dev->flags & IFF_NOARP) goto out; if (!pskb_may_pull(skb, arp_hdr_len(dev))) { 6798: 0f 83 a3 00 00 00 jae 6841 679e: f6 c2 04 test $0x4,%dl dev->stats.tx_dropped++; 67a1: 0f 85 d4 03 00 00 jne 6b7b 67a7: 85 d2 test %edx,%edx 67a9: 74 25 je 67d0 67ab: 0f b6 0e movzbl (%rsi),%ecx */ static inline void neigh_release(struct neighbour *neigh) { if (atomic_dec_and_test(&neigh->refcnt)) neigh_destroy(neigh); 67ae: f6 c2 02 test $0x2,%dl 67b1: 88 4e 06 mov %cl,0x6(%rsi) 67b4: 0f 85 15 04 00 00 jne 6bcf if (n) { bool diff; diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha); if (diff) { memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, 67ba: 0f b7 bb c6 00 00 00 movzwl 0xc6(%rbx),%edi 67c1: 41 0f b6 96 75 02 00 movzbl 0x275(%r14),%edx 67c8: 00 67c9: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx 67d0: 48 01 f9 add %rdi,%rcx 67d3: 83 fa 08 cmp $0x8,%edx 67d6: 48 8d b0 b8 00 00 00 lea 0xb8(%rax),%rsi 67dd: 73 31 jae 6810 67df: f6 c2 04 test $0x4,%dl 67e2: 0f 85 bd 03 00 00 jne 6ba5 67e8: 85 d2 test %edx,%edx 67ea: 0f 84 b8 f9 ff ff je 61a8 67f0: 0f b6 3e movzbl (%rsi),%edi 67f3: f6 c2 02 test $0x2,%dl 67f6: 40 88 39 mov %dil,(%rcx) 67f9: 0f 84 a9 f9 ff ff je 61a8 67ff: 89 d2 mov %edx,%edx dev->addr_len); memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len); 6801: 0f b7 74 16 fe movzwl -0x2(%rsi,%rdx,1),%esi 6806: 66 89 74 11 fe mov %si,-0x2(%rcx,%rdx,1) 680b: e9 98 f9 ff ff jmpq 61a8 6810: 48 8b b8 b8 00 00 00 mov 0xb8(%rax),%rdi 6817: 48 89 39 mov %rdi,(%rcx) 681a: 89 d7 mov %edx,%edi 681c: 4c 8b 44 3e f8 mov -0x8(%rsi,%rdi,1),%r8 6821: 4c 89 44 39 f8 mov %r8,-0x8(%rcx,%rdi,1) 6826: 48 8d 79 08 lea 0x8(%rcx),%rdi 682a: 48 83 e7 f8 and $0xfffffffffffffff8,%rdi 682e: 48 29 f9 sub %rdi,%rcx 6831: 48 29 ce sub %rcx,%rsi 6834: 01 d1 add %edx,%ecx 6836: c1 e9 03 shr $0x3,%ecx 6839: f3 48 a5 rep movsq %ds:(%rsi),%es:(%rdi) 683c: e9 67 f9 ff ff jmpq 61a8 6841: 48 8b 0e mov (%rsi),%rcx 6844: 48 89 4e 06 mov %rcx,0x6(%rsi) 6848: 89 d1 mov %edx,%ecx 684a: 48 8b 7c 0e f8 mov -0x8(%rsi,%rcx,1),%rdi 684f: 49 89 7c 08 f8 mov %rdi,-0x8(%r8,%rcx,1) 6854: 48 8d 7e 0e lea 0xe(%rsi),%rdi 6858: 48 83 e7 f8 and $0xfffffffffffffff8,%rdi 685c: 49 29 f8 sub %rdi,%r8 685f: 42 8d 0c 02 lea (%rdx,%r8,1),%ecx 6863: 4c 29 c6 sub %r8,%rsi 6866: c1 e9 03 shr $0x3,%ecx 6869: f3 48 a5 rep movsq %ds:(%rsi),%es:(%rdi) 686c: e9 49 ff ff ff jmpq 67ba if (n) { bool diff; diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha); if (diff) { memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, 6871: 83 f9 27 cmp $0x27,%ecx 6874: 0f 86 7d fe ff ff jbe 66f7 687a: be 28 00 00 00 mov $0x28,%esi 687f: 48 89 df mov %rbx,%rdi 6882: 29 c6 sub %eax,%esi 6884: e8 00 00 00 00 callq 6889 6889: 48 85 c0 test %rax,%rax 688c: 0f 84 65 fe ff ff je 66f7 6892: 48 8b 93 d0 00 00 00 mov 0xd0(%rbx),%rdx 6899: e9 9a f8 ff ff jmpq 6138 689e: 83 f9 13 cmp $0x13,%ecx static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) return 1; if (unlikely(len > skb->len)) 68a1: 0f 86 50 fe ff ff jbe 66f7 68a7: be 14 00 00 00 mov $0x14,%esi return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 68ac: 48 89 df mov %rbx,%rdi 68af: 29 c6 sub %eax,%esi 68b1: e8 00 00 00 00 callq 68b6 68b6: 48 85 c0 test %rax,%rax #if IS_ENABLED(CONFIG_IPV6) case ETH_P_IPV6: { struct ipv6hdr *pip6; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) 68b9: 0f 84 38 fe ff ff je 66f7 68bf: 48 8b 93 d0 00 00 00 mov 0xd0(%rbx),%rdx 68c6: e9 c9 fd ff ff jmpq 6694 68cb: c6 44 24 18 01 movb $0x1,0x18(%rsp) static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) { if (likely(len <= skb_headlen(skb))) return 1; if (unlikely(len > skb->len)) 68d0: e9 1b f9 ff ff jmpq 61f0 68d5: e8 00 00 00 00 callq 68da return 0; return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; 68da: 48 8b 48 e0 mov -0x20(%rax),%rcx 68de: 48 0b 48 e8 or -0x18(%rax),%rcx 68e2: 0f 94 c0 sete %al 68e5: e9 aa fc ff ff jmpq 6594 switch (ntohs(eth_hdr(skb)->h_proto)) { case ETH_P_IP: { struct iphdr *pip; if (!pskb_may_pull(skb, sizeof(struct iphdr))) 68ea: 4c 89 ff mov %r15,%rdi 68ed: e8 4e 9f ff ff callq 840 68f2: e9 70 fd ff ff jmpq 6667 68f7: 41 f6 86 d8 08 00 00 testb $0x10,0x8d8(%r14) 68fe: 10 const u8 *mac) { struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac); if (f) 68ff: 0f 84 62 fd ff ff je 6667 if (fdst) vxlan_xmit_one(skb, dev, fdst, did_rsc); else kfree_skb(skb); return NETDEV_TX_OK; } 6905: 48 8d 7c 24 30 lea 0x30(%rsp),%rdi static inline bool ipv6_addr_any(const struct in6_addr *a) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 const unsigned long *ul = (const unsigned long *)a; return (ul[0] | ul[1]) == 0UL; 690a: 31 c0 xor %eax,%eax 690c: b9 07 00 00 00 mov $0x7,%ecx 6911: 48 8d 74 24 30 lea 0x30(%rsp),%rsi 6916: f3 ab rep stos %eax,%es:(%rdi) 6918: 66 c7 44 24 30 0a 00 movw $0xa,0x30(%rsp) } reply = vxlan_na_create(skb, n, !!(f ? f->flags & NTF_ROUTER : 0)); neigh_release(n); 691f: 4c 89 f7 mov %r14,%rdi 6922: 49 8b 44 24 08 mov 0x8(%r12),%rax goto out; if (netif_rx_ni(reply) == NET_RX_DROP) dev->stats.rx_dropped++; } else if (vxlan->flags & VXLAN_F_L3MISS) { 6927: 49 8b 54 24 10 mov 0x10(%r12),%rdx 692c: 48 89 44 24 38 mov %rax,0x38(%rsp) 6931: 48 89 54 24 40 mov %rdx,0x40(%rsp) union vxlan_addr ipa = { 6936: e8 15 b7 ff ff callq 2050 693b: e9 27 fd ff ff jmpq 6667 6940: 45 31 c0 xor %r8d,%r8d .sin6.sin6_addr = msg->target, .sin6.sin6_family = AF_INET6, }; vxlan_ip_miss(dev, &ipa); 6943: 4a 8d 7c 02 1a lea 0x1a(%rdx,%r8,1),%rdi if (netif_rx_ni(reply) == NET_RX_DROP) dev->stats.rx_dropped++; } else if (vxlan->flags & VXLAN_F_L3MISS) { union vxlan_addr ipa = { 6948: 0f b7 c9 movzwl %cx,%ecx 694b: be 0e 00 00 00 mov $0xe,%esi .sin6.sin6_addr = msg->target, .sin6.sin6_family = AF_INET6, }; vxlan_ip_miss(dev, &ipa); 6950: 48 89 54 24 10 mov %rdx,0x10(%rsp) if (netif_rx_ni(reply) == NET_RX_DROP) dev->stats.rx_dropped++; } else if (vxlan->flags & VXLAN_F_L3MISS) { union vxlan_addr ipa = { 6955: 48 01 c8 add %rcx,%rax 6958: 8b 0f mov (%rdi),%ecx 695a: 89 08 mov %ecx,(%rax) 695c: 0f b7 4f 04 movzwl 0x4(%rdi),%ecx 6960: 4c 89 e7 mov %r12,%rdi 6963: 66 89 48 04 mov %cx,0x4(%rax) .sin6.sin6_addr = msg->target, .sin6.sin6_family = AF_INET6, }; vxlan_ip_miss(dev, &ipa); 6967: 41 0f b7 84 24 c6 00 movzwl 0xc6(%r12),%eax 696e: 00 00 6970: 49 03 84 24 d0 00 00 add 0xd0(%r12),%rax 6977: 00 skb->network_header += offset; } static inline unsigned char *skb_mac_header(const struct sk_buff *skb) { return skb->head + skb->mac_header; 6978: 41 8b 8f b8 00 00 00 mov 0xb8(%r15),%ecx ether_addr_copy(eth_hdr(reply)->h_dest, daddr); ether_addr_copy(eth_hdr(reply)->h_source, n->ha); eth_hdr(reply)->h_proto = htons(ETH_P_IPV6); reply->protocol = htons(ETH_P_IPV6); skb_pull(reply, sizeof(struct ethhdr)); 697f: 89 48 06 mov %ecx,0x6(%rax) 6982: 41 0f b7 8f bc 00 00 movzwl 0xbc(%r15),%ecx 6989: 00 * Please note: dst & src must both be aligned to u16. */ static inline void ether_addr_copy(u8 *dst, const u8 *src) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) *(u32 *)dst = *(const u32 *)src; 698a: 66 89 48 0a mov %cx,0xa(%rax) *(u16 *)(dst + 4) = *(const u16 *)(src + 4); 698e: 41 0f b7 84 24 c6 00 movzwl 0xc6(%r12),%eax 6995: 00 00 6997: 49 8b 8c 24 d0 00 00 mov 0xd0(%r12),%rcx 699e: 00 699f: 66 c7 44 01 0c 86 dd movw $0xdd86,0xc(%rcx,%rax,1) 69a6: 66 41 c7 84 24 c0 00 movw $0xdd86,0xc0(%r12) 69ad: 00 00 86 dd * Please note: dst & src must both be aligned to u16. */ static inline void ether_addr_copy(u8 *dst, const u8 *src) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) *(u32 *)dst = *(const u32 *)src; 69b1: e8 00 00 00 00 callq 69b6 *(u16 *)(dst + 4) = *(const u16 *)(src + 4); 69b6: 49 8b 84 24 d8 00 00 mov 0xd8(%r12),%rax 69bd: 00 } /* Ethernet header */ ether_addr_copy(eth_hdr(reply)->h_dest, daddr); ether_addr_copy(eth_hdr(reply)->h_source, n->ha); eth_hdr(reply)->h_proto = htons(ETH_P_IPV6); 69be: 49 2b 84 24 d0 00 00 sub 0xd0(%r12),%rax 69c5: 00 69c6: be 28 00 00 00 mov $0x28,%esi 69cb: 4c 89 e7 mov %r12,%rdi 69ce: 66 41 89 84 24 c4 00 mov %ax,0xc4(%r12) 69d5: 00 00 reply->protocol = htons(ETH_P_IPV6); 69d7: e8 00 00 00 00 callq 69dc 69dc: 45 0f b7 ac 24 c4 00 movzwl 0xc4(%r12),%r13d 69e3: 00 00 skb_pull(reply, sizeof(struct ethhdr)); 69e5: 45 31 c0 xor %r8d,%r8d return skb->head + skb->network_header; } static inline void skb_reset_network_header(struct sk_buff *skb) { skb->network_header = skb->data - skb->head; 69e8: b9 0a 00 00 00 mov $0xa,%ecx 69ed: 4d 03 ac 24 d0 00 00 add 0xd0(%r12),%r13 69f4: 00 69f5: 44 89 c0 mov %r8d,%eax skb_reset_network_header(reply); skb_put(reply, sizeof(struct ipv6hdr)); 69f8: 44 89 44 24 18 mov %r8d,0x18(%rsp) 69fd: 4c 89 ef mov %r13,%rdi 6a00: f3 ab rep stos %eax,%es:(%rdi) 6a02: b9 60 00 00 00 mov $0x60,%ecx 6a07: 41 88 4d 00 mov %cl,0x0(%r13) 6a0b: 0f b7 83 c4 00 00 00 movzwl 0xc4(%rbx),%eax skb->transport_header += offset; } static inline unsigned char *skb_network_header(const struct sk_buff *skb) { return skb->head + skb->network_header; 6a12: 48 8b b3 d0 00 00 00 mov 0xd0(%rbx),%rsi /* IPv6 header */ pip6 = ipv6_hdr(reply); memset(pip6, 0, sizeof(struct ipv6hdr)); 6a19: 0f b6 04 06 movzbl (%rsi,%rax,1),%eax 6a1d: 41 c6 45 06 3a movb $0x3a,0x6(%r13) 6a22: 41 c6 45 07 ff movb $0xff,0x7(%r13) 6a27: 83 e0 0f and $0xf,%eax 6a2a: 09 c8 or %ecx,%eax 6a2c: 41 88 45 00 mov %al,0x0(%r13) 6a30: 0f b7 83 c4 00 00 00 movzwl 0xc4(%rbx),%eax pip6->version = 6; 6a37: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx pip6->priority = ipv6_hdr(request)->priority; 6a3e: 48 8b 74 01 08 mov 0x8(%rcx,%rax,1),%rsi 6a43: 48 8b 7c 01 10 mov 0x10(%rcx,%rax,1),%rdi 6a48: 49 89 75 18 mov %rsi,0x18(%r13) 6a4c: 49 89 7d 20 mov %rdi,0x20(%r13) pip6->nexthdr = IPPROTO_ICMPV6; 6a50: 49 8b b7 90 01 00 00 mov 0x190(%r15),%rsi /* IPv6 header */ pip6 = ipv6_hdr(reply); memset(pip6, 0, sizeof(struct ipv6hdr)); pip6->version = 6; pip6->priority = ipv6_hdr(request)->priority; 6a57: 49 8b bf 98 01 00 00 mov 0x198(%r15),%rdi 6a5e: 49 89 75 08 mov %rsi,0x8(%r13) pip6->nexthdr = IPPROTO_ICMPV6; pip6->hop_limit = 255; pip6->daddr = ipv6_hdr(request)->saddr; 6a62: 49 89 7d 10 mov %rdi,0x10(%r13) 6a66: be 28 00 00 00 mov $0x28,%esi 6a6b: 4c 89 e7 mov %r12,%rdi 6a6e: e8 00 00 00 00 callq 6a73 6a73: 49 8b 84 24 d8 00 00 mov 0xd8(%r12),%rax 6a7a: 00 6a7b: 49 2b 84 24 d0 00 00 sub 0xd0(%r12),%rax 6a82: 00 pip6->saddr = *(struct in6_addr *)n->primary_key; 6a83: be 20 00 00 00 mov $0x20,%esi 6a88: 4c 89 e7 mov %r12,%rdi 6a8b: 66 41 89 84 24 c2 00 mov %ax,0xc2(%r12) 6a92: 00 00 6a94: e8 00 00 00 00 callq 6a99 skb_pull(reply, sizeof(struct ipv6hdr)); 6a99: 44 8b 44 24 18 mov 0x18(%rsp),%r8d 6a9e: 49 89 c2 mov %rax,%r10 6aa1: 48 89 c7 mov %rax,%rdi return skb->head + skb->transport_header; } static inline void skb_reset_transport_header(struct sk_buff *skb) { skb->transport_header = skb->data - skb->head; 6aa4: b9 08 00 00 00 mov $0x8,%ecx 6aa9: 48 8b 54 24 10 mov 0x10(%rsp),%rdx 6aae: be 20 00 00 00 mov $0x20,%esi skb_reset_transport_header(reply); na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen); 6ab3: 44 89 c0 mov %r8d,%eax 6ab6: f3 ab rep stos %eax,%es:(%rdi) 6ab8: 0f b6 44 24 20 movzbl 0x20(%rsp),%eax 6abd: 41 c6 02 88 movb $0x88,(%r10) 6ac1: 4c 89 d7 mov %r10,%rdi 6ac4: 4c 89 54 24 20 mov %r10,0x20(%rsp) /* Neighbor Advertisement */ memset(na, 0, sizeof(*na)+na_olen); 6ac9: c1 e0 07 shl $0x7,%eax 6acc: 83 c8 60 or $0x60,%eax pip6->saddr = *(struct in6_addr *)n->primary_key; skb_pull(reply, sizeof(struct ipv6hdr)); skb_reset_transport_header(reply); na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen); 6acf: 41 88 42 04 mov %al,0x4(%r10) /* Neighbor Advertisement */ memset(na, 0, sizeof(*na)+na_olen); 6ad3: 48 8b 42 08 mov 0x8(%rdx),%rax 6ad7: 48 8b 52 10 mov 0x10(%rdx),%rdx na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; na->icmph.icmp6_router = isrouter; na->icmph.icmp6_override = 1; na->icmph.icmp6_solicited = 1; na->target = ns->target; 6adb: 49 89 42 08 mov %rax,0x8(%r10) ether_addr_copy(&na->opt[2], n->ha); na->opt[0] = ND_OPT_TARGET_LL_ADDR; na->opt[1] = na_olen >> 3; na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr, 6adf: 49 89 52 10 mov %rdx,0x10(%r10) skb_reset_transport_header(reply); na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen); /* Neighbor Advertisement */ memset(na, 0, sizeof(*na)+na_olen); 6ae3: 41 8b 87 b8 00 00 00 mov 0xb8(%r15),%eax na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; na->icmph.icmp6_router = isrouter; 6aea: 31 d2 xor %edx,%edx 6aec: 41 89 42 1a mov %eax,0x1a(%r10) na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen); /* Neighbor Advertisement */ memset(na, 0, sizeof(*na)+na_olen); na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; 6af0: 41 0f b7 87 bc 00 00 movzwl 0xbc(%r15),%eax 6af7: 00 na->target = ns->target; ether_addr_copy(&na->opt[2], n->ha); na->opt[0] = ND_OPT_TARGET_LL_ADDR; na->opt[1] = na_olen >> 3; na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr, 6af8: 41 c6 42 18 02 movb $0x2,0x18(%r10) /* Neighbor Advertisement */ memset(na, 0, sizeof(*na)+na_olen); na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; na->icmph.icmp6_router = isrouter; na->icmph.icmp6_override = 1; na->icmph.icmp6_solicited = 1; 6afd: 41 c6 42 19 01 movb $0x1,0x19(%r10) 6b02: 66 41 89 42 1e mov %ax,0x1e(%r10) na->target = ns->target; 6b07: e8 00 00 00 00 callq 6b0c 6b0c: 49 8d 75 18 lea 0x18(%r13),%rsi 6b10: 49 8d 7d 08 lea 0x8(%r13),%rdi * Please note: dst & src must both be aligned to u16. */ static inline void ether_addr_copy(u8 *dst, const u8 *src) { #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) *(u32 *)dst = *(const u32 *)src; 6b14: 41 89 c0 mov %eax,%r8d 6b17: b9 3a 00 00 00 mov $0x3a,%ecx 6b1c: ba 20 00 00 00 mov $0x20,%edx *(u16 *)(dst + 4) = *(const u16 *)(src + 4); 6b21: e8 00 00 00 00 callq 6b26 6b26: 4c 8b 54 24 20 mov 0x20(%rsp),%r10 ether_addr_copy(&na->opt[2], n->ha); na->opt[0] = ND_OPT_TARGET_LL_ADDR; 6b2b: be 28 00 00 00 mov $0x28,%esi na->opt[1] = na_olen >> 3; 6b30: 4c 89 e7 mov %r12,%rdi 6b33: 66 41 89 42 02 mov %ax,0x2(%r10) na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr, 6b38: 66 41 c7 45 04 00 20 movw $0x2000,0x4(%r13) &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6, 6b3f: e8 00 00 00 00 callq 6b44 na->target = ns->target; ether_addr_copy(&na->opt[2], n->ha); na->opt[0] = ND_OPT_TARGET_LL_ADDR; na->opt[1] = na_olen >> 3; na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr, 6b44: 41 0f b6 84 24 91 00 movzbl 0x91(%r12),%eax 6b4b: 00 00 6b4d: 4c 89 ff mov %r15,%rdi 6b50: 83 e0 f9 and $0xfffffff9,%eax 6b53: 83 c8 02 or $0x2,%eax 6b56: 41 88 84 24 91 00 00 mov %al,0x91(%r12) 6b5d: 00 &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6, csum_partial(na, sizeof(*na)+na_olen, 0)); pip6->payload_len = htons(sizeof(*na)+na_olen); skb_push(reply, sizeof(struct ipv6hdr)); 6b5e: e8 dd 9c ff ff callq 840 na->target = ns->target; ether_addr_copy(&na->opt[2], n->ha); na->opt[0] = ND_OPT_TARGET_LL_ADDR; na->opt[1] = na_olen >> 3; na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr, 6b63: 4c 89 e7 mov %r12,%rdi 6b66: e8 00 00 00 00 callq 6b6b &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6, csum_partial(na, sizeof(*na)+na_olen, 0)); pip6->payload_len = htons(sizeof(*na)+na_olen); 6b6b: 83 e8 01 sub $0x1,%eax 6b6e: 0f 85 f3 fa ff ff jne 6667 skb_push(reply, sizeof(struct ipv6hdr)); reply->ip_summed = CHECKSUM_UNNECESSARY; 6b74: e9 e6 fa ff ff jmpq 665f 6b79: 0f 0b ud2 6b7b: 89 d2 mov %edx,%edx } reply = vxlan_na_create(skb, n, !!(f ? f->flags & NTF_ROUTER : 0)); neigh_release(n); 6b7d: 44 89 4e 06 mov %r9d,0x6(%rsi) pip6->payload_len = htons(sizeof(*na)+na_olen); skb_push(reply, sizeof(struct ipv6hdr)); reply->ip_summed = CHECKSUM_UNNECESSARY; 6b81: 8b 4c 16 fc mov -0x4(%rsi,%rdx,1),%ecx 6b85: 41 89 4c 10 fc mov %ecx,-0x4(%r8,%rdx,1) 6b8a: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx } reply = vxlan_na_create(skb, n, !!(f ? f->flags & NTF_ROUTER : 0)); neigh_release(n); 6b91: 0f b7 bb c6 00 00 00 movzwl 0xc6(%rbx),%edi if (reply == NULL) goto out; if (netif_rx_ni(reply) == NET_RX_DROP) 6b98: 41 0f b6 96 75 02 00 movzbl 0x275(%r14),%edx 6b9f: 00 6ba0: e9 2b fc ff ff jmpq 67d0 6ba5: 8b 3e mov (%rsi),%edi 6ba7: 89 d2 mov %edx,%edx unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) { skb->len -= len; BUG_ON(skb->len < skb->data_len); 6ba9: 89 39 mov %edi,(%rcx) if (n) { bool diff; diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha); if (diff) { memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, 6bab: 8b 74 16 fc mov -0x4(%rsi,%rdx,1),%esi 6baf: 89 74 11 fc mov %esi,-0x4(%rcx,%rdx,1) 6bb3: e9 f0 f5 ff ff jmpq 61a8 6bb8: 48 8b 4a e0 mov -0x20(%rdx),%rcx 6bbc: 48 0b 4a e8 or -0x18(%rdx),%rcx 6bc0: 0f 94 c2 sete %dl 6bc3: e9 3a f7 ff ff jmpq 6302 6bc8: 31 c0 xor %eax,%eax 6bca: e9 42 f7 ff ff jmpq 6311 6bcf: 89 d2 mov %edx,%edx 6bd1: 0f b7 4c 16 fe movzwl -0x2(%rsi,%rdx,1),%ecx dev->addr_len); memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len); 6bd6: 66 41 89 4c 10 fe mov %cx,-0x2(%r8,%rdx,1) 6bdc: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx 6be3: 0f b7 bb c6 00 00 00 movzwl 0xc6(%rbx),%edi 6bea: 41 0f b6 96 75 02 00 movzbl 0x275(%r14),%edx 6bf1: 00 6bf2: e9 d9 fb ff ff jmpq 67d0 6bf7: 41 f6 86 d8 08 00 00 testb $0x10,0x8d8(%r14) 6bfe: 10 if (n) { bool diff; diff = !ether_addr_equal(eth_hdr(skb)->h_dest, n->ha); if (diff) { memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, 6bff: 0f 84 f2 fa ff ff je 66f7 6c05: 48 8d 7c 24 30 lea 0x30(%rsp),%rdi 6c0a: b9 07 00 00 00 mov $0x7,%ecx 6c0f: 48 8d 74 24 30 lea 0x30(%rsp),%rsi 6c14: f3 ab rep stos %eax,%es:(%rdi) 6c16: 66 c7 44 24 30 0a 00 movw $0xa,0x30(%rsp) 6c1d: 4c 89 f7 mov %r14,%rdi 6c20: 49 8b 40 18 mov 0x18(%r8),%rax 6c24: 49 8b 50 20 mov 0x20(%r8),%rdx if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) return false; pip6 = ipv6_hdr(skb); n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev); if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { 6c28: 48 89 44 24 38 mov %rax,0x38(%rsp) 6c2d: 48 89 54 24 40 mov %rdx,0x40(%rsp) 6c32: e8 19 b4 ff ff callq 2050 union vxlan_addr ipa = { 6c37: e9 bb fa ff ff jmpq 66f7 6c3c: 41 f6 86 d8 08 00 00 testb $0x10,0x8d8(%r14) 6c43: 10 6c44: 0f 84 1d fa ff ff je 6667 6c4a: 48 8d 7c 24 30 lea 0x30(%rsp),%rdi .sin6.sin6_addr = pip6->daddr, .sin6.sin6_family = AF_INET6, }; vxlan_ip_miss(dev, &ipa); 6c4f: 31 c0 xor %eax,%eax if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) return false; pip6 = ipv6_hdr(skb); n = neigh_lookup(ipv6_stub->nd_tbl, &pip6->daddr, dev); if (!n && (vxlan->flags & VXLAN_F_L3MISS)) { union vxlan_addr ipa = { 6c51: b9 07 00 00 00 mov $0x7,%ecx 6c56: 48 8d 74 24 30 lea 0x30(%rsp),%rsi 6c5b: f3 ab rep stos %eax,%es:(%rdi) 6c5d: 8b 44 24 2c mov 0x2c(%rsp),%eax 6c61: 4c 89 f7 mov %r14,%rdi .sin6.sin6_addr = pip6->daddr, .sin6.sin6_family = AF_INET6, }; vxlan_ip_miss(dev, &ipa); 6c64: 66 c7 44 24 30 02 00 movw $0x2,0x30(%rsp) 6c6b: 89 44 24 34 mov %eax,0x34(%rsp) reply->ip_summed = CHECKSUM_UNNECESSARY; reply->pkt_type = PACKET_HOST; if (netif_rx_ni(reply) == NET_RX_DROP) dev->stats.rx_dropped++; } else if (vxlan->flags & VXLAN_F_L3MISS) { 6c6f: e8 dc b3 ff ff callq 2050 6c74: e9 ee f9 ff ff jmpq 6667 6c79: 48 8b 8b d0 00 00 00 mov 0xd0(%rbx),%rcx union vxlan_addr ipa = { 6c80: e9 23 f8 ff ff jmpq 64a8 Disassembly of section .init.text: 0000000000000000 : 0: 55 push %rbp 1: be 04 00 00 00 mov $0x4,%esi 6: 48 c7 c7 00 00 00 00 mov $0x0,%rdi d: 48 89 e5 mov %rsp,%rbp 10: 41 54 push %r12 12: 53 push %rbx 13: e8 00 00 00 00 callq 18 18: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 1f: e8 00 00 00 00 callq 24 24: 85 c0 test %eax,%eax 26: 41 89 c4 mov %eax,%r12d 29: 75 41 jne 6c 2b: 48 c7 c7 00 00 00 00 mov $0x0,%rdi } /* Look up Ethernet address in forwarding table */ static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { 32: e8 00 00 00 00 callq 37 struct hlist_head *head = vxlan_fdb_head(vxlan, mac); struct vxlan_fdb *f; hlist_for_each_entry_rcu(f, head, hlist) { 37: 85 c0 test %eax,%eax 39: 89 c3 mov %eax,%ebx 3b: 75 21 jne 5e 3d: 48 c7 c7 00 00 00 00 mov $0x0,%rdi } /* Look up Ethernet address in forwarding table */ static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan, const u8 *mac) { 44: e8 00 00 00 00 callq 49 struct hlist_head *head = vxlan_fdb_head(vxlan, mac); struct vxlan_fdb *f; hlist_for_each_entry_rcu(f, head, hlist) { 49: 89 c3 mov %eax,%ebx 4b: 44 89 e0 mov %r12d,%eax 4e: 85 db test %ebx,%ebx 50: 74 1a je 6c 52: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 59: e8 00 00 00 00 callq 5e 5e: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 65: e8 00 00 00 00 callq 6a if (ether_addr_equal(mac, f->eth_addr)) 6a: 89 d8 mov %ebx,%eax 6c: 5b pop %rbx 6d: 41 5c pop %r12 6f: 5d pop %rbp 70: c3 retq Disassembly of section .exit.text: 0000000000000000 : 0: 55 push %rbp 1: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 8: 48 89 e5 mov %rsp,%rbp b: e8 00 00 00 00 callq 10 10: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 17: e8 00 00 00 00 callq 1c 1c: 48 c7 c7 00 00 00 00 mov $0x0,%rdi 23: e8 00 00 00 00 callq 28 28: 5d pop %rbp 29: c3 retq