Commit 4d8bbbff authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Pull networking fixes from David Miller:
 "Hopefully the last round of fixes this release, fingers crossed :)

   1) Initialize static nf_conntrack_locks_all_lock properly, from
      Florian Westphal.

   2) Need to cancel pending work when destroying IDLETIMER entries,
      from Liping Zhang.

   3) Fix TX param usage when sending TSO over iwlwifi devices, from
      Emmanuel Grumbach.

   4) NFACCT quota params not validated properly, from Phil Turnbull.

   5) Resolve more glibc vs.  kernel header conflicts, from Mikko
      Tapeli.

   6) Missing IRQ free in ravb_close(), from Geert Uytterhoeven.

   7) Fix infoleak in x25, from Kangjie Lu.

   8) Similarly in thunderx driver, from Heinrich Schuchardt.

   9) tc_ife.h uapi header not exported properly, from Jamal Hadi Salim.

  10) Don't reenable PHY interreupts if device is in polling mode, from
      Shaohui Xie.

  11) Packet scheduler actions late binding was not being handled
      properly at all, from Jamal Hadi Salim.

  12) Fix binding of conntrack entries to helpers in openvswitch, from
      Joe Stringer"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (21 commits)
  gre: do not keep the GRE header around in collect medata mode
  openvswitch: Fix cached ct with helper.
  net sched: ife action fix late binding
  net sched: skbedit action fix late binding
  net sched: simple action fix late binding
  net sched: mirred action fix late binding
  net sched: ipt action fix late binding
  net sched: vlan action fix late binding
  net: phylib: fix interrupts re-enablement in phy_start
  tcp: refresh skb timestamp at retransmit time
  net: nps_enet: bug fix - handle lost tx interrupts
  net: nps_enet: Tx handler synchronization
  export tc ife uapi header
  net: thunderx: avoid exposing kernel stack
  net: fix a kernel infoleak in x25 module
  ravb: Add missing free_irq() call to ravb_close()
  uapi glibc compat: fix compile errors when glibc net/if.h included before linux/if.h
  netfilter: nfnetlink_acct: validate NFACCT_QUOTA parameter
  iwlwifi: mvm: don't override the rate with the AMSDU len
  netfilter: IDLETIMER: fix race condition when destroy the target
  ...
