Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 102770
b: refs/heads/master
c: e245494
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed May 22, 2008
1 parent b8489ac commit e8ffbe7
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 117 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2e92e6f2c50b4baf85cca968f0e6f1b5c0df7d39
refs/heads/master: e24549485f859be6518929bb1c9c0257d79f033d
234 changes: 118 additions & 116 deletions trunk/net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,106 +505,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
return TX_CONTINUE;
}

static ieee80211_tx_result
ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
size_t hdrlen, per_fragm, num_fragm, payload_len, left;
struct sk_buff **frags, *first, *frag;
int i;
u16 seq;
u8 *pos;
int frag_threshold = tx->local->fragmentation_threshold;

if (!(tx->flags & IEEE80211_TX_FRAGMENTED))
return TX_CONTINUE;

first = tx->skb;

hdrlen = ieee80211_get_hdrlen(tx->fc);
payload_len = first->len - hdrlen;
per_fragm = frag_threshold - hdrlen - FCS_LEN;
num_fragm = DIV_ROUND_UP(payload_len, per_fragm);

frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC);
if (!frags)
goto fail;

hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ;
pos = first->data + hdrlen + per_fragm;
left = payload_len - per_fragm;
for (i = 0; i < num_fragm - 1; i++) {
struct ieee80211_hdr *fhdr;
size_t copylen;

if (left <= 0)
goto fail;

/* reserve enough extra head and tail room for possible
* encryption */
frag = frags[i] =
dev_alloc_skb(tx->local->tx_headroom +
frag_threshold +
IEEE80211_ENCRYPT_HEADROOM +
IEEE80211_ENCRYPT_TAILROOM);
if (!frag)
goto fail;
/* Make sure that all fragments use the same priority so
* that they end up using the same TX queue */
frag->priority = first->priority;
skb_reserve(frag, tx->local->tx_headroom +
IEEE80211_ENCRYPT_HEADROOM);
fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);
memcpy(fhdr, first->data, hdrlen);
if (i == num_fragm - 2)
fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);
fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG));
copylen = left > per_fragm ? per_fragm : left;
memcpy(skb_put(frag, copylen), pos, copylen);

pos += copylen;
left -= copylen;
}
skb_trim(first, hdrlen + per_fragm);

tx->num_extra_frag = num_fragm - 1;
tx->extra_frag = frags;

return TX_CONTINUE;

fail:
printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
if (frags) {
for (i = 0; i < num_fragm - 1; i++)
if (frags[i])
dev_kfree_skb(frags[i]);
kfree(frags);
}
I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);
return TX_DROP;
}

static ieee80211_tx_result
ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
{
if (!tx->key)
return TX_CONTINUE;

switch (tx->key->conf.alg) {
case ALG_WEP:
return ieee80211_crypto_wep_encrypt(tx);
case ALG_TKIP:
return ieee80211_crypto_tkip_encrypt(tx);
case ALG_CCMP:
return ieee80211_crypto_ccmp_encrypt(tx);
}

/* not reached */
WARN_ON(1);
return TX_DROP;
}

static ieee80211_tx_result
ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
{
Expand Down Expand Up @@ -747,26 +647,114 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
control->rts_cts_rate_idx = 0;
}

if (tx->sta) {
if (tx->sta)
control->aid = tx->sta->aid;
tx->sta->tx_packets++;
tx->sta->tx_fragments++;
tx->sta->tx_bytes += tx->skb->len;
if (tx->extra_frag) {
int i;
tx->sta->tx_fragments += tx->num_extra_frag;
for (i = 0; i < tx->num_extra_frag; i++) {
tx->sta->tx_bytes +=
tx->extra_frag[i]->len;
}
}

return TX_CONTINUE;
}

static ieee80211_tx_result
ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
size_t hdrlen, per_fragm, num_fragm, payload_len, left;
struct sk_buff **frags, *first, *frag;
int i;
u16 seq;
u8 *pos;
int frag_threshold = tx->local->fragmentation_threshold;

if (!(tx->flags & IEEE80211_TX_FRAGMENTED))
return TX_CONTINUE;

