Skip to content

Commit

Permalink
batman-adv: set skb priority according to content
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Simon Wunderlich authored and Antonio Quartulli committed Aug 28, 2013
1 parent 5b2941b commit c54f38c
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 2 deletions.
1 change: 1 addition & 0 deletions net/batman-adv/bat_iv_ogm.c
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
kfree(forw_packet_aggr);
goto out;
}
forw_packet_aggr->skb->priority = TC_PRIO_CONTROL;
skb_reserve(forw_packet_aggr->skb, ETH_HLEN);

skb_buff = skb_put(forw_packet_aggr->skb, packet_len);
Expand Down
1 change: 1 addition & 0 deletions net/batman-adv/icmp_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
goto out;
}

skb->priority = TC_PRIO_CONTROL;
skb_reserve(skb, ETH_HLEN);
icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len);

Expand Down
58 changes: 58 additions & 0 deletions net/batman-adv/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

#include <linux/crc32c.h>
#include <linux/highmem.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/dsfield.h>
#include "main.h"
#include "sysfs.h"
#include "debugfs.h"
Expand Down Expand Up @@ -249,6 +253,60 @@ batadv_seq_print_text_primary_if_get(struct seq_file *seq)
return primary_if;
}

/**
* batadv_skb_set_priority - sets skb priority according to packet content
* @skb: the packet to be sent
* @offset: offset to the packet content
*
* This function sets a value between 256 and 263 (802.1d priority), which
* can be interpreted by the cfg80211 or other drivers.
*/
void batadv_skb_set_priority(struct sk_buff *skb, int offset)
{
struct iphdr ip_hdr_tmp, *ip_hdr;
struct ipv6hdr ip6_hdr_tmp, *ip6_hdr;
struct ethhdr ethhdr_tmp, *ethhdr;
struct vlan_ethhdr *vhdr, vhdr_tmp;
u32 prio;

/* already set, do nothing */
if (skb->priority >= 256 && skb->priority <= 263)
return;

ethhdr = skb_header_pointer(skb, offset, sizeof(*ethhdr), &ethhdr_tmp);
if (!ethhdr)
return;

switch (ethhdr->h_proto) {
case htons(ETH_P_8021Q):
vhdr = skb_header_pointer(skb, offset + sizeof(*vhdr),
sizeof(*vhdr), &vhdr_tmp);
if (!vhdr)
return;
prio = ntohs(vhdr->h_vlan_TCI) & VLAN_PRIO_MASK;
prio = prio >> VLAN_PRIO_SHIFT;
break;
case htons(ETH_P_IP):
ip_hdr = skb_header_pointer(skb, offset + sizeof(*ethhdr),
sizeof(*ip_hdr), &ip_hdr_tmp);
if (!ip_hdr)
return;
prio = (ipv4_get_dsfield(ip_hdr) & 0xfc) >> 5;
break;
case htons(ETH_P_IPV6):
ip6_hdr = skb_header_pointer(skb, offset + sizeof(*ethhdr),
sizeof(*ip6_hdr), &ip6_hdr_tmp);
if (!ip6_hdr)
return;
prio = (ipv6_get_dsfield(ip6_hdr) & 0xfc) >> 5;
break;
default:
return;
}

skb->priority = prio + 256;
}

static int batadv_recv_unhandled_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
Expand Down
1 change: 1 addition & 0 deletions net/batman-adv/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ void batadv_mesh_free(struct net_device *soft_iface);
int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr);
struct batadv_hard_iface *
batadv_seq_print_text_primary_if_get(struct seq_file *seq);
void batadv_skb_set_priority(struct sk_buff *skb, int offset);
int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype,
struct net_device *orig_dev);
Expand Down
20 changes: 19 additions & 1 deletion net/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
struct batadv_neigh_node *neigh_node = NULL;
struct batadv_unicast_packet *unicast_packet;
struct ethhdr *ethhdr = eth_hdr(skb);
int res, ret = NET_RX_DROP;
int res, hdr_len, ret = NET_RX_DROP;
struct sk_buff *new_skb;

