[PATCH v3 1/2] i40e: fix VLAN.TCI == 0 RX HW offload

2018-12-04 Thread Michał Mirosław
This fixes two bugs in hardware VLAN offload:
 1. VLAN.TCI == 0 was being dropped
 2. there was a race between disabling of VLAN RX feature in hardware
and processing RX queue, where packets processed in this window
could have their VLAN information dropped

Fix moves the VLAN handling into i40e_process_skb_fields() to save on
duplicated code. i40e_receive_skb() becomes trivial and so is removed.

Signed-off-by: Michał Mirosław 
Signed-off-by: Michał Mirosław 
---
v3:
 * fix whitespace for checkpatch
v2:
 * no changes
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   | 31 +--
 .../ethernet/intel/i40e/i40e_txrx_common.h|  2 --
 drivers/net/ethernet/intel/i40e/i40e_xsk.c|  6 +---
 3 files changed, 9 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c 
b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index aef3c89ee79c..bc6a873ec574 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1558,24 +1558,6 @@ static bool i40e_alloc_mapped_page(struct i40e_ring 
*rx_ring,
return true;
 }
 
-/**
- * i40e_receive_skb - Send a completed packet up the stack
- * @rx_ring:  rx ring in play
- * @skb: packet to send up
- * @vlan_tag: vlan tag for packet
- **/
-void i40e_receive_skb(struct i40e_ring *rx_ring,
- struct sk_buff *skb, u16 vlan_tag)
-{
-   struct i40e_q_vector *q_vector = rx_ring->q_vector;
-
-   if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
-   (vlan_tag & VLAN_VID_MASK))
-   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
-
-   napi_gro_receive(_vector->napi, skb);
-}
-
 /**
  * i40e_alloc_rx_buffers - Replace used receive buffers
  * @rx_ring: ring to place buffers on
@@ -1812,6 +1794,13 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
 
skb_record_rx_queue(skb, rx_ring->queue_index);
 
+   if (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) {
+   u16 vlan_tag = rx_desc->wb.qword0.lo_dword.l2tag1;
+
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+  le16_to_cpu(vlan_tag));
+   }
+
/* modifies the skb - consumes the enet header */
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 }
@@ -2350,7 +2339,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u16 vlan_tag;
u8 rx_ptype;
u64 qword;
 
@@ -2451,11 +2439,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
/* populate checksum, VLAN, and protocol */
i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
 
-   vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
-  le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
-
i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
-   i40e_receive_skb(rx_ring, skb, vlan_tag);
+   napi_gro_receive(_ring->q_vector->napi, skb);
skb = NULL;
 
/* update budget accounting */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h 
b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
index 09809dffe399..2c077f1c4eca 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
@@ -14,8 +14,6 @@ struct i40e_rx_buffer *i40e_clean_programming_status(
 void i40e_process_skb_fields(struct i40e_ring *rx_ring,
 union i40e_rx_desc *rx_desc, struct sk_buff *skb,
 u8 rx_ptype);
-void i40e_receive_skb(struct i40e_ring *rx_ring,
- struct sk_buff *skb, u16 vlan_tag);
 void i40e_xdp_ring_update_tail(struct i40e_ring *xdp_ring);
 void i40e_update_rx_stats(struct i40e_ring *rx_ring,
  unsigned int total_rx_bytes,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c 
b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index 433c8e688c78..a6ea2b249471 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -634,7 +634,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
struct i40e_rx_buffer *bi;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u16 vlan_tag;
u8 rx_ptype;
u64 qword;
 
@@ -717,10 +716,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
   I40E_RXD_QW1_PTYPE_SHIFT;
i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
-
- 

[PATCH v3 2/2] i40e: DRY rx_ptype handling code

2018-12-04 Thread Michał Mirosław
Move rx_ptype extracting to i40e_process_skb_fields() to avoid
duplicating the code.

Signed-off-by: Michał Mirosław 
Signed-off-by: Michał Mirosław 
---
v3:
 * no changes
v2:
 * fix prototype in i40e_txrx_common.h
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c| 12 
 drivers/net/ethernet/intel/i40e/i40e_txrx_common.h |  3 +--
 drivers/net/ethernet/intel/i40e/i40e_xsk.c |  6 +-
 3 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c 
b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index bc6a873ec574..d0a95424ce58 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1775,8 +1775,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,
  * other fields within the skb.
  **/
 void i40e_process_skb_fields(struct i40e_ring *rx_ring,
-union i40e_rx_desc *rx_desc, struct sk_buff *skb,
-u8 rx_ptype)
+union i40e_rx_desc *rx_desc, struct sk_buff *skb)
 {
u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
@@ -1784,6 +1783,8 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
u32 tsynvalid = rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK;
u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
   I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT;
+   u8 rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT;
 
if (unlikely(tsynvalid))
i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);
@@ -2339,7 +2340,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u8 rx_ptype;
u64 qword;
 
/* return some buffers to hardware, one at a time is too slow */
@@ -2432,12 +2432,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
 
-   qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-   rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-  I40E_RXD_QW1_PTYPE_SHIFT;
-
/* populate checksum, VLAN, and protocol */
-   i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
+   i40e_process_skb_fields(rx_ring, rx_desc, skb);
 
i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
napi_gro_receive(_ring->q_vector->napi, skb);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h 
b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
index 2c077f1c4eca..8af0e99c6c0d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
@@ -12,8 +12,7 @@ struct i40e_rx_buffer *i40e_clean_programming_status(
union i40e_rx_desc *rx_desc,
u64 qw);
 void i40e_process_skb_fields(struct i40e_ring *rx_ring,
-union i40e_rx_desc *rx_desc, struct sk_buff *skb,
-u8 rx_ptype);
+union i40e_rx_desc *rx_desc, struct sk_buff *skb);
 void i40e_xdp_ring_update_tail(struct i40e_ring *xdp_ring);
 void i40e_update_rx_stats(struct i40e_ring *rx_ring,
  unsigned int total_rx_bytes,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c 
b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index a6ea2b249471..870cf654e436 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -634,7 +634,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
struct i40e_rx_buffer *bi;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u8 rx_ptype;
u64 qword;
 
if (cleaned_count >= I40E_RX_BUFFER_WRITE) {
@@ -712,10 +711,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
total_rx_bytes += skb->len;
total_rx_packets++;
 
-   qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-   rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-  I40E_RXD_QW1_PTYPE_SHIFT;
-   i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
+   i40e_process_skb_fields(rx_ring, rx_desc, skb);
napi_gro_receive(_ring->q_vector->napi, skb);
}
 
-- 
2.19.2



[PATCH net v2 2/2] i40e: DRY rx_ptype handling code

2018-11-29 Thread Michał Mirosław
Move rx_ptype extracting to i40e_process_skb_fields() to avoid
duplicating the code.

Signed-off-by: Michał Mirosław 
Signed-off-by: Michał Mirosław 
---
v2:
 * fix prototype in i40e_txrx_common.h
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c| 12 
 drivers/net/ethernet/intel/i40e/i40e_txrx_common.h |  3 +--
 drivers/net/ethernet/intel/i40e/i40e_xsk.c |  6 +-
 3 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c 
b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 2cd69c65d722..48872d51fd31 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1775,8 +1775,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,
  * other fields within the skb.
  **/
 void i40e_process_skb_fields(struct i40e_ring *rx_ring,
-union i40e_rx_desc *rx_desc, struct sk_buff *skb,
-u8 rx_ptype)
+union i40e_rx_desc *rx_desc, struct sk_buff *skb)
 {
u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
@@ -1784,6 +1783,8 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
u32 tsynvalid = rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK;
u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
   I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT;
+   u8 rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT;
 
if (unlikely(tsynvalid))
i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);
@@ -2338,7 +2339,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u8 rx_ptype;
u64 qword;
 
/* return some buffers to hardware, one at a time is too slow */
@@ -2431,12 +2431,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
 
-   qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-   rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-  I40E_RXD_QW1_PTYPE_SHIFT;
-
/* populate checksum, VLAN, and protocol */
-   i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
+   i40e_process_skb_fields(rx_ring, rx_desc, skb);
 
i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
napi_gro_receive(_ring->q_vector->napi, skb);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h 
b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
index 2c077f1c4eca..8af0e99c6c0d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
@@ -12,8 +12,7 @@ struct i40e_rx_buffer *i40e_clean_programming_status(
union i40e_rx_desc *rx_desc,
u64 qw);
 void i40e_process_skb_fields(struct i40e_ring *rx_ring,
-union i40e_rx_desc *rx_desc, struct sk_buff *skb,
-u8 rx_ptype);
+union i40e_rx_desc *rx_desc, struct sk_buff *skb);
 void i40e_xdp_ring_update_tail(struct i40e_ring *xdp_ring);
 void i40e_update_rx_stats(struct i40e_ring *rx_ring,
  unsigned int total_rx_bytes,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c 
b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index a6ea2b249471..870cf654e436 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -634,7 +634,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
struct i40e_rx_buffer *bi;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u8 rx_ptype;
u64 qword;
 
if (cleaned_count >= I40E_RX_BUFFER_WRITE) {
@@ -712,10 +711,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
total_rx_bytes += skb->len;
total_rx_packets++;
 
-   qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-   rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-  I40E_RXD_QW1_PTYPE_SHIFT;
-   i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
+   i40e_process_skb_fields(rx_ring, rx_desc, skb);
napi_gro_receive(_ring->q_vector->napi, skb);
}
 
-- 
2.19.2



[PATCH net v2 1/2] i40e: fix VLAN.TCI == 0 RX HW offload

2018-11-29 Thread Michał Mirosław
This fixes two bugs in hardware VLAN offload:
 1. VLAN.TCI == 0 was being dropped
 2. there was a race between disabling of VLAN RX feature in hardware
and processing RX queue, where packets processed in this window
could have their VLAN information dropped

Fix moves the VLAN handling into i40e_process_skb_fields() to save on
duplicated code. i40e_receive_skb() becomes trivial and so is removed.

Signed-off-by: Michał Mirosław 
Signed-off-by: Michał Mirosław 
---
v2:
 * no changes
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   | 30 +--
 .../ethernet/intel/i40e/i40e_txrx_common.h|  2 --
 drivers/net/ethernet/intel/i40e/i40e_xsk.c|  6 +---
 3 files changed, 8 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c 
b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index aef3c89ee79c..2cd69c65d722 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1558,24 +1558,6 @@ static bool i40e_alloc_mapped_page(struct i40e_ring 
*rx_ring,
return true;
 }
 
-/**
- * i40e_receive_skb - Send a completed packet up the stack
- * @rx_ring:  rx ring in play
- * @skb: packet to send up
- * @vlan_tag: vlan tag for packet
- **/
-void i40e_receive_skb(struct i40e_ring *rx_ring,
- struct sk_buff *skb, u16 vlan_tag)
-{
-   struct i40e_q_vector *q_vector = rx_ring->q_vector;
-
-   if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
-   (vlan_tag & VLAN_VID_MASK))
-   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
-
-   napi_gro_receive(_vector->napi, skb);
-}
-
 /**
  * i40e_alloc_rx_buffers - Replace used receive buffers
  * @rx_ring: ring to place buffers on
@@ -1812,6 +1794,12 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
 
skb_record_rx_queue(skb, rx_ring->queue_index);
 
+   if (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) {
+   u16 vlan_tag = rx_desc->wb.qword0.lo_dword.l2tag1;
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+  le16_to_cpu(vlan_tag));
+   }
+
/* modifies the skb - consumes the enet header */
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 }
@@ -2350,7 +2338,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u16 vlan_tag;
u8 rx_ptype;
u64 qword;
 
@@ -2451,11 +2438,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
/* populate checksum, VLAN, and protocol */
i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
 
-   vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
-  le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
-
i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
-   i40e_receive_skb(rx_ring, skb, vlan_tag);
+   napi_gro_receive(_ring->q_vector->napi, skb);
skb = NULL;
 
/* update budget accounting */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h 
b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
index 09809dffe399..2c077f1c4eca 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
@@ -14,8 +14,6 @@ struct i40e_rx_buffer *i40e_clean_programming_status(
 void i40e_process_skb_fields(struct i40e_ring *rx_ring,
 union i40e_rx_desc *rx_desc, struct sk_buff *skb,
 u8 rx_ptype);
-void i40e_receive_skb(struct i40e_ring *rx_ring,
- struct sk_buff *skb, u16 vlan_tag);
 void i40e_xdp_ring_update_tail(struct i40e_ring *xdp_ring);
 void i40e_update_rx_stats(struct i40e_ring *rx_ring,
  unsigned int total_rx_bytes,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c 
b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index 433c8e688c78..a6ea2b249471 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -634,7 +634,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
struct i40e_rx_buffer *bi;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u16 vlan_tag;
u8 rx_ptype;
u64 qword;
 
@@ -717,10 +716,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
   I40E_RXD_QW1_PTYPE_SHIFT;
i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
-
-   vlan_tag = (qword & BIT(I40E_RX_DESC_

[PATCH net 2/2] i40e: DRY rx_ptype handling code

2018-11-29 Thread Michał Mirosław
Move rx_ptype extracting to i40e_process_skb_fields() to avoid
duplicating the code.

Signed-off-by: Michał Mirosław 
Signed-off-by: Michał Mirosław 
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c | 12 
 drivers/net/ethernet/intel/i40e/i40e_xsk.c  |  6 +-
 2 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c 
b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 2cd69c65d722..48872d51fd31 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1775,8 +1775,7 @@ static inline void i40e_rx_hash(struct i40e_ring *ring,
  * other fields within the skb.
  **/
 void i40e_process_skb_fields(struct i40e_ring *rx_ring,
-union i40e_rx_desc *rx_desc, struct sk_buff *skb,
-u8 rx_ptype)
+union i40e_rx_desc *rx_desc, struct sk_buff *skb)
 {
u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
@@ -1784,6 +1783,8 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
u32 tsynvalid = rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK;
u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
   I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT;
+   u8 rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+ I40E_RXD_QW1_PTYPE_SHIFT;
 
if (unlikely(tsynvalid))
i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);
@@ -2338,7 +2339,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u8 rx_ptype;
u64 qword;
 
/* return some buffers to hardware, one at a time is too slow */
@@ -2431,12 +2431,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
 
-   qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-   rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-  I40E_RXD_QW1_PTYPE_SHIFT;
-
/* populate checksum, VLAN, and protocol */
-   i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
+   i40e_process_skb_fields(rx_ring, rx_desc, skb);
 
i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
napi_gro_receive(_ring->q_vector->napi, skb);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c 
b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index e783a872707c..605d839d99e3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -634,7 +634,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
struct i40e_rx_buffer *bi;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u8 rx_ptype;
u64 qword;
 
if (cleaned_count >= I40E_RX_BUFFER_WRITE) {
@@ -712,10 +711,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
total_rx_bytes += skb->len;
total_rx_packets++;
 
-   qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-   rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-  I40E_RXD_QW1_PTYPE_SHIFT;
-   i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
+   i40e_process_skb_fields(rx_ring, rx_desc, skb);
napi_gro_receive(_ring->q_vector->napi, skb);
}
 
-- 
2.19.2



[PATCH net 1/2] i40e: fix VLAN.TCI == 0 RX HW offload

2018-11-29 Thread Michał Mirosław
This fixes two bugs in hardware VLAN offload:
 1. VLAN.TCI == 0 was being dropped
 2. there was a race between disabling of VLAN RX feature in hardware
and processing RX queue, where packets processed in this window
could have their VLAN information dropped

Fix moves the VLAN handling into i40e_process_skb_fields() to save on
duplicated code. i40e_receive_skb() becomes trivial and so is removed.

Signed-off-by: Michał Mirosław 
Signed-off-by: Michał Mirosław 
---
 drivers/net/ethernet/intel/i40e/i40e_txrx.c   | 30 +--
 .../ethernet/intel/i40e/i40e_txrx_common.h|  2 --
 drivers/net/ethernet/intel/i40e/i40e_xsk.c|  6 +---
 3 files changed, 8 insertions(+), 30 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c 
b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index aef3c89ee79c..2cd69c65d722 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1558,24 +1558,6 @@ static bool i40e_alloc_mapped_page(struct i40e_ring 
*rx_ring,
return true;
 }
 
-/**
- * i40e_receive_skb - Send a completed packet up the stack
- * @rx_ring:  rx ring in play
- * @skb: packet to send up
- * @vlan_tag: vlan tag for packet
- **/
-void i40e_receive_skb(struct i40e_ring *rx_ring,
- struct sk_buff *skb, u16 vlan_tag)
-{
-   struct i40e_q_vector *q_vector = rx_ring->q_vector;
-
-   if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
-   (vlan_tag & VLAN_VID_MASK))
-   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
-
-   napi_gro_receive(_vector->napi, skb);
-}
-
 /**
  * i40e_alloc_rx_buffers - Replace used receive buffers
  * @rx_ring: ring to place buffers on
@@ -1812,6 +1794,12 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,
 
skb_record_rx_queue(skb, rx_ring->queue_index);
 
+   if (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) {
+   u16 vlan_tag = rx_desc->wb.qword0.lo_dword.l2tag1;
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+  le16_to_cpu(vlan_tag));
+   }
+
/* modifies the skb - consumes the enet header */
skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 }
@@ -2350,7 +2338,6 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
struct i40e_rx_buffer *rx_buffer;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u16 vlan_tag;
u8 rx_ptype;
u64 qword;
 
@@ -2451,11 +2438,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, 
int budget)
/* populate checksum, VLAN, and protocol */
i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
 
-   vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TAG1P_SHIFT)) ?
-  le16_to_cpu(rx_desc->wb.qword0.lo_dword.l2tag1) : 0;
-
i40e_trace(clean_rx_irq_rx, rx_ring, rx_desc, skb);
-   i40e_receive_skb(rx_ring, skb, vlan_tag);
+   napi_gro_receive(_ring->q_vector->napi, skb);
skb = NULL;
 
/* update budget accounting */
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h 
b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
index 09809dffe399..2c077f1c4eca 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx_common.h
@@ -14,8 +14,6 @@ struct i40e_rx_buffer *i40e_clean_programming_status(
 void i40e_process_skb_fields(struct i40e_ring *rx_ring,
 union i40e_rx_desc *rx_desc, struct sk_buff *skb,
 u8 rx_ptype);
-void i40e_receive_skb(struct i40e_ring *rx_ring,
- struct sk_buff *skb, u16 vlan_tag);
 void i40e_xdp_ring_update_tail(struct i40e_ring *xdp_ring);
 void i40e_update_rx_stats(struct i40e_ring *rx_ring,
  unsigned int total_rx_bytes,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c 
b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index add1e457886d..e783a872707c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -634,7 +634,6 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
struct i40e_rx_buffer *bi;
union i40e_rx_desc *rx_desc;
unsigned int size;
-   u16 vlan_tag;
u8 rx_ptype;
u64 qword;
 
@@ -717,10 +716,7 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int 
budget)
rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
   I40E_RXD_QW1_PTYPE_SHIFT;
i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
-
-   vlan_tag = (qword & BIT(I40E_RX_DESC_STATUS_L2TA

[PATCH net-next 4/4] mlx5: use skb_vlan_tag_get_prio()

2018-11-20 Thread Michał Mirosław
Signed-off-by: Michał Mirosław 
---
 drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
index 6dacaeba2fbf..9afdf955f2bc 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
@@ -127,7 +127,7 @@ u16 mlx5e_select_queue(struct net_device *dev, struct 
sk_buff *skb,
else
 #endif
if (skb_vlan_tag_present(skb))
-   up = skb->vlan_tci >> VLAN_PRIO_SHIFT;
+   up = skb_vlan_tag_get_prio(skb);
 
/* channel_ix can be larger than num_channels since
 * dev->num_real_tx_queues = num_channels * num_tc
-- 
2.19.1



[PATCH net-next 0/4] VLAN tag handling cleanup

2018-11-20 Thread Michał Mirosław
This is a cleanup set after VLAN_TAG_PRESENT removal. The CFI bit
handling is made similar to how other tag fields are used.

Michał Mirosław (4):
  net/vlan: introduce skb_vlan_tag_get_cfi() helper
  net/hyperv: use skb_vlan_tag_*() helpers
  benet: use skb_vlan_tag_get_prio()
  mlx5: use skb_vlan_tag_get_prio()

 drivers/net/ethernet/emulex/benet/be_main.c | 2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 2 +-
 drivers/net/hyperv/netvsc_drv.c | 9 +
 include/linux/if_vlan.h | 3 ++-
 4 files changed, 9 insertions(+), 7 deletions(-)

-- 
2.19.1



[PATCH net-next 1/4] net/vlan: introduce skb_vlan_tag_get_cfi() helper

2018-11-20 Thread Michał Mirosław
Abstract CFI/DEI bit access consistently with other VLAN tag fields.

Signed-off-by: Michał Mirosław 
---
 include/linux/if_vlan.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 7a541eadf78e..4cca4da7a6de 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -65,7 +65,7 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct 
sk_buff *skb)
 
 #define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
 #define VLAN_PRIO_SHIFT13
-#define VLAN_CFI_MASK  0x1000 /* Canonical Format Indicator */
+#define VLAN_CFI_MASK  0x1000 /* Canonical Format Indicator / Drop 
Eligible Indicator */
 #define VLAN_VID_MASK  0x0fff /* VLAN Identifier */
 #define VLAN_N_VID 4096
 
@@ -80,6 +80,7 @@ static inline bool is_vlan_dev(const struct net_device *dev)
 #define skb_vlan_tag_present(__skb)((__skb)->vlan_present)
 #define skb_vlan_tag_get(__skb)((__skb)->vlan_tci)
 #define skb_vlan_tag_get_id(__skb) ((__skb)->vlan_tci & VLAN_VID_MASK)
+#define skb_vlan_tag_get_cfi(__skb)(!!((__skb)->vlan_tci & VLAN_CFI_MASK))
 #define skb_vlan_tag_get_prio(__skb)   (((__skb)->vlan_tci & VLAN_PRIO_MASK) 
>> VLAN_PRIO_SHIFT)
 
 static inline int vlan_get_rx_ctag_filter_info(struct net_device *dev)
-- 
2.19.1



[PATCH net-next 2/4] net/hyperv: use skb_vlan_tag_*() helpers

2018-11-20 Thread Michał Mirosław
Replace open-coded bitfield manipulation with skb_vlan_tag_*() helpers.
This also enables correctly passing of VLAN.CFI bit.

Signed-off-by: Michał Mirosław 
---
 drivers/net/hyperv/netvsc_drv.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index cf36e7ff3191..85936ed9e952 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -605,9 +605,9 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct 
net_device *net)
 IEEE_8021Q_INFO);
 
vlan->value = 0;
-   vlan->vlanid = skb->vlan_tci & VLAN_VID_MASK;
-   vlan->pri = (skb->vlan_tci & VLAN_PRIO_MASK) >>
-   VLAN_PRIO_SHIFT;
+   vlan->vlanid = skb_vlan_tag_get_id(skb);
+   vlan->cfi = skb_vlan_tag_get_cfi(skb);
+   vlan->pri = skb_vlan_tag_get_prio(skb);
}
 
