rocker: add offload_fwd_mark support
authorScott Feldman <sfeldma@gmail.com>
Sun, 19 Jul 2015 01:24:51 +0000 (18:24 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 21 Jul 2015 01:32:45 +0000 (18:32 -0700)
If device flags ingress packet as "fwd offload", mark the
skb->offlaod_fwd_mark using the ingress port's dev->offlaod_fwd_mark.  This
will be the hint to the kernel that this packet has already been forwarded
by device to egress ports matching skb->offlaod_fwd_mark.

For rocker, derive port dev->offlaod_fwd_mark based on device switch ID and
port ifindex.  If port is bridged, use the bridge ifindex rather than the
port ifindex.

Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/rocker/rocker.c
drivers/net/ethernet/rocker/rocker.h

index 4ccde93..7b4c347 100644 (file)
@@ -4822,6 +4822,7 @@ static int rocker_port_rx_proc(const struct rocker *rocker,
        const struct rocker_tlv *attrs[ROCKER_TLV_RX_MAX + 1];
        struct sk_buff *skb = rocker_desc_cookie_ptr_get(desc_info);
        size_t rx_len;
+       u16 rx_flags = 0;
 
        if (!skb)
                return -ENOENT;
@@ -4829,6 +4830,8 @@ static int rocker_port_rx_proc(const struct rocker *rocker,
        rocker_tlv_parse_desc(attrs, ROCKER_TLV_RX_MAX, desc_info);
        if (!attrs[ROCKER_TLV_RX_FRAG_LEN])
                return -EINVAL;
+       if (attrs[ROCKER_TLV_RX_FLAGS])
+               rx_flags = rocker_tlv_get_u16(attrs[ROCKER_TLV_RX_FLAGS]);
 
        rocker_dma_rx_ring_skb_unmap(rocker, attrs);
 
@@ -4836,6 +4839,9 @@ static int rocker_port_rx_proc(const struct rocker *rocker,
        skb_put(skb, rx_len);
        skb->protocol = eth_type_trans(skb, rocker_port->dev);
 
+       if (rx_flags & ROCKER_RX_FLAGS_FWD_OFFLOAD)
+               skb->offload_fwd_mark = rocker_port->dev->offload_fwd_mark;
+
        rocker_port->dev->stats.rx_packets++;
        rocker_port->dev->stats.rx_bytes += skb->len;
 
@@ -4973,6 +4979,8 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
        }
        rocker->ports[port_number] = rocker_port;
 
+       switchdev_port_fwd_mark_set(rocker_port->dev, NULL, false);
+
        rocker_port_set_learning(rocker_port, SWITCHDEV_TRANS_NONE);
 
        err = rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE, 0);
@@ -5252,6 +5260,7 @@ static int rocker_port_bridge_join(struct rocker_port *rocker_port,
                rocker_port_internal_vlan_id_get(rocker_port, bridge->ifindex);
 
        rocker_port->bridge_dev = bridge;
+       switchdev_port_fwd_mark_set(rocker_port->dev, bridge, true);
 
        return rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE,
                                    untagged_vid, 0);
@@ -5272,6 +5281,8 @@ static int rocker_port_bridge_leave(struct rocker_port *rocker_port)
                rocker_port_internal_vlan_id_get(rocker_port,
                                                 rocker_port->dev->ifindex);
 
+       switchdev_port_fwd_mark_set(rocker_port->dev, rocker_port->bridge_dev,
+                                   false);
        rocker_port->bridge_dev = NULL;
 
        err = rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE,
index 08b2c3d..12490b2 100644 (file)
@@ -246,6 +246,7 @@ enum {
 #define ROCKER_RX_FLAGS_TCP                    BIT(5)
 #define ROCKER_RX_FLAGS_UDP                    BIT(6)
 #define ROCKER_RX_FLAGS_TCP_UDP_CSUM_GOOD      BIT(7)
+#define ROCKER_RX_FLAGS_FWD_OFFLOAD            BIT(8)
 
 enum {
        ROCKER_TLV_TX_UNSPEC,