diff options
Diffstat (limited to 'include/linux/if_vlan.h')
| -rw-r--r-- | include/linux/if_vlan.h | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 218a3b686d90..52bd03b38962 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h | |||
| @@ -86,15 +86,15 @@ static inline int is_vlan_dev(struct net_device *dev) | |||
| 86 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | 86 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) |
| 87 | 87 | ||
| 88 | extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, | 88 | extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, |
| 89 | u16 vlan_id); | 89 | __be16 vlan_proto, u16 vlan_id); |
| 90 | extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); | 90 | extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); |
| 91 | extern u16 vlan_dev_vlan_id(const struct net_device *dev); | 91 | extern u16 vlan_dev_vlan_id(const struct net_device *dev); |
| 92 | 92 | ||
| 93 | extern bool vlan_do_receive(struct sk_buff **skb); | 93 | extern bool vlan_do_receive(struct sk_buff **skb); |
| 94 | extern struct sk_buff *vlan_untag(struct sk_buff *skb); | 94 | extern struct sk_buff *vlan_untag(struct sk_buff *skb); |
| 95 | 95 | ||
| 96 | extern int vlan_vid_add(struct net_device *dev, unsigned short vid); | 96 | extern int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid); |
| 97 | extern void vlan_vid_del(struct net_device *dev, unsigned short vid); | 97 | extern void vlan_vid_del(struct net_device *dev, __be16 proto, u16 vid); |
| 98 | 98 | ||
| 99 | extern int vlan_vids_add_by_dev(struct net_device *dev, | 99 | extern int vlan_vids_add_by_dev(struct net_device *dev, |
| 100 | const struct net_device *by_dev); | 100 | const struct net_device *by_dev); |
| @@ -104,7 +104,8 @@ extern void vlan_vids_del_by_dev(struct net_device *dev, | |||
| 104 | extern bool vlan_uses_dev(const struct net_device *dev); | 104 | extern bool vlan_uses_dev(const struct net_device *dev); |
| 105 | #else | 105 | #else |
| 106 | static inline struct net_device * | 106 | static inline struct net_device * |
| 107 | __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) | 107 | __vlan_find_dev_deep(struct net_device *real_dev, |
| 108 | __be16 vlan_proto, u16 vlan_id) | ||
| 108 | { | 109 | { |
| 109 | return NULL; | 110 | return NULL; |
| 110 | } | 111 | } |
| @@ -131,12 +132,12 @@ static inline struct sk_buff *vlan_untag(struct sk_buff *skb) | |||
| 131 | return skb; | 132 | return skb; |
| 132 | } | 133 | } |
| 133 | 134 | ||
| 134 | static inline int vlan_vid_add(struct net_device *dev, unsigned short vid) | 135 | static inline int vlan_vid_add(struct net_device *dev, __be16 proto, u16 vid) |
| 135 | { | 136 | { |
| 136 | return 0; | 137 | return 0; |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | static inline void vlan_vid_del(struct net_device *dev, unsigned short vid) | 140 | static inline void vlan_vid_del(struct net_device *dev, __be16 proto, u16 vid) |
| 140 | { | 141 | { |
| 141 | } | 142 | } |
| 142 | 143 | ||
| @@ -157,9 +158,20 @@ static inline bool vlan_uses_dev(const struct net_device *dev) | |||
| 157 | } | 158 | } |
| 158 | #endif | 159 | #endif |
| 159 | 160 | ||
| 161 | static inline bool vlan_hw_offload_capable(netdev_features_t features, | ||
| 162 | __be16 proto) | ||
| 163 | { | ||
| 164 | if (proto == htons(ETH_P_8021Q) && features & NETIF_F_HW_VLAN_CTAG_TX) | ||
| 165 | return true; | ||
| 166 | if (proto == htons(ETH_P_8021AD) && features & NETIF_F_HW_VLAN_STAG_TX) | ||
| 167 | return true; | ||
| 168 | return false; | ||
| 169 | } | ||
| 170 | |||
| 160 | /** | 171 | /** |
| 161 | * vlan_insert_tag - regular VLAN tag inserting | 172 | * vlan_insert_tag - regular VLAN tag inserting |
| 162 | * @skb: skbuff to tag | 173 | * @skb: skbuff to tag |
| 174 | * @vlan_proto: VLAN encapsulation protocol | ||
| 163 | * @vlan_tci: VLAN TCI to insert | 175 | * @vlan_tci: VLAN TCI to insert |
| 164 | * | 176 | * |
| 165 | * Inserts the VLAN tag into @skb as part of the payload | 177 | * Inserts the VLAN tag into @skb as part of the payload |
| @@ -170,7 +182,8 @@ static inline bool vlan_uses_dev(const struct net_device *dev) | |||
| 170 | * | 182 | * |
| 171 | * Does not change skb->protocol so this function can be used during receive. | 183 | * Does not change skb->protocol so this function can be used during receive. |
| 172 | */ | 184 | */ |
| 173 | static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, u16 vlan_tci) | 185 | static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, |
| 186 | __be16 vlan_proto, u16 vlan_tci) | ||
| 174 | { | 187 | { |
| 175 | struct vlan_ethhdr *veth; | 188 | struct vlan_ethhdr *veth; |
| 176 | 189 | ||
| @@ -185,7 +198,7 @@ static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, u16 vlan_tci) | |||
| 185 | skb->mac_header -= VLAN_HLEN; | 198 | skb->mac_header -= VLAN_HLEN; |
| 186 | 199 | ||
| 187 | /* first, the ethernet type */ | 200 | /* first, the ethernet type */ |
| 188 | veth->h_vlan_proto = htons(ETH_P_8021Q); | 201 | veth->h_vlan_proto = vlan_proto; |
| 189 | 202 | ||
| 190 | /* now, the TCI */ | 203 | /* now, the TCI */ |
| 191 | veth->h_vlan_TCI = htons(vlan_tci); | 204 | veth->h_vlan_TCI = htons(vlan_tci); |
| @@ -204,24 +217,28 @@ static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb, u16 vlan_tci) | |||
| 204 | * Following the skb_unshare() example, in case of error, the calling function | 217 | * Following the skb_unshare() example, in case of error, the calling function |
| 205 | * doesn't have to worry about freeing the original skb. | 218 | * doesn't have to worry about freeing the original skb. |
| 206 | */ | 219 | */ |
| 207 | static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) | 220 | static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, |
| 221 | __be16 vlan_proto, u16 vlan_tci) | ||
| 208 | { | 222 | { |
| 209 | skb = vlan_insert_tag(skb, vlan_tci); | 223 | skb = vlan_insert_tag(skb, vlan_proto, vlan_tci); |
| 210 | if (skb) | 224 | if (skb) |
| 211 | skb->protocol = htons(ETH_P_8021Q); | 225 | skb->protocol = vlan_proto; |
| 212 | return skb; | 226 | return skb; |
| 213 | } | 227 | } |
| 214 | 228 | ||
| 215 | /** | 229 | /** |
| 216 | * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting | 230 | * __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting |
| 217 | * @skb: skbuff to tag | 231 | * @skb: skbuff to tag |
| 232 | * @vlan_proto: VLAN encapsulation protocol | ||
| 218 | * @vlan_tci: VLAN TCI to insert | 233 | * @vlan_tci: VLAN TCI to insert |
| 219 | * | 234 | * |
| 220 | * Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest | 235 | * Puts the VLAN TCI in @skb->vlan_tci and lets the device do the rest |
| 221 | */ | 236 | */ |
| 222 | static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, | 237 | static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, |
| 238 | __be16 vlan_proto, | ||
| 223 | u16 vlan_tci) | 239 | u16 vlan_tci) |
| 224 | { | 240 | { |
| 241 | skb->vlan_proto = vlan_proto; | ||
| 225 | skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci; | 242 | skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci; |
| 226 | return skb; | 243 | return skb; |
| 227 | } | 244 | } |
| @@ -236,12 +253,13 @@ static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, | |||
| 236 | * Assumes skb->dev is the target that will xmit this frame. | 253 | * Assumes skb->dev is the target that will xmit this frame. |
| 237 | * Returns a VLAN tagged skb. | 254 | * Returns a VLAN tagged skb. |
| 238 | */ | 255 | */ |
| 239 | static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) | 256 | static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, |
| 257 | __be16 vlan_proto, u16 vlan_tci) | ||
| 240 | { | 258 | { |
| 241 | if (skb->dev->features & NETIF_F_HW_VLAN_TX) { | 259 | if (vlan_hw_offload_capable(skb->dev->features, vlan_proto)) { |
| 242 | return __vlan_hwaccel_put_tag(skb, vlan_tci); | 260 | return __vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci); |
| 243 | } else { | 261 | } else { |
| 244 | return __vlan_put_tag(skb, vlan_tci); | 262 | return __vlan_put_tag(skb, vlan_proto, vlan_tci); |
| 245 | } | 263 | } |
| 246 | } | 264 | } |
| 247 | 265 | ||
| @@ -256,9 +274,9 @@ static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci) | |||
| 256 | { | 274 | { |
| 257 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data; | 275 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data; |
| 258 | 276 | ||
| 259 | if (veth->h_vlan_proto != htons(ETH_P_8021Q)) { | 277 | if (veth->h_vlan_proto != htons(ETH_P_8021Q) && |
| 278 | veth->h_vlan_proto != htons(ETH_P_8021AD)) | ||
| 260 | return -EINVAL; | 279 | return -EINVAL; |
| 261 | } | ||
| 262 | 280 | ||
| 263 | *vlan_tci = ntohs(veth->h_vlan_TCI); | 281 | *vlan_tci = ntohs(veth->h_vlan_TCI); |
| 264 | return 0; | 282 | return 0; |
| @@ -294,7 +312,7 @@ static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb, | |||
| 294 | */ | 312 | */ |
| 295 | static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci) | 313 | static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci) |
| 296 | { | 314 | { |
| 297 | if (skb->dev->features & NETIF_F_HW_VLAN_TX) { | 315 | if (skb->dev->features & NETIF_F_HW_VLAN_CTAG_TX) { |
| 298 | return __vlan_hwaccel_get_tag(skb, vlan_tci); | 316 | return __vlan_hwaccel_get_tag(skb, vlan_tci); |
| 299 | } else { | 317 | } else { |
| 300 | return __vlan_get_tag(skb, vlan_tci); | 318 | return __vlan_get_tag(skb, vlan_tci); |
| @@ -339,7 +357,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, | |||
| 339 | */ | 357 | */ |
| 340 | 358 | ||
| 341 | proto = vhdr->h_vlan_encapsulated_proto; | 359 | proto = vhdr->h_vlan_encapsulated_proto; |
| 342 | if (ntohs(proto) >= 1536) { | 360 | if (ntohs(proto) >= ETH_P_802_3_MIN) { |
| 343 | skb->protocol = proto; | 361 | skb->protocol = proto; |
| 344 | return; | 362 | return; |
| 345 | } | 363 | } |