if (skb_is_gso(skb)) {
@@ -781,7 +781,8 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct 
net_device *net,
}
 
if (vlan) {
-   u16 vlan_tci = vlan->vlanid | (vlan->pri << VLAN_PRIO_SHIFT);
+   u16 vlan_tci = vlan->vlanid | (vlan->pri << VLAN_PRIO_SHIFT) |
+   (vlan->cfi ? VLAN_CFI_MASK : 0);
 
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
   vlan_tci);
-- 
2.19.1



[PATCH net-next 3/4] benet: use skb_vlan_tag_get_prio()

2018-11-20 Thread Michał Mirosław
Signed-off-by: Michał Mirosław 
---
 drivers/net/ethernet/emulex/benet/be_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_main.c 
b/drivers/net/ethernet/emulex/benet/be_main.c
index 80b2bd3747ce..245abf0d19c0 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -796,7 +796,7 @@ static inline u16 be_get_tx_vlan_tag(struct be_adapter 
*adapter,
u16 vlan_tag;
 
vlan_tag = skb_vlan_tag_get(skb);
-   vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+   vlan_prio = skb_vlan_tag_get_prio(skb);
/* If vlan priority provided by OS is NOT in available bmap */
if (!(adapter->vlan_prio_bmap & (1 << vlan_prio)))
vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) |
-- 
2.19.1



[PATCH net-next] OVS: remove VLAN_TAG_PRESENT - fixup

2018-11-10 Thread Michał Mirosław
It turns out I missed one VLAN_TAG_PRESENT in OVS code while rebasing.
This fixes it.

Fixes: 9df46aefafa6 ("OVS: remove use of VLAN_TAG_PRESENT")
Signed-off-by: Michał Mirosław 
---
 net/openvswitch/flow.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index fa393815991e..57e07768c9d1 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -597,7 +597,7 @@ static int key_extract(struct sk_buff *skb, struct 
sw_flow_key *key)
 * skb_vlan_pop(), which will later shift the ethertype into
 * skb->protocol.
 */
-   if (key->eth.cvlan.tci & htons(VLAN_TAG_PRESENT))
+   if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
skb->protocol = key->eth.cvlan.tpid;
else
skb->protocol = key->eth.type;
-- 
2.19.1



Re: [PATCH net-next 0/4] Remove VLAN_TAG_PRESENT from drivers

2018-11-08 Thread Michał Mirosław
On Thu, Nov 08, 2018 at 08:50:05PM +0200, Leon Romanovsky wrote:
> On Thu, Nov 08, 2018 at 06:44:46PM +0100, Michał Mirosław wrote:
> > This series removes VLAN_TAG_PRESENT use from network drivers in
> > preparation to removing its special meaning.
> Can you please give an extra explanation why it is removed?
> Such series come out-of-blue, for people who are not following
> netdev mailing list closely (drivers/infiniband/*).

This is one of the steps to remove VLAN_TAG_PRESENT overlap with CFI/DEI
bit of VLAN tag. Currently this overlap causes Linux kernel to always
clear CFI/DEI in packets.

There is skb_vlan_tag_present() that drivers should use to check if
the tag in skb is valid.

Best Regards,
Michał Mirosław


[PATCH net-next 0/4] Remove VLAN_TAG_PRESENT from drivers

2018-11-08 Thread Michał Mirosław
This series removes VLAN_TAG_PRESENT use from network drivers in
preparation to removing its special meaning.

Michał Mirosław (4):
  i40iw: remove use of VLAN_TAG_PRESENT
  cnic: remove use of VLAN_TAG_PRESENT
  gianfar: remove use of VLAN_TAG_PRESENT
  OVS: remove use of VLAN_TAG_PRESENT

 drivers/infiniband/hw/i40iw/i40iw_cm.c|  8 +++
 drivers/net/ethernet/broadcom/cnic.c  |  2 +-
 .../net/ethernet/freescale/gianfar_ethtool.c  |  8 +++
 net/openvswitch/actions.c | 13 +++
 net/openvswitch/flow.c|  4 ++--
 net/openvswitch/flow.h|  2 +-
 net/openvswitch/flow_netlink.c| 22 +--
 7 files changed, 31 insertions(+), 28 deletions(-)

-- 
2.19.1



[PATCH net-next 3/4] gianfar: remove use of VLAN_TAG_PRESENT

2018-11-08 Thread Michał Mirosław
Reviewed-by: Claudiu Manoil 
Signed-off-by: Michał Mirosław 
---
 drivers/net/ethernet/freescale/gianfar_ethtool.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c 
b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 0d76e15cd6dd..241325c35cb4 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1134,11 +1134,9 @@ static int gfar_convert_to_filer(struct 
ethtool_rx_flow_spec *rule,
prio = vlan_tci_prio(rule);
prio_mask = vlan_tci_priom(rule);
 
-   if (cfi == VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {
-   vlan |= RQFPR_CFI;
-   vlan_mask |= RQFPR_CFI;
-   } else if (cfi != VLAN_TAG_PRESENT &&
-  cfi_mask == VLAN_TAG_PRESENT) {
+   if (cfi_mask) {
+   if (cfi)
+   vlan |= RQFPR_CFI;
vlan_mask |= RQFPR_CFI;
}
}
-- 
2.19.1



[PATCH net-next] i40iw: remove use of VLAN_TAG_PRESENT

2018-11-08 Thread Michał Mirosław
Signed-off-by: Michał Mirosław 
---
 drivers/infiniband/hw/i40iw/i40iw_cm.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c 
b/drivers/infiniband/hw/i40iw/i40iw_cm.c
index 771eb6bd0785..4b3999d88c9e 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c
@@ -404,7 +404,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
if (pdata)
pd_len = pdata->size;
 
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT)
+   if (cm_node->vlan_id <= VLAN_VID_MASK)
eth_hlen += 4;
 
if (cm_node->ipv4)
@@ -433,7 +433,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
 
ether_addr_copy(ethh->h_dest, cm_node->rem_mac);
ether_addr_copy(ethh->h_source, cm_node->loc_mac);
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
((struct vlan_ethhdr *)ethh)->h_vlan_proto = 
htons(ETH_P_8021Q);
vtag = (cm_node->user_pri << VLAN_PRIO_SHIFT) | 
cm_node->vlan_id;
((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(vtag);
@@ -463,7 +463,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
 
ether_addr_copy(ethh->h_dest, cm_node->rem_mac);
ether_addr_copy(ethh->h_source, cm_node->loc_mac);
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
((struct vlan_ethhdr *)ethh)->h_vlan_proto = 
htons(ETH_P_8021Q);
vtag = (cm_node->user_pri << VLAN_PRIO_SHIFT) | 
cm_node->vlan_id;
((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(vtag);
@@ -3323,7 +3323,7 @@ static void i40iw_init_tcp_ctx(struct i40iw_cm_node 
*cm_node,
 
tcp_info->flow_label = 0;
tcp_info->snd_mss = cpu_to_le32(((u32)cm_node->tcp_cntxt.mss));
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
tcp_info->insert_vlan_tag = true;
tcp_info->vlan_tag = cpu_to_le16(((u16)cm_node->user_pri << 
I40IW_VLAN_PRIO_SHIFT) |
  cm_node->vlan_id);
-- 
2.19.1



[PATCH net-next 2/4] cnic: remove use of VLAN_TAG_PRESENT

2018-11-08 Thread Michał Mirosław
This just removes VLAN_TAG_PRESENT use.  VLAN TCI=0 special meaning is
deeply embedded in the driver code and so is left as is.

Signed-off-by: Michał Mirosław 
---
 drivers/net/ethernet/broadcom/cnic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/cnic.c 
b/drivers/net/ethernet/broadcom/cnic.c
index d83233ae4a15..510dfc1c236b 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -5731,7 +5731,7 @@ static int cnic_netdev_event(struct notifier_block *this, 
unsigned long event,
if (realdev) {
dev = cnic_from_netdev(realdev);
if (dev) {
-   vid |= VLAN_TAG_PRESENT;
+   vid |= VLAN_CFI_MASK;   /* make non-zero */
cnic_rcv_netevent(dev->cnic_priv, event, vid);
cnic_put(dev);
}
-- 
2.19.1



[PATCH net-next 4/4] OVS: remove use of VLAN_TAG_PRESENT

2018-11-08 Thread Michał Mirosław
This is a minimal change to allow removing of VLAN_TAG_PRESENT.
It leaves OVS unable to use CFI bit, as fixing this would need
a deeper surgery involving userspace interface.

Signed-off-by: Michał Mirosław 
---
 net/openvswitch/actions.c  | 13 +
 net/openvswitch/flow.c |  4 ++--
 net/openvswitch/flow.h |  2 +-
 net/openvswitch/flow_netlink.c | 22 +++---
 4 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 85ae53d8fd09..e47ebbbe71b8 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -301,7 +301,7 @@ static int push_vlan(struct sk_buff *skb, struct 
sw_flow_key *key,
key->eth.vlan.tpid = vlan->vlan_tpid;
}
return skb_vlan_push(skb, vlan->vlan_tpid,
-ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
+ntohs(vlan->vlan_tci) & ~VLAN_CFI_MASK);
 }
 
 /* 'src' is already properly masked. */