parents 50c73890 e271c7b4
...@@ -533,6 +533,7 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs, ...@@ -533,6 +533,7 @@ static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
nicvf_config_vlan_stripping(nic, nic->netdev->features); nicvf_config_vlan_stripping(nic, nic->netdev->features);
/* Enable Receive queue */ /* Enable Receive queue */
memset(&rq_cfg, 0, sizeof(struct rq_cfg));
rq_cfg.ena = 1; rq_cfg.ena = 1;
rq_cfg.tcp_ena = 0; rq_cfg.tcp_ena = 0;
nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, *(u64 *)&rq_cfg); nicvf_queue_reg_write(nic, NIC_QSET_RQ_0_7_CFG, qidx, *(u64 *)&rq_cfg);
...@@ -565,6 +566,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs, ...@@ -565,6 +566,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs,
qidx, (u64)(cq->dmem.phys_base)); qidx, (u64)(cq->dmem.phys_base));
/* Enable Completion queue */ /* Enable Completion queue */
memset(&cq_cfg, 0, sizeof(struct cq_cfg));
cq_cfg.ena = 1; cq_cfg.ena = 1;
cq_cfg.reset = 0; cq_cfg.reset = 0;
cq_cfg.caching = 0; cq_cfg.caching = 0;
...@@ -613,6 +615,7 @@ static void nicvf_snd_queue_config(struct nicvf *nic, struct queue_set *qs, ...@@ -613,6 +615,7 @@ static void nicvf_snd_queue_config(struct nicvf *nic, struct queue_set *qs,
qidx, (u64)(sq->dmem.phys_base)); qidx, (u64)(sq->dmem.phys_base));
/* Enable send queue & set queue size */ /* Enable send queue & set queue size */
memset(&sq_cfg, 0, sizeof(struct sq_cfg));
sq_cfg.ena = 1; sq_cfg.ena = 1;
sq_cfg.reset = 0; sq_cfg.reset = 0;
sq_cfg.ldwb = 0; sq_cfg.ldwb = 0;
...@@ -649,6 +652,7 @@ static void nicvf_rbdr_config(struct nicvf *nic, struct queue_set *qs, ...@@ -649,6 +652,7 @@ static void nicvf_rbdr_config(struct nicvf *nic, struct queue_set *qs,
/* Enable RBDR & set queue size */ /* Enable RBDR & set queue size */
/* Buffer size should be in multiples of 128 bytes */ /* Buffer size should be in multiples of 128 bytes */
memset(&rbdr_cfg, 0, sizeof(struct rbdr_cfg));
rbdr_cfg.ena = 1; rbdr_cfg.ena = 1;
rbdr_cfg.reset = 0; rbdr_cfg.reset = 0;
rbdr_cfg.ldwb = 0; rbdr_cfg.ldwb = 0;
......
...@@ -145,7 +145,7 @@ static void nps_enet_tx_handler(struct net_device *ndev) ...@@ -145,7 +145,7 @@ static void nps_enet_tx_handler(struct net_device *ndev)
u32 tx_ctrl_nt = (tx_ctrl_value & TX_CTL_NT_MASK) >> TX_CTL_NT_SHIFT; u32 tx_ctrl_nt = (tx_ctrl_value & TX_CTL_NT_MASK) >> TX_CTL_NT_SHIFT;
/* Check if we got TX */ /* Check if we got TX */
if (!priv->tx_packet_sent || tx_ctrl_ct) if (!priv->tx_skb || tx_ctrl_ct)
return; return;
/* Ack Tx ctrl register */ /* Ack Tx ctrl register */
...@@ -160,7 +160,7 @@ static void nps_enet_tx_handler(struct net_device *ndev) ...@@ -160,7 +160,7 @@ static void nps_enet_tx_handler(struct net_device *ndev)
} }
dev_kfree_skb(priv->tx_skb); dev_kfree_skb(priv->tx_skb);
priv->tx_packet_sent = false; priv->tx_skb = NULL;
if (netif_queue_stopped(ndev)) if (netif_queue_stopped(ndev))
netif_wake_queue(ndev); netif_wake_queue(ndev);
...@@ -183,6 +183,9 @@ static int nps_enet_poll(struct napi_struct *napi, int budget) ...@@ -183,6 +183,9 @@ static int nps_enet_poll(struct napi_struct *napi, int budget)
work_done = nps_enet_rx_handler(ndev); work_done = nps_enet_rx_handler(ndev);
if (work_done < budget) { if (work_done < budget) {
u32 buf_int_enable_value = 0; u32 buf_int_enable_value = 0;
u32 tx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL);
u32 tx_ctrl_ct =
(tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT;
napi_complete(napi); napi_complete(napi);
...@@ -192,6 +195,18 @@ static int nps_enet_poll(struct napi_struct *napi, int budget) ...@@ -192,6 +195,18 @@ static int nps_enet_poll(struct napi_struct *napi, int budget)
nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE,
buf_int_enable_value); buf_int_enable_value);
/* in case we will get a tx interrupt while interrupts
* are masked, we will lose it since the tx is edge interrupt.
* specifically, while executing the code section above,
* between nps_enet_tx_handler and the interrupts enable, all
* tx requests will be stuck until we will get an rx interrupt.
* the two code lines below will solve this situation by
* re-adding ourselves to the poll list.
*/
if (priv->tx_skb && !tx_ctrl_ct)
napi_reschedule(napi);
} }
return work_done; return work_done;
...@@ -217,7 +232,7 @@ static irqreturn_t nps_enet_irq_handler(s32 irq, void *dev_instance) ...@@ -217,7 +232,7 @@ static irqreturn_t nps_enet_irq_handler(s32 irq, void *dev_instance)
u32 tx_ctrl_ct = (tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT; u32 tx_ctrl_ct = (tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT;
u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT; u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT;
if ((!tx_ctrl_ct && priv->tx_packet_sent) || rx_ctrl_cr) if ((!tx_ctrl_ct && priv->tx_skb) || rx_ctrl_cr)
if (likely(napi_schedule_prep(&priv->napi))) { if (likely(napi_schedule_prep(&priv->napi))) {
nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0); nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, 0);
__napi_schedule(&priv->napi); __napi_schedule(&priv->napi);
...@@ -387,8 +402,6 @@ static void nps_enet_send_frame(struct net_device *ndev, ...@@ -387,8 +402,6 @@ static void nps_enet_send_frame(struct net_device *ndev,
/* Write the length of the Frame */ /* Write the length of the Frame */
tx_ctrl_value |= length << TX_CTL_NT_SHIFT; tx_ctrl_value |= length << TX_CTL_NT_SHIFT;
/* Indicate SW is done */
priv->tx_packet_sent = true;
tx_ctrl_value |= NPS_ENET_ENABLE << TX_CTL_CT_SHIFT; tx_ctrl_value |= NPS_ENET_ENABLE << TX_CTL_CT_SHIFT;
/* Send Frame */ /* Send Frame */
nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, tx_ctrl_value); nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, tx_ctrl_value);
...@@ -465,7 +478,7 @@ static s32 nps_enet_open(struct net_device *ndev) ...@@ -465,7 +478,7 @@ static s32 nps_enet_open(struct net_device *ndev)
s32 err; s32 err;
/* Reset private variables */ /* Reset private variables */
priv->tx_packet_sent = false; priv->tx_skb = NULL;
priv->ge_mac_cfg_2_value = 0; priv->ge_mac_cfg_2_value = 0;
priv->ge_mac_cfg_3_value = 0; priv->ge_mac_cfg_3_value = 0;
...@@ -534,6 +547,11 @@ static netdev_tx_t nps_enet_start_xmit(struct sk_buff *skb, ...@@ -534,6 +547,11 @@ static netdev_tx_t nps_enet_start_xmit(struct sk_buff *skb,
priv->tx_skb = skb; priv->tx_skb = skb;
/* make sure tx_skb is actually written to the memory
* before the HW is informed and the IRQ is fired.
*/
wmb();
nps_enet_send_frame(ndev, skb); nps_enet_send_frame(ndev, skb);
return NETDEV_TX_OK; return NETDEV_TX_OK;
......
...@@ -165,14 +165,12 @@ ...@@ -165,14 +165,12 @@
* struct nps_enet_priv - Storage of ENET's private information. * struct nps_enet_priv - Storage of ENET's private information.
* @regs_base: Base address of ENET memory-mapped control registers. * @regs_base: Base address of ENET memory-mapped control registers.
* @irq: For RX/TX IRQ number. * @irq: For RX/TX IRQ number.
* @tx_packet_sent: SW indication if frame is being sent.
* @tx_skb: socket buffer of sent frame. * @tx_skb: socket buffer of sent frame.
* @napi: Structure for NAPI. * @napi: Structure for NAPI.
*/ */
struct nps_enet_priv { struct nps_enet_priv {
void __iomem *regs_base; void __iomem *regs_base;
s32 irq; s32 irq;
bool tx_packet_sent;
struct sk_buff *tx_skb; struct sk_buff *tx_skb;
struct napi_struct napi; struct napi_struct napi;
u32 ge_mac_cfg_2_value; u32 ge_mac_cfg_2_value;
......
...@@ -1506,6 +1506,8 @@ static int ravb_close(struct net_device *ndev) ...@@ -1506,6 +1506,8 @@ static int ravb_close(struct net_device *ndev)
priv->phydev = NULL; priv->phydev = NULL;
} }
if (priv->chip_id == RCAR_GEN3)
free_irq(priv->emac_irq, ndev);
free_irq(ndev->irq, ndev); free_irq(ndev->irq, ndev);
napi_disable(&priv->napi[RAVB_NC]); napi_disable(&priv->napi[RAVB_NC]);
......
...@@ -790,9 +790,11 @@ void phy_start(struct phy_device *phydev) ...@@ -790,9 +790,11 @@ void phy_start(struct phy_device *phydev)
break; break;
case PHY_HALTED: case PHY_HALTED:
/* make sure interrupts are re-enabled for the PHY */ /* make sure interrupts are re-enabled for the PHY */
err = phy_enable_interrupts(phydev); if (phydev->irq != PHY_POLL) {
if (err < 0) err = phy_enable_interrupts(phydev);
break; if (err < 0)
break;
}
phydev->state = PHY_RESUMING; phydev->state = PHY_RESUMING;
do_resume = true; do_resume = true;
......
...@@ -105,6 +105,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -105,6 +105,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
struct iwl_tx_cmd *tx_cmd, struct iwl_tx_cmd *tx_cmd,
struct ieee80211_tx_info *info, u8 sta_id) struct ieee80211_tx_info *info, u8 sta_id)
{ {
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control; __le16 fc = hdr->frame_control;
u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
...@@ -185,7 +186,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -185,7 +186,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_cmd->tx_flags = cpu_to_le32(tx_flags); tx_cmd->tx_flags = cpu_to_le32(tx_flags);
/* Total # bytes to be transmitted */ /* Total # bytes to be transmitted */
tx_cmd->len = cpu_to_le16((u16)skb->len + tx_cmd->len = cpu_to_le16((u16)skb->len +
(uintptr_t)info->driver_data[0]); (uintptr_t)skb_info->driver_data[0]);
tx_cmd->next_frame_len = 0; tx_cmd->next_frame_len = 0;
tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
tx_cmd->sta_id = sta_id; tx_cmd->sta_id = sta_id;
...@@ -327,10 +328,11 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, ...@@ -327,10 +328,11 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
*/ */
static struct iwl_device_cmd * static struct iwl_device_cmd *
iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
int hdrlen, struct ieee80211_sta *sta, u8 sta_id) struct ieee80211_tx_info *info, int hdrlen,
struct ieee80211_sta *sta, u8 sta_id)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct iwl_device_cmd *dev_cmd; struct iwl_device_cmd *dev_cmd;
struct iwl_tx_cmd *tx_cmd; struct iwl_tx_cmd *tx_cmd;
...@@ -350,10 +352,10 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -350,10 +352,10 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control); iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control);
memset(&info->status, 0, sizeof(info->status)); memset(&skb_info->status, 0, sizeof(skb_info->status));
memset(info->driver_data, 0, sizeof(info->driver_data)); memset(skb_info->driver_data, 0, sizeof(skb_info->driver_data));
info->driver_data[1] = dev_cmd; skb_info->driver_data[1] = dev_cmd;
return dev_cmd; return dev_cmd;
} }
...@@ -361,22 +363,25 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -361,22 +363,25 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_info info;
struct iwl_device_cmd *dev_cmd; struct iwl_device_cmd *dev_cmd;
struct iwl_tx_cmd *tx_cmd; struct iwl_tx_cmd *tx_cmd;
u8 sta_id; u8 sta_id;
int hdrlen = ieee80211_hdrlen(hdr->frame_control); int hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU)) memcpy(&info, skb->cb, sizeof(info));
if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_AMPDU))
return -1; return -1;
if (WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && if (WARN_ON_ONCE(info.flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
(!info->control.vif || (!info.control.vif ||
info->hw_queue != info->control.vif->cab_queue))) info.hw_queue != info.control.vif->cab_queue)))
return -1; return -1;
/* This holds the amsdu headers length */ /* This holds the amsdu headers length */
info->driver_data[0] = (void *)(uintptr_t)0; skb_info->driver_data[0] = (void *)(uintptr_t)0;
/* /*
* IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used * IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
...@@ -385,7 +390,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -385,7 +390,7 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
* and hence needs to be sent on the aux queue * and hence needs to be sent on the aux queue
*/ */
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
info->control.vif->type == NL80211_IFTYPE_STATION) info.control.vif->type == NL80211_IFTYPE_STATION)
IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue; IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;
/* /*
...@@ -398,14 +403,14 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -398,14 +403,14 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
* AUX station. * AUX station.
*/ */
sta_id = mvm->aux_sta.sta_id; sta_id = mvm->aux_sta.sta_id;
if (info->control.vif) { if (info.control.vif) {
struct iwl_mvm_vif *mvmvif = struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(info->control.vif); iwl_mvm_vif_from_mac80211(info.control.vif);
if (info->control.vif->type == NL80211_IFTYPE_P2P_DEVICE || if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE ||
info->control.vif->type == NL80211_IFTYPE_AP) info.control.vif->type == NL80211_IFTYPE_AP)
sta_id = mvmvif->bcast_sta.sta_id; sta_id = mvmvif->bcast_sta.sta_id;
else if (info->control.vif->type == NL80211_IFTYPE_STATION && else if (info.control.vif->type == NL80211_IFTYPE_STATION &&
is_multicast_ether_addr(hdr->addr1)) { is_multicast_ether_addr(hdr->addr1)) {
u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id); u8 ap_sta_id = ACCESS_ONCE(mvmvif->ap_sta_id);
...@@ -414,19 +419,18 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -414,19 +419,18 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
} }
} }
IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info->hw_queue); IWL_DEBUG_TX(mvm, "station Id %d, queue=%d\n", sta_id, info.hw_queue);
dev_cmd = iwl_mvm_set_tx_params(mvm, skb, hdrlen, NULL, sta_id); dev_cmd = iwl_mvm_set_tx_params(mvm, skb, &info, hdrlen, NULL, sta_id);
if (!dev_cmd) if (!dev_cmd)
return -1; return -1;
/* From now on, we cannot access info->control */
tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
/* Copy MAC header from skb into command buffer */ /* Copy MAC header from skb into command buffer */
memcpy(tx_cmd->hdr, hdr, hdrlen); memcpy(tx_cmd->hdr, hdr, hdrlen);
if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info->hw_queue)) { if (iwl_trans_tx(mvm->trans, skb, dev_cmd, info.hw_queue)) {
iwl_trans_free_tx_cmd(mvm->trans, dev_cmd); iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
return -1; return -1;
} }
...@@ -445,11 +449,11 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -445,11 +449,11 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
#ifdef CONFIG_INET #ifdef CONFIG_INET
static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct sk_buff_head *mpdus_skb) struct sk_buff_head *mpdus_skb)
{ {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_hdr *hdr = (void *)skb->data;
unsigned int mss = skb_shinfo(skb)->gso_size; unsigned int mss = skb_shinfo(skb)->gso_size;
struct sk_buff *tmp, *next; struct sk_buff *tmp, *next;
...@@ -544,6 +548,8 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -544,6 +548,8 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
/* This skb fits in one single A-MSDU */ /* This skb fits in one single A-MSDU */
if (num_subframes * mss >= tcp_payload_len) { if (num_subframes * mss >= tcp_payload_len) {
struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
/* /*
* Compute the length of all the data added for the A-MSDU. * Compute the length of all the data added for the A-MSDU.
* This will be used to compute the length to write in the TX * This will be used to compute the length to write in the TX
...@@ -552,11 +558,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -552,11 +558,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
* already had one set of SNAP / IP / TCP headers. * already had one set of SNAP / IP / TCP headers.
*/ */
num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
info = IEEE80211_SKB_CB(skb);
amsdu_add = num_subframes * sizeof(struct ethhdr) + amsdu_add = num_subframes * sizeof(struct ethhdr) +
(num_subframes - 1) * (snap_ip_tcp + pad); (num_subframes - 1) * (snap_ip_tcp + pad);
/* This holds the amsdu headers length */ /* This holds the amsdu headers length */
info->driver_data[0] = (void *)(uintptr_t)amsdu_add; skb_info->driver_data[0] = (void *)(uintptr_t)amsdu_add;
__skb_queue_tail(mpdus_skb, skb); __skb_queue_tail(mpdus_skb, skb);
return 0; return 0;
...@@ -596,11 +601,14 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -596,11 +601,14 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes);
if (tcp_payload_len > mss) { if (tcp_payload_len > mss) {
struct ieee80211_tx_info *skb_info =
IEEE80211_SKB_CB(tmp);
num_subframes = DIV_ROUND_UP(tcp_payload_len, mss); num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
info = IEEE80211_SKB_CB(tmp);
amsdu_add = num_subframes * sizeof(struct ethhdr) + amsdu_add = num_subframes * sizeof(struct ethhdr) +
(num_subframes - 1) * (snap_ip_tcp + pad); (num_subframes - 1) * (snap_ip_tcp + pad);
info->driver_data[0] = (void *)(uintptr_t)amsdu_add; skb_info->driver_data[0] =
(void *)(uintptr_t)amsdu_add;
skb_shinfo(tmp)->gso_size = mss; skb_shinfo(tmp)->gso_size = mss;
} else { } else {
qc = ieee80211_get_qos_ctl((void *)tmp->data); qc = ieee80211_get_qos_ctl((void *)tmp->data);
...@@ -622,6 +630,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -622,6 +630,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
} }
#else /* CONFIG_INET */ #else /* CONFIG_INET */
static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct sk_buff_head *mpdus_skb) struct sk_buff_head *mpdus_skb)
{ {
...@@ -636,10 +645,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -636,10 +645,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
* Sets the fields in the Tx cmd that are crypto related * Sets the fields in the Tx cmd that are crypto related
*/ */
static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct iwl_mvm_sta *mvmsta; struct iwl_mvm_sta *mvmsta;
struct iwl_device_cmd *dev_cmd; struct iwl_device_cmd *dev_cmd;
struct iwl_tx_cmd *tx_cmd; struct iwl_tx_cmd *tx_cmd;
...@@ -660,7 +669,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -660,7 +669,8 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
return -1; return -1;
dev_cmd = iwl_mvm_set_tx_params(mvm, skb, hdrlen, sta, mvmsta->sta_id); dev_cmd = iwl_mvm_set_tx_params(mvm, skb, info, hdrlen,
sta, mvmsta->sta_id);
if (!dev_cmd) if (!dev_cmd)
goto drop; goto drop;
...@@ -736,7 +746,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -736,7 +746,8 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_info info;
struct sk_buff_head mpdus_skbs; struct sk_buff_head mpdus_skbs;
unsigned int payload_len; unsigned int payload_len;
int ret; int ret;
...@@ -747,21 +758,23 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -747,21 +758,23 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_STATION_COUNT))
return -1; return -1;
memcpy(&info, skb->cb, sizeof(info));
/* This holds the amsdu headers length */ /* This holds the amsdu headers length */
info->driver_data[0] = (void *)(uintptr_t)0; skb_info->driver_data[0] = (void *)(uintptr_t)0;
if (!skb_is_gso(skb)) if (!skb_is_gso(skb))
return iwl_mvm_tx_mpdu(mvm, skb, sta); return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) - payload_len = skb_tail_pointer(skb) - skb_transport_header(skb) -
tcp_hdrlen(skb) + skb->data_len; tcp_hdrlen(skb) + skb->data_len;
if (payload_len <= skb_shinfo(skb)->gso_size) if (payload_len <= skb_shinfo(skb)->gso_size)
return iwl_mvm_tx_mpdu(mvm, skb, sta); return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
__skb_queue_head_init(&mpdus_skbs); __skb_queue_head_init(&mpdus_skbs);
ret = iwl_mvm_tx_tso(mvm, skb, sta, &mpdus_skbs); ret = iwl_mvm_tx_tso(mvm, skb, &info, sta, &mpdus_skbs);
if (ret) if (ret)
return ret; return ret;
...@@ -771,7 +784,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -771,7 +784,7 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
while (!skb_queue_empty(&mpdus_skbs)) { while (!skb_queue_empty(&mpdus_skbs)) {
skb = __skb_dequeue(&mpdus_skbs); skb = __skb_dequeue(&mpdus_skbs);
ret = iwl_mvm_tx_mpdu(mvm, skb, sta); ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
if (ret) { if (ret) {
__skb_queue_purge(&mpdus_skbs); __skb_queue_purge(&mpdus_skbs);
return ret; return ret;
......
...@@ -19,14 +19,20 @@ ...@@ -19,14 +19,20 @@
#ifndef _LINUX_IF_H #ifndef _LINUX_IF_H
#define _LINUX_IF_H #define _LINUX_IF_H
#include <linux/libc-compat.h> /* for compatibility with glibc */
#include <linux/types.h> /* for "__kernel_caddr_t" et al */ #include <linux/types.h> /* for "__kernel_caddr_t" et al */
#include <linux/socket.h> /* for "struct sockaddr" et al */ #include <linux/socket.h> /* for "struct sockaddr" et al */
#include <linux/compiler.h> /* for "__user" et al */ #include <linux/compiler.h> /* for "__user" et al */
#if __UAPI_DEF_IF_IFNAMSIZ
#define IFNAMSIZ 16 #define IFNAMSIZ 16
#endif /* __UAPI_DEF_IF_IFNAMSIZ */
#define IFALIASZ 256 #define IFALIASZ 256
#include <linux/hdlc/ioctl.h> #include <linux/hdlc/ioctl.h>
/* For glibc compatibility. An empty enum does not compile. */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 && \
__UAPI_DEF_IF_NET_DEVICE_FLAGS != 0
/** /**
* enum net_device_flags - &struct net_device flags * enum net_device_flags - &struct net_device flags
* *
...@@ -68,6 +74,8 @@ ...@@ -68,6 +74,8 @@
* @IFF_ECHO: echo sent packets. Volatile. * @IFF_ECHO: echo sent packets. Volatile.
*/ */
enum net_device_flags { enum net_device_flags {
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
IFF_UP = 1<<0, /* sysfs */ IFF_UP = 1<<0, /* sysfs */
IFF_BROADCAST = 1<<1, /* volatile */ IFF_BROADCAST = 1<<1, /* volatile */
IFF_DEBUG = 1<<2, /* sysfs */ IFF_DEBUG = 1<<2, /* sysfs */
...@@ -84,11 +92,17 @@ enum net_device_flags { ...@@ -84,11 +92,17 @@ enum net_device_flags {
IFF_PORTSEL = 1<<13, /* sysfs */ IFF_PORTSEL = 1<<13, /* sysfs */
IFF_AUTOMEDIA = 1<<14, /* sysfs */ IFF_AUTOMEDIA = 1<<14, /* sysfs */
IFF_DYNAMIC = 1<<15, /* sysfs */ IFF_DYNAMIC = 1<<15, /* sysfs */
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
IFF_LOWER_UP = 1<<16, /* volatile */ IFF_LOWER_UP = 1<<16, /* volatile */
IFF_DORMANT = 1<<17, /* volatile */ IFF_DORMANT = 1<<17, /* volatile */
IFF_ECHO = 1<<18, /* volatile */ IFF_ECHO = 1<<18, /* volatile */
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
}; };
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 && __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
#define IFF_UP IFF_UP #define IFF_UP IFF_UP
#define IFF_BROADCAST IFF_BROADCAST #define IFF_BROADCAST IFF_BROADCAST
#define IFF_DEBUG IFF_DEBUG #define IFF_DEBUG IFF_DEBUG
...@@ -105,9 +119,13 @@ enum net_device_flags { ...@@ -105,9 +119,13 @@ enum net_device_flags {
#define IFF_PORTSEL IFF_PORTSEL #define IFF_PORTSEL IFF_PORTSEL
#define IFF_AUTOMEDIA IFF_AUTOMEDIA #define IFF_AUTOMEDIA IFF_AUTOMEDIA
#define IFF_DYNAMIC IFF_DYNAMIC #define IFF_DYNAMIC IFF_DYNAMIC
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
#define IFF_LOWER_UP IFF_LOWER_UP #define IFF_LOWER_UP IFF_LOWER_UP
#define IFF_DORMANT IFF_DORMANT #define IFF_DORMANT IFF_DORMANT
#define IFF_ECHO IFF_ECHO #define IFF_ECHO IFF_ECHO
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\ #define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
...@@ -166,6 +184,8 @@ enum { ...@@ -166,6 +184,8 @@ enum {
* being very small might be worth keeping for clean configuration. * being very small might be worth keeping for clean configuration.
*/ */
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_IFMAP
struct ifmap { struct ifmap {
unsigned long mem_start; unsigned long mem_start;
unsigned long mem_end; unsigned long mem_end;
...@@ -175,6 +195,7 @@ struct ifmap { ...@@ -175,6 +195,7 @@ struct ifmap {
unsigned char port; unsigned char port;
/* 3 bytes spare */ /* 3 bytes spare */
}; };
#endif /* __UAPI_DEF_IF_IFMAP */
struct if_settings { struct if_settings {
unsigned int type; /* Type of physical device or protocol */ unsigned int type; /* Type of physical device or protocol */
...@@ -200,6 +221,8 @@ struct if_settings { ...@@ -200,6 +221,8 @@ struct if_settings {
* remainder may be interface specific. * remainder may be interface specific.
*/ */
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_IFREQ
struct ifreq { struct ifreq {
#define IFHWADDRLEN 6 #define IFHWADDRLEN 6
union union
...@@ -223,6 +246,7 @@ struct ifreq { ...@@ -223,6 +246,7 @@ struct ifreq {
struct if_settings ifru_settings; struct if_settings ifru_settings;
} ifr_ifru; } ifr_ifru;
}; };
#endif /* __UAPI_DEF_IF_IFREQ */
#define ifr_name ifr_ifrn.ifrn_name /* interface name */ #define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ #define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
...@@ -249,6 +273,8 @@ struct ifreq { ...@@ -249,6 +273,8 @@ struct ifreq {
* must know all networks accessible). * must know all networks accessible).
*/ */
/* for compatibility with glibc net/if.h */
#if __UAPI_DEF_IF_IFCONF
struct ifconf { struct ifconf {
int ifc_len; /* size of buffer */ int ifc_len; /* size of buffer */
union { union {
...@@ -256,6 +282,8 @@ struct ifconf { ...@@ -256,6 +282,8 @@ struct ifconf {
struct ifreq __user *ifcu_req; struct ifreq __user *ifcu_req;
} ifc_ifcu; } ifc_ifcu;
}; };
#endif /* __UAPI_DEF_IF_IFCONF */
#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
#define ifc_req ifc_ifcu.ifcu_req /* array of structures */ #define ifc_req ifc_ifcu.ifcu_req /* array of structures */
......
...@@ -51,6 +51,40 @@ ...@@ -51,6 +51,40 @@
/* We have included glibc headers... */ /* We have included glibc headers... */
#if defined(__GLIBC__) #if defined(__GLIBC__)
/* Coordinate with glibc net/if.h header. */
#if defined(_NET_IF_H)
/* GLIBC headers included first so don't define anything
* that would already be defined. */
#define __UAPI_DEF_IF_IFCONF 0
#define __UAPI_DEF_IF_IFMAP 0
#define __UAPI_DEF_IF_IFNAMSIZ 0
#define __UAPI_DEF_IF_IFREQ 0
/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0
/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
#else /* _NET_IF_H */
/* Linux headers included first, and we must define everything
* we need. The expectation is that glibc will check the
* __UAPI_DEF_* defines and adjust appropriately. */
#define __UAPI_DEF_IF_IFCONF 1
#define __UAPI_DEF_IF_IFMAP 1
#define __UAPI_DEF_IF_IFNAMSIZ 1
#define __UAPI_DEF_IF_IFREQ 1
/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
#endif /* _NET_IF_H */
/* Coordinate with glibc netinet/in.h header. */ /* Coordinate with glibc netinet/in.h header. */
#if defined(_NETINET_IN_H) #if defined(_NETINET_IN_H)
...@@ -117,6 +151,16 @@ ...@@ -117,6 +151,16 @@
* that we need. */ * that we need. */
#else /* !defined(__GLIBC__) */ #else /* !defined(__GLIBC__) */
/* Definitions for if.h */
#define __UAPI_DEF_IF_IFCONF 1
#define __UAPI_DEF_IF_IFMAP 1
#define __UAPI_DEF_IF_IFNAMSIZ 1
#define __UAPI_DEF_IF_IFREQ 1
/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
/* Definitions for in.h */ /* Definitions for in.h */
#define __UAPI_DEF_IN_ADDR 1 #define __UAPI_DEF_IN_ADDR 1
#define __UAPI_DEF_IN_IPPROTO 1 #define __UAPI_DEF_IN_IPPROTO 1
......
...@@ -10,3 +10,4 @@ header-y += tc_skbedit.h ...@@ -10,3 +10,4 @@ header-y += tc_skbedit.h
header-y += tc_vlan.h header-y += tc_vlan.h
header-y += tc_bpf.h header-y += tc_bpf.h
header-y += tc_connmark.h header-y += tc_connmark.h
header-y += tc_ife.h
...@@ -398,7 +398,10 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) ...@@ -398,7 +398,10 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
iph->saddr, iph->daddr, tpi->key); iph->saddr, iph->daddr, tpi->key);
if (tunnel) { if (tunnel) {
skb_pop_mac_header(skb); if (tunnel->dev->type != ARPHRD_NONE)
skb_pop_mac_header(skb);
else
skb_reset_mac_header(skb);
if (tunnel->collect_md) { if (tunnel->collect_md) {
__be16 flags; __be16 flags;
__be64 tun_id; __be64 tun_id;
...@@ -1031,6 +1034,8 @@ static void ipgre_netlink_parms(struct net_device *dev, ...@@ -1031,6 +1034,8 @@ static void ipgre_netlink_parms(struct net_device *dev,
struct ip_tunnel *t = netdev_priv(dev); struct ip_tunnel *t = netdev_priv(dev);
t->collect_md = true; t->collect_md = true;
if (dev->type == ARPHRD_IPGRE)
dev->type = ARPHRD_NONE;
} }
} }
......
...@@ -2640,8 +2640,10 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) ...@@ -2640,8 +2640,10 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
*/ */
if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) || if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) ||
skb_headroom(skb) >= 0xFFFF)) { skb_headroom(skb) >= 0xFFFF)) {
struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, struct sk_buff *nskb;
GFP_ATOMIC);
skb_mstamp_get(&skb->skb_mstamp);
nskb = __pskb_copy(skb, MAX_TCP_HEADER, GFP_ATOMIC);
err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
-ENOBUFS; -ENOBUFS;
} else { } else {
......
...@@ -66,7 +66,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_locks); ...@@ -66,7 +66,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_locks);
__cacheline_aligned_in_smp DEFINE_SPINLOCK(nf_conntrack_expect_lock); __cacheline_aligned_in_smp DEFINE_SPINLOCK(nf_conntrack_expect_lock);
EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock);
static __read_mostly spinlock_t nf_conntrack_locks_all_lock; static __read_mostly DEFINE_SPINLOCK(nf_conntrack_locks_all_lock);
static __read_mostly bool nf_conntrack_locks_all; static __read_mostly bool nf_conntrack_locks_all;
void nf_conntrack_lock(spinlock_t *lock) __acquires(lock) void nf_conntrack_lock(spinlock_t *lock) __acquires(lock)
......
...@@ -96,6 +96,8 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl, ...@@ -96,6 +96,8 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
return -EINVAL; return -EINVAL;
if (flags & NFACCT_F_OVERQUOTA) if (flags & NFACCT_F_OVERQUOTA)
return -EINVAL; return -EINVAL;
if ((flags & NFACCT_F_QUOTA) && !tb[NFACCT_QUOTA])
return -EINVAL;
size += sizeof(u64); size += sizeof(u64);
} }
......
...@@ -236,6 +236,7 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par) ...@@ -236,6 +236,7 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par)
list_del(&info->timer->entry); list_del(&info->timer->entry);
del_timer_sync(&info->timer->timer); del_timer_sync(&info->timer->timer);
cancel_work_sync(&info->timer->work);
sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr); sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
kfree(info->timer->attr.attr.name); kfree(info->timer->attr.attr.name);
kfree(info->timer); kfree(info->timer);
......
...@@ -776,6 +776,19 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key, ...@@ -776,6 +776,19 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
return -EINVAL; return -EINVAL;
} }
/* Userspace may decide to perform a ct lookup without a helper
* specified followed by a (recirculate and) commit with one.
* Therefore, for unconfirmed connections which we will commit,
* we need to attach the helper here.
*/
if (!nf_ct_is_confirmed(ct) && info->commit &&
info->helper && !nfct_help(ct)) {
int err = __nf_ct_try_assign_helper(ct, info->ct,
GFP_ATOMIC);
if (err)
return err;
}
/* Call the helper only if: /* Call the helper only if:
* - nf_conntrack_in() was executed above ("!cached") for a * - nf_conntrack_in() was executed above ("!cached") for a
* confirmed connection, or * confirmed connection, or
......
...@@ -423,7 +423,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -423,7 +423,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
u16 ife_type = 0; u16 ife_type = 0;
u8 *daddr = NULL; u8 *daddr = NULL;
u8 *saddr = NULL; u8 *saddr = NULL;
int ret = 0; int ret = 0, exists = 0;
int err; int err;
err = nla_parse_nested(tb, TCA_IFE_MAX, nla, ife_policy); err = nla_parse_nested(tb, TCA_IFE_MAX, nla, ife_policy);
...@@ -435,25 +435,29 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -435,25 +435,29 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_IFE_PARMS]); parm = nla_data(tb[TCA_IFE_PARMS]);
exists = tcf_hash_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
if (parm->flags & IFE_ENCODE) { if (parm->flags & IFE_ENCODE) {
/* Until we get issued the ethertype, we cant have /* Until we get issued the ethertype, we cant have
* a default.. * a default..
**/ **/
if (!tb[TCA_IFE_TYPE]) { if (!tb[TCA_IFE_TYPE]) {
if (exists)
tcf_hash_release(a, bind);
pr_info("You MUST pass etherype for encoding\n"); pr_info("You MUST pass etherype for encoding\n");
return -EINVAL; return -EINVAL;
} }
} }
if (!tcf_hash_check(tn, parm->index, a, bind)) { if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife), ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife),
bind, false); bind, false);
if (ret) if (ret)
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
if (bind) /* dont override defaults */
return 0;
tcf_hash_release(a, bind); tcf_hash_release(a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
...@@ -495,6 +499,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -495,6 +499,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
NULL); NULL);
if (err) { if (err) {
metadata_parse_err: metadata_parse_err:
if (exists)
tcf_hash_release(a, bind);
if (ret == ACT_P_CREATED) if (ret == ACT_P_CREATED)
_tcf_ife_cleanup(a, bind); _tcf_ife_cleanup(a, bind);
......
...@@ -96,7 +96,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, ...@@ -96,7 +96,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
struct tcf_ipt *ipt; struct tcf_ipt *ipt;
struct xt_entry_target *td, *t; struct xt_entry_target *td, *t;
char *tname; char *tname;
int ret = 0, err; int ret = 0, err, exists = 0;
u32 hook = 0; u32 hook = 0;
u32 index = 0; u32 index = 0;
...@@ -107,18 +107,23 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, ...@@ -107,18 +107,23 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
if (err < 0) if (err < 0)
return err; return err;
if (tb[TCA_IPT_HOOK] == NULL) if (tb[TCA_IPT_INDEX] != NULL)
return -EINVAL; index = nla_get_u32(tb[TCA_IPT_INDEX]);
if (tb[TCA_IPT_TARG] == NULL)
exists = tcf_hash_check(tn, index, a, bind);
if (exists && bind)
return 0;
if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) {
if (exists)
tcf_hash_release(a, bind);
return -EINVAL; return -EINVAL;
}
td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size)
return -EINVAL; return -EINVAL;
if (tb[TCA_IPT_INDEX] != NULL)
index = nla_get_u32(tb[TCA_IPT_INDEX]);
if (!tcf_hash_check(tn, index, a, bind)) { if (!tcf_hash_check(tn, index, a, bind)) {
ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind, ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind,
false); false);
......
...@@ -61,7 +61,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -61,7 +61,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
struct tc_mirred *parm; struct tc_mirred *parm;
struct tcf_mirred *m; struct tcf_mirred *m;
struct net_device *dev; struct net_device *dev;
int ret, ok_push = 0; int ret, ok_push = 0, exists = 0;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
...@@ -71,17 +71,27 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -71,17 +71,27 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
if (tb[TCA_MIRRED_PARMS] == NULL) if (tb[TCA_MIRRED_PARMS] == NULL)
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_MIRRED_PARMS]); parm = nla_data(tb[TCA_MIRRED_PARMS]);
exists = tcf_hash_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
switch (parm->eaction) { switch (parm->eaction) {
case TCA_EGRESS_MIRROR: case TCA_EGRESS_MIRROR:
case TCA_EGRESS_REDIR: case TCA_EGRESS_REDIR:
break; break;
default: default:
if (exists)
tcf_hash_release(a, bind);
return -EINVAL; return -EINVAL;
} }
if (parm->ifindex) { if (parm->ifindex) {
dev = __dev_get_by_index(net, parm->ifindex); dev = __dev_get_by_index(net, parm->ifindex);
if (dev == NULL) if (dev == NULL) {
if (exists)
tcf_hash_release(a, bind);
return -ENODEV; return -ENODEV;
}
switch (dev->type) { switch (dev->type) {
case ARPHRD_TUNNEL: case ARPHRD_TUNNEL:
case ARPHRD_TUNNEL6: case ARPHRD_TUNNEL6:
...@@ -99,7 +109,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -99,7 +109,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
dev = NULL; dev = NULL;
} }
if (!tcf_hash_check(tn, parm->index, a, bind)) { if (!exists) {
if (dev == NULL) if (dev == NULL)
return -EINVAL; return -EINVAL;
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
...@@ -108,9 +118,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -108,9 +118,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
return ret; return ret;
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
if (bind)
return 0;
tcf_hash_release(a, bind); tcf_hash_release(a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
......
...@@ -87,7 +87,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -87,7 +87,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
struct tc_defact *parm; struct tc_defact *parm;
struct tcf_defact *d; struct tcf_defact *d;
char *defdata; char *defdata;
int ret = 0, err; int ret = 0, err, exists = 0;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
...@@ -99,13 +99,21 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -99,13 +99,21 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (tb[TCA_DEF_PARMS] == NULL) if (tb[TCA_DEF_PARMS] == NULL)
return -EINVAL; return -EINVAL;
if (tb[TCA_DEF_DATA] == NULL)
return -EINVAL;
parm = nla_data(tb[TCA_DEF_PARMS]); parm = nla_data(tb[TCA_DEF_PARMS]);
exists = tcf_hash_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
if (tb[TCA_DEF_DATA] == NULL) {
if (exists)
tcf_hash_release(a, bind);
return -EINVAL;
}
defdata = nla_data(tb[TCA_DEF_DATA]); defdata = nla_data(tb[TCA_DEF_DATA]);
if (!tcf_hash_check(tn, parm->index, a, bind)) { if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*d), bind, false); sizeof(*d), bind, false);
if (ret) if (ret)
...@@ -122,8 +130,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -122,8 +130,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
} else { } else {
d = to_defact(a); d = to_defact(a);
if (bind)
return 0;
tcf_hash_release(a, bind); tcf_hash_release(a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
......
...@@ -69,7 +69,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -69,7 +69,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
struct tcf_skbedit *d; struct tcf_skbedit *d;
u32 flags = 0, *priority = NULL, *mark = NULL; u32 flags = 0, *priority = NULL, *mark = NULL;
u16 *queue_mapping = NULL; u16 *queue_mapping = NULL;
int ret = 0, err; int ret = 0, err, exists = 0;
if (nla == NULL) if (nla == NULL)
return -EINVAL; return -EINVAL;
...@@ -96,12 +96,18 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -96,12 +96,18 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
mark = nla_data(tb[TCA_SKBEDIT_MARK]); mark = nla_data(tb[TCA_SKBEDIT_MARK]);
} }
if (!flags)
return -EINVAL;
parm = nla_data(tb[TCA_SKBEDIT_PARMS]); parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
if (!tcf_hash_check(tn, parm->index, a, bind)) { exists = tcf_hash_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
if (!flags) {
tcf_hash_release(a, bind);
return -EINVAL;
}
if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*d), bind, false); sizeof(*d), bind, false);
if (ret) if (ret)
...@@ -111,8 +117,6 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -111,8 +117,6 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
d = to_skbedit(a); d = to_skbedit(a);
if (bind)
return 0;
tcf_hash_release(a, bind); tcf_hash_release(a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
......
...@@ -77,7 +77,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -77,7 +77,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
int action; int action;
__be16 push_vid = 0; __be16 push_vid = 0;
__be16 push_proto = 0; __be16 push_proto = 0;
int ret = 0; int ret = 0, exists = 0;
int err; int err;
if (!nla) if (!nla)
...@@ -90,15 +90,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -90,15 +90,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (!tb[TCA_VLAN_PARMS]) if (!tb[TCA_VLAN_PARMS])
return -EINVAL; return -EINVAL;
parm = nla_data(tb[TCA_VLAN_PARMS]); parm = nla_data(tb[TCA_VLAN_PARMS]);
exists = tcf_hash_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
switch (parm->v_action) { switch (parm->v_action) {
case TCA_VLAN_ACT_POP: case TCA_VLAN_ACT_POP:
break; break;
case TCA_VLAN_ACT_PUSH: case TCA_VLAN_ACT_PUSH:
if (!tb[TCA_VLAN_PUSH_VLAN_ID]) if (!tb[TCA_VLAN_PUSH_VLAN_ID]) {
if (exists)
tcf_hash_release(a, bind);
return -EINVAL; return -EINVAL;
}
push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
if (push_vid >= VLAN_VID_MASK) if (push_vid >= VLAN_VID_MASK) {
if (exists)
tcf_hash_release(a, bind);
return -ERANGE; return -ERANGE;
}
if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) { if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) {
push_proto = nla_get_be16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]); push_proto = nla_get_be16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]);
...@@ -114,11 +124,13 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -114,11 +124,13 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
} }
break; break;
default: default:
if (exists)
tcf_hash_release(a, bind);
return -EINVAL; return -EINVAL;
} }
action = parm->v_action; action = parm->v_action;
if (!tcf_hash_check(tn, parm->index, a, bind)) { if (!exists) {
ret = tcf_hash_create(tn, parm->index, est, a, ret = tcf_hash_create(tn, parm->index, est, a,
sizeof(*v), bind, false); sizeof(*v), bind, false);
if (ret) if (ret)
...@@ -126,8 +138,6 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -126,8 +138,6 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
ret = ACT_P_CREATED; ret = ACT_P_CREATED;
} else { } else {
if (bind)
return 0;
tcf_hash_release(a, bind); tcf_hash_release(a, bind);
if (!ovr) if (!ovr)
return -EEXIST; return -EEXIST;
......
...@@ -277,6 +277,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, ...@@ -277,6 +277,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
memset(&theirs, 0, sizeof(theirs)); memset(&theirs, 0, sizeof(theirs));
memcpy(new, ours, sizeof(*new)); memcpy(new, ours, sizeof(*new));
memset(dte, 0, sizeof(*dte));
len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask);
if (len < 0) if (len < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment