summaryrefslogtreecommitdiffstats
path: root/drivers/net/ifb.c
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2017-01-07 23:06:38 +0100
committerDavid S. Miller <davem@davemloft.net>2017-01-09 02:58:52 +0100
commitbc31c905e946b5c55df5d2938335e78ffb3157ca (patch)
tree2a40cf0584931cbc96185814f8d922fd4f363f00 /drivers/net/ifb.c
parentnet-tc: convert tc_at to tc_at_ingress (diff)
downloadlinux-bc31c905e946b5c55df5d2938335e78ffb3157ca.tar.xz
linux-bc31c905e946b5c55df5d2938335e78ffb3157ca.zip
net-tc: convert tc_from to tc_from_ingress and tc_redirected
The tc_from field fulfills two roles. It encodes whether a packet was redirected by an act_mirred device and, if so, whether act_mirred was called on ingress or egress. Split it into separate fields. The information is needed by the special IFB loop, where packets are taken out of the normal path by act_mirred, forwarded to IFB, then reinjected at their original location (ingress or egress) by IFB. The IFB device cannot use skb->tc_at_ingress, because that may have been overwritten as the packet travels from act_mirred to ifb_xmit, when it passes through tc_classify on the IFB egress path. Cache this value in skb->tc_from_ingress. That field is valid only if a packet arriving at ifb_xmit came from act_mirred. Other packets can be crafted to reach ifb_xmit. These must be dropped. Set tc_redirected on redirection and drop all packets that do not have this bit set. Both fields are set only on cloned skbs in tc actions, so original packet sources do not have to clear the bit when reusing packets (notably, pktgen and octeon). Signed-off-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ifb.c')
-rw-r--r--drivers/net/ifb.c13
1 files changed, 5 insertions, 8 deletions
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index b73b6b6c066b..312fce7302d3 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -78,9 +78,7 @@ static void ifb_ri_tasklet(unsigned long _txp)
}
while ((skb = __skb_dequeue(&txp->tq)) != NULL) {
- u32 from = skb->tc_from;
-
- skb_reset_tc(skb);
+ skb->tc_redirected = 0;
skb->tc_skip_classify = 1;
u64_stats_update_begin(&txp->tsync);
@@ -101,13 +99,12 @@ static void ifb_ri_tasklet(unsigned long _txp)
rcu_read_unlock();
skb->skb_iif = txp->dev->ifindex;
- if (from & AT_EGRESS) {
+ if (!skb->tc_from_ingress) {
dev_queue_xmit(skb);
- } else if (from & AT_INGRESS) {
+ } else {
skb_pull(skb, skb->mac_len);
netif_receive_skb(skb);
- } else
- BUG();
+ }
}
if (__netif_tx_trylock(txq)) {
@@ -246,7 +243,7 @@ static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
txp->rx_bytes += skb->len;
u64_stats_update_end(&txp->rsync);
- if (skb->tc_from == AT_STACK || !skb->skb_iif) {
+ if (!skb->tc_redirected || !skb->skb_iif) {
dev_kfree_skb(skb);
dev->stats.rx_dropped++;
return NETDEV_TX_OK;