diff options
author | Simon Wunderlich <simon@open-mesh.com> | 2013-07-29 11:56:44 -0400 |
---|---|---|
committer | Antonio Quartulli <ordex@autistici.org> | 2013-08-28 05:31:50 -0400 |
commit | c54f38c9aa22ff65ca9f4c1bdbf2a11d017205f3 (patch) | |
tree | e12190c69088c2fee771a49e94c5ab6619ec3817 /net/batman-adv/main.c | |
parent | 5b2941b18dc5f60a5c14a5c15693f9c58b0dd922 (diff) |
batman-adv: set skb priority according to content
The skb priority field may help the wireless driver to choose the right
queue (e.g. WMM queues). This should be set in batman-adv, as this
information is only available here.
This patch adds support for IPv4/IPv6 DS fields and VLAN PCP. Note that
only VLAN PCP is used if a VLAN header is present. Also initially set
TC_PRIO_CONTROL only for self-generated packets, and keep the priority
set by higher layers.
Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Diffstat (limited to 'net/batman-adv/main.c')
-rw-r--r-- | net/batman-adv/main.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 08125f3f6064..c72d1bcdcf49 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -19,6 +19,10 @@ | |||
19 | 19 | ||
20 | #include <linux/crc32c.h> | 20 | #include <linux/crc32c.h> |
21 | #include <linux/highmem.h> | 21 | #include <linux/highmem.h> |
22 | #include <linux/if_vlan.h> | ||
23 | #include <net/ip.h> | ||
24 | #include <net/ipv6.h> | ||
25 | #include <net/dsfield.h> | ||
22 | #include "main.h" | 26 | #include "main.h" |
23 | #include "sysfs.h" | 27 | #include "sysfs.h" |
24 | #include "debugfs.h" | 28 | #include "debugfs.h" |
@@ -249,6 +253,60 @@ out: | |||
249 | return primary_if; | 253 | return primary_if; |
250 | } | 254 | } |
251 | 255 | ||
256 | /** | ||
257 | * batadv_skb_set_priority - sets skb priority according to packet content | ||
258 | * @skb: the packet to be sent | ||
259 | * @offset: offset to the packet content | ||
260 | * | ||
261 | * This function sets a value between 256 and 263 (802.1d priority), which | ||
262 | * can be interpreted by the cfg80211 or other drivers. | ||
263 | */ | ||
264 | void batadv_skb_set_priority(struct sk_buff *skb, int offset) | ||
265 | { | ||
266 | struct iphdr ip_hdr_tmp, *ip_hdr; | ||
267 | struct ipv6hdr ip6_hdr_tmp, *ip6_hdr; | ||
268 | struct ethhdr ethhdr_tmp, *ethhdr; | ||
269 | struct vlan_ethhdr *vhdr, vhdr_tmp; | ||
270 | u32 prio; | ||
271 | |||
272 | /* already set, do nothing */ | ||
273 | if (skb->priority >= 256 && skb->priority <= 263) | ||
274 | return; | ||
275 | |||
276 | ethhdr = skb_header_pointer(skb, offset, sizeof(*ethhdr), ðhdr_tmp); | ||
277 | if (!ethhdr) | ||
278 | return; | ||
279 | |||
280 | switch (ethhdr->h_proto) { | ||
281 | case htons(ETH_P_8021Q): | ||
282 | vhdr = skb_header_pointer(skb, offset + sizeof(*vhdr), | ||
283 | sizeof(*vhdr), &vhdr_tmp); | ||
284 | if (!vhdr) | ||
285 | return; | ||
286 | prio = ntohs(vhdr->h_vlan_TCI) & VLAN_PRIO_MASK; | ||
287 | prio = prio >> VLAN_PRIO_SHIFT; | ||
288 | break; | ||
289 | case htons(ETH_P_IP): | ||
290 | ip_hdr = skb_header_pointer(skb, offset + sizeof(*ethhdr), | ||
291 | sizeof(*ip_hdr), &ip_hdr_tmp); | ||
292 | if (!ip_hdr) | ||
293 | return; | ||
294 | prio = (ipv4_get_dsfield(ip_hdr) & 0xfc) >> 5; | ||
295 | break; | ||
296 | case htons(ETH_P_IPV6): | ||
297 | ip6_hdr = skb_header_pointer(skb, offset + sizeof(*ethhdr), | ||
298 | sizeof(*ip6_hdr), &ip6_hdr_tmp); | ||
299 | if (!ip6_hdr) | ||
300 | return; | ||
301 | prio = (ipv6_get_dsfield(ip6_hdr) & 0xfc) >> 5; | ||
302 | break; | ||
303 | default: | ||
304 | return; | ||
305 | } | ||
306 | |||
307 | skb->priority = prio + 256; | ||
308 | } | ||
309 | |||
252 | static int batadv_recv_unhandled_packet(struct sk_buff *skb, | 310 | static int batadv_recv_unhandled_packet(struct sk_buff *skb, |
253 | struct batadv_hard_iface *recv_if) | 311 | struct batadv_hard_iface *recv_if) |
254 | { | 312 | { |