summaryrefslogtreecommitdiffstats
path: root/net/batman-adv/main.c
diff options
context:
space:
mode:
authorSimon Wunderlich <simon@open-mesh.com>2013-07-29 11:56:44 -0400
committerAntonio Quartulli <ordex@autistici.org>2013-08-28 05:31:50 -0400
commitc54f38c9aa22ff65ca9f4c1bdbf2a11d017205f3 (patch)
treee12190c69088c2fee771a49e94c5ab6619ec3817 /net/batman-adv/main.c
parent5b2941b18dc5f60a5c14a5c15693f9c58b0dd922 (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.c58
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 */
264void 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), &ethhdr_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
252static int batadv_recv_unhandled_packet(struct sk_buff *skb, 310static 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{