| .. | .. |
|---|
| 36 | 36 | struct rcu_head rcu; |
|---|
| 37 | 37 | }; |
|---|
| 38 | 38 | |
|---|
| 39 | | -static inline unsigned int vlan_proto_idx(__be16 proto) |
|---|
| 39 | +static inline int vlan_proto_idx(__be16 proto) |
|---|
| 40 | 40 | { |
|---|
| 41 | 41 | switch (proto) { |
|---|
| 42 | 42 | case htons(ETH_P_8021Q): |
|---|
| .. | .. |
|---|
| 44 | 44 | case htons(ETH_P_8021AD): |
|---|
| 45 | 45 | return VLAN_PROTO_8021AD; |
|---|
| 46 | 46 | default: |
|---|
| 47 | | - BUG(); |
|---|
| 48 | | - return 0; |
|---|
| 47 | + WARN(1, "invalid VLAN protocol: 0x%04x\n", ntohs(proto)); |
|---|
| 48 | + return -EINVAL; |
|---|
| 49 | 49 | } |
|---|
| 50 | 50 | } |
|---|
| 51 | 51 | |
|---|
| .. | .. |
|---|
| 64 | 64 | __be16 vlan_proto, |
|---|
| 65 | 65 | u16 vlan_id) |
|---|
| 66 | 66 | { |
|---|
| 67 | | - return __vlan_group_get_device(vg, vlan_proto_idx(vlan_proto), vlan_id); |
|---|
| 67 | + int pidx = vlan_proto_idx(vlan_proto); |
|---|
| 68 | + |
|---|
| 69 | + if (pidx < 0) |
|---|
| 70 | + return NULL; |
|---|
| 71 | + |
|---|
| 72 | + return __vlan_group_get_device(vg, pidx, vlan_id); |
|---|
| 68 | 73 | } |
|---|
| 69 | 74 | |
|---|
| 70 | 75 | static inline void vlan_group_set_device(struct vlan_group *vg, |
|---|
| 71 | 76 | __be16 vlan_proto, u16 vlan_id, |
|---|
| 72 | 77 | struct net_device *dev) |
|---|
| 73 | 78 | { |
|---|
| 79 | + int pidx = vlan_proto_idx(vlan_proto); |
|---|
| 74 | 80 | struct net_device **array; |
|---|
| 75 | | - if (!vg) |
|---|
| 81 | + |
|---|
| 82 | + if (!vg || pidx < 0) |
|---|
| 76 | 83 | return; |
|---|
| 77 | | - array = vg->vlan_devices_arrays[vlan_proto_idx(vlan_proto)] |
|---|
| 84 | + array = vg->vlan_devices_arrays[pidx] |
|---|
| 78 | 85 | [vlan_id / VLAN_GROUP_ARRAY_PART_LEN]; |
|---|
| 79 | 86 | array[vlan_id % VLAN_GROUP_ARRAY_PART_LEN] = dev; |
|---|
| 80 | 87 | } |
|---|
| .. | .. |
|---|
| 92 | 99 | return NULL; |
|---|
| 93 | 100 | } |
|---|
| 94 | 101 | |
|---|
| 102 | +static inline netdev_features_t vlan_tnl_features(struct net_device *real_dev) |
|---|
| 103 | +{ |
|---|
| 104 | + netdev_features_t ret; |
|---|
| 105 | + |
|---|
| 106 | + ret = real_dev->hw_enc_features & |
|---|
| 107 | + (NETIF_F_CSUM_MASK | NETIF_F_ALL_TSO | NETIF_F_GSO_ENCAP_ALL); |
|---|
| 108 | + |
|---|
| 109 | + if ((ret & NETIF_F_GSO_ENCAP_ALL) && (ret & NETIF_F_CSUM_MASK)) |
|---|
| 110 | + return (ret & ~NETIF_F_CSUM_MASK) | NETIF_F_HW_CSUM; |
|---|
| 111 | + return 0; |
|---|
| 112 | +} |
|---|
| 113 | + |
|---|
| 95 | 114 | #define vlan_group_for_each_dev(grp, i, dev) \ |
|---|
| 96 | 115 | for ((i) = 0; i < VLAN_PROTO_NUM * VLAN_N_VID; i++) \ |
|---|
| 97 | 116 | if (((dev) = __vlan_group_get_device((grp), (i) / VLAN_N_VID, \ |
|---|