unicast_packet = (struct batadv_unicast_packet *)skb->data;
Expand Down Expand Up @@ -835,6 +835,22 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
/* decrement ttl */
unicast_packet->header.ttl--;

switch (unicast_packet->header.packet_type) {
case BATADV_UNICAST_4ADDR:
hdr_len = sizeof(struct batadv_unicast_4addr_packet);
break;
case BATADV_UNICAST:
hdr_len = sizeof(struct batadv_unicast_packet);
break;
default:
/* other packet types not supported - yet */
hdr_len = -1;
break;
}

if (hdr_len > 0)
batadv_skb_set_priority(skb, hdr_len);

res = batadv_send_skb_to_orig(skb, orig_node, recv_if);

/* translate transmit result into receive result */
Expand Down Expand Up @@ -1193,6 +1209,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
if (batadv_bla_check_bcast_duplist(bat_priv, skb))
goto out;

batadv_skb_set_priority(skb, sizeof(struct batadv_bcast_packet));

/* rebroadcast packet */
batadv_add_bcast_packet_to_list(bat_priv, skb, 1);

Expand Down
1 change: 0 additions & 1 deletion net/batman-adv/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ int batadv_send_skb_packet(struct sk_buff *skb,
ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);

skb_set_network_header(skb, ETH_HLEN);
skb->priority = TC_PRIO_CONTROL;
skb->protocol = __constant_htons(ETH_P_BATMAN);

skb->dev = hard_iface->net_dev;
Expand Down
2 changes: 2 additions & 0 deletions net/batman-adv/soft-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
*/
}

batadv_skb_set_priority(skb, 0);

/* ethernet packet should be broadcasted */
if (do_bcast) {
primary_if = batadv_primary_if_get_selected(bat_priv);
Expand Down
5 changes: 5 additions & 0 deletions net/batman-adv/translation-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
if (!skb)
goto out;

skb->priority = TC_PRIO_CONTROL;
skb_reserve(skb, ETH_HLEN);
tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
tt_response->ttvn = ttvn;
Expand Down Expand Up @@ -1691,6 +1692,7 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
if (!skb)
goto out;

skb->priority = TC_PRIO_CONTROL;
skb_reserve(skb, ETH_HLEN);

tt_req_len = sizeof(*tt_request);
Expand Down Expand Up @@ -1788,6 +1790,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
if (!skb)
goto unlock;

skb->priority = TC_PRIO_CONTROL;
skb_reserve(skb, ETH_HLEN);
packet_pos = skb_put(skb, len);
tt_response = (struct batadv_tt_query_packet *)packet_pos;
Expand Down Expand Up @@ -1906,6 +1909,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
if (!skb)
goto unlock;

skb->priority = TC_PRIO_CONTROL;
skb_reserve(skb, ETH_HLEN);
packet_pos = skb_put(skb, len);
tt_response = (struct batadv_tt_query_packet *)packet_pos;
Expand Down Expand Up @@ -2240,6 +2244,7 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
if (!skb)
goto out;

skb->priority = TC_PRIO_CONTROL;
skb_reserve(skb, ETH_HLEN);

roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
Expand Down
2 changes: 2 additions & 0 deletions net/batman-adv/unicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv,
frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
if (!frag_skb)
goto dropped;

skb->priority = TC_PRIO_CONTROL;
skb_reserve(frag_skb, ucf_hdr_len);

unicast_packet = (struct batadv_unicast_packet *)skb->data;
Expand Down
2 changes: 2 additions & 0 deletions net/batman-adv/vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ batadv_add_packet(struct batadv_priv *bat_priv,
kfree(info);
return NULL;
}
info->skb_packet->priority = TC_PRIO_CONTROL;
skb_reserve(info->skb_packet, ETH_HLEN);
packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);

Expand Down Expand Up @@ -861,6 +862,7 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
if (!bat_priv->vis.my_info->skb_packet)
goto free_info;

bat_priv->vis.my_info->skb_packet->priority = TC_PRIO_CONTROL;
skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
tmp_skb = bat_priv->vis.my_info->skb_packet;
packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
Expand Down

0 comments on commit c54f38c

Please sign in to comment.