@@ -822,8 +822,10 @@ static int ovs_vport_output(struct net *net, struct sock 
*sk, struct sk_buff *sk
__skb_dst_copy(skb, data->dst);
*OVS_CB(skb) = data->cb;
skb->inner_protocol = data->inner_protocol;
-   skb->vlan_tci = data->vlan_tci;
-   skb->vlan_proto = data->vlan_proto;
+   if (data->vlan_tci & VLAN_CFI_MASK)
+   __vlan_hwaccel_put_tag(skb, data->vlan_proto, data->vlan_tci & 
~VLAN_CFI_MASK);
+   else
+   __vlan_hwaccel_clear_tag(skb);
 
/* Reconstruct the MAC header.  */
skb_push(skb, data->l2_len);
@@ -867,7 +869,10 @@ static void prepare_frag(struct vport *vport, struct 
sk_buff *skb,
data->cb = *OVS_CB(skb);
data->inner_protocol = skb->inner_protocol;
data->network_offset = orig_network_offset;
-   data->vlan_tci = skb->vlan_tci;
+   if (skb_vlan_tag_present(skb))
+   data->vlan_tci = skb_vlan_tag_get(skb) | VLAN_CFI_MASK;
+   else
+   data->vlan_tci = 0;
data->vlan_proto = skb->vlan_proto;
data->mac_proto = mac_proto;
data->l2_len = hlen;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 35966da84769..fa393815991e 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -325,7 +325,7 @@ static int parse_vlan_tag(struct sk_buff *skb, struct 
vlan_head *key_vh,
return -ENOMEM;
 
vh = (struct vlan_head *)skb->data;
-   key_vh->tci = vh->tci | htons(VLAN_TAG_PRESENT);
+   key_vh->tci = vh->tci | htons(VLAN_CFI_MASK);
key_vh->tpid = vh->tpid;
 
if (unlikely(untag_vlan)) {
@@ -358,7 +358,7 @@ static int parse_vlan(struct sk_buff *skb, struct 
sw_flow_key *key)
int res;
 
if (skb_vlan_tag_present(skb)) {
-   key->eth.vlan.tci = htons(skb->vlan_tci);
+   key->eth.vlan.tci = htons(skb->vlan_tci) | htons(VLAN_CFI_MASK);
key->eth.vlan.tpid = skb->vlan_proto;
} else {
/* Parse outer vlan tag in the non-accelerated case. */
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index c670dd24b8b7..ba01fc4270bd 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -60,7 +60,7 @@ struct ovs_tunnel_info {
 
 struct vlan_head {
__be16 tpid; /* Vlan type. Generally 802.1q or 802.1ad.*/
-   __be16 tci;  /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
+   __be16 tci;  /* 0 if no VLAN, VLAN_CFI_MASK set otherwise. */
 };
 
 #define OVS_SW_FLOW_KEY_METADATA_SIZE  \
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 865ecef68196..435a4bdf8f89 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -990,9 +990,9 @@ static int validate_vlan_from_nlattrs(const struct 
sw_flow_match *match,
if (a[OVS_KEY_ATTR_VLAN])
tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
 
-   if (!(tci & htons(VLAN_TAG_PRESENT))) {
+   if (!(tci & htons(VLAN_CFI_MASK))) {
if (tci) {
-   OVS_NLERR(log, "%s TCI does not have VLAN_TAG_PRESENT 
bit set.",
+   OVS_NLERR(log, "%s TCI does not have VLAN_CFI_MASK bit 
set.",
  (inner) ? "C-VLAN" : "VLAN");
return -EINVAL;
} else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) {
@@ -1013,9 +1013,9 @@ static int validate_vlan_mask_from_nlattrs(const struct 
sw_flow_match *match,
__be16 tci = 0;
__be16 tpid = 0;
bool encap_valid = !!(match->key->eth.vlan.tci &
- htons(VLAN_TAG_PRESENT));
+ htons(VLAN_CFI_MASK));
bool i_encap_vali

[PATCH net-next 2/4] net/vlan: introduce __vlan_hwaccel_copy_tag() helper

2018-11-07 Thread Michał Mirosław
Signed-off-by: Michał Mirosław 
---
 include/linux/if_vlan.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index c438fa0a1c6a..941da4bf3929 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -472,6 +472,19 @@ static inline void __vlan_hwaccel_clear_tag(struct sk_buff 
*skb)
skb->vlan_tci = 0;
 }
 
+/**
+ * __vlan_hwaccel_copy_tag - copy hardware accelerated VLAN info from another 
skb
+ * @dst: skbuff to copy to
+ * @src: skbuff to copy from
+ *
+ * Copies VLAN information from @src to @dst (for branchless code)
+ */
+static inline void __vlan_hwaccel_copy_tag(struct sk_buff *dst, const struct 
sk_buff *src)
+{
+   dst->vlan_proto = src->vlan_proto;
+   dst->vlan_tci = src->vlan_tci;
+}
+
 /*
  * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
  * @skb: skbuff to tag
-- 
2.19.1



[PATCH net-next 4/4] net/vlan: remove unused #define HAVE_VLAN_GET_TAG

2018-11-07 Thread Michał Mirosław
Signed-off-by: Michał Mirosław 
---
 include/linux/if_vlan.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index b14bf87999aa..03b08ffded07 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -555,8 +555,6 @@ static inline int __vlan_hwaccel_get_tag(const struct 
sk_buff *skb,
}
 }
 
-#define HAVE_VLAN_GET_TAG
-
 /**
  * vlan_get_tag - get the VLAN ID from the skb
  * @skb: skbuff to query
-- 
2.19.1



[PATCH net-next 3/4] net/vlan: include the shift in skb_vlan_tag_get_prio()

2018-11-07 Thread Michał Mirosław
Signed-off-by: Michał Mirosław 
---
 include/linux/if_vlan.h   | 2 +-
 net/core/flow_dissector.c | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 941da4bf3929..b14bf87999aa 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -81,7 +81,7 @@ static inline bool is_vlan_dev(const struct net_device *dev)
 #define skb_vlan_tag_present(__skb)((__skb)->vlan_tci & VLAN_TAG_PRESENT)
 #define skb_vlan_tag_get(__skb)((__skb)->vlan_tci & 
~VLAN_TAG_PRESENT)
 #define skb_vlan_tag_get_id(__skb) ((__skb)->vlan_tci & VLAN_VID_MASK)
-#define skb_vlan_tag_get_prio(__skb)   ((__skb)->vlan_tci & VLAN_PRIO_MASK)
+#define skb_vlan_tag_get_prio(__skb)   (((__skb)->vlan_tci & VLAN_PRIO_MASK) 
>> VLAN_PRIO_SHIFT)
 
 static inline int vlan_get_rx_ctag_filter_info(struct net_device *dev)
 {
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 676f3ad629f9..56d1e9b73142 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -952,8 +952,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 
if (!vlan) {
key_vlan->vlan_id = skb_vlan_tag_get_id(skb);
-   key_vlan->vlan_priority =
-   (skb_vlan_tag_get_prio(skb) >> 
VLAN_PRIO_SHIFT);
+   key_vlan->vlan_priority = 
skb_vlan_tag_get_prio(skb);
} else {
key_vlan->vlan_id = ntohs(vlan->h_vlan_TCI) &
VLAN_VID_MASK;
-- 
2.19.1



[PATCH net-next 1/4] net/vlan: introduce __vlan_hwaccel_clear_tag() helper

2018-11-07 Thread Michał Mirosław
Signed-off-by: Michał Mirosław 
---
 include/linux/if_vlan.h | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 83ea4df6ab81..c438fa0a1c6a 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -461,6 +461,17 @@ static inline struct sk_buff 
*vlan_insert_tag_set_proto(struct sk_buff *skb,
return skb;
 }
 
+/**
+ * __vlan_hwaccel_clear_tag - clear hardware accelerated VLAN info
+ * @skb: skbuff to clear
+ *
+ * Clears the VLAN information from @skb
+ */
+static inline void __vlan_hwaccel_clear_tag(struct sk_buff *skb)
+{
+   skb->vlan_tci = 0;
+}
+
 /*
  * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
  * @skb: skbuff to tag
@@ -475,7 +486,7 @@ static inline struct sk_buff 
*__vlan_hwaccel_push_inside(struct sk_buff *skb)
skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
skb_vlan_tag_get(skb));
if (likely(skb))
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
return skb;
 }
 
-- 
2.19.1



[PATCH net-next 0/4] net/vlan: prepare for removal of VLAN_TAG_PRESENT

2018-11-07 Thread Michał Mirosław
This is a preparatory patchset before removing the use of VLAN_TAG_PRESENT
bit in skb->vlan_tci as indication of VLAN offload. This set includes
only cleanups that allow abstracting of code testing VLAN tag presence
in drivers and networking code.

Michał Mirosław (4):
  net/vlan: introduce __vlan_hwaccel_clear_tag() helper
  net/vlan: introduce __vlan_hwaccel_copy_tag() helper
  net/vlan: include the shift in skb_vlan_tag_get_prio()
  net/vlan: remove unused #define HAVE_VLAN_GET_TAG

 include/linux/if_vlan.h   | 30 ++
 net/core/flow_dissector.c |  3 +--
 2 files changed, 27 insertions(+), 6 deletions(-)

-- 
2.19.1



[PATCH net] ibmvnic: fix accelerated VLAN handling

2018-11-07 Thread Michał Mirosław
Don't request tag insertion when it isn't present in outgoing skb.

Signed-off-by: Michał Mirosław 
---
 drivers/net/ethernet/ibm/ibmvnic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/ibm/ibmvnic.c 
b/drivers/net/ethernet/ibm/ibmvnic.c
index 7893beffcc71..c9d5d0a7fbf1 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -1545,7 +1545,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, 
struct net_device *netdev)
tx_crq.v1.sge_len = cpu_to_be32(skb->len);
tx_crq.v1.ioba = cpu_to_be64(data_dma_addr);
 
-   if (adapter->vlan_header_insertion) {
+   if (adapter->vlan_header_insertion && skb_vlan_tag_present(skb)) {
tx_crq.v1.flags2 |= IBMVNIC_TX_VLAN_INSERT;
tx_crq.v1.vlan_id = cpu_to_be16(skb->vlan_tci);
}
-- 
2.19.1



[PATCH net] qlcnic: remove assumption that vlan_tci != 0

2018-11-07 Thread Michał Mirosław
VLAN.TCI == 0 is perfectly valid (802.1p), so allow it to be accelerated.

Signed-off-by: Michał Mirosław 
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c 
b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 9647578cbe6a..14f26bf3b388 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -459,7 +459,7 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
 struct cmd_desc_type0 *first_desc, struct sk_buff *skb,
 struct qlcnic_host_tx_ring *tx_ring)
 {
-   u8 l4proto, opcode = 0, hdr_len = 0;
+   u8 l4proto, opcode = 0, hdr_len = 0, tag_vlan = 0;
u16 flags = 0, vlan_tci = 0;
int copied, offset, copy_len, size;
struct cmd_desc_type0 *hwdesc;
@@ -472,14 +472,16 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
flags = QLCNIC_FLAGS_VLAN_TAGGED;
vlan_tci = ntohs(vh->h_vlan_TCI);
protocol = ntohs(vh->h_vlan_encapsulated_proto);
+   tag_vlan = 1;
} else if (skb_vlan_tag_present(skb)) {
flags = QLCNIC_FLAGS_VLAN_OOB;
vlan_tci = skb_vlan_tag_get(skb);
+   tag_vlan = 1;
}
if (unlikely(adapter->tx_pvid)) {
-   if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+   if (tag_vlan && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
return -EIO;
-   if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
+   if (tag_vlan && (adapter->flags & QLCNIC_TAGGING_ENABLED))
goto set_flags;
 
flags = QLCNIC_FLAGS_VLAN_OOB;
-- 
2.19.1



Re: [PATCH net-next 1/5 v2] net: gemini: Look up L3 maxlen from table

2018-07-07 Thread Michał Mirosław
On Wed, Jul 04, 2018 at 08:33:20PM +0200, Linus Walleij wrote:
> The code to calculate the hardware register enumerator
> for the maximum L3 length isn't entirely simple to read.
> Use the existing defines and rewrite the function into a
> table look-up.

A matter of habit. ;-)
I think that if you just renamed 'n' to 'best_index' and avoided
reusing 'max_l3_len' (as you already did) the idea could be made
more obvious without expading the code to twice the lines.

The max_len[] array in the original code documents how the HW reacts
to a specific setting.

Acked-by: Michał Mirosław 

Best Regards,
Michał Mirosław

> 
> Signed-off-by: Linus Walleij 
> ---
> ChangeLog v1->v2:
> - No changes, just resending with the rest.
> ---
>  drivers/net/ethernet/cortina/gemini.c | 61 ---
>  1 file changed, 46 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/net/ethernet/cortina/gemini.c 
> b/drivers/net/ethernet/cortina/gemini.c
> index 6d7404f66f84..8fc31723f700 100644
> --- a/drivers/net/ethernet/cortina/gemini.c
> +++ b/drivers/net/ethernet/cortina/gemini.c
> @@ -401,26 +401,57 @@ static int gmac_setup_phy(struct net_device *netdev)
>   return 0;
>  }
>  
> -static int gmac_pick_rx_max_len(int max_l3_len)
> -{
> - /* index = CONFIG_MAXLEN_XXX values */
> - static const int max_len[8] = {
> - 1536, 1518, 1522, 1542,
> - 9212, 10236, 1518, 1518
> - };
> - int i, n = 5;
> +/* The maximum frame length is not logically enumerated in the
> + * hardware, so we do a table lookup to find the applicable max
> + * frame length.
> + */
> +struct gmac_max_framelen {
> + unsigned int max_l3_len;
> + u8 val;
> +};
>  
> - max_l3_len += ETH_HLEN + VLAN_HLEN;
> +static const struct gmac_max_framelen gmac_maxlens[] = {
> + {
> + .max_l3_len = 1518,
> + .val = CONFIG0_MAXLEN_1518,
> + },
> + {
> + .max_l3_len = 1522,
> + .val = CONFIG0_MAXLEN_1522,
> + },
> + {
> + .max_l3_len = 1536,
> + .val = CONFIG0_MAXLEN_1536,
> + },
> + {
> + .max_l3_len = 1542,
> + .val = CONFIG0_MAXLEN_1542,
> + },
> + {
> + .max_l3_len = 9212,
> + .val = CONFIG0_MAXLEN_9k,
> + },
> + {
> + .max_l3_len = 10236,
> + .val = CONFIG0_MAXLEN_10k,
> + },
> +};
> +
> +static int gmac_pick_rx_max_len(unsigned int max_l3_len)
> +{
> + const struct gmac_max_framelen *maxlen;
> + int maxtot;
> + int i;
>  
> - if (max_l3_len > max_len[n])
> - return -1;
> + maxtot = max_l3_len + ETH_HLEN + VLAN_HLEN;
>  
> - for (i = 0; i < 5; i++) {
> - if (max_len[i] >= max_l3_len && max_len[i] < max_len[n])
> - n = i;
> + for (i = 0; i < ARRAY_SIZE(gmac_maxlens); i++) {
> + maxlen = _maxlens[i];
> + if (maxtot <= maxlen->max_l3_len)
> + return maxlen->val;
>   }
>  
> - return n;
> + return -1;
>  }
>  
>  static int gmac_init(struct net_device *netdev)
> -- 
> 2.17.1
> 


Re: [PATCH net-next 2/2 v9] net: ethernet: Add a driver for Gemini gigabit ethernet

2017-12-18 Thread Michał Mirosław
On Mon, Dec 18, 2017 at 02:57:37PM +0100, Linus Walleij wrote:
> On Sat, Dec 16, 2017 at 8:39 PM, Linus Walleij <linus.wall...@linaro.org> 
> wrote:
> 
> > The Gemini ethernet has been around for years as an out-of-tree
> > patch used with the NAS boxen and routers built on StorLink
> > SL3512 and SL3516, later Storm Semiconductor, later Cortina
> > Systems. These ASICs are still being deployed and brand new
> > off-the-shelf systems using it can easily be acquired.
[...]
> > ---
> > Changes from v8:
> > - Remove dependency guards in Kconfig to get a wider compile
> >   coverage for the driver to detect broken APIs etc.
> 
> I guess we need to hold this off for a while, the code does
> some weird stuff using the ARM-internal page DMA mapping
> API.
> 
> I *think* what happens is that the driver allocates a global queue
> used for RX and TX on both interfaces, then initializes that with
> page pointers and gives that to the hardware to play with.
> 
> When an RX packet comes in, the RX routine needs to figure
> out from the DMA (physical) address which remapped
> page/address this random physical address pointer
> corresponds to.
> 
> The Linux DMA API assumption is that the driver keeps track
> of this mapping, not the hardware. So we need to figure out
> a way to reverse-map this. Preferably quickly, and without
> using any ARM-internal mapping APIs.

IIRC, the hardware copies descriptors from free queue (FREEQ)
to RX queues. FREEQ is shared among the two ethernet ports.

This platform is CPU bound, so every additional lookup will
hit performance here. In my version I had an #ifdef for
COMPILE_TEST that replaced ARM-specific calls with stubs.
Since the driver is not expected to work on other platforms,
this seemed like the best workaround to make it compile
on other arches.

Best Regards,
Michał Mirosław


Re: [PATCH net-next 2/2 v6] net: ethernet: Add a driver for Gemini gigabit ethernet

2017-12-05 Thread Michał Mirosław
On Sat, Dec 02, 2017 at 12:06:40PM +0100, Linus Walleij wrote:
[...]
> The latest v6 incarnation of this driver was written by Michał
> Mirosław and submitted for inclusion in 2011. This was the
> last post:
> https://lwn.net/Articles/437889/
> 
> DaveM ACKed it at the time:
> https://marc.info/?l=linux-netdev=130255434310315=2
> 
> The controversial pieces under ARM (board files) and other
> subsystems are now gone and replaced by DeviceTree.
> 
> Michał: I hope you don't mind me picking it up and hope
> you can still test it on your ICYbox, I have device tree
> patches in my tree:
> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik.git/log/?h=gemini-ethernet

I'm happy to see that my work didn't go to /dev/null after all.
I haven't finished it at the time because the box I had broke down
beyond repair.

I skimmed through the patch - please find my comments below.

Best Regards,
Michał Mirosław


[...]
> --- /dev/null
> +++ b/drivers/net/ethernet/cortina/gemini.c
> @@ -0,0 +1,2461 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Ethernet device driver for Cortina Systems Gemini SoC
> + * Also known as the StorLink SL3512 and SL3516 (SL351x) GMAC
> + *
> + * Authors:
> + * Linus Walleij <linus.wall...@linaro.org>
> + * Tobias Waldvogel <tobias.waldvo...@gmail.com> (OpenWRT)
> + * Michał Mirosław <mirq-li...@rere.qmqm.pl>

Doubly UTF-8 encoded?

[...]
> +static int gmac_setup_txqs(struct net_device *netdev)
> +{
[...]
> + desc_ring = dma_alloc_coherent(geth->dev, len * sizeof(*desc_ring),
> + >txq_dma_base, GFP_KERNEL);
> +
> + if (!desc_ring) {

Should check with dma_mapping_error().

> + kfree(skb_tab);
> + return -ENOMEM;
> + }
> +
> + BUG_ON(port->txq_dma_base & ~DMA_Q_BASE_MASK);

BUG is too hard here. return -EINVAL or other error? Shouldn't happen
if dma_alloc_coherent() guarantees 16B alignment.

[...]
> +static int gmac_setup_rxq(struct net_device *netdev)
> +{
[...]
> + BUG_ON(port->rxq_dma_base & ~NONTOE_QHDR0_BASE_MASK);

Like above.

[...]
> +static struct page *geth_freeq_alloc_map_page(struct gemini_ethernet *geth,
> +   int pn)
> +{
> + unsigned int fpp_order = PAGE_SHIFT - geth->freeq_frag_order;
> + unsigned int frag_len = 1 << geth->freeq_frag_order;
> + GMAC_RXDESC_T *freeq_entry;
> + dma_addr_t mapping;
> + struct page *page;
> + int i;
> +
> + page = alloc_page(GFP_ATOMIC);
> + if (!page)
> + return NULL;
> +
> + mapping = dma_map_single(geth->dev, page_address(page),
> + PAGE_SIZE, DMA_FROM_DEVICE);
> +
> + if (unlikely(dma_mapping_error(geth->dev, mapping) || !mapping)) {

This should test only dma_mapping_error() since mapping == 0 is valid,
but unlikely.

> +static int geth_setup_freeq(struct gemini_ethernet *geth)
> +{
> + void __iomem *dma_reg = geth->base + GLOBAL_SW_FREEQ_BASE_SIZE_REG;
> + QUEUE_THRESHOLD_T qt;
> + DMA_SKB_SIZE_T skbsz;
> + unsigned int filled;
> + unsigned int frag_len = 1 << geth->freeq_frag_order;
> + unsigned int len = 1 << geth->freeq_order;
> + unsigned int fpp_order = PAGE_SHIFT - geth->freeq_frag_order;
> + unsigned int pages = len >> fpp_order;
> + dma_addr_t mapping;
> + unsigned int pn;
> +
> + geth->freeq_ring = dma_alloc_coherent(geth->dev,
> + sizeof(*geth->freeq_ring) << geth->freeq_order,
> + >freeq_dma_base, GFP_KERNEL);
> + if (!geth->freeq_ring)
> + return -ENOMEM;
> +
> + BUG_ON(geth->freeq_dma_base & ~DMA_Q_BASE_MASK);

Another BUG_ON:

if (WARN_ON(...)) goto err_freeq;

[...]
> +static int gmac_map_tx_bufs(struct net_device *netdev, struct sk_buff *skb,
> + struct gmac_txq *txq, unsigned short *desc)
> +{
[...]
> + if (word1 > mtu) {
> + word1 |= TSS_MTU_ENABLE_BIT;
> + word3 += mtu;

word3 |= mtu; would be more natural.

[...]
> + mapping = dma_map_single(geth->dev, buffer, buflen,
> + DMA_TO_DEVICE);
> + if (dma_mapping_error(geth->dev, mapping) ||
> + !(mapping & PAGE_MASK))
> + goto map_error;

Is page at phys 0 special to the HW?

[...]
> +map_error:
> + while (w != *desc) {
> + w--;
> + w &= m;
> +
> + dma_unmap_page(geth->dev, txq->ring[w].word2.buf_adr,
> + txq->ring[w].word0.bits.buffer_size, DMA_TO_DEVICE);
&

Re: [PATCH net] ipv4: fib: Fix NULL pointer deref during fib_sync_down_dev()

2017-07-29 Thread Michał Mirosław
On Fri, Jul 28, 2017 at 11:27:44PM +0300, Ido Schimmel wrote:
> Michał reported a NULL pointer deref during fib_sync_down_dev() when
> unregistering a netdevice. The problem is that we don't check for
> 'in_dev' being NULL, which can happen in very specific cases.
> 
> Usually routes are flushed upon NETDEV_DOWN sent in either the netdev or
> the inetaddr notification chains. However, if an interface isn't
> configured with any IP address, then it's possible for host routes to be
> flushed following NETDEV_UNREGISTER, after NULLing dev->ip_ptr in
> inetdev_destroy().
> 
> To reproduce:
> $ ip link add type dummy
> $ ip route add local 1.1.1.0/24 dev dummy0
> $ ip link del dev dummy0
> 
> Fix this by checking for the presence of 'in_dev' before referencing it.
> 
> Fixes: 982acb97560c ("ipv4: fib: Notify about nexthop status changes")
> Signed-off-by: Ido Schimmel <ido...@mellanox.com>
> Reported-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>

Tested-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>

Thanks!


Re: [v4.12 regression] netns: NULL deref in fib_sync_down_dev()

2017-07-28 Thread Michał Mirosław
On Fri, Jul 28, 2017 at 08:36:02PM +0300, Ido Schimmel wrote:
> On Fri, Jul 28, 2017 at 10:28:16AM -0700, Cong Wang wrote:
> > On Fri, Jul 28, 2017 at 9:43 AM, Ido Schimmel <ido...@idosch.org> wrote:
> > > On Fri, Jul 28, 2017 at 06:00:47PM +0200, Michał Mirosław wrote:
> > >> Dear NetDevs,
> > >>
> > >> Before I go to bisecting, have you seen a following NULL dereference,
> > >> yet?  Where should I start looking?  It is triggered by deleting netns
> > >> (cut-down script attached - triggers every time).  This was working
> > >> correctly under v4.11.x.
> > > Thanks for the report. I just reproduced this on my system. I believe
> > > the problem is a missing NULL check for 'in_dev' in
> > > call_fib_nh_notifiers(). I'll test a fix.
> > But your commit 982acb97560c8118c2109504a22b0d78a580547d
> > is merged in v4.11-rc1. How could 4.11.x work correctly?
> It doesn't. I just reproduced this on v4.11.

Thanks for looking into this.  I was sure that I ran v4.11.7 last time,
but it turns out I worked on this earlier than that.  I'll be glad to
test patches for this issue when you have it.

Best Regards,
Michał Mirosław


[v4.12 regression] netns: NULL deref in fib_sync_down_dev()

2017-07-28 Thread Michał Mirosław
Dear NetDevs,

Before I go to bisecting, have you seen a following NULL dereference,
yet?  Where should I start looking?  It is triggered by deleting netns
(cut-down script attached - triggers every time).  This was working
correctly under v4.11.x.

Best Regards,
Michał Mirosław
[1097925.958758] eth0: renamed from tve0x
[1097926.012266] IPv6: ADDRCONF(NETDEV_UP): tve0: link is not ready
[1097926.035396] IPv6: ADDRCONF(NETDEV_CHANGE): tve0: link becomes ready
[1097926.709371] ip6_tables: (C) 2000-2006 Netfilter Core Team
[1097929.961977] BUG: unable to handle kernel NULL pointer dereference at 
0138
[1097929.961983] IP: fib_sync_down_dev+0x19a/0x230
[1097929.961983] PGD 0
[1097929.961984] P4D 0
[1097929.961986] Oops:  [#1] PREEMPT SMP
[1097929.961987] Modules linked in: ip6table_mangle ip6_tables xt_tcpudp 
iptable_mangle xt_TPROXY nf_defrag_ipv6 veth nvidia_uvm(PO) cpuid cdc_ether 
cdc_subset usbnet mii pci_stub vboxpci(O) vboxnetadp(O) vboxnetflt(O) 
vboxdrv(O) tun xt_REDIRECT nf_nat_redirect cdc_acm ipt_MASQUERADE 
nf_nat_masquerade_ipv4 iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 
nf_nat nf_conntrack bridge stp llc rfcomm snd_emu10k1_synth snd_emux_synth 
snd_seq_midi_emul snd_seq_virmidi snd_hrtimer snd_seq_midi snd_seq_midi_event 
snd_seq xfrm_user iptable_filter xfrm4_tunnel tunnel4 ipcomp xfrm_ipcomp esp4 
ah4 af_key xfrm_algo cpufreq_powersave cpufreq_userspace cpufreq_conservative 
nfc fuse bnep binfmt_misc xfs snd_hda_codec_hdmi mxm_wmi btusb btrtl btbcm 
btintel bluetooth intel_powerclamp snd_hda_codec_realtek snd_hda_codec_generic
[1097929.962009]  kvm_intel snd_hda_intel pl2303 snd_emu10k1 usbserial 
input_leds ecdh_generic snd_hda_codec kvm snd_util_mem snd_hda_core 
snd_ac97_codec ac97_bus snd_rawmidi snd_seq_device snd_hwdep snd_pcm_oss 
snd_mixer_oss snd_pcm snd_timer snd irqbypass sg pcspkr soundcore emu10k1_gp 
gameport iTCO_wdt wmi video nvidia_drm(PO) drm_kms_helper syscopyarea 
sysfillrect sysimgblt fb_sys_fops drm nvidia_modeset(PO) nvidia(PO) nfsd 
auth_rpcgss oid_registry nfs_acl lockd grace sunrpc loop firewire_sbp2 
firewire_core crc_itu_t ecryptfs ip_tables x_tables autofs4 algif_skcipher 
af_alg sr_mod cdrom raid10 raid0 multipath linear raid456 async_raid6_recov 
async_memcpy async_pq uas usb_storage raid6_pq async_xor xor async_tx libcrc32c 
crc32c_intel ghash_clmulni_intel i2c_i801 i2c_core xhci_pci xhci_hcd e1000e
[1097929.962034] CPU: 2 PID: 28976 Comm: kworker/u16:2 Tainted: P   O   
 4.12.2mq+ #204
[1097929.962035] Hardware name: System manufacturer System Product Name/P8Z68-V 
PRO, BIOS 3603 11/09/2012
[1097929.962037] Workqueue: netns cleanup_net
[1097929.962038] task: 8804078ae600 task.stack: c90003b0c000
[1097929.962039] RIP: 0010:fib_sync_down_dev+0x19a/0x230
[1097929.962040] RSP: 0018:c90003b0fc80 EFLAGS: 00010206
[1097929.962041] RAX: 0011 RBX: 880005b70570 RCX: 

[1097929.962042] RDX:  RSI: 00ff RDI: 

[1097929.962043] RBP:  R08:  R09: 

[1097929.962044] R10: c90003b0fd10 R11: 0c79 R12: 
880005b70500
[1097929.962044] R13: 0006 R14: 880005b70570 R15: 
880405bc5000
[1097929.962045] FS:  () GS:88041ec8() 
knlGS:
[1097929.962046] CS:  0010 DS:  ES:  CR0: 80050033
[1097929.962047] CR2: 0138 CR3: 01c09000 CR4: 
000406e0
[1097929.962047] Call Trace:
[1097929.962050]  ? fib_disable_ip+0xc/0x40
[1097929.962051]  ? fib_netdev_event+0xe8/0x110
[1097929.962053]  ? notifier_call_chain+0x40/0x60
[1097929.962054]  ? rollback_registered_many+0x2b6/0x400
[1097929.962056]  ? unregister_netdevice_many+0x15/0xa0
[1097929.962057]  ? default_device_exit_batch+0x13c/0x170
[1097929.962059]  ? do_wait_intr_irq+0x80/0x80
[1097929.962061]  ? cleanup_net+0x1d0/0x2c0
[1097929.962062]  ? process_one_work+0x1d2/0x3e0
[1097929.962064]  ? worker_thread+0x42/0x3d0
[1097929.962065]  ? kthread+0xf7/0x130
[1097929.962067]  ? trace_event_raw_event_workqueue_work+0xa0/0xa0
[1097929.962068]  ? kthread_create_on_node+0x60/0x60
[1097929.962069]  ? do_group_exit+0x35/0xa0
[1097929.962070]  ? ret_from_fork+0x22/0x30
[1097929.962071] Code: 39 f0 74 77 49 83 fd 04 74 69 49 83 fd 06 74 60 49 83 fd 
02 74 5a 49 8b 97 d8 02 00 00 48 89 5c 24 18 48 c7 44 24 10 00 00 00 00 <8b> 92 
38 01 00 00 85 d2 74 04 a8 10 75 08 a8 01 0f 84 12 ff ff
[1097929.962085] RIP: fib_sync_down_dev+0x19a/0x230 RSP: c90003b0fc80
[1097929.962086] CR2: 0138
[1097929.962087] ---[ end trace 07d937abbfe4921d ]---
#!/bin/bash

trap cleanup EXIT
cleanup() {
ip netns del test
ip link del tve0
}

ip netns add test || exit 1
ip link add name tve0 type veth peer name tve0x
ip link set tve0x netns test
ip netns exec test ip link set tve0x name eth0

ip link set tve0 up
ip addr add 10.22.0.1/24 dev tve0
ip rou

Re: [PATCH net-next 0/6] Prepare BPF for VLAN_TAG_PRESENT cleanup

2017-01-04 Thread Michał Mirosław
On Wed, Jan 04, 2017 at 09:11:57PM +0100, Daniel Borkmann wrote:
> On 01/04/2017 02:18 AM, Michał Mirosław wrote:
> > Those patches prepare BPF ant its JITs for removal of VLAN_TAG_PRESENT.
> > The set depends on "Preparation for VLAN_TAG_PRESENT cleanup" patchset.
> > 
> > The series is supposed to be bisect-friendly and that requires temporary
> > insertion of #define VLAN_TAG_PRESENT in BPF code to be able to split
> > JIT changes per architecture.
> > 
> > Michał Mirosław (6):
> >net/skbuff: add macros for VLAN_PRESENT bit
> >net/bpf_jit: ARM: split VLAN_PRESENT bit handling from VLAN_TCI
> >net/bpf_jit: MIPS: split VLAN_PRESENT bit handling from VLAN_TCI
> >net/bpf_jit: PPC: split VLAN_PRESENT bit handling from VLAN_TCI
> >net/bpf_jit: SPARC: split VLAN_PRESENT bit handling from VLAN_TCI
> >net/bpf: split VLAN_PRESENT bit handling from VLAN_TCI
> 
> Please add a proper changelog to all the individual patches, right now
> they have none. Also, how was this runtime tested? Did you run BPF selftest
> suite with them? Seems like they weren't even compile tested properly
> given the kbuild bot barking on sparc ...

Compile bot is barking because it doesn't have patches, which this set depends 
on.
Sorry about that.

Best Regards,
Michał Mirosław


[PATCH net-next 3/6] net/bpf_jit: MIPS: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Acked-by: Ralf Baechle <r...@linux-mips.org>
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 arch/mips/net/bpf_jit.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 49a2e2226fee..d06722294ede 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -1138,19 +1138,21 @@ static int build_body(struct jit_ctx *ctx)
emit_load(r_A, r_skb, off, ctx);
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
-   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
ctx->flags |= SEEN_SKB | SEEN_A;
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
  vlan_tci) != 2);
off = offsetof(struct sk_buff, vlan_tci);
emit_half_load(r_s0, r_skb, off, ctx);
-   if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) {
-   emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, 
ctx);
-   } else {
-   emit_andi(r_A, r_s0, VLAN_TAG_PRESENT, ctx);
-   /* return 1 if present */
-   emit_sltu(r_A, r_zero, r_A, ctx);
-   }
+#ifdef VLAN_TAG_PRESENT
+   emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, ctx);
+#endif
+   break;
+   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+   ctx->flags |= SEEN_SKB | SEEN_A;
+   emit_load_byte(r_A, r_skb, PKT_VLAN_PRESENT_OFFSET(), 
ctx);
+   if (PKT_VLAN_PRESENT_BIT)
+   emit_srl(r_A, r_A, PKT_VLAN_PRESENT_BIT, ctx);
+   emit_andi(r_A, r_s0, 1, ctx);
break;
case BPF_ANC | SKF_AD_PKTTYPE:
ctx->flags |= SEEN_SKB;
-- 
2.11.0



[PATCH net-next 2/6] net/bpf_jit: ARM: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
v2: remove one insn for big-endians

 arch/arm/net/bpf_jit_32.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 93d0b6d0b63e..0700cbbe4f14 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -915,17 +915,21 @@ static int build_body(struct jit_ctx *ctx)
emit(ARM_LDR_I(r_A, r_skb, off), ctx);
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
-   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
ctx->seen |= SEEN_SKB;
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 
2);
off = offsetof(struct sk_buff, vlan_tci);
emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
-   if (code == (BPF_ANC | SKF_AD_VLAN_TAG))
-   OP_IMM3(ARM_AND, r_A, r_A, ~VLAN_TAG_PRESENT, 
ctx);
-   else {
-   OP_IMM3(ARM_LSR, r_A, r_A, 12, ctx);
+#ifdef VLAN_TAG_PRESENT
+   OP_IMM3(ARM_AND, r_A, r_A, ~VLAN_TAG_PRESENT, ctx);
+#endif
+   break;
+   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+   off = PKT_VLAN_PRESENT_OFFSET();
+   emit(ARM_LDRB_I(r_A, r_skb, off), ctx);
+   if (PKT_VLAN_PRESENT_BIT)
+   OP_IMM3(ARM_LSR, r_A, r_A, 
PKT_VLAN_PRESENT_BIT, ctx);
+   if (PKT_VLAN_PRESENT_BIT < 7)
OP_IMM3(ARM_AND, r_A, r_A, 0x1, ctx);
-   }
break;
case BPF_ANC | SKF_AD_PKTTYPE:
ctx->seen |= SEEN_SKB;
-- 
2.11.0



[PATCH net-next 1/6] net/skbuff: add macros for VLAN_PRESENT bit

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/skbuff.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b53c0cfd417e..168c3e486bd4 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -768,6 +768,12 @@ struct sk_buff {
__u32   priority;
int skb_iif;
__u32   hash;
+#define PKT_VLAN_PRESENT_BIT   4   // CFI (12-th bit) in TCI
+#ifdef __BIG_ENDIAN
+#define PKT_VLAN_PRESENT_OFFSET()  offsetof(struct sk_buff, vlan_tci)
+#else
+#define PKT_VLAN_PRESENT_OFFSET()  (offsetof(struct sk_buff, vlan_tci) + 1)
+#endif
__be16  vlan_proto;
__u16   vlan_tci;
 #if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS)
-- 
2.11.0



[PATCH net-next 0/6] Prepare BPF for VLAN_TAG_PRESENT cleanup

2017-01-03 Thread Michał Mirosław
Those patches prepare BPF ant its JITs for removal of VLAN_TAG_PRESENT.
The set depends on "Preparation for VLAN_TAG_PRESENT cleanup" patchset.

The series is supposed to be bisect-friendly and that requires temporary
insertion of #define VLAN_TAG_PRESENT in BPF code to be able to split
JIT changes per architecture.

Michał Mirosław (6):
  net/skbuff: add macros for VLAN_PRESENT bit
  net/bpf_jit: ARM: split VLAN_PRESENT bit handling from VLAN_TCI
  net/bpf_jit: MIPS: split VLAN_PRESENT bit handling from VLAN_TCI
  net/bpf_jit: PPC: split VLAN_PRESENT bit handling from VLAN_TCI
  net/bpf_jit: SPARC: split VLAN_PRESENT bit handling from VLAN_TCI
  net/bpf: split VLAN_PRESENT bit handling from VLAN_TCI

 arch/arm/net/bpf_jit_32.c   | 16 ++--
 arch/mips/net/bpf_jit.c | 18 ++
 arch/powerpc/net/bpf_jit_comp.c | 17 +
 arch/sparc/net/bpf_jit_comp.c   | 18 ++
 include/linux/skbuff.h  |  6 ++
 net/core/filter.c   | 19 +--
 6 files changed, 54 insertions(+), 40 deletions(-)

-- 
2.11.0



[PATCH net-next 4/6] net/bpf_jit: PPC: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 arch/powerpc/net/bpf_jit_comp.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 7e706f36e364..22ae63fb9b7d 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -377,18 +377,19 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 
*image,
  hash));
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
-   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 
2);
-   BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
 
PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
  vlan_tci));
-   if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) {
-   PPC_ANDI(r_A, r_A, ~VLAN_TAG_PRESENT);
-   } else {
-   PPC_ANDI(r_A, r_A, VLAN_TAG_PRESENT);
-   PPC_SRWI(r_A, r_A, 12);
-   }
+#ifdef VLAN_TAG_PRESENT
+   PPC_ANDI(r_A, r_A, ~VLAN_TAG_PRESENT);
+#endif
+   break;
+   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+   PPC_LBZ_OFFS(r_A, r_skb, PKT_VLAN_PRESENT_OFFSET());
+   if (PKT_VLAN_PRESENT_BIT)
+   PPC_SRWI(r_A, r_A, PKT_VLAN_PRESENT_BIT);
+   PPC_ANDI(r_A, r_A, 1);
break;
case BPF_ANC | SKF_AD_QUEUE:
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
-- 
2.11.0



[PATCH net-next 6/6] net/bpf: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
v2: save an insn on big-endiands

 net/core/filter.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index 1969b3f118c1..7caf0bbbd092 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -188,22 +188,21 @@ static u32 convert_skb_access(int skb_field, int dst_reg, 
int src_reg,
break;
 
case SKF_AD_VLAN_TAG:
-   case SKF_AD_VLAN_TAG_PRESENT:
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
-   BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
 
/* dst_reg = *(u16 *) (src_reg + offsetof(vlan_tci)) */
*insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
  offsetof(struct sk_buff, vlan_tci));
-   if (skb_field == SKF_AD_VLAN_TAG) {
-   *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg,
-   ~VLAN_TAG_PRESENT);
-   } else {
-   /* dst_reg >>= 12 */
-   *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, 12);
-   /* dst_reg &= 1 */
+#ifdef VLAN_TAG_PRESENT
+   *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, ~VLAN_TAG_PRESENT);
+#endif
+   break;
+   case SKF_AD_VLAN_TAG_PRESENT:
+   *insn++ = BPF_LDX_MEM(BPF_B, dst_reg, src_reg, 
PKT_VLAN_PRESENT_OFFSET());
+   if (PKT_VLAN_PRESENT_BIT)
+   *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, 
PKT_VLAN_PRESENT_BIT);
+   if (PKT_VLAN_PRESENT_BIT < 7)
*insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, 1);
-   }
break;
}
 
-- 
2.11.0



[PATCH net-next 5/6] net/bpf_jit: SPARC: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 arch/sparc/net/bpf_jit_comp.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index a6d9204a6a0b..61cc15dc86f7 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -601,15 +601,17 @@ void bpf_jit_compile(struct bpf_prog *fp)
emit_skb_load32(hash, r_A);
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
-   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
emit_skb_load16(vlan_tci, r_A);
-   if (code != (BPF_ANC | SKF_AD_VLAN_TAG)) {
-   emit_alu_K(SRL, 12);
-   emit_andi(r_A, 1, r_A);
-   } else {
-   emit_loadimm(~VLAN_TAG_PRESENT, r_TMP);
-   emit_and(r_A, r_TMP, r_A);
-   }
+#ifdef VLAN_TAG_PRESENT
+   emit_loadimm(~VLAN_TAG_PRESENT, r_TMP);
+   emit_and(r_A, r_TMP, r_A);
+#endif
+   break;
+   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+   __emit_skb_load8(__pkt_vlan_present_offset, 
r_A);
+   if (PKT_VLAN_PRESENT_BIT)
+   emit_alu_K(SRL, PKT_VLAN_PRESENT_BIT);
+   emit_andi(r_A, 1, r_A);
break;
case BPF_LD | BPF_W | BPF_LEN:
emit_skb_load32(len, r_A);
-- 
2.11.0



[PATCH net-next 0/8] Preparation for VLAN_TAG_PRESENT cleanup, drivers part

2017-01-03 Thread Michał Mirosław
Cleanups needed before enabling passing of VLAN.CFI.
Those patches depend on '*** SUBJECT HERE ***' patchset, but
are otherwise independent of each other.

Michał Mirosław (8):
  benet: use __vlan_hwaccel helpers
  benet: use skb_vlan_tag_get_prio()
  sky2: use __vlan_hwaccel helpers
  net/core: use __vlan_hwaccel helpers
  bridge: use __vlan_hwaccel helpers
  8021q: use __vlan_hwaccel helpers
  ipv4/tunnel: use __vlan_hwaccel helpers
  OVS: remove use of VLAN_TAG_PRESENT

 drivers/net/ethernet/emulex/benet/be_main.c | 15 ++-
 drivers/net/ethernet/marvell/sky2.c |  6 ++
 net/8021q/vlan_core.c   |  2 +-
 net/bridge/br_netfilter_hooks.c | 15 +--
 net/bridge/br_private.h |  2 +-
 net/bridge/br_vlan.c|  6 +++---
 net/core/dev.c  |  8 +---
 net/core/skbuff.c   |  2 +-
 net/ipv4/ip_tunnel_core.c   |  2 +-
 net/openvswitch/actions.c   | 13 +
 net/openvswitch/flow.c  |  4 ++--
 net/openvswitch/flow.h  |  2 +-
 net/openvswitch/flow_netlink.c  | 22 +++---
 net/sched/act_vlan.c|  2 +-
 14 files changed, 57 insertions(+), 44 deletions(-)

-- 
2.11.0



[PATCH net-next 1/8] benet: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
v3: fix adapter->pvid handling

 drivers/net/ethernet/emulex/benet/be_main.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_main.c 
b/drivers/net/ethernet/emulex/benet/be_main.c
index 7e1633bf5a22..cd12c9a7664b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1035,30 +1035,35 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct 
be_adapter *adapter,
 struct be_wrb_params
 *wrb_params)
 {
+   bool insert_vlan = false;
u16 vlan_tag = 0;
 
skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb))
return skb;
 
-   if (skb_vlan_tag_present(skb))
+   if (skb_vlan_tag_present(skb)) {
vlan_tag = be_get_tx_vlan_tag(adapter, skb);
+   insert_vlan = true;
+   }
 
if (qnq_async_evt_rcvd(adapter) && adapter->pvid) {
-   if (!vlan_tag)
+   if (!insert_vlan) {
vlan_tag = adapter->pvid;
+   insert_vlan = true;
+   }
/* f/w workaround to set skip_hw_vlan = 1, informs the F/W to
 * skip VLAN insertion
 */
BE_WRB_F_SET(wrb_params->features, VLAN_SKIP_HW, 1);
}
 
-   if (vlan_tag) {
+   if (insert_vlan) {
skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q),
vlan_tag);
if (unlikely(!skb))
return skb;
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
}
 
/* Insert the outer VLAN, if any */
-- 
2.11.0



[PATCH net-next 4/8] net/core: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
This removes assumptions about VLAN_TAG_PRESENT bit.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/core/dev.c   | 8 +---
 net/core/skbuff.c| 2 +-
 net/sched/act_vlan.c | 2 +-
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 56818f7eab2b..3e2d617970e4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4172,7 +4172,7 @@ static int __netif_receive_skb_core(struct sk_buff *skb, 
bool pfmemalloc)
 * and set skb->priority like in vlan_do_receive()
 * For the time being, just ignore Priority Code Point
 */
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
}
 
type = skb->protocol;
@@ -4419,7 +4419,9 @@ static void gro_list_prepare(struct napi_struct *napi, 
struct sk_buff *skb)
}
 
diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
-   diffs |= p->vlan_tci ^ skb->vlan_tci;
+   diffs |= skb_vlan_tag_present(p) ^ skb_vlan_tag_present(skb);
+   if (skb_vlan_tag_present(p))
+   diffs |= p->vlan_tci ^ skb->vlan_tci;
diffs |= skb_metadata_dst_cmp(p, skb);
if (maclen == ETH_HLEN)
diffs |= compare_ether_header(skb_mac_header(p),
@@ -4657,7 +4659,7 @@ static void napi_reuse_skb(struct napi_struct *napi, 
struct sk_buff *skb)
__skb_pull(skb, skb_headlen(skb));
/* restore the reserve we had after netdev_alloc_skb_ip_align() */
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb));
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
skb->dev = napi->dev;
skb->skb_iif = 0;
skb->encapsulation = 0;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5a03730fbc1a..4b2aba3a28b2 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4565,7 +4565,7 @@ int skb_vlan_pop(struct sk_buff *skb)
int err;
 
if (likely(skb_vlan_tag_present(skb))) {
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
} else {
if (unlikely(!eth_type_vlan(skb->protocol)))
return 0;
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 19e0dba305ce..8d563806f518 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -62,7 +62,7 @@ static int tcf_vlan(struct sk_buff *skb, const struct 
tc_action *a,
/* extract existing tag (and guarantee no hw-accel tag) */
if (skb_vlan_tag_present(skb)) {
tci = skb_vlan_tag_get(skb);
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
} else {
/* in-payload vlan tag, pop it */
err = __skb_vlan_pop(skb, );
-- 
2.11.0



[PATCH net-next 2/8] benet: use skb_vlan_tag_get_prio()

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/emulex/benet/be_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_main.c 
b/drivers/net/ethernet/emulex/benet/be_main.c
index cd12c9a7664b..7e50c6c224c4 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -781,7 +781,7 @@ static inline u16 be_get_tx_vlan_tag(struct be_adapter 
*adapter,
u16 vlan_tag;
 
vlan_tag = skb_vlan_tag_get(skb);
-   vlan_prio = (vlan_tag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+   vlan_prio = skb_vlan_tag_get_prio(skb);
/* If vlan priority provided by OS is NOT in available bmap */
if (!(adapter->vlan_prio_bmap & (1 << vlan_prio)))
vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) |
-- 
2.11.0



[PATCH net-next 3/8] sky2: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/marvell/sky2.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/sky2.c 
b/drivers/net/ethernet/marvell/sky2.c
index b60ad0e56a9f..bcd20e04caba 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -2485,13 +2485,11 @@ static struct sk_buff *receive_copy(struct sky2_port 
*sky2,
skb->ip_summed = re->skb->ip_summed;
skb->csum = re->skb->csum;
skb_copy_hash(skb, re->skb);
-   skb->vlan_proto = re->skb->vlan_proto;
-   skb->vlan_tci = re->skb->vlan_tci;
+   __vlan_hwaccel_copy_tag(skb, re->skb);
 
pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
   length, PCI_DMA_FROMDEVICE);
-   re->skb->vlan_proto = 0;
-   re->skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(re->skb);
skb_clear_hash(re->skb);
re->skb->ip_summed = CHECKSUM_NONE;
skb_put(skb, length);
-- 
2.11.0



[PATCH net-next 8/8] OVS: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
This is a minimal change to allow removing of VLAN_TAG_PRESENT.
It leaves OVS unable to use CFI bit, as fixing this would need
a deeper surgery involving userspace interface.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
v2: removed userspace-facing changes

 net/openvswitch/actions.c  | 13 +
 net/openvswitch/flow.c |  4 ++--
 net/openvswitch/flow.h |  2 +-
 net/openvswitch/flow_netlink.c | 22 +++---
 4 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 514f7bcf7c63..fb41833423ea 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -278,7 +278,7 @@ static int push_vlan(struct sk_buff *skb, struct 
sw_flow_key *key,
key->eth.vlan.tpid = vlan->vlan_tpid;
}
return skb_vlan_push(skb, vlan->vlan_tpid,
-ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
+ntohs(vlan->vlan_tci) & ~VLAN_CFI_MASK);
 }
 
 /* 'src' is already properly masked. */
@@ -704,8 +704,10 @@ static int ovs_vport_output(struct net *net, struct sock 
*sk, struct sk_buff *sk
__skb_dst_copy(skb, data->dst);
*OVS_CB(skb) = data->cb;
skb->inner_protocol = data->inner_protocol;
-   skb->vlan_tci = data->vlan_tci;
-   skb->vlan_proto = data->vlan_proto;
+   if (data->vlan_tci & VLAN_CFI_MASK)
+   __vlan_hwaccel_put_tag(skb, data->vlan_proto, data->vlan_tci & 
~VLAN_CFI_MASK);
+   else
+   __vlan_hwaccel_clear_tag(skb);
 
/* Reconstruct the MAC header.  */
skb_push(skb, data->l2_len);
@@ -749,7 +751,10 @@ static void prepare_frag(struct vport *vport, struct 
sk_buff *skb,
data->cb = *OVS_CB(skb);
data->inner_protocol = skb->inner_protocol;
data->network_offset = orig_network_offset;
-   data->vlan_tci = skb->vlan_tci;
+   if (skb_vlan_tag_present(skb))
+   data->vlan_tci = skb_vlan_tag_get(skb) | VLAN_CFI_MASK;
+   else
+   data->vlan_tci = 0;
data->vlan_proto = skb->vlan_proto;
data->mac_proto = mac_proto;
data->l2_len = hlen;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 2c0a00f7f1b7..e632de603081 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -328,7 +328,7 @@ static int parse_vlan_tag(struct sk_buff *skb, struct 
vlan_head *key_vh,
return -ENOMEM;
 
vh = (struct vlan_head *)skb->data;
-   key_vh->tci = vh->tci | htons(VLAN_TAG_PRESENT);
+   key_vh->tci = vh->tci | htons(VLAN_CFI_MASK);
key_vh->tpid = vh->tpid;
 
if (unlikely(untag_vlan)) {
@@ -361,7 +361,7 @@ static int parse_vlan(struct sk_buff *skb, struct 
sw_flow_key *key)
int res;
 
if (skb_vlan_tag_present(skb)) {
-   key->eth.vlan.tci = htons(skb->vlan_tci);
+   key->eth.vlan.tci = htons(skb->vlan_tci) | htons(VLAN_CFI_MASK);
key->eth.vlan.tpid = skb->vlan_proto;
} else {
/* Parse outer vlan tag in the non-accelerated case. */
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index f61cae7f9030..c8724ca2e4c3 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -58,7 +58,7 @@ struct ovs_tunnel_info {
 
 struct vlan_head {
__be16 tpid; /* Vlan type. Generally 802.1q or 802.1ad.*/
-   __be16 tci;  /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
+   __be16 tci;  /* 0 if no VLAN, VLAN_CFI_MASK set otherwise. */
 };
 
 #define OVS_SW_FLOW_KEY_METADATA_SIZE  \
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index c87d359b9b37..05a31950f69c 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -853,9 +853,9 @@ static int validate_vlan_from_nlattrs(const struct 
sw_flow_match *match,
if (a[OVS_KEY_ATTR_VLAN])
tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
 
-   if (!(tci & htons(VLAN_TAG_PRESENT))) {
+   if (!(tci & htons(VLAN_CFI_MASK))) {
if (tci) {
-   OVS_NLERR(log, "%s TCI does not have VLAN_TAG_PRESENT 
bit set.",
+   OVS_NLERR(log, "%s TCI does not have VLAN_CFI_MASK bit 
set.",
  (inner) ? "C-VLAN" : "VLAN");
return -EINVAL;
} else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) {
@@ -876,9 +876,9 @@ static int validate_vlan_mask_from_nlattrs(const struct 
sw_flow_match *match,
__be16 tci = 0;
__be16 tpid = 0;
bool encap_valid = !!(match->key->eth.vlan.tci &
- htons(VLAN_TAG_PRESENT));
+   

[PATCH net-next 6/8] 8021q: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/8021q/vlan_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index e2ed69850489..604a67abdeb6 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -50,7 +50,7 @@ bool vlan_do_receive(struct sk_buff **skbp)
}
 
skb->priority = vlan_get_ingress_priority(vlan_dev, skb->vlan_tci);
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
 
rx_stats = this_cpu_ptr(vlan_dev_priv(vlan_dev)->vlan_pcpu_stats);
 
-- 
2.11.0



[PATCH net-next 7/8] ipv4/tunnel: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/ipv4/ip_tunnel_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index fed3d29f9eb3..0004a54373f0 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -120,7 +120,7 @@ int __iptunnel_pull_header(struct sk_buff *skb, int hdr_len,
}
 
skb_clear_hash_if_not_l4(skb);
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
skb_set_queue_mapping(skb, 0);
skb_scrub_packet(skb, xnet);
 
-- 
2.11.0



[PATCH net-next 5/8] bridge: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
This removes assumption than vlan_tci != 0 when tag is present.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/bridge/br_netfilter_hooks.c | 15 +--
 net/bridge/br_private.h |  2 +-
 net/bridge/br_vlan.c|  6 +++---
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 8ca6a929bf12..b62177a980e1 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -682,10 +682,8 @@ static int br_nf_push_frag_xmit(struct net *net, struct 
sock *sk, struct sk_buff
return 0;
}
 
-   if (data->vlan_tci) {
-   skb->vlan_tci = data->vlan_tci;
-   skb->vlan_proto = data->vlan_proto;
-   }
+   if (data->vlan_proto)
+   __vlan_hwaccel_put_tag(skb, data->vlan_proto, data->vlan_tci);
 
skb_copy_to_linear_data_offset(skb, -data->size, data->mac, data->size);
__skb_push(skb, data->encap_size);
@@ -749,8 +747,13 @@ static int br_nf_dev_queue_xmit(struct net *net, struct 
sock *sk, struct sk_buff
 
data = this_cpu_ptr(_frag_data_storage);
 
-   data->vlan_tci = skb->vlan_tci;
-   data->vlan_proto = skb->vlan_proto;
+   if (skb_vlan_tag_present(skb)) {
+   data->vlan_tci = skb->vlan_tci;
+   data->vlan_proto = skb->vlan_proto;
+   } else {
+   data->vlan_proto = 0;
+   }
+
data->encap_size = nf_bridge_encap_header_len(skb);
data->size = ETH_HLEN + data->encap_size;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e8345c..2efbdaf9ae1b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -819,7 +819,7 @@ static inline int br_vlan_get_tag(const struct sk_buff 
*skb, u16 *vid)
int err = 0;
 
if (skb_vlan_tag_present(skb)) {
-   *vid = skb_vlan_tag_get(skb) & VLAN_VID_MASK;
+   *vid = skb_vlan_tag_get_id(skb);
} else {
*vid = 0;
err = -EINVAL;
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index b6de4f457161..d25a5b34dc76 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -377,7 +377,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
}
 
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
 out:
return skb;
 }
@@ -444,8 +444,8 @@ static bool __allowed_ingress(const struct net_bridge *br,
__vlan_hwaccel_put_tag(skb, br->vlan_proto, pvid);
else
/* Priority-tagged Frame.
-* At this point, We know that skb->vlan_tci had
-* VLAN_TAG_PRESENT bit and its VID field was 0x000.
+* At this point, we know that skb->vlan_tci VID
+* field was 0.
 * We update only VID field and preserve PCP field.
 */
skb->vlan_tci |= pvid;
-- 
2.11.0



Re: [PATCH net-next v2 00/27] Allow passing of VLAN CFI bit through network stack

2017-01-03 Thread Michał Mirosław
On Tue, Jan 03, 2017 at 04:32:17PM -0500, David Miller wrote:
> From: Michał Mirosław <mirq-li...@rere.qmqm.pl>
> Date: Tue,  3 Jan 2017 21:52:33 +0100 (CET)
> 
> > Dear NetDevs
> > 
> > This series removes an abuse of VLAN CFI bit in Linux networking stack.
> > Currently Linux always clears the bit on outgoing traffic and presents
> > it cleared to userspace (even via AF_PACKET/tcpdump when hw-accelerated).
> > 
> > This uses a new vlan_present bit in struct skbuff, and removes an assumption
> > that vlan_proto != 0 when VLAN tag is present.
> > 
> > As I can't test most of the driver changes, please look at them carefully.
> > 
> > The series is supposed to be bisect-friendly and that requires temporary
> > insertion of #define VLAN_TAG_PRESENT in BPF code to be able to split
> > JIT changes per architecture.
> > 
> > Best Regards,
> > Michał Mirosław
 
> This patch series is really way too large.
> 
> You're going to have to find a way to combine related changes, or submit
> this as a series of logical sets, one at a time.

I have sent all the cleanups that don't depend on each other.
Please consider for applying.

Best Regards,
Michał Mirosław


[PATCH net-next] nfnetlink/queue: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/netfilter/nfnetlink_queue.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 3ee0b8a000a4..8c7923aac826 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -,8 +,9 @@ static int nfqa_parse_bridge(struct nf_queue_entry *entry,
if (!tb[NFQA_VLAN_TCI] || !tb[NFQA_VLAN_PROTO])
return -EINVAL;
 
-   entry->skb->vlan_tci = ntohs(nla_get_be16(tb[NFQA_VLAN_TCI]));
-   entry->skb->vlan_proto = nla_get_be16(tb[NFQA_VLAN_PROTO]);
+   __vlan_hwaccel_put_tag(entry->skb,
+   nla_get_be16(tb[NFQA_VLAN_PROTO]),
+   ntohs(nla_get_be16(tb[NFQA_VLAN_TCI])));
}
 
if (nfqa[NFQA_L2HDR]) {
-- 
2.11.0



[PATCH net-next] cnic: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/broadcom/cnic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/cnic.c 
b/drivers/net/ethernet/broadcom/cnic.c
index b1d2ac818710..6e3c61081338 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -5734,7 +5734,7 @@ static int cnic_netdev_event(struct notifier_block *this, 
unsigned long event,
if (realdev) {
dev = cnic_from_netdev(realdev);
if (dev) {
-   vid |= VLAN_TAG_PRESENT;
+   vid |= VLAN_CFI_MASK;   /* make non-zero */
cnic_rcv_netevent(dev->cnic_priv, event, vid);
cnic_put(dev);
}
-- 
2.11.0



[PATCH net-next] gianfar: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
Reviewed-by: Claudiu Manoil <claudiu.man...@nxp.com>
---
 drivers/net/ethernet/freescale/gianfar_ethtool.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c 
b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index a93e0199c369..fd5110dd13b6 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1155,11 +1155,9 @@ static int gfar_convert_to_filer(struct 
ethtool_rx_flow_spec *rule,
prio = vlan_tci_prio(rule);
prio_mask = vlan_tci_priom(rule);
 
-   if (cfi == VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {
-   vlan |= RQFPR_CFI;
-   vlan_mask |= RQFPR_CFI;
-   } else if (cfi != VLAN_TAG_PRESENT &&
-  cfi_mask == VLAN_TAG_PRESENT) {
+   if (cfi_mask) {
+   if (cfi)
+   vlan |= RQFPR_CFI;
vlan_mask |= RQFPR_CFI;
}
}
-- 
2.11.0



[PATCH net-next] cxgb4: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
This also initializes vlan_proto field.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/infiniband/hw/cxgb4/cm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index f1510cc76d2d..66a3d39b3d54 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -3899,7 +3899,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff 
*skb)
} else {
vlan_eh = (struct vlan_ethhdr *)(req + 1);
iph = (struct iphdr *)(vlan_eh + 1);
-   skb->vlan_tci = ntohs(cpl->vlan);
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), 
ntohs(cpl->vlan));
}
 
if (iph->version != 0x4)
-- 
2.11.0



[PATCH net-next] net/hyperv: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/hyperv/hyperv_net.h   |  2 +-
 drivers/net/hyperv/netvsc_drv.c   | 13 ++---
 drivers/net/hyperv/rndis_filter.c |  4 ++--
 3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 3958adade7eb..b53729e85a79 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -186,7 +186,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
void **data,
struct ndis_tcp_ip_checksum_info *csum_info,
struct vmbus_channel *channel,
-   u16 vlan_tci);
+   u16 vlan_tci, bool vlan_present);
 void netvsc_channel_cb(void *context);
 int rndis_filter_open(struct netvsc_device *nvdev);
 int rndis_filter_close(struct netvsc_device *nvdev);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index c9414c054852..6597d7901929 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -595,7 +595,7 @@ void netvsc_linkstatus_callback(struct hv_device 
*device_obj,
 static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
struct hv_netvsc_packet *packet,
struct ndis_tcp_ip_checksum_info *csum_info,
-   void *data, u16 vlan_tci)
+   void *data)
 {
struct sk_buff *skb;
 
@@ -625,10 +625,6 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct 
net_device *net,
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
 
-   if (vlan_tci & VLAN_TAG_PRESENT)
-   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
-  vlan_tci);
-
return skb;
 }
 
@@ -641,7 +637,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
void **data,
struct ndis_tcp_ip_checksum_info *csum_info,
struct vmbus_channel *channel,
-   u16 vlan_tci)
+   u16 vlan_tci, bool vlan_present)
 {
struct net_device *net = hv_get_drvdata(device_obj);
struct net_device_context *net_device_ctx = netdev_priv(net);
@@ -664,12 +660,15 @@ int netvsc_recv_callback(struct hv_device *device_obj,
net = vf_netdev;
 
/* Allocate a skb - TODO direct I/O to pages? */
-   skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data, vlan_tci);
+   skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data);
if (unlikely(!skb)) {
++net->stats.rx_dropped;
return NVSP_STAT_FAIL;
}
 
+   if (vlan_present)
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
+
if (net != vf_netdev)
skb_record_rx_queue(skb,
channel->offermsg.offer.sub_channel_index);
diff --git a/drivers/net/hyperv/rndis_filter.c 
b/drivers/net/hyperv/rndis_filter.c
index 8d90904e0e49..7f7b410a41c2 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -381,13 +381,13 @@ static int rndis_filter_receive_data(struct rndis_device 
*dev,
 
vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO);
if (vlan) {
-   vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid |
+   vlan_tci = vlan->vlanid |
(vlan->pri << VLAN_PRIO_SHIFT);
}
 
csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO);
return netvsc_recv_callback(net_device_ctx->device_ctx, pkt, data,
-   csum_info, channel, vlan_tci);
+   csum_info, channel, vlan_tci, vlan);
 }
 
 int rndis_filter_receive(struct hv_device *dev,
-- 
2.11.0



[PATCH net-next] ibmvnic: fix accelerated VLAN handling

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/ibm/ibmvnic.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ibm/ibmvnic.c 
b/drivers/net/ethernet/ibm/ibmvnic.c
index c12596676bbb..c7664db9019c 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -765,7 +765,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct 
net_device *netdev)
tx_crq.v1.sge_len = cpu_to_be32(skb->len);
tx_crq.v1.ioba = cpu_to_be64(data_dma_addr);
 
-   if (adapter->vlan_header_insertion) {
+   if (adapter->vlan_header_insertion && skb_vlan_tag_present(skb)) {
tx_crq.v1.flags2 |= IBMVNIC_TX_VLAN_INSERT;
tx_crq.v1.vlan_id = cpu_to_be16(skb->vlan_tci);
}
@@ -964,7 +964,8 @@ static int ibmvnic_poll(struct napi_struct *napi, int 
budget)
skb = rx_buff->skb;
skb_copy_to_linear_data(skb, rx_buff->data + offset,
length);
-   skb->vlan_tci = be16_to_cpu(next->rx_comp.vlan_tci);
+   if (flags & IBMVNIC_VLAN_STRIPPED)
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), 
be16_to_cpu(next->rx_comp.vlan_tci));
/* free the entry */
next->rx_comp.first = 0;
remove_buff_from_pool(adapter, rx_buff);
-- 
2.11.0



[PATCH net-next] i40iw: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/infiniband/hw/i40iw/i40iw_cm.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c 
b/drivers/infiniband/hw/i40iw/i40iw_cm.c
index 95a0586a4da8..125c66bf6107 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c
@@ -405,7 +405,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
if (pdata)
pd_len = pdata->size;
 
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT)
+   if (cm_node->vlan_id <= VLAN_VID_MASK)
eth_hlen += 4;
 
if (cm_node->ipv4)
@@ -434,7 +434,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
 
ether_addr_copy(ethh->h_dest, cm_node->rem_mac);
ether_addr_copy(ethh->h_source, cm_node->loc_mac);
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
((struct vlan_ethhdr *)ethh)->h_vlan_proto = 
htons(ETH_P_8021Q);
vtag = (cm_node->user_pri << VLAN_PRIO_SHIFT) | 
cm_node->vlan_id;
((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(vtag);
@@ -464,7 +464,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
 
ether_addr_copy(ethh->h_dest, cm_node->rem_mac);
ether_addr_copy(ethh->h_source, cm_node->loc_mac);
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
((struct vlan_ethhdr *)ethh)->h_vlan_proto = 
htons(ETH_P_8021Q);
vtag = (cm_node->user_pri << VLAN_PRIO_SHIFT) | 
cm_node->vlan_id;
((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(vtag);
@@ -3260,7 +3260,7 @@ static void i40iw_init_tcp_ctx(struct i40iw_cm_node 
*cm_node,
 
tcp_info->flow_label = 0;
tcp_info->snd_mss = cpu_to_le32(((u32)cm_node->tcp_cntxt.mss));
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
tcp_info->insert_vlan_tag = true;
tcp_info->vlan_tag = cpu_to_le16(cm_node->vlan_id);
}
-- 
2.11.0



[PATCH net-next] qlcnic: remove assumption that vlan_tci != 0

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c 
b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index fedd7366713c..c3cc707cc265 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -459,7 +459,7 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
 struct cmd_desc_type0 *first_desc, struct sk_buff *skb,
 struct qlcnic_host_tx_ring *tx_ring)
 {
-   u8 l4proto, opcode = 0, hdr_len = 0;
+   u8 l4proto, opcode = 0, hdr_len = 0, tag_vlan = 0;
u16 flags = 0, vlan_tci = 0;
int copied, offset, copy_len, size;
struct cmd_desc_type0 *hwdesc;
@@ -472,14 +472,16 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
flags = QLCNIC_FLAGS_VLAN_TAGGED;
vlan_tci = ntohs(vh->h_vlan_TCI);
protocol = ntohs(vh->h_vlan_encapsulated_proto);
+   tag_vlan = 1;
} else if (skb_vlan_tag_present(skb)) {
flags = QLCNIC_FLAGS_VLAN_OOB;
vlan_tci = skb_vlan_tag_get(skb);
+   tag_vlan = 1;
}
if (unlikely(adapter->tx_pvid)) {
-   if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+   if (tag_vlan && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
return -EIO;
-   if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
+   if (tag_vlan && (adapter->flags & QLCNIC_TAGGING_ENABLED))
goto set_flags;
 
flags = QLCNIC_FLAGS_VLAN_OOB;
-- 
2.11.0



[PATCH net-next 1/1] net/vlan: remove unused #define HAVE_VLAN_GET_TAG

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/if_vlan.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index bc4e8c2533da..74675312f8d9 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -476,8 +476,6 @@ static inline int __vlan_hwaccel_get_tag(const struct 
sk_buff *skb,
}
 }
 
-#define HAVE_VLAN_GET_TAG
-
 /**
  * vlan_get_tag - get the VLAN ID from the skb
  * @skb: skbuff to query
-- 
2.11.0



[PATCH net-next 3/3] net/vlan: include the shift in skb_vlan_tag_get_prio()

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/if_vlan.h   | 2 +-
 net/core/flow_dissector.c | 3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 75e839b84a63..bc4e8c2533da 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -81,7 +81,7 @@ static inline bool is_vlan_dev(const struct net_device *dev)
 #define skb_vlan_tag_present(__skb)((__skb)->vlan_tci & VLAN_TAG_PRESENT)
 #define skb_vlan_tag_get(__skb)((__skb)->vlan_tci & 
~VLAN_TAG_PRESENT)
 #define skb_vlan_tag_get_id(__skb) ((__skb)->vlan_tci & VLAN_VID_MASK)
-#define skb_vlan_tag_get_prio(__skb)   ((__skb)->vlan_tci & VLAN_PRIO_MASK)
+#define skb_vlan_tag_get_prio(__skb)   (((__skb)->vlan_tci & VLAN_PRIO_MASK) 
>> VLAN_PRIO_SHIFT)
 
 /**
  * struct vlan_pcpu_stats - VLAN percpu rx/tx stats
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index d6447dc10371..d93768ac39a1 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -295,8 +295,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
 
if (vlan_tag_present) {
key_vlan->vlan_id = skb_vlan_tag_get_id(skb);
-   key_vlan->vlan_priority =
-   (skb_vlan_tag_get_prio(skb) >> 
VLAN_PRIO_SHIFT);
+   key_vlan->vlan_priority = 
skb_vlan_tag_get_prio(skb);
} else {
key_vlan->vlan_id = ntohs(vlan->h_vlan_TCI) &
VLAN_VID_MASK;
-- 
2.11.0



[PATCH net-next 1/3] net/vlan: introduce __vlan_hwaccel_clear_tag() helper

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/if_vlan.h | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 8d5fcd6284ce..38be9041cde4 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -382,6 +382,17 @@ static inline struct sk_buff 
*vlan_insert_tag_set_proto(struct sk_buff *skb,
return skb;
 }
 
+/**
+ * __vlan_hwaccel_clear_tag - clear hardware accelerated VLAN info
+ * @skb: skbuff to clear
+ *
+ * Clears the VLAN information from @skb
+ */
+static inline void __vlan_hwaccel_clear_tag(struct sk_buff *skb)
+{
+   skb->vlan_tci = 0;
+}
+
 /*
  * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
  * @skb: skbuff to tag
@@ -396,7 +407,7 @@ static inline struct sk_buff 
*__vlan_hwaccel_push_inside(struct sk_buff *skb)
skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
skb_vlan_tag_get(skb));
if (likely(skb))
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
return skb;
 }
 
-- 
2.11.0



[PATCH net-next 2/3] net/vlan: introduce __vlan_hwaccel_copy_tag() helper

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/if_vlan.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 38be9041cde4..75e839b84a63 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -393,6 +393,19 @@ static inline void __vlan_hwaccel_clear_tag(struct sk_buff 
*skb)
skb->vlan_tci = 0;
 }
 
+/**
+ * __vlan_hwaccel_copy_tag - copy hardware accelerated VLAN info from another 
skb
+ * @dst: skbuff to copy to
+ * @src: skbuff to copy from
+ *
+ * Copies VLAN information from @src to @dst (for branchless code)
+ */
+static inline void __vlan_hwaccel_copy_tag(struct sk_buff *dst, const struct 
sk_buff *src)
+{
+   dst->vlan_proto = src->vlan_proto;
+   dst->vlan_tci = src->vlan_tci;
+}
+
 /*
  * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
  * @skb: skbuff to tag
-- 
2.11.0



[PATCH net-next 0/3] Preparation for VLAN_TAG_PRESENT cleanup

2017-01-03 Thread Michał Mirosław
This introduces additional and fixes existing helpers for accessing
skb->vlan_tag.

Michał Mirosław (3):
  net/vlan: introduce __vlan_hwaccel_clear_tag() helper
  net/vlan: introduce __vlan_hwaccel_copy_tag() helper
  net/vlan: include the shift in skb_vlan_tag_get_prio()

 include/linux/if_vlan.h   | 28 ++--
 net/core/flow_dissector.c |  3 +--
 2 files changed, 27 insertions(+), 4 deletions(-)

-- 
2.11.0



Re: [PATCH net-next v2 00/27] Allow passing of VLAN CFI bit through network stack

2017-01-03 Thread Michał Mirosław
On Wed, Jan 04, 2017 at 12:21:51AM +0100, Michał Mirosław wrote:
> On Tue, Jan 03, 2017 at 04:32:17PM -0500, David Miller wrote:
> > From: Michał Mirosław <mirq-li...@rere.qmqm.pl>
> > Date: Tue,  3 Jan 2017 21:52:33 +0100 (CET)
> > 
> > > Dear NetDevs
> > > 
> > > This series removes an abuse of VLAN CFI bit in Linux networking stack.
> > > Currently Linux always clears the bit on outgoing traffic and presents
> > > it cleared to userspace (even via AF_PACKET/tcpdump when hw-accelerated).
> > > 
> > > This uses a new vlan_present bit in struct skbuff, and removes an 
> > > assumption
> > > that vlan_proto != 0 when VLAN tag is present.
> > > 
> > > As I can't test most of the driver changes, please look at them carefully.
> > > 
> > > The series is supposed to be bisect-friendly and that requires temporary
> > > insertion of #define VLAN_TAG_PRESENT in BPF code to be able to split
> > > JIT changes per architecture.
> > > 
> > > Best Regards,
> > > Michał Mirosław
> > > 
> > > v2: rebase onto net-next
> > 
> > This patch series is really way too large.
> > 
> > You're going to have to find a way to combine related changes, or submit
> > this as a series of logical sets, one at a time.
> 
> The dependency graph is really sparse: main patch 25 depends on all previous,
> 19-23 all depend only on 18 and 26 depends on 25.
> 
> That's it. So the question is: how would it be easier for you to manage?

Ah, I forgot about patches 1-2 that most depend on... So if you get those two
early, then most others can be split.

Best Regards,
Michał Mirosław


Re: [PATCH net-next v2 00/27] Allow passing of VLAN CFI bit through network stack

2017-01-03 Thread Michał Mirosław
On Tue, Jan 03, 2017 at 04:32:17PM -0500, David Miller wrote:
> From: Michał Mirosław <mirq-li...@rere.qmqm.pl>
> Date: Tue,  3 Jan 2017 21:52:33 +0100 (CET)
> 
> > Dear NetDevs
> > 
> > This series removes an abuse of VLAN CFI bit in Linux networking stack.
> > Currently Linux always clears the bit on outgoing traffic and presents
> > it cleared to userspace (even via AF_PACKET/tcpdump when hw-accelerated).
> > 
> > This uses a new vlan_present bit in struct skbuff, and removes an assumption
> > that vlan_proto != 0 when VLAN tag is present.
> > 
> > As I can't test most of the driver changes, please look at them carefully.
> > 
> > The series is supposed to be bisect-friendly and that requires temporary
> > insertion of #define VLAN_TAG_PRESENT in BPF code to be able to split
> > JIT changes per architecture.
> > 
> > Best Regards,
> > Michał Mirosław
> > 
> > v2: rebase onto net-next
> 
> This patch series is really way too large.
> 
> You're going to have to find a way to combine related changes, or submit
> this as a series of logical sets, one at a time.

The dependency graph is really sparse: main patch 25 depends on all previous,
19-23 all depend only on 18 and 26 depends on 25.

That's it. So the question is: how would it be easier for you to manage?

Best Regards,
Michał Mirosław


[PATCH net-next v3 10/27] benet: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
v3: fix adapter->pvid handling

 drivers/net/ethernet/emulex/benet/be_main.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_main.c 
b/drivers/net/ethernet/emulex/benet/be_main.c
index 7e1633bf5a22..cd12c9a7664b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1035,30 +1035,35 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct 
be_adapter *adapter,
 struct be_wrb_params
 *wrb_params)
 {
+   bool insert_vlan = false;
u16 vlan_tag = 0;
 
skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb))
return skb;
 
-   if (skb_vlan_tag_present(skb))
+   if (skb_vlan_tag_present(skb)) {
vlan_tag = be_get_tx_vlan_tag(adapter, skb);
+   insert_vlan = true;
+   }
 
if (qnq_async_evt_rcvd(adapter) && adapter->pvid) {
-   if (!vlan_tag)
+   if (!insert_vlan) {
vlan_tag = adapter->pvid;
+   insert_vlan = true;
+   }
/* f/w workaround to set skip_hw_vlan = 1, informs the F/W to
 * skip VLAN insertion
 */
BE_WRB_F_SET(wrb_params->features, VLAN_SKIP_HW, 1);
}
 
-   if (vlan_tag) {
+   if (insert_vlan) {
skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q),
vlan_tag);
if (unlikely(!skb))
return skb;
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
}
 
/* Insert the outer VLAN, if any */
-- 
2.11.0



Re: [PATCH net-next v2 24/27] bpf_test: prepare for VLAN_TAG_PRESENT removal

2017-01-03 Thread Michał Mirosław
On Tue, Jan 03, 2017 at 09:52:40PM +0100, Michał Mirosław wrote:
> ---
>  lib/test_bpf.c | 15 +++
>  1 file changed, 15 insertions(+)
 
Please ignore - squashed with #25.

Best Regards,
Michał Mirosław


[PATCH net-next v3 25/27] net: remove VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
v3: merged with #24 (test_bpf temporary changes)

 arch/mips/net/bpf_jit.c |  3 ---
 arch/powerpc/net/bpf_jit_comp.c |  3 ---
 arch/sparc/net/bpf_jit_comp.c   |  4 
 include/linux/if_vlan.h | 11 ++-
 include/linux/skbuff.h  | 16 +---
 lib/test_bpf.c  | 14 --
 net/core/filter.c   |  3 ---
 7 files changed, 23 insertions(+), 31 deletions(-)

diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 4b12b5df47e8..fb6d23415d16 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -1143,9 +1143,6 @@ static int build_body(struct jit_ctx *ctx)
  vlan_tci) != 2);
off = offsetof(struct sk_buff, vlan_tci);
emit_half_load(r_s0, r_skb, off, ctx);
-#ifdef VLAN_TAG_PRESENT
-   emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, ctx);
-#endif
break;
case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
ctx->flags |= SEEN_SKB | SEEN_A;
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 22ae63fb9b7d..fb3892763fff 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -381,9 +381,6 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 
*image,
 
PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
  vlan_tci));
-#ifdef VLAN_TAG_PRESENT
-   PPC_ANDI(r_A, r_A, ~VLAN_TAG_PRESENT);
-#endif
break;
case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
PPC_LBZ_OFFS(r_A, r_skb, PKT_VLAN_PRESENT_OFFSET());
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 61cc15dc86f7..d499b391393e 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -602,10 +602,6 @@ void bpf_jit_compile(struct bpf_prog *fp)
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
emit_skb_load16(vlan_tci, r_A);
-#ifdef VLAN_TAG_PRESENT
-   emit_loadimm(~VLAN_TAG_PRESENT, r_TMP);
-   emit_and(r_A, r_TMP, r_A);
-#endif
break;
case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
__emit_skb_load8(__pkt_vlan_present_offset, 
r_A);
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 75e839b84a63..8ff2f0ed4c27 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -66,7 +66,6 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct 
sk_buff *skb)
 #define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
 #define VLAN_PRIO_SHIFT13
 #define VLAN_CFI_MASK  0x1000 /* Canonical Format Indicator */