first = tx->skb;

hdrlen = ieee80211_get_hdrlen(tx->fc);
payload_len = first->len - hdrlen;
per_fragm = frag_threshold - hdrlen - FCS_LEN;
num_fragm = DIV_ROUND_UP(payload_len, per_fragm);

frags = kzalloc(num_fragm * sizeof(struct sk_buff *), GFP_ATOMIC);
if (!frags)
goto fail;

hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ;
pos = first->data + hdrlen + per_fragm;
left = payload_len - per_fragm;
for (i = 0; i < num_fragm - 1; i++) {
struct ieee80211_hdr *fhdr;
size_t copylen;

if (left <= 0)
goto fail;

/* reserve enough extra head and tail room for possible
* encryption */
frag = frags[i] =
dev_alloc_skb(tx->local->tx_headroom +
frag_threshold +
IEEE80211_ENCRYPT_HEADROOM +
IEEE80211_ENCRYPT_TAILROOM);
if (!frag)
goto fail;
/* Make sure that all fragments use the same priority so
* that they end up using the same TX queue */
frag->priority = first->priority;
skb_reserve(frag, tx->local->tx_headroom +
IEEE80211_ENCRYPT_HEADROOM);
fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen);
memcpy(fhdr, first->data, hdrlen);
if (i == num_fragm - 2)
fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);
fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG));
copylen = left > per_fragm ? per_fragm : left;
memcpy(skb_put(frag, copylen), pos, copylen);

pos += copylen;
left -= copylen;
}
skb_trim(first, hdrlen + per_fragm);

tx->num_extra_frag = num_fragm - 1;
tx->extra_frag = frags;

return TX_CONTINUE;

fail:
printk(KERN_DEBUG "%s: failed to fragment frame\n", tx->dev->name);
if (frags) {
for (i = 0; i < num_fragm - 1; i++)
if (frags[i])
dev_kfree_skb(frags[i]);
kfree(frags);
}
I802_DEBUG_INC(tx->local->tx_handlers_drop_fragment);
return TX_DROP;
}

static ieee80211_tx_result
ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
{
if (!tx->key)
return TX_CONTINUE;

switch (tx->key->conf.alg) {
case ALG_WEP:
return ieee80211_crypto_wep_encrypt(tx);
case ALG_TKIP:
return ieee80211_crypto_tkip_encrypt(tx);
case ALG_CCMP:
return ieee80211_crypto_ccmp_encrypt(tx);
}

/* not reached */
WARN_ON(1);
return TX_DROP;
}

static ieee80211_tx_result
ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
{
struct ieee80211_local *local = tx->local;
struct sk_buff *skb = tx->skb;
Expand Down Expand Up @@ -822,6 +810,20 @@ ieee80211_tx_h_load_stats(struct ieee80211_tx_data *tx)
tx->sta->channel_use_raw += load;
tx->sdata->channel_use_raw += load;

if (tx->sta) {
tx->sta->tx_packets++;
tx->sta->tx_fragments++;
tx->sta->tx_bytes += tx->skb->len;
if (tx->extra_frag) {
int i;
tx->sta->tx_fragments += tx->num_extra_frag;
for (i = 0; i < tx->num_extra_frag; i++) {
tx->sta->tx_bytes +=
tx->extra_frag[i]->len;
}
}
}

return TX_CONTINUE;
}

Expand All @@ -834,11 +836,11 @@ static ieee80211_tx_handler ieee80211_tx_handlers[] =
ieee80211_tx_h_ps_buf,
ieee80211_tx_h_select_key,
ieee80211_tx_h_michael_mic_add,
ieee80211_tx_h_fragment,
ieee80211_tx_h_encrypt,
ieee80211_tx_h_rate_ctrl,
ieee80211_tx_h_misc,
ieee80211_tx_h_load_stats,
ieee80211_tx_h_fragment,
ieee80211_tx_h_encrypt,
ieee80211_tx_h_stats,
NULL
};

Expand Down

0 comments on commit e8ffbe7

Please sign in to comment.