-#define VLAN_TAG_PRESENT   VLAN_CFI_MASK
 #define VLAN_VID_MASK  0x0fff /* VLAN Identifier */
 #define VLAN_N_VID 4096
 
@@ -78,8 +77,8 @@ static inline bool is_vlan_dev(const struct net_device *dev)
 return dev->priv_flags & IFF_802_1Q_VLAN;
 }
 
-#define skb_vlan_tag_present(__skb)((__skb)->vlan_tci & VLAN_TAG_PRESENT)
-#define skb_vlan_tag_get(__skb)((__skb)->vlan_tci & 
~VLAN_TAG_PRESENT)
+#define skb_vlan_tag_present(__skb)((__skb)->vlan_present)
+#define skb_vlan_tag_get(__skb)((__skb)->vlan_tci)
 #define skb_vlan_tag_get_id(__skb) ((__skb)->vlan_tci & VLAN_VID_MASK)
 #define skb_vlan_tag_get_prio(__skb)   ((__skb)->vlan_tci & VLAN_PRIO_MASK)
 
@@ -390,7 +389,7 @@ static inline struct sk_buff 
*vlan_insert_tag_set_proto(struct sk_buff *skb,
  */
 static inline void __vlan_hwaccel_clear_tag(struct sk_buff *skb)
 {
-   skb->vlan_tci = 0;
+   skb->vlan_present = 0;
 }
 
 /**
@@ -402,6 +401,7 @@ static inline void __vlan_hwaccel_clear_tag(struct sk_buff 
*skb)
  */
 static inline void __vlan_hwaccel_copy_tag(struct sk_buff *dst, const struct 
sk_buff *src)
 {
+   dst->vlan_present = src->vlan_present;
dst->vlan_proto = src->vlan_proto;
dst->vlan_tci = src->vlan_tci;
 }
@@ -436,7 +436,8 @@ static inline void __vlan_hwaccel_put_tag(struct sk_buff 
*skb,
  __be16 vlan_proto, u16 vlan_tci)
 {
skb->vlan_proto = vlan_proto;
-   skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
+   skb->vlan_tci = vlan_tci;
+   skb->vlan_present = 1;
 }
 
 /**
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 168c3e486bd4..c37d8d76fe34 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -740,6 +740,14 @@ struct sk_buff {
__u8csum_level:2

[PATCH net-next v2 09/27] cxgb4: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
This also initializes vlan_proto field.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/infiniband/hw/cxgb4/cm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index f1510cc76d2d..66a3d39b3d54 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -3899,7 +3899,7 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff 
*skb)
} else {
vlan_eh = (struct vlan_ethhdr *)(req + 1);
iph = (struct iphdr *)(vlan_eh + 1);
-   skb->vlan_tci = ntohs(cpl->vlan);
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), 
ntohs(cpl->vlan));
}
 
if (iph->version != 0x4)
-- 
2.11.0



[PATCH net-next v2 07/27] gianfar: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Reviewed-by: Claudiu Manoil <claudiu.man...@nxp.com>
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/freescale/gianfar_ethtool.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c 
b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index a93e0199c369..fd5110dd13b6 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1155,11 +1155,9 @@ static int gfar_convert_to_filer(struct 
ethtool_rx_flow_spec *rule,
prio = vlan_tci_prio(rule);
prio_mask = vlan_tci_priom(rule);
 
-   if (cfi == VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {
-   vlan |= RQFPR_CFI;
-   vlan_mask |= RQFPR_CFI;
-   } else if (cfi != VLAN_TAG_PRESENT &&
-  cfi_mask == VLAN_TAG_PRESENT) {
+   if (cfi_mask) {
+   if (cfi)
+   vlan |= RQFPR_CFI;
vlan_mask |= RQFPR_CFI;
}
}
-- 
2.11.0



[PATCH net-next v2 08/27] net/hyperv: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/hyperv/hyperv_net.h   |  2 +-
 drivers/net/hyperv/netvsc_drv.c   | 13 ++---
 drivers/net/hyperv/rndis_filter.c |  4 ++--
 3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 3958adade7eb..b53729e85a79 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -186,7 +186,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
void **data,
struct ndis_tcp_ip_checksum_info *csum_info,
struct vmbus_channel *channel,
-   u16 vlan_tci);
+   u16 vlan_tci, bool vlan_present);
 void netvsc_channel_cb(void *context);
 int rndis_filter_open(struct netvsc_device *nvdev);
 int rndis_filter_close(struct netvsc_device *nvdev);
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index c9414c054852..6597d7901929 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -595,7 +595,7 @@ void netvsc_linkstatus_callback(struct hv_device 
*device_obj,
 static struct sk_buff *netvsc_alloc_recv_skb(struct net_device *net,
struct hv_netvsc_packet *packet,
struct ndis_tcp_ip_checksum_info *csum_info,
-   void *data, u16 vlan_tci)
+   void *data)
 {
struct sk_buff *skb;
 
@@ -625,10 +625,6 @@ static struct sk_buff *netvsc_alloc_recv_skb(struct 
net_device *net,
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
 
-   if (vlan_tci & VLAN_TAG_PRESENT)
-   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
-  vlan_tci);
-
return skb;
 }
 
@@ -641,7 +637,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
void **data,
struct ndis_tcp_ip_checksum_info *csum_info,
struct vmbus_channel *channel,
-   u16 vlan_tci)
+   u16 vlan_tci, bool vlan_present)
 {
struct net_device *net = hv_get_drvdata(device_obj);
struct net_device_context *net_device_ctx = netdev_priv(net);
@@ -664,12 +660,15 @@ int netvsc_recv_callback(struct hv_device *device_obj,
net = vf_netdev;
 
/* Allocate a skb - TODO direct I/O to pages? */
-   skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data, vlan_tci);
+   skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data);
if (unlikely(!skb)) {
++net->stats.rx_dropped;
return NVSP_STAT_FAIL;
}
 
+   if (vlan_present)
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
+
if (net != vf_netdev)
skb_record_rx_queue(skb,
channel->offermsg.offer.sub_channel_index);
diff --git a/drivers/net/hyperv/rndis_filter.c 
b/drivers/net/hyperv/rndis_filter.c
index 8d90904e0e49..7f7b410a41c2 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -381,13 +381,13 @@ static int rndis_filter_receive_data(struct rndis_device 
*dev,
 
vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO);
if (vlan) {
-   vlan_tci = VLAN_TAG_PRESENT | vlan->vlanid |
+   vlan_tci = vlan->vlanid |
(vlan->pri << VLAN_PRIO_SHIFT);
}
 
csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO);
return netvsc_recv_callback(net_device_ctx->device_ctx, pkt, data,
-   csum_info, channel, vlan_tci);
+   csum_info, channel, vlan_tci, vlan);
 }
 
 int rndis_filter_receive(struct hv_device *dev,
-- 
2.11.0



[PATCH net-next v2 18/27] net/skbuff: add macros for VLAN_PRESENT bit

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/skbuff.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b53c0cfd417e..168c3e486bd4 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -768,6 +768,12 @@ struct sk_buff {
__u32   priority;
int skb_iif;
__u32   hash;
+#define PKT_VLAN_PRESENT_BIT   4   // CFI (12-th bit) in TCI
+#ifdef __BIG_ENDIAN
+#define PKT_VLAN_PRESENT_OFFSET()  offsetof(struct sk_buff, vlan_tci)
+#else
+#define PKT_VLAN_PRESENT_OFFSET()  (offsetof(struct sk_buff, vlan_tci) + 1)
+#endif
__be16  vlan_proto;
__u16   vlan_tci;
 #if defined(CONFIG_NET_RX_BUSY_POLL) || defined(CONFIG_XPS)
-- 
2.11.0



[PATCH net-next v2 06/27] cnic: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/broadcom/cnic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/cnic.c 
b/drivers/net/ethernet/broadcom/cnic.c
index b1d2ac818710..6e3c61081338 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -5734,7 +5734,7 @@ static int cnic_netdev_event(struct notifier_block *this, 
unsigned long event,
if (realdev) {
dev = cnic_from_netdev(realdev);
if (dev) {
-   vid |= VLAN_TAG_PRESENT;
+   vid |= VLAN_CFI_MASK;   /* make non-zero */
cnic_rcv_netevent(dev->cnic_priv, event, vid);
cnic_put(dev);
}
-- 
2.11.0



[PATCH net-next v2 10/27] benet: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/emulex/benet/be_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/emulex/benet/be_main.c 
b/drivers/net/ethernet/emulex/benet/be_main.c
index 7e1633bf5a22..b365a0117349 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1053,12 +1053,12 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct 
be_adapter *adapter,
BE_WRB_F_SET(wrb_params->features, VLAN_SKIP_HW, 1);
}
 
-   if (vlan_tag) {
+   if (skb_vlan_tag_present(skb)) {
skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q),
vlan_tag);
if (unlikely(!skb))
return skb;
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
}
 
/* Insert the outer VLAN, if any */
-- 
2.11.0



[PATCH net-next v2 05/27] i40iw: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/infiniband/hw/i40iw/i40iw_cm.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c 
b/drivers/infiniband/hw/i40iw/i40iw_cm.c
index 95a0586a4da8..125c66bf6107 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_cm.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c
@@ -405,7 +405,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
if (pdata)
pd_len = pdata->size;
 
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT)
+   if (cm_node->vlan_id <= VLAN_VID_MASK)
eth_hlen += 4;
 
if (cm_node->ipv4)
@@ -434,7 +434,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
 
ether_addr_copy(ethh->h_dest, cm_node->rem_mac);
ether_addr_copy(ethh->h_source, cm_node->loc_mac);
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
((struct vlan_ethhdr *)ethh)->h_vlan_proto = 
htons(ETH_P_8021Q);
vtag = (cm_node->user_pri << VLAN_PRIO_SHIFT) | 
cm_node->vlan_id;
((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(vtag);
@@ -464,7 +464,7 @@ static struct i40iw_puda_buf *i40iw_form_cm_frame(struct 
i40iw_cm_node *cm_node,
 
ether_addr_copy(ethh->h_dest, cm_node->rem_mac);
ether_addr_copy(ethh->h_source, cm_node->loc_mac);
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
((struct vlan_ethhdr *)ethh)->h_vlan_proto = 
htons(ETH_P_8021Q);
vtag = (cm_node->user_pri << VLAN_PRIO_SHIFT) | 
cm_node->vlan_id;
((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(vtag);
@@ -3260,7 +3260,7 @@ static void i40iw_init_tcp_ctx(struct i40iw_cm_node 
*cm_node,
 
tcp_info->flow_label = 0;
tcp_info->snd_mss = cpu_to_le32(((u32)cm_node->tcp_cntxt.mss));
-   if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
+   if (cm_node->vlan_id <= VLAN_VID_MASK) {
tcp_info->insert_vlan_tag = true;
tcp_info->vlan_tag = cpu_to_le16(cm_node->vlan_id);
}
-- 
2.11.0



[PATCH net-next v2 00/27] Allow passing of VLAN CFI bit through network stack

2017-01-03 Thread Michał Mirosław
Dear NetDevs

This series removes an abuse of VLAN CFI bit in Linux networking stack.
Currently Linux always clears the bit on outgoing traffic and presents
it cleared to userspace (even via AF_PACKET/tcpdump when hw-accelerated).

This uses a new vlan_present bit in struct skbuff, and removes an assumption
that vlan_proto != 0 when VLAN tag is present.

As I can't test most of the driver changes, please look at them carefully.

The series is supposed to be bisect-friendly and that requires temporary
insertion of #define VLAN_TAG_PRESENT in BPF code to be able to split
JIT changes per architecture.

Best Regards,
Michał Mirosław

v2: rebase onto net-next

---


Michał Mirosław (27):
  net/vlan: introduce __vlan_hwaccel_clear_tag() helper
  net/vlan: introduce __vlan_hwaccel_copy_tag() helper
  ibmvnic: fix accelerated VLAN handling
  qlcnic: remove assumption that vlan_tci != 0
  i40iw: remove use of VLAN_TAG_PRESENT
  cnic: remove use of VLAN_TAG_PRESENT
  gianfar: remove use of VLAN_TAG_PRESENT
  net/hyperv: remove use of VLAN_TAG_PRESENT
  cxgb4: use __vlan_hwaccel helpers
  benet: use __vlan_hwaccel helpers
  sky2: use __vlan_hwaccel helpers
  net/core: use __vlan_hwaccel helpers
  bridge: use __vlan_hwaccel helpers
  8021q: use __vlan_hwaccel helpers
  ipv4/tunnel: use __vlan_hwaccel helpers
  nfnetlink/queue: use __vlan_hwaccel helpers
  OVS: remove use of VLAN_TAG_PRESENT
  net/skbuff: add macros for VLAN_PRESENT bit
  net/bpf_jit: ARM: split VLAN_PRESENT bit handling from VLAN_TCI
  net/bpf_jit: MIPS: split VLAN_PRESENT bit handling from VLAN_TCI
  net/bpf_jit: PPC: split VLAN_PRESENT bit handling from VLAN_TCI
  net/bpf_jit: SPARC: split VLAN_PRESENT bit handling from VLAN_TCI
  net/bpf: split VLAN_PRESENT bit handling from VLAN_TCI
  bpf_test: prepare for VLAN_TAG_PRESENT removal
  net: remove VLAN_TAG_PRESENT
  net/hyperv: enable passing of VLAN.CFI bit
  net/vlan: remove unused #define HAVE_VLAN_GET_TAG

 arch/arm/net/bpf_jit_32.c| 17 ++-
 arch/mips/net/bpf_jit.c  | 17 ++-
 arch/powerpc/net/bpf_jit_comp.c  | 14 -
 arch/sparc/net/bpf_jit_comp.c| 14 -
 drivers/infiniband/hw/cxgb4/cm.c |  2 +-
 drivers/infiniband/hw/i40iw/i40iw_cm.c   |  8 ++---
 drivers/net/ethernet/broadcom/cnic.c |  2 +-
 drivers/net/ethernet/emulex/benet/be_main.c  |  4 +--
 drivers/net/ethernet/freescale/gianfar_ethtool.c |  8 ++---
 drivers/net/ethernet/ibm/ibmvnic.c   |  5 ++--
 drivers/net/ethernet/marvell/sky2.c  |  6 ++--
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c   |  8 +++--
 drivers/net/hyperv/hyperv_net.h  |  2 +-
 drivers/net/hyperv/netvsc_drv.c  | 14 -
 drivers/net/hyperv/rndis_filter.c|  5 ++--
 include/linux/if_vlan.h  | 37 +++-
 include/linux/skbuff.h   | 10 ++-
 lib/test_bpf.c   | 14 +
 net/8021q/vlan_core.c|  2 +-
 net/bridge/br_netfilter_hooks.c  | 15 ++
 net/bridge/br_private.h  |  2 +-
 net/bridge/br_vlan.c |  6 ++--
 net/core/dev.c   |  8 +++--
 net/core/filter.c| 17 ---
 net/core/skbuff.c|  2 +-
 net/ipv4/ip_tunnel_core.c|  2 +-
 net/netfilter/nfnetlink_queue.c  |  5 ++--
 net/openvswitch/actions.c| 13 ++---
 net/openvswitch/flow.c   |  2 +-
 net/openvswitch/flow.h   |  2 +-
 net/openvswitch/flow_netlink.c   | 22 +++---
 net/sched/act_vlan.c |  2 +-
 32 files changed, 163 insertions(+), 124 deletions(-)

-- 
2.11.0



[PATCH net-next v2 26/27] net/hyperv: enable passing of VLAN.CFI bit

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/hyperv/netvsc_drv.c   | 1 +
 drivers/net/hyperv/rndis_filter.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 6597d7901929..4e20f4c247fa 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -441,6 +441,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct 
net_device *net)
vlan = (struct ndis_pkt_8021q_info *)((void *)ppi +
ppi->ppi_offset);
vlan->vlanid = skb->vlan_tci & VLAN_VID_MASK;
+   vlan->cfi = !!(skb->vlan_tci & VLAN_CFI_MASK);
vlan->pri = (skb->vlan_tci & VLAN_PRIO_MASK) >>
VLAN_PRIO_SHIFT;
}
diff --git a/drivers/net/hyperv/rndis_filter.c 
b/drivers/net/hyperv/rndis_filter.c
index 7f7b410a41c2..9759d7380037 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -382,6 +382,7 @@ static int rndis_filter_receive_data(struct rndis_device 
*dev,
vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO);
if (vlan) {
vlan_tci = vlan->vlanid |
+   (vlan->cfi ? VLAN_CFI_MASK : 0) |
(vlan->pri << VLAN_PRIO_SHIFT);
}
 
-- 
2.11.0



[PATCH net-next v2 17/27] OVS: remove use of VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
This is a minimal change to allow removing of VLAN_TAG_PRESENT.
It leaves OVS unable to use CFI bit, as fixing this would need
a deeper surgery involving userspace interface.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
v2: removed userspace-facing changes

 net/openvswitch/actions.c  | 13 +
 net/openvswitch/flow.c |  2 +-
 net/openvswitch/flow.h |  2 +-
 net/openvswitch/flow_netlink.c | 22 +++---
 4 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 514f7bcf7c63..fb41833423ea 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -278,7 +278,7 @@ static int push_vlan(struct sk_buff *skb, struct 
sw_flow_key *key,
key->eth.vlan.tpid = vlan->vlan_tpid;
}
return skb_vlan_push(skb, vlan->vlan_tpid,
-ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
+ntohs(vlan->vlan_tci) & ~VLAN_CFI_MASK);
 }
 
 /* 'src' is already properly masked. */
@@ -704,8 +704,10 @@ static int ovs_vport_output(struct net *net, struct sock 
*sk, struct sk_buff *sk
__skb_dst_copy(skb, data->dst);
*OVS_CB(skb) = data->cb;
skb->inner_protocol = data->inner_protocol;
-   skb->vlan_tci = data->vlan_tci;
-   skb->vlan_proto = data->vlan_proto;
+   if (data->vlan_tci & VLAN_CFI_MASK)
+   __vlan_hwaccel_put_tag(skb, data->vlan_proto, data->vlan_tci & 
~VLAN_CFI_MASK);
+   else
+   __vlan_hwaccel_clear_tag(skb);
 
/* Reconstruct the MAC header.  */
skb_push(skb, data->l2_len);
@@ -749,7 +751,10 @@ static void prepare_frag(struct vport *vport, struct 
sk_buff *skb,
data->cb = *OVS_CB(skb);
data->inner_protocol = skb->inner_protocol;
data->network_offset = orig_network_offset;
-   data->vlan_tci = skb->vlan_tci;
+   if (skb_vlan_tag_present(skb))
+   data->vlan_tci = skb_vlan_tag_get(skb) | VLAN_CFI_MASK;
+   else
+   data->vlan_tci = 0;
data->vlan_proto = skb->vlan_proto;
data->mac_proto = mac_proto;
data->l2_len = hlen;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 2c0a00f7f1b7..0dff00a9bada 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -361,7 +361,7 @@ static int parse_vlan(struct sk_buff *skb, struct 
sw_flow_key *key)
int res;
 
if (skb_vlan_tag_present(skb)) {
-   key->eth.vlan.tci = htons(skb->vlan_tci);
+   key->eth.vlan.tci = htons(skb->vlan_tci) | htons(VLAN_CFI_MASK);
key->eth.vlan.tpid = skb->vlan_proto;
} else {
/* Parse outer vlan tag in the non-accelerated case. */
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index f61cae7f9030..c8724ca2e4c3 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -58,7 +58,7 @@ struct ovs_tunnel_info {
 
 struct vlan_head {
__be16 tpid; /* Vlan type. Generally 802.1q or 802.1ad.*/
-   __be16 tci;  /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
+   __be16 tci;  /* 0 if no VLAN, VLAN_CFI_MASK set otherwise. */
 };
 
 #define OVS_SW_FLOW_KEY_METADATA_SIZE  \
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index c87d359b9b37..05a31950f69c 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -853,9 +853,9 @@ static int validate_vlan_from_nlattrs(const struct 
sw_flow_match *match,
if (a[OVS_KEY_ATTR_VLAN])
tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
 
-   if (!(tci & htons(VLAN_TAG_PRESENT))) {
+   if (!(tci & htons(VLAN_CFI_MASK))) {
if (tci) {
-   OVS_NLERR(log, "%s TCI does not have VLAN_TAG_PRESENT 
bit set.",
+   OVS_NLERR(log, "%s TCI does not have VLAN_CFI_MASK bit 
set.",
  (inner) ? "C-VLAN" : "VLAN");
return -EINVAL;
} else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) {
@@ -876,9 +876,9 @@ static int validate_vlan_mask_from_nlattrs(const struct 
sw_flow_match *match,
__be16 tci = 0;
__be16 tpid = 0;
bool encap_valid = !!(match->key->eth.vlan.tci &
- htons(VLAN_TAG_PRESENT));
+ htons(VLAN_CFI_MASK));
bool i_encap_valid = !!(match->key->eth.cvlan.tci &
-   htons(VLAN_TAG_PRESENT));
+   htons(VLAN_CFI_MASK));
 
if (!(key_attrs & (1 << OVS_KEY_ATTR_ENCAP))) {
/* Not a VLAN. */
@@ -902,8 +902,8 @@ static int validate_vlan_ma

[PATCH net-next v2 25/27] net: remove VLAN_TAG_PRESENT

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 arch/mips/net/bpf_jit.c |  3 ---
 arch/powerpc/net/bpf_jit_comp.c |  3 ---
 arch/sparc/net/bpf_jit_comp.c   |  4 
 include/linux/if_vlan.h | 11 ++-
 include/linux/skbuff.h  | 16 +---
 lib/test_bpf.c  | 17 ++---
 net/core/filter.c   |  3 ---
 7 files changed, 17 insertions(+), 40 deletions(-)

diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 4b12b5df47e8..fb6d23415d16 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -1143,9 +1143,6 @@ static int build_body(struct jit_ctx *ctx)
  vlan_tci) != 2);
off = offsetof(struct sk_buff, vlan_tci);
emit_half_load(r_s0, r_skb, off, ctx);
-#ifdef VLAN_TAG_PRESENT
-   emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, ctx);
-#endif
break;
case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
ctx->flags |= SEEN_SKB | SEEN_A;
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 22ae63fb9b7d..fb3892763fff 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -381,9 +381,6 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 
*image,
 
PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
  vlan_tci));
-#ifdef VLAN_TAG_PRESENT
-   PPC_ANDI(r_A, r_A, ~VLAN_TAG_PRESENT);
-#endif
break;
case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
PPC_LBZ_OFFS(r_A, r_skb, PKT_VLAN_PRESENT_OFFSET());
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index 61cc15dc86f7..d499b391393e 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -602,10 +602,6 @@ void bpf_jit_compile(struct bpf_prog *fp)
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
emit_skb_load16(vlan_tci, r_A);
-#ifdef VLAN_TAG_PRESENT
-   emit_loadimm(~VLAN_TAG_PRESENT, r_TMP);
-   emit_and(r_A, r_TMP, r_A);
-#endif
break;
case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
__emit_skb_load8(__pkt_vlan_present_offset, 
r_A);
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 75e839b84a63..8ff2f0ed4c27 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -66,7 +66,6 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct 
sk_buff *skb)
 #define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */
 #define VLAN_PRIO_SHIFT13
 #define VLAN_CFI_MASK  0x1000 /* Canonical Format Indicator */
-#define VLAN_TAG_PRESENT   VLAN_CFI_MASK
 #define VLAN_VID_MASK  0x0fff /* VLAN Identifier */
 #define VLAN_N_VID 4096
 
@@ -78,8 +77,8 @@ static inline bool is_vlan_dev(const struct net_device *dev)
 return dev->priv_flags & IFF_802_1Q_VLAN;
 }
 
-#define skb_vlan_tag_present(__skb)((__skb)->vlan_tci & VLAN_TAG_PRESENT)
-#define skb_vlan_tag_get(__skb)((__skb)->vlan_tci & 
~VLAN_TAG_PRESENT)
+#define skb_vlan_tag_present(__skb)((__skb)->vlan_present)
+#define skb_vlan_tag_get(__skb)((__skb)->vlan_tci)
 #define skb_vlan_tag_get_id(__skb) ((__skb)->vlan_tci & VLAN_VID_MASK)
 #define skb_vlan_tag_get_prio(__skb)   ((__skb)->vlan_tci & VLAN_PRIO_MASK)
 
@@ -390,7 +389,7 @@ static inline struct sk_buff 
*vlan_insert_tag_set_proto(struct sk_buff *skb,
  */
 static inline void __vlan_hwaccel_clear_tag(struct sk_buff *skb)
 {
-   skb->vlan_tci = 0;
+   skb->vlan_present = 0;
 }
 
 /**
@@ -402,6 +401,7 @@ static inline void __vlan_hwaccel_clear_tag(struct sk_buff 
*skb)
  */
 static inline void __vlan_hwaccel_copy_tag(struct sk_buff *dst, const struct 
sk_buff *src)
 {
+   dst->vlan_present = src->vlan_present;
dst->vlan_proto = src->vlan_proto;
dst->vlan_tci = src->vlan_tci;
 }
@@ -436,7 +436,8 @@ static inline void __vlan_hwaccel_put_tag(struct sk_buff 
*skb,
  __be16 vlan_proto, u16 vlan_tci)
 {
skb->vlan_proto = vlan_proto;
-   skb->vlan_tci = VLAN_TAG_PRESENT | vlan_tci;
+   skb->vlan_tci = vlan_tci;
+   skb->vlan_present = 1;
 }
 
 /**
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 168c3e486bd4..c37d8d76fe34 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -740,6 +740,14 @@ struct sk_buff {
__u8csum_level:2;
__u8csum_ba

[PATCH net-next v2 11/27] sky2: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/marvell/sky2.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/marvell/sky2.c 
b/drivers/net/ethernet/marvell/sky2.c
index b60ad0e56a9f..bcd20e04caba 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -2485,13 +2485,11 @@ static struct sk_buff *receive_copy(struct sky2_port 
*sky2,
skb->ip_summed = re->skb->ip_summed;
skb->csum = re->skb->csum;
skb_copy_hash(skb, re->skb);
-   skb->vlan_proto = re->skb->vlan_proto;
-   skb->vlan_tci = re->skb->vlan_tci;
+   __vlan_hwaccel_copy_tag(skb, re->skb);
 
pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
   length, PCI_DMA_FROMDEVICE);
-   re->skb->vlan_proto = 0;
-   re->skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(re->skb);
skb_clear_hash(re->skb);
re->skb->ip_summed = CHECKSUM_NONE;
skb_put(skb, length);
-- 
2.11.0



[PATCH net-next v2 14/27] 8021q: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/8021q/vlan_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index e2ed69850489..604a67abdeb6 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -50,7 +50,7 @@ bool vlan_do_receive(struct sk_buff **skbp)
}
 
skb->priority = vlan_get_ingress_priority(vlan_dev, skb->vlan_tci);
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
 
rx_stats = this_cpu_ptr(vlan_dev_priv(vlan_dev)->vlan_pcpu_stats);
 
-- 
2.11.0



[PATCH net-next v2 27/27] net/vlan: remove unused #define HAVE_VLAN_GET_TAG

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/if_vlan.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 8ff2f0ed4c27..f0b935625bc8 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -477,8 +477,6 @@ static inline int __vlan_hwaccel_get_tag(const struct 
sk_buff *skb,
}
 }
 
-#define HAVE_VLAN_GET_TAG
-
 /**
  * vlan_get_tag - get the VLAN ID from the skb
  * @skb: skbuff to query
-- 
2.11.0



[PATCH net-next v2 19/27] net/bpf_jit: ARM: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 arch/arm/net/bpf_jit_32.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 93d0b6d0b63e..6dbc60241f9d 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -915,17 +915,20 @@ static int build_body(struct jit_ctx *ctx)
emit(ARM_LDR_I(r_A, r_skb, off), ctx);
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
-   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
ctx->seen |= SEEN_SKB;
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 
2);
off = offsetof(struct sk_buff, vlan_tci);
emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
-   if (code == (BPF_ANC | SKF_AD_VLAN_TAG))
-   OP_IMM3(ARM_AND, r_A, r_A, ~VLAN_TAG_PRESENT, 
ctx);
-   else {
-   OP_IMM3(ARM_LSR, r_A, r_A, 12, ctx);
-   OP_IMM3(ARM_AND, r_A, r_A, 0x1, ctx);
-   }
+#ifdef VLAN_TAG_PRESENT
+   OP_IMM3(ARM_AND, r_A, r_A, ~VLAN_TAG_PRESENT, ctx);
+#endif
+   break;
+   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+   off = PKT_VLAN_PRESENT_OFFSET();
+   emit(ARM_LDRB_I(r_A, r_skb, off), ctx);
+   if (PKT_VLAN_PRESENT_BIT)
+   OP_IMM3(ARM_LSR, r_A, r_A, 
PKT_VLAN_PRESENT_BIT, ctx);
+   OP_IMM3(ARM_AND, r_A, r_A, 0x1, ctx);
break;
case BPF_ANC | SKF_AD_PKTTYPE:
ctx->seen |= SEEN_SKB;
-- 
2.11.0



[PATCH net-next v2 20/27] net/bpf_jit: MIPS: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Acked-by: Ralf Baechle <r...@linux-mips.org>
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 arch/mips/net/bpf_jit.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 49a2e2226fee..4b12b5df47e8 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -1138,19 +1138,23 @@ static int build_body(struct jit_ctx *ctx)
emit_load(r_A, r_skb, off, ctx);
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
-   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
ctx->flags |= SEEN_SKB | SEEN_A;
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
  vlan_tci) != 2);
off = offsetof(struct sk_buff, vlan_tci);
emit_half_load(r_s0, r_skb, off, ctx);
-   if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) {
-   emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, 
ctx);
-   } else {
-   emit_andi(r_A, r_s0, VLAN_TAG_PRESENT, ctx);
-   /* return 1 if present */
-   emit_sltu(r_A, r_zero, r_A, ctx);
-   }
+#ifdef VLAN_TAG_PRESENT
+   emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, ctx);
+#endif
+   break;
+   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+   ctx->flags |= SEEN_SKB | SEEN_A;
+   emit_load_byte(r_A, r_skb, PKT_VLAN_PRESENT_OFFSET(), 
ctx);
+   if (PKT_VLAN_PRESENT_BIT)
+   emit_srl(r_A, r_A, PKT_VLAN_PRESENT_BIT, ctx);
+   emit_andi(r_A, r_s0, 1, ctx);
+   /* return 1 if present */
+   emit_sltu(r_A, r_zero, r_A, ctx);
break;
case BPF_ANC | SKF_AD_PKTTYPE:
ctx->flags |= SEEN_SKB;
-- 
2.11.0



[PATCH net-next v2 12/27] net/core: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
This removes assumptions about VLAN_TAG_PRESENT bit.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/core/dev.c   | 8 +---
 net/core/skbuff.c| 2 +-
 net/sched/act_vlan.c | 2 +-
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 56818f7eab2b..3e2d617970e4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4172,7 +4172,7 @@ static int __netif_receive_skb_core(struct sk_buff *skb, 
bool pfmemalloc)
 * and set skb->priority like in vlan_do_receive()
 * For the time being, just ignore Priority Code Point
 */
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
}
 
type = skb->protocol;
@@ -4419,7 +4419,9 @@ static void gro_list_prepare(struct napi_struct *napi, 
struct sk_buff *skb)
}
 
diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
-   diffs |= p->vlan_tci ^ skb->vlan_tci;
+   diffs |= skb_vlan_tag_present(p) ^ skb_vlan_tag_present(skb);
+   if (skb_vlan_tag_present(p))
+   diffs |= p->vlan_tci ^ skb->vlan_tci;
diffs |= skb_metadata_dst_cmp(p, skb);
if (maclen == ETH_HLEN)
diffs |= compare_ether_header(skb_mac_header(p),
@@ -4657,7 +4659,7 @@ static void napi_reuse_skb(struct napi_struct *napi, 
struct sk_buff *skb)
__skb_pull(skb, skb_headlen(skb));
/* restore the reserve we had after netdev_alloc_skb_ip_align() */
skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb));
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
skb->dev = napi->dev;
skb->skb_iif = 0;
skb->encapsulation = 0;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5a03730fbc1a..4b2aba3a28b2 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4565,7 +4565,7 @@ int skb_vlan_pop(struct sk_buff *skb)
int err;
 
if (likely(skb_vlan_tag_present(skb))) {
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
} else {
if (unlikely(!eth_type_vlan(skb->protocol)))
return 0;
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 19e0dba305ce..8d563806f518 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -62,7 +62,7 @@ static int tcf_vlan(struct sk_buff *skb, const struct 
tc_action *a,
/* extract existing tag (and guarantee no hw-accel tag) */
if (skb_vlan_tag_present(skb)) {
tci = skb_vlan_tag_get(skb);
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
} else {
/* in-payload vlan tag, pop it */
err = __skb_vlan_pop(skb, );
-- 
2.11.0



[PATCH net-next v2 15/27] ipv4/tunnel: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/ipv4/ip_tunnel_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index fed3d29f9eb3..0004a54373f0 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -120,7 +120,7 @@ int __iptunnel_pull_header(struct sk_buff *skb, int hdr_len,
}
 
skb_clear_hash_if_not_l4(skb);
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
skb_set_queue_mapping(skb, 0);
skb_scrub_packet(skb, xnet);
 
-- 
2.11.0



[PATCH net-next v2 16/27] nfnetlink/queue: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/netfilter/nfnetlink_queue.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 3ee0b8a000a4..8c7923aac826 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -,8 +,9 @@ static int nfqa_parse_bridge(struct nf_queue_entry *entry,
if (!tb[NFQA_VLAN_TCI] || !tb[NFQA_VLAN_PROTO])
return -EINVAL;
 
-   entry->skb->vlan_tci = ntohs(nla_get_be16(tb[NFQA_VLAN_TCI]));
-   entry->skb->vlan_proto = nla_get_be16(tb[NFQA_VLAN_PROTO]);
+   __vlan_hwaccel_put_tag(entry->skb,
+   nla_get_be16(tb[NFQA_VLAN_PROTO]),
+   ntohs(nla_get_be16(tb[NFQA_VLAN_TCI])));
}
 
if (nfqa[NFQA_L2HDR]) {
-- 
2.11.0



[PATCH net-next v2 24/27] bpf_test: prepare for VLAN_TAG_PRESENT removal

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 lib/test_bpf.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 0362da0b66c3..00d345006671 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -691,8 +691,13 @@ static struct bpf_test tests[] = {
CLASSIC,
{ },
{
+#ifdef VLAN_TAG_PRESENT
{ 1, SKB_VLAN_TCI & ~VLAN_TAG_PRESENT },
{ 10, SKB_VLAN_TCI & ~VLAN_TAG_PRESENT }
+#else
+   { 1, SKB_VLAN_TCI },
+   { 10, SKB_VLAN_TCI }
+#endif
},
},
{
@@ -705,8 +710,13 @@ static struct bpf_test tests[] = {
CLASSIC,
{ },
{
+#ifdef VLAN_TAG_PRESENT
{ 1, !!(SKB_VLAN_TCI & VLAN_TAG_PRESENT) },
{ 10, !!(SKB_VLAN_TCI & VLAN_TAG_PRESENT) }
+#else
+   { 1, SKB_VLAN_PRESENT },
+   { 10, SKB_VLAN_PRESENT }
+#endif
},
},
{
@@ -4773,8 +4783,13 @@ static struct bpf_test tests[] = {
CLASSIC,
{ },
{
+#ifdef VLAN_TAG_PRESENT
{  1, !!(SKB_VLAN_TCI & VLAN_TAG_PRESENT) },
{ 10, !!(SKB_VLAN_TCI & VLAN_TAG_PRESENT) }
+#else
+   {  1, SKB_VLAN_PRESENT },
+   { 10, SKB_VLAN_PRESENT }
+#endif
},
.fill_helper = bpf_fill_maxinsns6,
},
-- 
2.11.0



[PATCH net-next v2 22/27] net/bpf_jit: SPARC: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 arch/sparc/net/bpf_jit_comp.c | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index a6d9204a6a0b..61cc15dc86f7 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -601,15 +601,17 @@ void bpf_jit_compile(struct bpf_prog *fp)
emit_skb_load32(hash, r_A);
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
-   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
emit_skb_load16(vlan_tci, r_A);
-   if (code != (BPF_ANC | SKF_AD_VLAN_TAG)) {
-   emit_alu_K(SRL, 12);
-   emit_andi(r_A, 1, r_A);
-   } else {
-   emit_loadimm(~VLAN_TAG_PRESENT, r_TMP);
-   emit_and(r_A, r_TMP, r_A);
-   }
+#ifdef VLAN_TAG_PRESENT
+   emit_loadimm(~VLAN_TAG_PRESENT, r_TMP);
+   emit_and(r_A, r_TMP, r_A);
+#endif
+   break;
+   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+   __emit_skb_load8(__pkt_vlan_present_offset, 
r_A);
+   if (PKT_VLAN_PRESENT_BIT)
+   emit_alu_K(SRL, PKT_VLAN_PRESENT_BIT);
+   emit_andi(r_A, 1, r_A);
break;
case BPF_LD | BPF_W | BPF_LEN:
emit_skb_load32(len, r_A);
-- 
2.11.0



[PATCH net-next v2 21/27] net/bpf_jit: PPC: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 arch/powerpc/net/bpf_jit_comp.c | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 7e706f36e364..22ae63fb9b7d 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -377,18 +377,19 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 
*image,
  hash));
break;
case BPF_ANC | SKF_AD_VLAN_TAG:
-   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 
2);
-   BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
 
PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
  vlan_tci));
-   if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) {
-   PPC_ANDI(r_A, r_A, ~VLAN_TAG_PRESENT);
-   } else {
-   PPC_ANDI(r_A, r_A, VLAN_TAG_PRESENT);
-   PPC_SRWI(r_A, r_A, 12);
-   }
+#ifdef VLAN_TAG_PRESENT
+   PPC_ANDI(r_A, r_A, ~VLAN_TAG_PRESENT);
+#endif
+   break;
+   case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+   PPC_LBZ_OFFS(r_A, r_skb, PKT_VLAN_PRESENT_OFFSET());
+   if (PKT_VLAN_PRESENT_BIT)
+   PPC_SRWI(r_A, r_A, PKT_VLAN_PRESENT_BIT);
+   PPC_ANDI(r_A, r_A, 1);
break;
case BPF_ANC | SKF_AD_QUEUE:
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
-- 
2.11.0



[PATCH net-next v2 13/27] bridge: use __vlan_hwaccel helpers

2017-01-03 Thread Michał Mirosław
This removes assumption than vlan_tci != 0 when tag is present.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/bridge/br_netfilter_hooks.c | 15 +--
 net/bridge/br_private.h |  2 +-
 net/bridge/br_vlan.c|  6 +++---
 3 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 8ca6a929bf12..b62177a980e1 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -682,10 +682,8 @@ static int br_nf_push_frag_xmit(struct net *net, struct 
sock *sk, struct sk_buff
return 0;
}
 
-   if (data->vlan_tci) {
-   skb->vlan_tci = data->vlan_tci;
-   skb->vlan_proto = data->vlan_proto;
-   }
+   if (data->vlan_proto)
+   __vlan_hwaccel_put_tag(skb, data->vlan_proto, data->vlan_tci);
 
skb_copy_to_linear_data_offset(skb, -data->size, data->mac, data->size);
__skb_push(skb, data->encap_size);
@@ -749,8 +747,13 @@ static int br_nf_dev_queue_xmit(struct net *net, struct 
sock *sk, struct sk_buff
 
data = this_cpu_ptr(_frag_data_storage);
 
-   data->vlan_tci = skb->vlan_tci;
-   data->vlan_proto = skb->vlan_proto;
+   if (skb_vlan_tag_present(skb)) {
+   data->vlan_tci = skb->vlan_tci;
+   data->vlan_proto = skb->vlan_proto;
+   } else {
+   data->vlan_proto = 0;
+   }
+
data->encap_size = nf_bridge_encap_header_len(skb);
data->size = ETH_HLEN + data->encap_size;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e8345c..2efbdaf9ae1b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -819,7 +819,7 @@ static inline int br_vlan_get_tag(const struct sk_buff 
*skb, u16 *vid)
int err = 0;
 
if (skb_vlan_tag_present(skb)) {
-   *vid = skb_vlan_tag_get(skb) & VLAN_VID_MASK;
+   *vid = skb_vlan_tag_get_id(skb);
} else {
*vid = 0;
err = -EINVAL;
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index b6de4f457161..d25a5b34dc76 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -377,7 +377,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
}
 
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
 out:
return skb;
 }
@@ -444,8 +444,8 @@ static bool __allowed_ingress(const struct net_bridge *br,
__vlan_hwaccel_put_tag(skb, br->vlan_proto, pvid);
else
/* Priority-tagged Frame.
-* At this point, We know that skb->vlan_tci had
-* VLAN_TAG_PRESENT bit and its VID field was 0x000.
+* At this point, we know that skb->vlan_tci VID
+* field was 0.
 * We update only VID field and preserve PCP field.
 */
skb->vlan_tci |= pvid;
-- 
2.11.0



[PATCH net-next v2 23/27] net/bpf: split VLAN_PRESENT bit handling from VLAN_TCI

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/core/filter.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index 1969b3f118c1..5209c5f5ac4a 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -188,22 +188,20 @@ static u32 convert_skb_access(int skb_field, int dst_reg, 
int src_reg,
break;
 
case SKF_AD_VLAN_TAG:
-   case SKF_AD_VLAN_TAG_PRESENT:
BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
-   BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
 
/* dst_reg = *(u16 *) (src_reg + offsetof(vlan_tci)) */
*insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
  offsetof(struct sk_buff, vlan_tci));
-   if (skb_field == SKF_AD_VLAN_TAG) {
-   *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg,
-   ~VLAN_TAG_PRESENT);
-   } else {
-   /* dst_reg >>= 12 */
-   *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, 12);
-   /* dst_reg &= 1 */
-   *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, 1);
-   }
+#ifdef VLAN_TAG_PRESENT
+   *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, ~VLAN_TAG_PRESENT);
+#endif
+   break;
+   case SKF_AD_VLAN_TAG_PRESENT:
+   *insn++ = BPF_LDX_MEM(BPF_B, dst_reg, src_reg, 
PKT_VLAN_PRESENT_OFFSET());
+   if (PKT_VLAN_PRESENT_BIT)
+   *insn++ = BPF_ALU32_IMM(BPF_RSH, dst_reg, 
PKT_VLAN_PRESENT_BIT);
+   *insn++ = BPF_ALU32_IMM(BPF_AND, dst_reg, 1);
break;
}
 
-- 
2.11.0



[PATCH net-next v2 03/27] ibmvnic: fix accelerated VLAN handling

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/ibm/ibmvnic.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/ibm/ibmvnic.c 
b/drivers/net/ethernet/ibm/ibmvnic.c
index c12596676bbb..c7664db9019c 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -765,7 +765,7 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct 
net_device *netdev)
tx_crq.v1.sge_len = cpu_to_be32(skb->len);
tx_crq.v1.ioba = cpu_to_be64(data_dma_addr);
 
-   if (adapter->vlan_header_insertion) {
+   if (adapter->vlan_header_insertion && skb_vlan_tag_present(skb)) {
tx_crq.v1.flags2 |= IBMVNIC_TX_VLAN_INSERT;
tx_crq.v1.vlan_id = cpu_to_be16(skb->vlan_tci);
}
@@ -964,7 +964,8 @@ static int ibmvnic_poll(struct napi_struct *napi, int 
budget)
skb = rx_buff->skb;
skb_copy_to_linear_data(skb, rx_buff->data + offset,
length);
-   skb->vlan_tci = be16_to_cpu(next->rx_comp.vlan_tci);
+   if (flags & IBMVNIC_VLAN_STRIPPED)
+   __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), 
be16_to_cpu(next->rx_comp.vlan_tci));
/* free the entry */
next->rx_comp.first = 0;
remove_buff_from_pool(adapter, rx_buff);
-- 
2.11.0



[PATCH net-next v2 02/27] net/vlan: introduce __vlan_hwaccel_copy_tag() helper

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/if_vlan.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 38be9041cde4..75e839b84a63 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -393,6 +393,19 @@ static inline void __vlan_hwaccel_clear_tag(struct sk_buff 
*skb)
skb->vlan_tci = 0;
 }
 
+/**
+ * __vlan_hwaccel_copy_tag - copy hardware accelerated VLAN info from another 
skb
+ * @dst: skbuff to copy to
+ * @src: skbuff to copy from
+ *
+ * Copies VLAN information from @src to @dst (for branchless code)
+ */
+static inline void __vlan_hwaccel_copy_tag(struct sk_buff *dst, const struct 
sk_buff *src)
+{
+   dst->vlan_proto = src->vlan_proto;
+   dst->vlan_tci = src->vlan_tci;
+}
+
 /*
  * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
  * @skb: skbuff to tag
-- 
2.11.0



[PATCH net-next v2 01/27] net/vlan: introduce __vlan_hwaccel_clear_tag() helper

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 include/linux/if_vlan.h | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index 8d5fcd6284ce..38be9041cde4 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -382,6 +382,17 @@ static inline struct sk_buff 
*vlan_insert_tag_set_proto(struct sk_buff *skb,
return skb;
 }
 
+/**
+ * __vlan_hwaccel_clear_tag - clear hardware accelerated VLAN info
+ * @skb: skbuff to clear
+ *
+ * Clears the VLAN information from @skb
+ */
+static inline void __vlan_hwaccel_clear_tag(struct sk_buff *skb)
+{
+   skb->vlan_tci = 0;
+}
+
 /*
  * __vlan_hwaccel_push_inside - pushes vlan tag to the payload
  * @skb: skbuff to tag
@@ -396,7 +407,7 @@ static inline struct sk_buff 
*__vlan_hwaccel_push_inside(struct sk_buff *skb)
skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
skb_vlan_tag_get(skb));
if (likely(skb))
-   skb->vlan_tci = 0;
+   __vlan_hwaccel_clear_tag(skb);
return skb;
 }
 
-- 
2.11.0



[PATCH net-next v2 04/27] qlcnic: remove assumption that vlan_tci != 0

2017-01-03 Thread Michał Mirosław
Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c 
b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index fedd7366713c..c3cc707cc265 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -459,7 +459,7 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
 struct cmd_desc_type0 *first_desc, struct sk_buff *skb,
 struct qlcnic_host_tx_ring *tx_ring)
 {
-   u8 l4proto, opcode = 0, hdr_len = 0;
+   u8 l4proto, opcode = 0, hdr_len = 0, tag_vlan = 0;
u16 flags = 0, vlan_tci = 0;
int copied, offset, copy_len, size;
struct cmd_desc_type0 *hwdesc;
@@ -472,14 +472,16 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
flags = QLCNIC_FLAGS_VLAN_TAGGED;
vlan_tci = ntohs(vh->h_vlan_TCI);
protocol = ntohs(vh->h_vlan_encapsulated_proto);
+   tag_vlan = 1;
} else if (skb_vlan_tag_present(skb)) {
flags = QLCNIC_FLAGS_VLAN_OOB;
vlan_tci = skb_vlan_tag_get(skb);
+   tag_vlan = 1;
}
if (unlikely(adapter->tx_pvid)) {
-   if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+   if (tag_vlan && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
return -EIO;
-   if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
+   if (tag_vlan && (adapter->flags & QLCNIC_TAGGING_ENABLED))
goto set_flags;
 
flags = QLCNIC_FLAGS_VLAN_OOB;
-- 
2.11.0



Re: [PATCH net-next] net: remove abuse of VLAN DEI/CFI bit

2016-12-14 Thread Michał Mirosław
On Tue, Dec 13, 2016 at 05:21:18PM -0800, Stephen Hemminger wrote:
> On Sat,  3 Dec 2016 10:22:28 +0100 (CET)
> Michał Mirosław <mirq-li...@rere.qmqm.pl> wrote:
> 
> > This All-in-one patch removes abuse of VLAN CFI bit, so it can be passed
> > intact through linux networking stack.
> > 
> > Signed-off-by: Michał Mirosław <michal.miros...@atendesoftware.pl>
> > ---
> > 
> > Dear NetDevs
> > 
> > I guess this needs to be split to the prep..convert[]..finish sequence,
> > but if you like it as is, then it's ready.
> > 
> > The biggest question is if the modified interface and vlan_present
> > is the way to go. This can be changed to use vlan_proto != 0 instead
> > of an extra flag bit.
> > 
> > As I can't test most of the driver changes, please look at them carefully.
> > OVS and bridge eyes are especially welcome.
> > 
> > Best Regards,
> > Michał Mirosław
> 
> Is the motivation to support 802.1ad Drop Eligability Indicator (DEI)?
> 
> If so then you need to be more verbose in the commit log, and lots more
> work is needed. You need to rename fields and validate every place a
> driver is using DEI bit to make sure it really does the right thing
> on that hardware. It is not just a mechanical change.

There are not many mentions of CFI bit in the Linux tree. Places that
used it as VLAN_TAG_PRESENT are fixed with this patchset. Other uses are:

 - VLAN code: ignored
 - ebt_vlan: ignored
 - OVS: cleared because of netlink API assumptions
 - DSA: transferred to/from (E)DSA tag
 - drivers: gianfar: uses properly in filtering rules
 - drivers: cnic: false-positive (uses only VLAN ID, CFI bit marks the field 
'valid')
 - drivers: qedr: false-positive (like cnic)

So unless there is something hidden in the hardware, no driver does anything
special with the CFI bit.

After this patchset only OVS will need further modifications to be able to
support handling of DEI bit.

Best Regards,
Michał Mirosław


Re: [PATCH net-next] net: remove abuse of VLAN DEI/CFI bit

2016-12-13 Thread Michał Mirosław
On Tue, Dec 13, 2016 at 05:21:18PM -0800, Stephen Hemminger wrote:
> On Sat,  3 Dec 2016 10:22:28 +0100 (CET)
> Michał Mirosław <mirq-li...@rere.qmqm.pl> wrote:
> > This All-in-one patch removes abuse of VLAN CFI bit, so it can be passed
> > intact through linux networking stack.
> > 
> > Signed-off-by: Michał Mirosław <michal.miros...@atendesoftware.pl>
> > ---
> > 
> > Dear NetDevs
> > 
> > I guess this needs to be split to the prep..convert[]..finish sequence,
> > but if you like it as is, then it's ready.
> > 
> > The biggest question is if the modified interface and vlan_present
> > is the way to go. This can be changed to use vlan_proto != 0 instead
> > of an extra flag bit.
> > 
> > As I can't test most of the driver changes, please look at them carefully.
> > OVS and bridge eyes are especially welcome.
> > 
> > Best Regards,
> > Michał Mirosław
> Is the motivation to support 802.1ad Drop Eligability Indicator (DEI)?
> 
> If so then you need to be more verbose in the commit log, and lots more
> work is needed. You need to rename fields and validate every place a
> driver is using DEI bit to make sure it really does the right thing
> on that hardware. It is not just a mechanical change.

My main motivation is to be able to see the bit intact in tcpdump and be
able to pass it untouched through at least a veth pair. It would be great
if all devices didn't do something stupid with the bit, but it's not
something I am able to make happen.

Best Regards,
Michał Mirosław


Re: [PATCH net-next 00/27] Remove VLAN CFI bit abuse

2016-12-13 Thread Michał Mirosław
On Tue, Dec 13, 2016 at 05:16:26PM -0800, Stephen Hemminger wrote:
> On Tue, 13 Dec 2016 01:12:32 +0100 (CET)
> Michał Mirosław <mirq-li...@rere.qmqm.pl> wrote:
> > This series removes an abuse of VLAN CFI bit in Linux networking stack.
> > Currently Linux always clears the bit on outgoing traffic and presents
> > it cleared to userspace (even via AF_PACKET/tcpdump when hw-accelerated).
> > 
> > This uses a new vlan_present bit in struct skbuff, and removes an assumption
> > that vlan_proto != 0 when VLAN tag is present.
> > 
> > As I can't test most of the driver changes, please look at them carefully.
> > 
> > The series is supposed to be bisect-friendly and that requires temporary
> > insertion of #define VLAN_TAG_PRESENT in BPF code to be able to split
> > JIT changes per architecture.
> 
> I wonder if CFI can every validly be non-zero in the modern world, on Hyper-V.
> There are no token ring devices and that seems to be the only use case where 
> CFI would
> be non-zero. Unless someone is planning to reuse it a a protocol bit which 
> seems
> like a really bad idea.
> 
> Maybe the right thing is to keep hard coded as zero and not start adding
> more untestable code conditions.
> 
> My recommendation would be get rid of VLAN_TAG_PRESENT, but don't preserve
> CFI bit.

According to Wikipedia page [1] on 802.1Q, CFI bit got already changed
to DEI (Drop eligible indicator) in 2011 revision of the IEEE standard.

I can't verify this, though.

Best Regards,
Michał Mirosław

[1] https://en.wikipedia.org/wiki/IEEE_802.1Q#Frame_format


[PATCH/replace net-next 17/27] OVS: remove use of VLAN_TAG_PRESENT

2016-12-13 Thread Michał Mirosław
This is a minimal change to allow removing of VLAN_TAG_PRESENT.
It leaves OVS unable to use CFI bit, as fixing this would need
a deeper surgery involving userspace interface.

Signed-off-by: Michał Mirosław <mirq-li...@rere.qmqm.pl>
---
 net/openvswitch/actions.c  | 13 +
 net/openvswitch/flow.c |  2 +-
 net/openvswitch/flow.h |  2 +-
 net/openvswitch/flow_netlink.c | 22 +++---
 4 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 514f7bc..fb41833 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -278,7 +278,7 @@ static int push_vlan(struct sk_buff *skb, struct 
sw_flow_key *key,
key->eth.vlan.tpid = vlan->vlan_tpid;
}
return skb_vlan_push(skb, vlan->vlan_tpid,
-ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
+ntohs(vlan->vlan_tci) & ~VLAN_CFI_MASK);
 }
 
 /* 'src' is already properly masked. */
@@ -704,8 +704,10 @@ static int ovs_vport_output(struct net *net, struct sock 
*sk, struct sk_buff *sk
__skb_dst_copy(skb, data->dst);
*OVS_CB(skb) = data->cb;
skb->inner_protocol = data->inner_protocol;
-   skb->vlan_tci = data->vlan_tci;
-   skb->vlan_proto = data->vlan_proto;
+   if (data->vlan_tci & VLAN_CFI_MASK)
+   __vlan_hwaccel_put_tag(skb, data->vlan_proto, data->vlan_tci & 
~VLAN_CFI_MASK);
+   else
+   __vlan_hwaccel_clear_tag(skb);
 
/* Reconstruct the MAC header.  */
skb_push(skb, data->l2_len);
@@ -749,7 +751,10 @@ static void prepare_frag(struct vport *vport, struct 
sk_buff *skb,
data->cb = *OVS_CB(skb);
data->inner_protocol = skb->inner_protocol;
data->network_offset = orig_network_offset;
-   data->vlan_tci = skb->vlan_tci;
+   if (skb_vlan_tag_present(skb))
+   data->vlan_tci = skb_vlan_tag_get(skb) | VLAN_CFI_MASK;
+   else
+   data->vlan_tci = 0;
data->vlan_proto = skb->vlan_proto;
data->mac_proto = mac_proto;
data->l2_len = hlen;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 08aa926..2bd4eac 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -347,7 +347,7 @@ static int parse_vlan(struct sk_buff *skb, struct 
sw_flow_key *key)
int res;
 
if (skb_vlan_tag_present(skb)) {
-   key->eth.vlan.tci = htons(skb->vlan_tci);
+   key->eth.vlan.tci = htons(skb->vlan_tci) | htons(VLAN_CFI_MASK);
key->eth.vlan.tpid = skb->vlan_proto;
} else {
/* Parse outer vlan tag in the non-accelerated case. */
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index f61cae7..c8724ca 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -58,7 +58,7 @@ struct ovs_tunnel_info {
 
 struct vlan_head {
__be16 tpid; /* Vlan type. Generally 802.1q or 802.1ad.*/
-   __be16 tci;  /* 0 if no VLAN, VLAN_TAG_PRESENT set otherwise. */
+   __be16 tci;  /* 0 if no VLAN, VLAN_CFI_MASK set otherwise. */
 };
 
 #define OVS_SW_FLOW_KEY_METADATA_SIZE  \
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index d19044f..b72fcbd 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -853,9 +853,9 @@ static int validate_vlan_from_nlattrs(const struct 
sw_flow_match *match,
if (a[OVS_KEY_ATTR_VLAN])
tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
 
-   if (!(tci & htons(VLAN_TAG_PRESENT))) {
+   if (!(tci & htons(VLAN_CFI_MASK))) {
if (tci) {
-   OVS_NLERR(log, "%s TCI does not have VLAN_TAG_PRESENT 
bit set.",
+   OVS_NLERR(log, "%s TCI does not have VLAN_CFI_MASK bit 
set.",
  (inner) ? "C-VLAN" : "VLAN");
return -EINVAL;
} else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) {
@@ -876,9 +876,9 @@ static int validate_vlan_mask_from_nlattrs(const struct 
sw_flow_match *match,
__be16 tci = 0;
__be16 tpid = 0;
bool encap_valid = !!(match->key->eth.vlan.tci &
- htons(VLAN_TAG_PRESENT));
+ htons(VLAN_CFI_MASK));
bool i_encap_valid = !!(match->key->eth.cvlan.tci &
-   htons(VLAN_TAG_PRESENT));
+   htons(VLAN_CFI_MASK));
 
if (!(key_attrs & (1 << OVS_KEY_ATTR_ENCAP))) {
/* Not a VLAN. */
@@ -902,8 +902,8 @@ static int validate_vlan_mask_from_nlattrs(const struct 
sw_flow_match *match,
  (inner) ? "C-VLAN&

Re: [PATCH net-next 17/27] OVS: remove assumptions about VLAN_TAG_PRESENT bit

2016-12-13 Thread Michał Mirosław
On Tue, Dec 13, 2016 at 11:40:10AM +0100, Jiri Benc wrote:
> On Tue, 13 Dec 2016 01:12:38 +0100 (CET), Michał Mirosław wrote:
> > @@ -850,20 +848,11 @@ static int validate_vlan_from_nlattrs(const struct 
> > sw_flow_match *match,
> > return -EINVAL;
> > }
> >  
> > -   if (a[OVS_KEY_ATTR_VLAN])
> > -   tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
> > -
> > -   if (!(tci & htons(VLAN_TAG_PRESENT))) {
> > -   if (tci) {
> > -   OVS_NLERR(log, "%s TCI does not have VLAN_TAG_PRESENT 
> > bit set.",
> > - (inner) ? "C-VLAN" : "VLAN");
> > -   return -EINVAL;
> > -   } else if (nla_len(a[OVS_KEY_ATTR_ENCAP])) {
> > -   /* Corner case for truncated VLAN header. */
> > -   OVS_NLERR(log, "Truncated %s header has non-zero encap 
> > attribute.",
> > - (inner) ? "C-VLAN" : "VLAN");
> > -   return -EINVAL;
> > -   }
> > +   if (!a[OVS_KEY_ATTR_VLAN] && nla_len(a[OVS_KEY_ATTR_ENCAP])) {
> > +   /* Corner case for truncated VLAN header. */
> > +   OVS_NLERR(log, "Truncated %s header has non-zero encap 
> > attribute.",
> > +   (inner) ? "C-VLAN" : "VLAN");
> > +   return -EINVAL;
> 
> This looks wrong. The zero value of nla_get_be16(a[OVS_KEY_ATTR_VLAN])
> together with empty a[OVS_KEY_ATTR_ENCAP] means truncated VLAN header
> and this needs to be preserved.
> 
> In other words, you need to check also !nla_get_be16(a[OVS_KEY_ATTR_VLAN])
> here.
> 
> 
> Overall, this whole patch looks very suspicious from the very
> beginning. The xors used are strong indication that something is not
> right.
> 
> And indeed, you're breaking uAPI compatibility. Previously, the
> VLAG_TAG_PRESENT bit set in OVS_KEY_ATTR_VLAN caused the flow to match
> on packets with VLAN tag present. After this patch, it causes the flow
> to match only on those packets that have a certain value of
> VLAN_CFI_MASK in their VLAN tag (I haven't bother deciphering what
> value is checked after all these xors, it's as well possible that it
> will also match on packets _without_ any VLAN header).
> 
> You have to preserve the old meaning of VLAN_TAG_PRESENT in
> OVS_KEY_ATTR_VLAN. When doing flow lookups, VLAN_TAG_PRESENT must match
> on and only on packets that have VLAN tag present, irrespective of their
> VLAN_CFI_MASK.
> 
> If you want to introduce support for lookups on VLAN_CFI_MASK, you'll
> have to do that by introducing a new netlink attribute.

Hmm. In that case I'll just mask the CFI bit on entry to OVS.
Otherwise it's for me like to stab in a dark at a large beast
I know nothing about.

Best Regards,
Michał Mirosław


  1   2   >