mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-14 12:37:32 +00:00
Merge remote-tracking branch 'net/master' into afs-next
This commit is contained in:
commit
f16180739c
89 changed files with 761 additions and 487 deletions
|
@ -12,6 +12,7 @@ Required properties:
|
||||||
- "microchip,ksz8565"
|
- "microchip,ksz8565"
|
||||||
- "microchip,ksz9893"
|
- "microchip,ksz9893"
|
||||||
- "microchip,ksz9563"
|
- "microchip,ksz9563"
|
||||||
|
- "microchip,ksz8563"
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@ Required properties:
|
||||||
Use "atmel,sama5d4-gem" for the GEM IP (10/100) available on Atmel sama5d4 SoCs.
|
Use "atmel,sama5d4-gem" for the GEM IP (10/100) available on Atmel sama5d4 SoCs.
|
||||||
Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
|
Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
|
||||||
Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
|
Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
|
||||||
Use "sifive,fu540-macb" for SiFive FU540-C000 SoC.
|
Use "sifive,fu540-c000-gem" for SiFive FU540-C000 SoC.
|
||||||
Or the generic form: "cdns,emac".
|
Or the generic form: "cdns,emac".
|
||||||
- reg: Address and length of the register set for the device
|
- reg: Address and length of the register set for the device
|
||||||
For "sifive,fu540-macb", second range is required to specify the
|
For "sifive,fu540-c000-gem", second range is required to specify the
|
||||||
address and length of the registers for GEMGXL Management block.
|
address and length of the registers for GEMGXL Management block.
|
||||||
- interrupts: Should contain macb interrupt
|
- interrupts: Should contain macb interrupt
|
||||||
- phy-mode: See ethernet.txt file in the same directory.
|
- phy-mode: See ethernet.txt file in the same directory.
|
||||||
|
|
|
@ -81,6 +81,7 @@ static const struct of_device_id ksz9477_dt_ids[] = {
|
||||||
{ .compatible = "microchip,ksz9897" },
|
{ .compatible = "microchip,ksz9897" },
|
||||||
{ .compatible = "microchip,ksz9893" },
|
{ .compatible = "microchip,ksz9893" },
|
||||||
{ .compatible = "microchip,ksz9563" },
|
{ .compatible = "microchip,ksz9563" },
|
||||||
|
{ .compatible = "microchip,ksz8563" },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
|
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
|
||||||
|
|
|
@ -128,6 +128,7 @@ static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,
|
||||||
|
|
||||||
#define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign) \
|
#define KSZ_REGMAP_ENTRY(width, swp, regbits, regpad, regalign) \
|
||||||
{ \
|
{ \
|
||||||
|
.name = #width, \
|
||||||
.val_bits = (width), \
|
.val_bits = (width), \
|
||||||
.reg_stride = (width) / 8, \
|
.reg_stride = (width) / 8, \
|
||||||
.reg_bits = (regbits) + (regalign), \
|
.reg_bits = (regbits) + (regalign), \
|
||||||
|
|
|
@ -469,13 +469,19 @@ static int __init xgbe_mod_init(void)
|
||||||
|
|
||||||
ret = xgbe_platform_init();
|
ret = xgbe_platform_init();
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto err_platform_init;
|
||||||
|
|
||||||
ret = xgbe_pci_init();
|
ret = xgbe_pci_init();
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto err_pci_init;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_pci_init:
|
||||||
|
xgbe_platform_exit();
|
||||||
|
err_platform_init:
|
||||||
|
unregister_netdevice_notifier(&xgbe_netdev_notifier);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit xgbe_mod_exit(void)
|
static void __exit xgbe_mod_exit(void)
|
||||||
|
|
|
@ -431,7 +431,8 @@ int aq_del_fvlan_by_vlan(struct aq_nic_s *aq_nic, u16 vlan_id)
|
||||||
if (be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id)
|
if (be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (rule && be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) {
|
if (rule && rule->type == aq_rx_filter_vlan &&
|
||||||
|
be16_to_cpu(rule->aq_fsp.h_ext.vlan_tci) == vlan_id) {
|
||||||
struct ethtool_rxnfc cmd;
|
struct ethtool_rxnfc cmd;
|
||||||
|
|
||||||
cmd.fs.location = rule->aq_fsp.location;
|
cmd.fs.location = rule->aq_fsp.location;
|
||||||
|
@ -843,7 +844,7 @@ int aq_filters_vlans_update(struct aq_nic_s *aq_nic)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
|
if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
|
||||||
if (hweight < AQ_VLAN_MAX_FILTERS && hweight > 0) {
|
if (hweight <= AQ_VLAN_MAX_FILTERS && hweight > 0) {
|
||||||
err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw,
|
err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw,
|
||||||
!(aq_nic->packet_filter & IFF_PROMISC));
|
!(aq_nic->packet_filter & IFF_PROMISC));
|
||||||
aq_nic->aq_nic_cfg.is_vlan_force_promisc = false;
|
aq_nic->aq_nic_cfg.is_vlan_force_promisc = false;
|
||||||
|
|
|
@ -61,6 +61,10 @@ static int aq_ndev_open(struct net_device *ndev)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
|
|
||||||
|
err = aq_filters_vlans_update(aq_nic);
|
||||||
|
if (err < 0)
|
||||||
|
goto err_exit;
|
||||||
|
|
||||||
err = aq_nic_start(aq_nic);
|
err = aq_nic_start(aq_nic);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
|
|
|
@ -393,7 +393,7 @@ int aq_nic_start(struct aq_nic_s *self)
|
||||||
self->aq_nic_cfg.link_irq_vec);
|
self->aq_nic_cfg.link_irq_vec);
|
||||||
err = request_threaded_irq(irqvec, NULL,
|
err = request_threaded_irq(irqvec, NULL,
|
||||||
aq_linkstate_threaded_isr,
|
aq_linkstate_threaded_isr,
|
||||||
IRQF_SHARED,
|
IRQF_SHARED | IRQF_ONESHOT,
|
||||||
self->ndev->name, self);
|
self->ndev->name, self);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err_exit;
|
goto err_exit;
|
||||||
|
|
|
@ -86,6 +86,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err_exit:
|
||||||
if (!was_tx_cleaned)
|
if (!was_tx_cleaned)
|
||||||
work_done = budget;
|
work_done = budget;
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
|
||||||
1U << self->aq_ring_param.vec_idx);
|
1U << self->aq_ring_param.vec_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err_exit:
|
|
||||||
return work_done;
|
return work_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1124,6 +1124,7 @@ static const struct ethtool_ops bcmgenet_ethtool_ops = {
|
||||||
.set_coalesce = bcmgenet_set_coalesce,
|
.set_coalesce = bcmgenet_set_coalesce,
|
||||||
.get_link_ksettings = bcmgenet_get_link_ksettings,
|
.get_link_ksettings = bcmgenet_get_link_ksettings,
|
||||||
.set_link_ksettings = bcmgenet_set_link_ksettings,
|
.set_link_ksettings = bcmgenet_set_link_ksettings,
|
||||||
|
.get_ts_info = ethtool_op_get_ts_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Power down the unimac, based on mode. */
|
/* Power down the unimac, based on mode. */
|
||||||
|
|
|
@ -4154,7 +4154,7 @@ static const struct of_device_id macb_dt_ids[] = {
|
||||||
{ .compatible = "cdns,emac", .data = &emac_config },
|
{ .compatible = "cdns,emac", .data = &emac_config },
|
||||||
{ .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
|
{ .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
|
||||||
{ .compatible = "cdns,zynq-gem", .data = &zynq_config },
|
{ .compatible = "cdns,zynq-gem", .data = &zynq_config },
|
||||||
{ .compatible = "sifive,fu540-macb", .data = &fu540_c000_config },
|
{ .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, macb_dt_ids);
|
MODULE_DEVICE_TABLE(of, macb_dt_ids);
|
||||||
|
|
|
@ -82,7 +82,7 @@ static int enetc_ptp_probe(struct pci_dev *pdev,
|
||||||
n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
|
n = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSIX);
|
||||||
if (n != 1) {
|
if (n != 1) {
|
||||||
err = -EPERM;
|
err = -EPERM;
|
||||||
goto err_irq;
|
goto err_irq_vectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptp_qoriq->irq = pci_irq_vector(pdev, 0);
|
ptp_qoriq->irq = pci_irq_vector(pdev, 0);
|
||||||
|
@ -107,6 +107,8 @@ static int enetc_ptp_probe(struct pci_dev *pdev,
|
||||||
err_no_clock:
|
err_no_clock:
|
||||||
free_irq(ptp_qoriq->irq, ptp_qoriq);
|
free_irq(ptp_qoriq->irq, ptp_qoriq);
|
||||||
err_irq:
|
err_irq:
|
||||||
|
pci_free_irq_vectors(pdev);
|
||||||
|
err_irq_vectors:
|
||||||
iounmap(base);
|
iounmap(base);
|
||||||
err_ioremap:
|
err_ioremap:
|
||||||
kfree(ptp_qoriq);
|
kfree(ptp_qoriq);
|
||||||
|
@ -125,6 +127,7 @@ static void enetc_ptp_remove(struct pci_dev *pdev)
|
||||||
|
|
||||||
enetc_phc_index = -1;
|
enetc_phc_index = -1;
|
||||||
ptp_qoriq_free(ptp_qoriq);
|
ptp_qoriq_free(ptp_qoriq);
|
||||||
|
pci_free_irq_vectors(pdev);
|
||||||
kfree(ptp_qoriq);
|
kfree(ptp_qoriq);
|
||||||
|
|
||||||
pci_release_mem_regions(pdev);
|
pci_release_mem_regions(pdev);
|
||||||
|
|
|
@ -1983,6 +1983,10 @@ static void __ibmvnic_reset(struct work_struct *work)
|
||||||
|
|
||||||
rwi = get_next_rwi(adapter);
|
rwi = get_next_rwi(adapter);
|
||||||
while (rwi) {
|
while (rwi) {
|
||||||
|
if (adapter->state == VNIC_REMOVING ||
|
||||||
|
adapter->state == VNIC_REMOVED)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (adapter->force_reset_recovery) {
|
if (adapter->force_reset_recovery) {
|
||||||
adapter->force_reset_recovery = false;
|
adapter->force_reset_recovery = false;
|
||||||
rc = do_hard_reset(adapter, rwi, reset_state);
|
rc = do_hard_reset(adapter, rwi, reset_state);
|
||||||
|
@ -2007,7 +2011,7 @@ static void __ibmvnic_reset(struct work_struct *work)
|
||||||
netdev_dbg(adapter->netdev, "Reset failed\n");
|
netdev_dbg(adapter->netdev, "Reset failed\n");
|
||||||
free_all_rwi(adapter);
|
free_all_rwi(adapter);
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
adapter->resetting = false;
|
adapter->resetting = false;
|
||||||
if (we_lock_rtnl)
|
if (we_lock_rtnl)
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
|
@ -4931,6 +4931,13 @@ static const struct dmi_system_id msi_blacklist[] = {
|
||||||
DMI_MATCH(DMI_BOARD_NAME, "P6T"),
|
DMI_MATCH(DMI_BOARD_NAME, "P6T"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.ident = "ASUS P6X",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "P6X"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1163,7 +1163,7 @@ mem_op_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
||||||
bool clr_gpr, lmem_step step)
|
bool clr_gpr, lmem_step step)
|
||||||
{
|
{
|
||||||
s32 off = nfp_prog->stack_frame_depth + meta->insn.off + ptr_off;
|
s32 off = nfp_prog->stack_frame_depth + meta->insn.off + ptr_off;
|
||||||
bool first = true, last;
|
bool first = true, narrow_ld, last;
|
||||||
bool needs_inc = false;
|
bool needs_inc = false;
|
||||||
swreg stack_off_reg;
|
swreg stack_off_reg;
|
||||||
u8 prev_gpr = 255;
|
u8 prev_gpr = 255;
|
||||||
|
@ -1209,13 +1209,22 @@ mem_op_stack(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
|
||||||
|
|
||||||
needs_inc = true;
|
needs_inc = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
narrow_ld = clr_gpr && size < 8;
|
||||||
|
|
||||||
if (lm3) {
|
if (lm3) {
|
||||||
|
unsigned int nop_cnt;
|
||||||
|
|
||||||
emit_csr_wr(nfp_prog, imm_b(nfp_prog), NFP_CSR_ACT_LM_ADDR3);
|
emit_csr_wr(nfp_prog, imm_b(nfp_prog), NFP_CSR_ACT_LM_ADDR3);
|
||||||
/* For size < 4 one slot will be filled by zeroing of upper. */
|
/* For size < 4 one slot will be filled by zeroing of upper,
|
||||||
wrp_nops(nfp_prog, clr_gpr && size < 8 ? 2 : 3);
|
* but be careful, that zeroing could be eliminated by zext
|
||||||
|
* optimization.
|
||||||
|
*/
|
||||||
|
nop_cnt = narrow_ld && meta->flags & FLAG_INSN_DO_ZEXT ? 2 : 3;
|
||||||
|
wrp_nops(nfp_prog, nop_cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clr_gpr && size < 8)
|
if (narrow_ld)
|
||||||
wrp_zext(nfp_prog, meta, gpr);
|
wrp_zext(nfp_prog, meta, gpr);
|
||||||
|
|
||||||
while (size) {
|
while (size) {
|
||||||
|
|
|
@ -1409,9 +1409,10 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct nfp_app *app,
|
||||||
struct nfp_flower_priv *priv = app->priv;
|
struct nfp_flower_priv *priv = app->priv;
|
||||||
struct flow_block_cb *block_cb;
|
struct flow_block_cb *block_cb;
|
||||||
|
|
||||||
if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
|
if ((f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS &&
|
||||||
!(f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
|
!nfp_flower_internal_port_can_offload(app, netdev)) ||
|
||||||
nfp_flower_internal_port_can_offload(app, netdev)))
|
(f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS &&
|
||||||
|
nfp_flower_internal_port_can_offload(app, netdev)))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
switch (f->command) {
|
switch (f->command) {
|
||||||
|
|
|
@ -328,13 +328,13 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
|
||||||
|
|
||||||
flow.daddr = *(__be32 *)n->primary_key;
|
flow.daddr = *(__be32 *)n->primary_key;
|
||||||
|
|
||||||
/* Only concerned with route changes for representors. */
|
|
||||||
if (!nfp_netdev_is_nfp_repr(n->dev))
|
|
||||||
return NOTIFY_DONE;
|
|
||||||
|
|
||||||
app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
|
app_priv = container_of(nb, struct nfp_flower_priv, tun.neigh_nb);
|
||||||
app = app_priv->app;
|
app = app_priv->app;
|
||||||
|
|
||||||
|
if (!nfp_netdev_is_nfp_repr(n->dev) &&
|
||||||
|
!nfp_flower_internal_port_can_offload(app, n->dev))
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
/* Only concerned with changes to routes already added to NFP. */
|
/* Only concerned with changes to routes already added to NFP. */
|
||||||
if (!nfp_tun_has_route(app, flow.daddr))
|
if (!nfp_tun_has_route(app, flow.daddr))
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
|
@ -794,15 +794,16 @@ static int sgiseeq_probe(struct platform_device *pdev)
|
||||||
printk(KERN_ERR "Sgiseeq: Cannot register net device, "
|
printk(KERN_ERR "Sgiseeq: Cannot register net device, "
|
||||||
"aborting.\n");
|
"aborting.\n");
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
goto err_out_free_page;
|
goto err_out_free_attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "%s: %s %pM\n", dev->name, sgiseeqstr, dev->dev_addr);
|
printk(KERN_INFO "%s: %s %pM\n", dev->name, sgiseeqstr, dev->dev_addr);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out_free_page:
|
err_out_free_attrs:
|
||||||
free_page((unsigned long) sp->srings);
|
dma_free_attrs(&pdev->dev, sizeof(*sp->srings), sp->srings,
|
||||||
|
sp->srings_dma, DMA_ATTR_NON_CONSISTENT);
|
||||||
err_out_free_dev:
|
err_out_free_dev:
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
|
|
||||||
|
|
|
@ -1194,10 +1194,8 @@ static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable)
|
||||||
int ret;
|
int ret;
|
||||||
struct device *dev = &bsp_priv->pdev->dev;
|
struct device *dev = &bsp_priv->pdev->dev;
|
||||||
|
|
||||||
if (!ldo) {
|
if (!ldo)
|
||||||
dev_err(dev, "no regulator found\n");
|
return 0;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
ret = regulator_enable(ldo);
|
ret = regulator_enable(ldo);
|
||||||
|
|
|
@ -523,6 +523,32 @@ int genphy_c45_read_status(struct phy_device *phydev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(genphy_c45_read_status);
|
EXPORT_SYMBOL_GPL(genphy_c45_read_status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* genphy_c45_config_aneg - restart auto-negotiation or forced setup
|
||||||
|
* @phydev: target phy_device struct
|
||||||
|
*
|
||||||
|
* Description: If auto-negotiation is enabled, we configure the
|
||||||
|
* advertising, and then restart auto-negotiation. If it is not
|
||||||
|
* enabled, then we force a configuration.
|
||||||
|
*/
|
||||||
|
int genphy_c45_config_aneg(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (phydev->autoneg == AUTONEG_DISABLE)
|
||||||
|
return genphy_c45_pma_setup_forced(phydev);
|
||||||
|
|
||||||
|
ret = genphy_c45_an_config_aneg(phydev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
if (ret > 0)
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
return genphy_c45_check_and_restart_aneg(phydev, changed);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(genphy_c45_config_aneg);
|
||||||
|
|
||||||
/* The gen10g_* functions are the old Clause 45 stub */
|
/* The gen10g_* functions are the old Clause 45 stub */
|
||||||
|
|
||||||
int gen10g_config_aneg(struct phy_device *phydev)
|
int gen10g_config_aneg(struct phy_device *phydev)
|
||||||
|
|
|
@ -507,7 +507,7 @@ static int phy_config_aneg(struct phy_device *phydev)
|
||||||
* allowed to call genphy_config_aneg()
|
* allowed to call genphy_config_aneg()
|
||||||
*/
|
*/
|
||||||
if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0)))
|
if (phydev->is_c45 && !(phydev->c45_ids.devices_in_package & BIT(0)))
|
||||||
return -EOPNOTSUPP;
|
return genphy_c45_config_aneg(phydev);
|
||||||
|
|
||||||
return genphy_config_aneg(phydev);
|
return genphy_config_aneg(phydev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4021,8 +4021,7 @@ static int rtl8152_close(struct net_device *netdev)
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
unregister_pm_notifier(&tp->pm_notifier);
|
unregister_pm_notifier(&tp->pm_notifier);
|
||||||
#endif
|
#endif
|
||||||
if (!test_bit(RTL8152_UNPLUG, &tp->flags))
|
napi_disable(&tp->napi);
|
||||||
napi_disable(&tp->napi);
|
|
||||||
clear_bit(WORK_ENABLE, &tp->flags);
|
clear_bit(WORK_ENABLE, &tp->flags);
|
||||||
usb_kill_urb(tp->intr_urb);
|
usb_kill_urb(tp->intr_urb);
|
||||||
cancel_delayed_work_sync(&tp->schedule);
|
cancel_delayed_work_sync(&tp->schedule);
|
||||||
|
@ -5353,7 +5352,6 @@ static int rtl8152_probe(struct usb_interface *intf,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out1:
|
out1:
|
||||||
netif_napi_del(&tp->napi);
|
|
||||||
usb_set_intfdata(intf, NULL);
|
usb_set_intfdata(intf, NULL);
|
||||||
out:
|
out:
|
||||||
free_netdev(netdev);
|
free_netdev(netdev);
|
||||||
|
@ -5368,7 +5366,6 @@ static void rtl8152_disconnect(struct usb_interface *intf)
|
||||||
if (tp) {
|
if (tp) {
|
||||||
rtl_set_unplug(tp);
|
rtl_set_unplug(tp);
|
||||||
|
|
||||||
netif_napi_del(&tp->napi);
|
|
||||||
unregister_netdev(tp->netdev);
|
unregister_netdev(tp->netdev);
|
||||||
cancel_delayed_work_sync(&tp->hw_phy_work);
|
cancel_delayed_work_sync(&tp->hw_phy_work);
|
||||||
tp->rtl_ops.unload(tp);
|
tp->rtl_ops.unload(tp);
|
||||||
|
|
|
@ -556,6 +556,30 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
|
||||||
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
|
||||||
|
.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
|
||||||
|
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||||
|
IWL_DEVICE_22500,
|
||||||
|
/*
|
||||||
|
* This device doesn't support receiving BlockAck with a large bitmap
|
||||||
|
* so we need to restrict the size of transmitted aggregation to the
|
||||||
|
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||||
|
*/
|
||||||
|
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
|
||||||
|
.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
|
||||||
|
.fw_name_pre = IWL_QU_C_HR_B_FW_PRE,
|
||||||
|
IWL_DEVICE_22500,
|
||||||
|
/*
|
||||||
|
* This device doesn't support receiving BlockAck with a large bitmap
|
||||||
|
* so we need to restrict the size of transmitted aggregation to the
|
||||||
|
* HT size; mac80211 would otherwise pick the HE max (256) by default.
|
||||||
|
*/
|
||||||
|
.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
|
||||||
|
};
|
||||||
|
|
||||||
const struct iwl_cfg iwl22000_2ax_cfg_jf = {
|
const struct iwl_cfg iwl22000_2ax_cfg_jf = {
|
||||||
.name = "Intel(R) Dual Band Wireless AX 22000",
|
.name = "Intel(R) Dual Band Wireless AX 22000",
|
||||||
.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
|
.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
|
||||||
|
|
|
@ -577,6 +577,8 @@ extern const struct iwl_cfg iwl_ax1650i_cfg_quz_hr;
|
||||||
extern const struct iwl_cfg iwl_ax1650s_cfg_quz_hr;
|
extern const struct iwl_cfg iwl_ax1650s_cfg_quz_hr;
|
||||||
extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0;
|
extern const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0;
|
||||||
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0;
|
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0;
|
||||||
|
extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0;
|
||||||
|
extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0;
|
||||||
extern const struct iwl_cfg killer1650x_2ax_cfg;
|
extern const struct iwl_cfg killer1650x_2ax_cfg;
|
||||||
extern const struct iwl_cfg killer1650w_2ax_cfg;
|
extern const struct iwl_cfg killer1650w_2ax_cfg;
|
||||||
extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0;
|
extern const struct iwl_cfg iwl9461_2ac_cfg_qu_b0_jf_b0;
|
||||||
|
|
|
@ -1062,6 +1062,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
iwl_trans->cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0;
|
iwl_trans->cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0;
|
||||||
else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
|
else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
|
||||||
iwl_trans->cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0;
|
iwl_trans->cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0;
|
||||||
|
else if (iwl_trans->cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)
|
||||||
|
iwl_trans->cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0;
|
||||||
|
else if (iwl_trans->cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)
|
||||||
|
iwl_trans->cfg = &killer1650i_2ax_cfg_qu_c0_hr_b0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* same thing for QuZ... */
|
/* same thing for QuZ... */
|
||||||
|
|
|
@ -3602,12 +3602,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||||
}
|
}
|
||||||
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) ==
|
||||||
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
|
CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
|
||||||
((trans->cfg != &iwl_ax200_cfg_cc &&
|
trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) {
|
||||||
trans->cfg != &iwl_ax201_cfg_qu_hr &&
|
|
||||||
trans->cfg != &killer1650x_2ax_cfg &&
|
|
||||||
trans->cfg != &killer1650w_2ax_cfg &&
|
|
||||||
trans->cfg != &iwl_ax201_cfg_quz_hr) ||
|
|
||||||
trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0)) {
|
|
||||||
u32 hw_status;
|
u32 hw_status;
|
||||||
|
|
||||||
hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS);
|
hw_status = iwl_read_prph(trans, UMAG_GEN_HW_STATUS);
|
||||||
|
|
|
@ -1107,6 +1107,7 @@ int genphy_c45_an_disable_aneg(struct phy_device *phydev);
|
||||||
int genphy_c45_read_mdix(struct phy_device *phydev);
|
int genphy_c45_read_mdix(struct phy_device *phydev);
|
||||||
int genphy_c45_pma_read_abilities(struct phy_device *phydev);
|
int genphy_c45_pma_read_abilities(struct phy_device *phydev);
|
||||||
int genphy_c45_read_status(struct phy_device *phydev);
|
int genphy_c45_read_status(struct phy_device *phydev);
|
||||||
|
int genphy_c45_config_aneg(struct phy_device *phydev);
|
||||||
|
|
||||||
/* The gen10g_* functions are the old Clause 45 stub */
|
/* The gen10g_* functions are the old Clause 45 stub */
|
||||||
int gen10g_config_aneg(struct phy_device *phydev);
|
int gen10g_config_aneg(struct phy_device *phydev);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
struct tcf_idrinfo {
|
struct tcf_idrinfo {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct idr action_idr;
|
struct idr action_idr;
|
||||||
|
struct net *net;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tc_action_ops;
|
struct tc_action_ops;
|
||||||
|
@ -108,7 +109,7 @@ struct tc_action_net {
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
int tc_action_net_init(struct tc_action_net *tn,
|
int tc_action_net_init(struct net *net, struct tc_action_net *tn,
|
||||||
const struct tc_action_ops *ops)
|
const struct tc_action_ops *ops)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -117,6 +118,7 @@ int tc_action_net_init(struct tc_action_net *tn,
|
||||||
if (!tn->idrinfo)
|
if (!tn->idrinfo)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
tn->ops = ops;
|
tn->ops = ops;
|
||||||
|
tn->idrinfo->net = net;
|
||||||
mutex_init(&tn->idrinfo->lock);
|
mutex_init(&tn->idrinfo->lock);
|
||||||
idr_init(&tn->idrinfo->action_idr);
|
idr_init(&tn->idrinfo->action_idr);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct psample_group {
|
||||||
u32 group_num;
|
u32 group_num;
|
||||||
u32 refcount;
|
u32 refcount;
|
||||||
u32 seq;
|
u32 seq;
|
||||||
|
struct rcu_head rcu;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct psample_group *psample_group_get(struct net *net, u32 group_num);
|
struct psample_group *psample_group_get(struct net *net, u32 group_num);
|
||||||
|
|
|
@ -23,20 +23,17 @@
|
||||||
#define __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
#define __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY
|
||||||
|
|
||||||
enum rxrpc_skb_trace {
|
enum rxrpc_skb_trace {
|
||||||
rxrpc_skb_rx_cleaned,
|
rxrpc_skb_cleaned,
|
||||||
rxrpc_skb_rx_freed,
|
rxrpc_skb_freed,
|
||||||
rxrpc_skb_rx_got,
|
rxrpc_skb_got,
|
||||||
rxrpc_skb_rx_lost,
|
rxrpc_skb_lost,
|
||||||
rxrpc_skb_rx_purged,
|
rxrpc_skb_new,
|
||||||
rxrpc_skb_rx_received,
|
rxrpc_skb_purged,
|
||||||
rxrpc_skb_rx_rotated,
|
rxrpc_skb_received,
|
||||||
rxrpc_skb_rx_seen,
|
rxrpc_skb_rotated,
|
||||||
rxrpc_skb_tx_cleaned,
|
rxrpc_skb_seen,
|
||||||
rxrpc_skb_tx_freed,
|
rxrpc_skb_unshared,
|
||||||
rxrpc_skb_tx_got,
|
rxrpc_skb_unshared_nomem,
|
||||||
rxrpc_skb_tx_new,
|
|
||||||
rxrpc_skb_tx_rotated,
|
|
||||||
rxrpc_skb_tx_seen,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum rxrpc_local_trace {
|
enum rxrpc_local_trace {
|
||||||
|
@ -228,20 +225,17 @@ enum rxrpc_tx_point {
|
||||||
* Declare tracing information enums and their string mappings for display.
|
* Declare tracing information enums and their string mappings for display.
|
||||||
*/
|
*/
|
||||||
#define rxrpc_skb_traces \
|
#define rxrpc_skb_traces \
|
||||||
EM(rxrpc_skb_rx_cleaned, "Rx CLN") \
|
EM(rxrpc_skb_cleaned, "CLN") \
|
||||||
EM(rxrpc_skb_rx_freed, "Rx FRE") \
|
EM(rxrpc_skb_freed, "FRE") \
|
||||||
EM(rxrpc_skb_rx_got, "Rx GOT") \
|
EM(rxrpc_skb_got, "GOT") \
|
||||||
EM(rxrpc_skb_rx_lost, "Rx *L*") \
|
EM(rxrpc_skb_lost, "*L*") \
|
||||||
EM(rxrpc_skb_rx_purged, "Rx PUR") \
|
EM(rxrpc_skb_new, "NEW") \
|
||||||
EM(rxrpc_skb_rx_received, "Rx RCV") \
|
EM(rxrpc_skb_purged, "PUR") \
|
||||||
EM(rxrpc_skb_rx_rotated, "Rx ROT") \
|
EM(rxrpc_skb_received, "RCV") \
|
||||||
EM(rxrpc_skb_rx_seen, "Rx SEE") \
|
EM(rxrpc_skb_rotated, "ROT") \
|
||||||
EM(rxrpc_skb_tx_cleaned, "Tx CLN") \
|
EM(rxrpc_skb_seen, "SEE") \
|
||||||
EM(rxrpc_skb_tx_freed, "Tx FRE") \
|
EM(rxrpc_skb_unshared, "UNS") \
|
||||||
EM(rxrpc_skb_tx_got, "Tx GOT") \
|
E_(rxrpc_skb_unshared_nomem, "US0")
|
||||||
EM(rxrpc_skb_tx_new, "Tx NEW") \
|
|
||||||
EM(rxrpc_skb_tx_rotated, "Tx ROT") \
|
|
||||||
E_(rxrpc_skb_tx_seen, "Tx SEE")
|
|
||||||
|
|
||||||
#define rxrpc_local_traces \
|
#define rxrpc_local_traces \
|
||||||
EM(rxrpc_local_got, "GOT") \
|
EM(rxrpc_local_got, "GOT") \
|
||||||
|
@ -643,13 +637,14 @@ TRACE_EVENT(rxrpc_call,
|
||||||
|
|
||||||
TRACE_EVENT(rxrpc_skb,
|
TRACE_EVENT(rxrpc_skb,
|
||||||
TP_PROTO(struct sk_buff *skb, enum rxrpc_skb_trace op,
|
TP_PROTO(struct sk_buff *skb, enum rxrpc_skb_trace op,
|
||||||
int usage, int mod_count, const void *where),
|
int usage, int mod_count, u8 flags, const void *where),
|
||||||
|
|
||||||
TP_ARGS(skb, op, usage, mod_count, where),
|
TP_ARGS(skb, op, usage, mod_count, flags, where),
|
||||||
|
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
__field(struct sk_buff *, skb )
|
__field(struct sk_buff *, skb )
|
||||||
__field(enum rxrpc_skb_trace, op )
|
__field(enum rxrpc_skb_trace, op )
|
||||||
|
__field(u8, flags )
|
||||||
__field(int, usage )
|
__field(int, usage )
|
||||||
__field(int, mod_count )
|
__field(int, mod_count )
|
||||||
__field(const void *, where )
|
__field(const void *, where )
|
||||||
|
@ -657,14 +652,16 @@ TRACE_EVENT(rxrpc_skb,
|
||||||
|
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
__entry->skb = skb;
|
__entry->skb = skb;
|
||||||
|
__entry->flags = flags;
|
||||||
__entry->op = op;
|
__entry->op = op;
|
||||||
__entry->usage = usage;
|
__entry->usage = usage;
|
||||||
__entry->mod_count = mod_count;
|
__entry->mod_count = mod_count;
|
||||||
__entry->where = where;
|
__entry->where = where;
|
||||||
),
|
),
|
||||||
|
|
||||||
TP_printk("s=%p %s u=%d m=%d p=%pSR",
|
TP_printk("s=%p %cx %s u=%d m=%d p=%pSR",
|
||||||
__entry->skb,
|
__entry->skb,
|
||||||
|
__entry->flags & RXRPC_SKB_TX_BUFFER ? 'T' : 'R',
|
||||||
__print_symbolic(__entry->op, rxrpc_skb_traces),
|
__print_symbolic(__entry->op, rxrpc_skb_traces),
|
||||||
__entry->usage,
|
__entry->usage,
|
||||||
__entry->mod_count,
|
__entry->mod_count,
|
||||||
|
|
|
@ -890,7 +890,8 @@ int bpf_jit_get_func_addr(const struct bpf_prog *prog,
|
||||||
|
|
||||||
static int bpf_jit_blind_insn(const struct bpf_insn *from,
|
static int bpf_jit_blind_insn(const struct bpf_insn *from,
|
||||||
const struct bpf_insn *aux,
|
const struct bpf_insn *aux,
|
||||||
struct bpf_insn *to_buff)
|
struct bpf_insn *to_buff,
|
||||||
|
bool emit_zext)
|
||||||
{
|
{
|
||||||
struct bpf_insn *to = to_buff;
|
struct bpf_insn *to = to_buff;
|
||||||
u32 imm_rnd = get_random_int();
|
u32 imm_rnd = get_random_int();
|
||||||
|
@ -1005,6 +1006,8 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from,
|
||||||
case 0: /* Part 2 of BPF_LD | BPF_IMM | BPF_DW. */
|
case 0: /* Part 2 of BPF_LD | BPF_IMM | BPF_DW. */
|
||||||
*to++ = BPF_ALU32_IMM(BPF_MOV, BPF_REG_AX, imm_rnd ^ aux[0].imm);
|
*to++ = BPF_ALU32_IMM(BPF_MOV, BPF_REG_AX, imm_rnd ^ aux[0].imm);
|
||||||
*to++ = BPF_ALU32_IMM(BPF_XOR, BPF_REG_AX, imm_rnd);
|
*to++ = BPF_ALU32_IMM(BPF_XOR, BPF_REG_AX, imm_rnd);
|
||||||
|
if (emit_zext)
|
||||||
|
*to++ = BPF_ZEXT_REG(BPF_REG_AX);
|
||||||
*to++ = BPF_ALU64_REG(BPF_OR, aux[0].dst_reg, BPF_REG_AX);
|
*to++ = BPF_ALU64_REG(BPF_OR, aux[0].dst_reg, BPF_REG_AX);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1088,7 +1091,8 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
|
||||||
insn[1].code == 0)
|
insn[1].code == 0)
|
||||||
memcpy(aux, insn, sizeof(aux));
|
memcpy(aux, insn, sizeof(aux));
|
||||||
|
|
||||||
rewritten = bpf_jit_blind_insn(insn, aux, insn_buff);
|
rewritten = bpf_jit_blind_insn(insn, aux, insn_buff,
|
||||||
|
clone->aux->verifier_zext);
|
||||||
if (!rewritten)
|
if (!rewritten)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -277,17 +277,23 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
|
||||||
* batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached
|
* batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached
|
||||||
* @buff_pos: current position in the skb
|
* @buff_pos: current position in the skb
|
||||||
* @packet_len: total length of the skb
|
* @packet_len: total length of the skb
|
||||||
* @tvlv_len: tvlv length of the previously considered OGM
|
* @ogm_packet: potential OGM in buffer
|
||||||
*
|
*
|
||||||
* Return: true if there is enough space for another OGM, false otherwise.
|
* Return: true if there is enough space for another OGM, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
|
static bool
|
||||||
__be16 tvlv_len)
|
batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
|
||||||
|
const struct batadv_ogm_packet *ogm_packet)
|
||||||
{
|
{
|
||||||
int next_buff_pos = 0;
|
int next_buff_pos = 0;
|
||||||
|
|
||||||
next_buff_pos += buff_pos + BATADV_OGM_HLEN;
|
/* check if there is enough space for the header */
|
||||||
next_buff_pos += ntohs(tvlv_len);
|
next_buff_pos += buff_pos + sizeof(*ogm_packet);
|
||||||
|
if (next_buff_pos > packet_len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* check if there is enough space for the optional TVLV */
|
||||||
|
next_buff_pos += ntohs(ogm_packet->tvlv_len);
|
||||||
|
|
||||||
return (next_buff_pos <= packet_len) &&
|
return (next_buff_pos <= packet_len) &&
|
||||||
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
|
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
|
||||||
|
@ -315,7 +321,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
|
||||||
|
|
||||||
/* adjust all flags and log packets */
|
/* adjust all flags and log packets */
|
||||||
while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
|
while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
|
||||||
batadv_ogm_packet->tvlv_len)) {
|
batadv_ogm_packet)) {
|
||||||
/* we might have aggregated direct link packets with an
|
/* we might have aggregated direct link packets with an
|
||||||
* ordinary base packet
|
* ordinary base packet
|
||||||
*/
|
*/
|
||||||
|
@ -1704,7 +1710,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
|
||||||
|
|
||||||
/* unpack the aggregated packets and process them one by one */
|
/* unpack the aggregated packets and process them one by one */
|
||||||
while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
|
while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
|
||||||
ogm_packet->tvlv_len)) {
|
ogm_packet)) {
|
||||||
batadv_iv_ogm_process(skb, ogm_offset, if_incoming);
|
batadv_iv_ogm_process(skb, ogm_offset, if_incoming);
|
||||||
|
|
||||||
ogm_offset += BATADV_OGM_HLEN;
|
ogm_offset += BATADV_OGM_HLEN;
|
||||||
|
|
|
@ -631,17 +631,23 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv,
|
||||||
* batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated
|
* batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated
|
||||||
* @buff_pos: current position in the skb
|
* @buff_pos: current position in the skb
|
||||||
* @packet_len: total length of the skb
|
* @packet_len: total length of the skb
|
||||||
* @tvlv_len: tvlv length of the previously considered OGM
|
* @ogm2_packet: potential OGM2 in buffer
|
||||||
*
|
*
|
||||||
* Return: true if there is enough space for another OGM, false otherwise.
|
* Return: true if there is enough space for another OGM, false otherwise.
|
||||||
*/
|
*/
|
||||||
static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
|
static bool
|
||||||
__be16 tvlv_len)
|
batadv_v_ogm_aggr_packet(int buff_pos, int packet_len,
|
||||||
|
const struct batadv_ogm2_packet *ogm2_packet)
|
||||||
{
|
{
|
||||||
int next_buff_pos = 0;
|
int next_buff_pos = 0;
|
||||||
|
|
||||||
next_buff_pos += buff_pos + BATADV_OGM2_HLEN;
|
/* check if there is enough space for the header */
|
||||||
next_buff_pos += ntohs(tvlv_len);
|
next_buff_pos += buff_pos + sizeof(*ogm2_packet);
|
||||||
|
if (next_buff_pos > packet_len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* check if there is enough space for the optional TVLV */
|
||||||
|
next_buff_pos += ntohs(ogm2_packet->tvlv_len);
|
||||||
|
|
||||||
return (next_buff_pos <= packet_len) &&
|
return (next_buff_pos <= packet_len) &&
|
||||||
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
|
(next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
|
||||||
|
@ -818,7 +824,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb,
|
||||||
ogm_packet = (struct batadv_ogm2_packet *)skb->data;
|
ogm_packet = (struct batadv_ogm2_packet *)skb->data;
|
||||||
|
|
||||||
while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
|
while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
|
||||||
ogm_packet->tvlv_len)) {
|
ogm_packet)) {
|
||||||
batadv_v_ogm_process(skb, ogm_offset, if_incoming);
|
batadv_v_ogm_process(skb, ogm_offset, if_incoming);
|
||||||
|
|
||||||
ogm_offset += BATADV_OGM2_HLEN;
|
ogm_offset += BATADV_OGM2_HLEN;
|
||||||
|
|
|
@ -53,7 +53,7 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
br_vlan_get_proto(br_dev, &p_proto);
|
br_vlan_get_proto(br_dev, &p_proto);
|
||||||
nft_reg_store16(dest, p_proto);
|
nft_reg_store16(dest, htons(p_proto));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -122,7 +122,7 @@ static void queue_process(struct work_struct *work)
|
||||||
txq = netdev_get_tx_queue(dev, q_index);
|
txq = netdev_get_tx_queue(dev, q_index);
|
||||||
HARD_TX_LOCK(dev, txq, smp_processor_id());
|
HARD_TX_LOCK(dev, txq, smp_processor_id());
|
||||||
if (netif_xmit_frozen_or_stopped(txq) ||
|
if (netif_xmit_frozen_or_stopped(txq) ||
|
||||||
netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) {
|
!dev_xmit_complete(netpoll_start_xmit(skb, dev, txq))) {
|
||||||
skb_queue_head(&npinfo->txq, skb);
|
skb_queue_head(&npinfo->txq, skb);
|
||||||
HARD_TX_UNLOCK(dev, txq);
|
HARD_TX_UNLOCK(dev, txq);
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
@ -335,7 +335,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
|
||||||
|
|
||||||
HARD_TX_UNLOCK(dev, txq);
|
HARD_TX_UNLOCK(dev, txq);
|
||||||
|
|
||||||
if (status == NETDEV_TX_OK)
|
if (dev_xmit_complete(status))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -352,7 +352,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != NETDEV_TX_OK) {
|
if (!dev_xmit_complete(status)) {
|
||||||
skb_queue_tail(&npinfo->txq, skb);
|
skb_queue_tail(&npinfo->txq, skb);
|
||||||
schedule_delayed_work(&npinfo->tx_work,0);
|
schedule_delayed_work(&npinfo->tx_work,0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
*
|
*
|
||||||
* RSV - VID[9]:
|
* RSV - VID[9]:
|
||||||
* To be used for further expansion of SWITCH_ID or for other purposes.
|
* To be used for further expansion of SWITCH_ID or for other purposes.
|
||||||
|
* Must be transmitted as zero and ignored on receive.
|
||||||
*
|
*
|
||||||
* SWITCH_ID - VID[8:6]:
|
* SWITCH_ID - VID[8:6]:
|
||||||
* Index of switch within DSA tree. Must be between 0 and
|
* Index of switch within DSA tree. Must be between 0 and
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
*
|
*
|
||||||
* RSV - VID[5:4]:
|
* RSV - VID[5:4]:
|
||||||
* To be used for further expansion of PORT or for other purposes.
|
* To be used for further expansion of PORT or for other purposes.
|
||||||
|
* Must be transmitted as zero and ignored on receive.
|
||||||
*
|
*
|
||||||
* PORT - VID[3:0]:
|
* PORT - VID[3:0]:
|
||||||
* Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1.
|
* Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1.
|
||||||
|
|
|
@ -935,6 +935,22 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
|
||||||
return mss_now;
|
return mss_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In some cases, both sendpage() and sendmsg() could have added
|
||||||
|
* an skb to the write queue, but failed adding payload on it.
|
||||||
|
* We need to remove it to consume less memory, but more
|
||||||
|
* importantly be able to generate EPOLLOUT for Edge Trigger epoll()
|
||||||
|
* users.
|
||||||
|
*/
|
||||||
|
static void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
if (skb && !skb->len) {
|
||||||
|
tcp_unlink_write_queue(skb, sk);
|
||||||
|
if (tcp_write_queue_empty(sk))
|
||||||
|
tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
|
||||||
|
sk_wmem_free_skb(sk, skb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
|
ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
|
||||||
size_t size, int flags)
|
size_t size, int flags)
|
||||||
{
|
{
|
||||||
|
@ -1064,6 +1080,7 @@ ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
|
||||||
return copied;
|
return copied;
|
||||||
|
|
||||||
do_error:
|
do_error:
|
||||||
|
tcp_remove_empty_skb(sk, tcp_write_queue_tail(sk));
|
||||||
if (copied)
|
if (copied)
|
||||||
goto out;
|
goto out;
|
||||||
out_err:
|
out_err:
|
||||||
|
@ -1388,18 +1405,11 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
|
||||||
sock_zerocopy_put(uarg);
|
sock_zerocopy_put(uarg);
|
||||||
return copied + copied_syn;
|
return copied + copied_syn;
|
||||||
|
|
||||||
do_fault:
|
|
||||||
if (!skb->len) {
|
|
||||||
tcp_unlink_write_queue(skb, sk);
|
|
||||||
/* It is the one place in all of TCP, except connection
|
|
||||||
* reset, where we can be unlinking the send_head.
|
|
||||||
*/
|
|
||||||
if (tcp_write_queue_empty(sk))
|
|
||||||
tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
|
|
||||||
sk_wmem_free_skb(sk, skb);
|
|
||||||
}
|
|
||||||
|
|
||||||
do_error:
|
do_error:
|
||||||
|
skb = tcp_write_queue_tail(sk);
|
||||||
|
do_fault:
|
||||||
|
tcp_remove_empty_skb(sk, skb);
|
||||||
|
|
||||||
if (copied + copied_syn)
|
if (copied + copied_syn)
|
||||||
goto out;
|
goto out;
|
||||||
out_err:
|
out_err:
|
||||||
|
|
|
@ -2053,7 +2053,7 @@ static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len)
|
||||||
if (len <= skb->len)
|
if (len <= skb->len)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (unlikely(TCP_SKB_CB(skb)->eor))
|
if (unlikely(TCP_SKB_CB(skb)->eor) || tcp_has_tx_tstamp(skb))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
len -= skb->len;
|
len -= skb->len;
|
||||||
|
@ -2170,6 +2170,7 @@ static int tcp_mtu_probe(struct sock *sk)
|
||||||
* we need to propagate it to the new skb.
|
* we need to propagate it to the new skb.
|
||||||
*/
|
*/
|
||||||
TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor;
|
TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor;
|
||||||
|
tcp_skb_collapse_tstamp(nskb, skb);
|
||||||
tcp_unlink_write_queue(skb, sk);
|
tcp_unlink_write_queue(skb, sk);
|
||||||
sk_wmem_free_skb(sk, skb);
|
sk_wmem_free_skb(sk, skb);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -787,14 +787,15 @@ static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
|
||||||
if (pmc) {
|
if (pmc) {
|
||||||
im->idev = pmc->idev;
|
im->idev = pmc->idev;
|
||||||
if (im->mca_sfmode == MCAST_INCLUDE) {
|
if (im->mca_sfmode == MCAST_INCLUDE) {
|
||||||
im->mca_tomb = pmc->mca_tomb;
|
swap(im->mca_tomb, pmc->mca_tomb);
|
||||||
im->mca_sources = pmc->mca_sources;
|
swap(im->mca_sources, pmc->mca_sources);
|
||||||
for (psf = im->mca_sources; psf; psf = psf->sf_next)
|
for (psf = im->mca_sources; psf; psf = psf->sf_next)
|
||||||
psf->sf_crcount = idev->mc_qrv;
|
psf->sf_crcount = idev->mc_qrv;
|
||||||
} else {
|
} else {
|
||||||
im->mca_crcount = idev->mc_qrv;
|
im->mca_crcount = idev->mc_qrv;
|
||||||
}
|
}
|
||||||
in6_dev_put(pmc->idev);
|
in6_dev_put(pmc->idev);
|
||||||
|
ip6_mc_clear_src(pmc);
|
||||||
kfree(pmc);
|
kfree(pmc);
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&im->mca_lock);
|
spin_unlock_bh(&im->mca_lock);
|
||||||
|
|
|
@ -2447,11 +2447,13 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
|
||||||
skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) &&
|
skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) &&
|
||||||
sdata->control_port_over_nl80211)) {
|
sdata->control_port_over_nl80211)) {
|
||||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||||
bool noencrypt = status->flag & RX_FLAG_DECRYPTED;
|
bool noencrypt = !(status->flag & RX_FLAG_DECRYPTED);
|
||||||
|
|
||||||
cfg80211_rx_control_port(dev, skb, noencrypt);
|
cfg80211_rx_control_port(dev, skb, noencrypt);
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb(skb);
|
||||||
} else {
|
} else {
|
||||||
|
memset(skb->cb, 0, sizeof(skb->cb));
|
||||||
|
|
||||||
/* deliver to local stack */
|
/* deliver to local stack */
|
||||||
if (rx->napi)
|
if (rx->napi)
|
||||||
napi_gro_receive(rx->napi, skb);
|
napi_gro_receive(rx->napi, skb);
|
||||||
|
@ -2546,8 +2548,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
||||||
|
|
||||||
if (skb) {
|
if (skb) {
|
||||||
skb->protocol = eth_type_trans(skb, dev);
|
skb->protocol = eth_type_trans(skb, dev);
|
||||||
memset(skb->cb, 0, sizeof(skb->cb));
|
|
||||||
|
|
||||||
ieee80211_deliver_skb_to_local_stack(skb, rx);
|
ieee80211_deliver_skb_to_local_stack(skb, rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -322,7 +322,7 @@ static int find_pattern(const char *data, size_t dlen,
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("Skipped up to `%c'!\n", skip);
|
pr_debug("Skipped up to 0x%hhx delimiter!\n", skip);
|
||||||
|
|
||||||
*numoff = i;
|
*numoff = i;
|
||||||
*numlen = getnum(data + i, dlen - i, cmd, term, numoff);
|
*numlen = getnum(data + i, dlen - i, cmd, term, numoff);
|
||||||
|
|
|
@ -1037,8 +1037,13 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
|
||||||
table[NF_SYSCTL_CT_COUNT].data = &net->ct.count;
|
table[NF_SYSCTL_CT_COUNT].data = &net->ct.count;
|
||||||
table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum;
|
table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum;
|
||||||
table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid;
|
table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid;
|
||||||
|
table[NF_SYSCTL_CT_ACCT].data = &net->ct.sysctl_acct;
|
||||||
|
table[NF_SYSCTL_CT_HELPER].data = &net->ct.sysctl_auto_assign_helper;
|
||||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||||
table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events;
|
table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
|
||||||
|
table[NF_SYSCTL_CT_TIMESTAMP].data = &net->ct.sysctl_tstamp;
|
||||||
#endif
|
#endif
|
||||||
table[NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC].data = &nf_generic_pernet(net)->timeout;
|
table[NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC].data = &nf_generic_pernet(net)->timeout;
|
||||||
table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP].data = &nf_icmp_pernet(net)->timeout;
|
table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP].data = &nf_icmp_pernet(net)->timeout;
|
||||||
|
|
|
@ -228,7 +228,6 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
|
||||||
{
|
{
|
||||||
skb_orphan(skb);
|
skb_orphan(skb);
|
||||||
skb_dst_set_noref(skb, dst);
|
skb_dst_set_noref(skb, dst);
|
||||||
skb->tstamp = 0;
|
|
||||||
dst_output(state->net, state->sk, skb);
|
dst_output(state->net, state->sk, skb);
|
||||||
return NF_STOLEN;
|
return NF_STOLEN;
|
||||||
}
|
}
|
||||||
|
@ -284,6 +283,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||||
flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
|
flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
|
||||||
iph = ip_hdr(skb);
|
iph = ip_hdr(skb);
|
||||||
ip_decrease_ttl(iph);
|
ip_decrease_ttl(iph);
|
||||||
|
skb->tstamp = 0;
|
||||||
|
|
||||||
if (unlikely(dst_xfrm(&rt->dst))) {
|
if (unlikely(dst_xfrm(&rt->dst))) {
|
||||||
memset(skb->cb, 0, sizeof(struct inet_skb_parm));
|
memset(skb->cb, 0, sizeof(struct inet_skb_parm));
|
||||||
|
@ -512,6 +512,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||||
flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
|
flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
|
||||||
ip6h = ipv6_hdr(skb);
|
ip6h = ipv6_hdr(skb);
|
||||||
ip6h->hop_limit--;
|
ip6h->hop_limit--;
|
||||||
|
skb->tstamp = 0;
|
||||||
|
|
||||||
if (unlikely(dst_xfrm(&rt->dst))) {
|
if (unlikely(dst_xfrm(&rt->dst))) {
|
||||||
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
|
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
|
||||||
|
|
|
@ -101,11 +101,9 @@ static int physdev_mt_check(const struct xt_mtchk_param *par)
|
||||||
if (info->bitmask & (XT_PHYSDEV_OP_OUT | XT_PHYSDEV_OP_ISOUT) &&
|
if (info->bitmask & (XT_PHYSDEV_OP_OUT | XT_PHYSDEV_OP_ISOUT) &&
|
||||||
(!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
|
(!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
|
||||||
info->invert & XT_PHYSDEV_OP_BRIDGED) &&
|
info->invert & XT_PHYSDEV_OP_BRIDGED) &&
|
||||||
par->hook_mask & ((1 << NF_INET_LOCAL_OUT) |
|
par->hook_mask & (1 << NF_INET_LOCAL_OUT)) {
|
||||||
(1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) {
|
|
||||||
pr_info_ratelimited("--physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic\n");
|
pr_info_ratelimited("--physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic\n");
|
||||||
if (par->hook_mask & (1 << NF_INET_LOCAL_OUT))
|
return -EINVAL;
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!brnf_probed) {
|
if (!brnf_probed) {
|
||||||
|
|
|
@ -525,6 +525,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
|
||||||
return -EPFNOSUPPORT;
|
return -EPFNOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The key extracted from the fragment that completed this datagram
|
||||||
|
* likely didn't have an L4 header, so regenerate it.
|
||||||
|
*/
|
||||||
|
ovs_flow_key_update_l3l4(skb, key);
|
||||||
|
|
||||||
key->ip.frag = OVS_FRAG_TYPE_NONE;
|
key->ip.frag = OVS_FRAG_TYPE_NONE;
|
||||||
skb_clear_hash(skb);
|
skb_clear_hash(skb);
|
||||||
skb->ignore_df = 1;
|
skb->ignore_df = 1;
|
||||||
|
|
|
@ -523,78 +523,15 @@ static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* key_extract - extracts a flow key from an Ethernet frame.
|
* key_extract_l3l4 - extracts L3/L4 header information.
|
||||||
* @skb: sk_buff that contains the frame, with skb->data pointing to the
|
* @skb: sk_buff that contains the frame, with skb->data pointing to the
|
||||||
* Ethernet header
|
* L3 header
|
||||||
* @key: output flow key
|
* @key: output flow key
|
||||||
*
|
*
|
||||||
* The caller must ensure that skb->len >= ETH_HLEN.
|
|
||||||
*
|
|
||||||
* Returns 0 if successful, otherwise a negative errno value.
|
|
||||||
*
|
|
||||||
* Initializes @skb header fields as follows:
|
|
||||||
*
|
|
||||||
* - skb->mac_header: the L2 header.
|
|
||||||
*
|
|
||||||
* - skb->network_header: just past the L2 header, or just past the
|
|
||||||
* VLAN header, to the first byte of the L2 payload.
|
|
||||||
*
|
|
||||||
* - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
|
|
||||||
* on output, then just past the IP header, if one is present and
|
|
||||||
* of a correct length, otherwise the same as skb->network_header.
|
|
||||||
* For other key->eth.type values it is left untouched.
|
|
||||||
*
|
|
||||||
* - skb->protocol: the type of the data starting at skb->network_header.
|
|
||||||
* Equals to key->eth.type.
|
|
||||||
*/
|
*/
|
||||||
static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
struct ethhdr *eth;
|
|
||||||
|
|
||||||
/* Flags are always used as part of stats */
|
|
||||||
key->tp.flags = 0;
|
|
||||||
|
|
||||||
skb_reset_mac_header(skb);
|
|
||||||
|
|
||||||
/* Link layer. */
|
|
||||||
clear_vlan(key);
|
|
||||||
if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
|
|
||||||
if (unlikely(eth_type_vlan(skb->protocol)))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
skb_reset_network_header(skb);
|
|
||||||
key->eth.type = skb->protocol;
|
|
||||||
} else {
|
|
||||||
eth = eth_hdr(skb);
|
|
||||||
ether_addr_copy(key->eth.src, eth->h_source);
|
|
||||||
ether_addr_copy(key->eth.dst, eth->h_dest);
|
|
||||||
|
|
||||||
__skb_pull(skb, 2 * ETH_ALEN);
|
|
||||||
/* We are going to push all headers that we pull, so no need to
|
|
||||||
* update skb->csum here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (unlikely(parse_vlan(skb, key)))
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
key->eth.type = parse_ethertype(skb);
|
|
||||||
if (unlikely(key->eth.type == htons(0)))
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* Multiple tagged packets need to retain TPID to satisfy
|
|
||||||
* skb_vlan_pop(), which will later shift the ethertype into
|
|
||||||
* skb->protocol.
|
|
||||||
*/
|
|
||||||
if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
|
|
||||||
skb->protocol = key->eth.cvlan.tpid;
|
|
||||||
else
|
|
||||||
skb->protocol = key->eth.type;
|
|
||||||
|
|
||||||
skb_reset_network_header(skb);
|
|
||||||
__skb_push(skb, skb->data - skb_mac_header(skb));
|
|
||||||
}
|
|
||||||
skb_reset_mac_len(skb);
|
|
||||||
|
|
||||||
/* Network layer. */
|
/* Network layer. */
|
||||||
if (key->eth.type == htons(ETH_P_IP)) {
|
if (key->eth.type == htons(ETH_P_IP)) {
|
||||||
|
@ -623,6 +560,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
||||||
offset = nh->frag_off & htons(IP_OFFSET);
|
offset = nh->frag_off & htons(IP_OFFSET);
|
||||||
if (offset) {
|
if (offset) {
|
||||||
key->ip.frag = OVS_FRAG_TYPE_LATER;
|
key->ip.frag = OVS_FRAG_TYPE_LATER;
|
||||||
|
memset(&key->tp, 0, sizeof(key->tp));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (nh->frag_off & htons(IP_MF) ||
|
if (nh->frag_off & htons(IP_MF) ||
|
||||||
|
@ -740,8 +678,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key->ip.frag == OVS_FRAG_TYPE_LATER)
|
if (key->ip.frag == OVS_FRAG_TYPE_LATER) {
|
||||||
|
memset(&key->tp, 0, sizeof(key->tp));
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
|
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
|
||||||
key->ip.frag = OVS_FRAG_TYPE_FIRST;
|
key->ip.frag = OVS_FRAG_TYPE_FIRST;
|
||||||
|
|
||||||
|
@ -788,6 +728,92 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key_extract - extracts a flow key from an Ethernet frame.
|
||||||
|
* @skb: sk_buff that contains the frame, with skb->data pointing to the
|
||||||
|
* Ethernet header
|
||||||
|
* @key: output flow key
|
||||||
|
*
|
||||||
|
* The caller must ensure that skb->len >= ETH_HLEN.
|
||||||
|
*
|
||||||
|
* Returns 0 if successful, otherwise a negative errno value.
|
||||||
|
*
|
||||||
|
* Initializes @skb header fields as follows:
|
||||||
|
*
|
||||||
|
* - skb->mac_header: the L2 header.
|
||||||
|
*
|
||||||
|
* - skb->network_header: just past the L2 header, or just past the
|
||||||
|
* VLAN header, to the first byte of the L2 payload.
|
||||||
|
*
|
||||||
|
* - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
|
||||||
|
* on output, then just past the IP header, if one is present and
|
||||||
|
* of a correct length, otherwise the same as skb->network_header.
|
||||||
|
* For other key->eth.type values it is left untouched.
|
||||||
|
*
|
||||||
|
* - skb->protocol: the type of the data starting at skb->network_header.
|
||||||
|
* Equals to key->eth.type.
|
||||||
|
*/
|
||||||
|
static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
|
||||||
|
{
|
||||||
|
struct ethhdr *eth;
|
||||||
|
|
||||||
|
/* Flags are always used as part of stats */
|
||||||
|
key->tp.flags = 0;
|
||||||
|
|
||||||
|
skb_reset_mac_header(skb);
|
||||||
|
|
||||||
|
/* Link layer. */
|
||||||
|
clear_vlan(key);
|
||||||
|
if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
|
||||||
|
if (unlikely(eth_type_vlan(skb->protocol)))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
skb_reset_network_header(skb);
|
||||||
|
key->eth.type = skb->protocol;
|
||||||
|
} else {
|
||||||
|
eth = eth_hdr(skb);
|
||||||
|
ether_addr_copy(key->eth.src, eth->h_source);
|
||||||
|
ether_addr_copy(key->eth.dst, eth->h_dest);
|
||||||
|
|
||||||
|
__skb_pull(skb, 2 * ETH_ALEN);
|
||||||
|
/* We are going to push all headers that we pull, so no need to
|
||||||
|
* update skb->csum here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (unlikely(parse_vlan(skb, key)))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
key->eth.type = parse_ethertype(skb);
|
||||||
|
if (unlikely(key->eth.type == htons(0)))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
/* Multiple tagged packets need to retain TPID to satisfy
|
||||||
|
* skb_vlan_pop(), which will later shift the ethertype into
|
||||||
|
* skb->protocol.
|
||||||
|
*/
|
||||||
|
if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
|
||||||
|
skb->protocol = key->eth.cvlan.tpid;
|
||||||
|
else
|
||||||
|
skb->protocol = key->eth.type;
|
||||||
|
|
||||||
|
skb_reset_network_header(skb);
|
||||||
|
__skb_push(skb, skb->data - skb_mac_header(skb));
|
||||||
|
}
|
||||||
|
|
||||||
|
skb_reset_mac_len(skb);
|
||||||
|
|
||||||
|
/* Fill out L3/L4 key info, if any */
|
||||||
|
return key_extract_l3l4(skb, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In the case of conntrack fragment handling it expects L3 headers,
|
||||||
|
* add a helper.
|
||||||
|
*/
|
||||||
|
int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
|
||||||
|
{
|
||||||
|
return key_extract_l3l4(skb, key);
|
||||||
|
}
|
||||||
|
|
||||||
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
|
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
|
@ -270,6 +270,7 @@ void ovs_flow_stats_clear(struct sw_flow *);
|
||||||
u64 ovs_flow_used_time(unsigned long flow_jiffies);
|
u64 ovs_flow_used_time(unsigned long flow_jiffies);
|
||||||
|
|
||||||
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
|
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
|
||||||
|
int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key);
|
||||||
int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
|
int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct sw_flow_key *key);
|
struct sw_flow_key *key);
|
||||||
|
|
|
@ -154,7 +154,7 @@ static void psample_group_destroy(struct psample_group *group)
|
||||||
{
|
{
|
||||||
psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP);
|
psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP);
|
||||||
list_del(&group->list);
|
list_del(&group->list);
|
||||||
kfree(group);
|
kfree_rcu(group, rcu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct psample_group *
|
static struct psample_group *
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved.
|
||||||
*
|
*
|
||||||
* This software is available to you under a choice of one of two
|
* This software is available to you under a choice of one of two
|
||||||
* licenses. You may choose to be licensed under the terms of the GNU
|
* licenses. You may choose to be licensed under the terms of the GNU
|
||||||
|
@ -811,6 +811,7 @@ void rds6_inc_info_copy(struct rds_incoming *inc,
|
||||||
|
|
||||||
minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence);
|
minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence);
|
||||||
minfo6.len = be32_to_cpu(inc->i_hdr.h_len);
|
minfo6.len = be32_to_cpu(inc->i_hdr.h_len);
|
||||||
|
minfo6.tos = inc->i_conn->c_tos;
|
||||||
|
|
||||||
if (flip) {
|
if (flip) {
|
||||||
minfo6.laddr = *daddr;
|
minfo6.laddr = *daddr;
|
||||||
|
@ -824,6 +825,8 @@ void rds6_inc_info_copy(struct rds_incoming *inc,
|
||||||
minfo6.fport = inc->i_hdr.h_dport;
|
minfo6.fport = inc->i_hdr.h_dport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
minfo6.flags = 0;
|
||||||
|
|
||||||
rds_info_copy(iter, &minfo6, sizeof(minfo6));
|
rds_info_copy(iter, &minfo6, sizeof(minfo6));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -862,7 +862,6 @@ static void rxrpc_sock_destructor(struct sock *sk)
|
||||||
static int rxrpc_release_sock(struct sock *sk)
|
static int rxrpc_release_sock(struct sock *sk)
|
||||||
{
|
{
|
||||||
struct rxrpc_sock *rx = rxrpc_sk(sk);
|
struct rxrpc_sock *rx = rxrpc_sk(sk);
|
||||||
struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
|
|
||||||
|
|
||||||
_enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
|
_enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt));
|
||||||
|
|
||||||
|
@ -898,8 +897,6 @@ static int rxrpc_release_sock(struct sock *sk)
|
||||||
rxrpc_release_calls_on_socket(rx);
|
rxrpc_release_calls_on_socket(rx);
|
||||||
flush_workqueue(rxrpc_workqueue);
|
flush_workqueue(rxrpc_workqueue);
|
||||||
rxrpc_purge_queue(&sk->sk_receive_queue);
|
rxrpc_purge_queue(&sk->sk_receive_queue);
|
||||||
rxrpc_queue_work(&rxnet->service_conn_reaper);
|
|
||||||
rxrpc_queue_work(&rxnet->client_conn_reaper);
|
|
||||||
|
|
||||||
rxrpc_unuse_local(rx->local);
|
rxrpc_unuse_local(rx->local);
|
||||||
rx->local = NULL;
|
rx->local = NULL;
|
||||||
|
|
|
@ -185,11 +185,17 @@ struct rxrpc_host_header {
|
||||||
* - max 48 bytes (struct sk_buff::cb)
|
* - max 48 bytes (struct sk_buff::cb)
|
||||||
*/
|
*/
|
||||||
struct rxrpc_skb_priv {
|
struct rxrpc_skb_priv {
|
||||||
union {
|
atomic_t nr_ring_pins; /* Number of rxtx ring pins */
|
||||||
u8 nr_jumbo; /* Number of jumbo subpackets */
|
u8 nr_subpackets; /* Number of subpackets */
|
||||||
};
|
u8 rx_flags; /* Received packet flags */
|
||||||
|
#define RXRPC_SKB_INCL_LAST 0x01 /* - Includes last packet */
|
||||||
|
#define RXRPC_SKB_TX_BUFFER 0x02 /* - Is transmit buffer */
|
||||||
union {
|
union {
|
||||||
int remain; /* amount of space remaining for next write */
|
int remain; /* amount of space remaining for next write */
|
||||||
|
|
||||||
|
/* List of requested ACKs on subpackets */
|
||||||
|
unsigned long rx_req_ack[(RXRPC_MAX_NR_JUMBO + BITS_PER_LONG - 1) /
|
||||||
|
BITS_PER_LONG];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */
|
struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */
|
||||||
|
@ -613,8 +619,7 @@ struct rxrpc_call {
|
||||||
#define RXRPC_TX_ANNO_LAST 0x04
|
#define RXRPC_TX_ANNO_LAST 0x04
|
||||||
#define RXRPC_TX_ANNO_RESENT 0x08
|
#define RXRPC_TX_ANNO_RESENT 0x08
|
||||||
|
|
||||||
#define RXRPC_RX_ANNO_JUMBO 0x3f /* Jumbo subpacket number + 1 if not zero */
|
#define RXRPC_RX_ANNO_SUBPACKET 0x3f /* Subpacket number in jumbogram */
|
||||||
#define RXRPC_RX_ANNO_JLAST 0x40 /* Set if last element of a jumbo packet */
|
|
||||||
#define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */
|
#define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */
|
||||||
rxrpc_seq_t tx_hard_ack; /* Dead slot in buffer; the first transmitted but
|
rxrpc_seq_t tx_hard_ack; /* Dead slot in buffer; the first transmitted but
|
||||||
* not hard-ACK'd packet follows this.
|
* not hard-ACK'd packet follows this.
|
||||||
|
@ -905,6 +910,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *);
|
||||||
void rxrpc_put_client_conn(struct rxrpc_connection *);
|
void rxrpc_put_client_conn(struct rxrpc_connection *);
|
||||||
void rxrpc_discard_expired_client_conns(struct work_struct *);
|
void rxrpc_discard_expired_client_conns(struct work_struct *);
|
||||||
void rxrpc_destroy_all_client_connections(struct rxrpc_net *);
|
void rxrpc_destroy_all_client_connections(struct rxrpc_net *);
|
||||||
|
void rxrpc_clean_up_local_conns(struct rxrpc_local *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* conn_event.c
|
* conn_event.c
|
||||||
|
@ -1105,6 +1111,7 @@ void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *);
|
||||||
void rxrpc_packet_destructor(struct sk_buff *);
|
void rxrpc_packet_destructor(struct sk_buff *);
|
||||||
void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
||||||
void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
||||||
|
void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
||||||
void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
||||||
void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
|
||||||
void rxrpc_purge_queue(struct sk_buff_head *);
|
void rxrpc_purge_queue(struct sk_buff_head *);
|
||||||
|
|
|
@ -199,7 +199,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
skb = call->rxtx_buffer[ix];
|
skb = call->rxtx_buffer[ix];
|
||||||
rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
|
rxrpc_see_skb(skb, rxrpc_skb_seen);
|
||||||
|
|
||||||
if (anno_type == RXRPC_TX_ANNO_UNACK) {
|
if (anno_type == RXRPC_TX_ANNO_UNACK) {
|
||||||
if (ktime_after(skb->tstamp, max_age)) {
|
if (ktime_after(skb->tstamp, max_age)) {
|
||||||
|
@ -255,18 +255,18 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
skb = call->rxtx_buffer[ix];
|
skb = call->rxtx_buffer[ix];
|
||||||
rxrpc_get_skb(skb, rxrpc_skb_tx_got);
|
rxrpc_get_skb(skb, rxrpc_skb_got);
|
||||||
spin_unlock_bh(&call->lock);
|
spin_unlock_bh(&call->lock);
|
||||||
|
|
||||||
if (rxrpc_send_data_packet(call, skb, true) < 0) {
|
if (rxrpc_send_data_packet(call, skb, true) < 0) {
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rxrpc_is_client_call(call))
|
if (rxrpc_is_client_call(call))
|
||||||
rxrpc_expose_client_call(call);
|
rxrpc_expose_client_call(call);
|
||||||
|
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
spin_lock_bh(&call->lock);
|
spin_lock_bh(&call->lock);
|
||||||
|
|
||||||
/* We need to clear the retransmit state, but there are two
|
/* We need to clear the retransmit state, but there are two
|
||||||
|
|
|
@ -421,6 +421,19 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
|
||||||
trace_rxrpc_call(call, op, n, here, NULL);
|
trace_rxrpc_call(call, op, n, here, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up the RxTx skb ring.
|
||||||
|
*/
|
||||||
|
static void rxrpc_cleanup_ring(struct rxrpc_call *call)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
|
||||||
|
rxrpc_free_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned);
|
||||||
|
call->rxtx_buffer[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detach a call from its owning socket.
|
* Detach a call from its owning socket.
|
||||||
*/
|
*/
|
||||||
|
@ -429,7 +442,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
|
||||||
const void *here = __builtin_return_address(0);
|
const void *here = __builtin_return_address(0);
|
||||||
struct rxrpc_connection *conn = call->conn;
|
struct rxrpc_connection *conn = call->conn;
|
||||||
bool put = false;
|
bool put = false;
|
||||||
int i;
|
|
||||||
|
|
||||||
_enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
|
_enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
|
||||||
|
|
||||||
|
@ -479,13 +491,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
|
||||||
if (conn)
|
if (conn)
|
||||||
rxrpc_disconnect_call(call);
|
rxrpc_disconnect_call(call);
|
||||||
|
|
||||||
for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
|
rxrpc_cleanup_ring(call);
|
||||||
rxrpc_free_skb(call->rxtx_buffer[i],
|
|
||||||
(call->tx_phase ? rxrpc_skb_tx_cleaned :
|
|
||||||
rxrpc_skb_rx_cleaned));
|
|
||||||
call->rxtx_buffer[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
_leave("");
|
_leave("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,8 +574,6 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
|
||||||
*/
|
*/
|
||||||
void rxrpc_cleanup_call(struct rxrpc_call *call)
|
void rxrpc_cleanup_call(struct rxrpc_call *call)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
_net("DESTROY CALL %d", call->debug_id);
|
_net("DESTROY CALL %d", call->debug_id);
|
||||||
|
|
||||||
memset(&call->sock_node, 0xcd, sizeof(call->sock_node));
|
memset(&call->sock_node, 0xcd, sizeof(call->sock_node));
|
||||||
|
@ -580,13 +584,8 @@ void rxrpc_cleanup_call(struct rxrpc_call *call)
|
||||||
ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags));
|
ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags));
|
||||||
ASSERTCMP(call->conn, ==, NULL);
|
ASSERTCMP(call->conn, ==, NULL);
|
||||||
|
|
||||||
/* Clean up the Rx/Tx buffer */
|
rxrpc_cleanup_ring(call);
|
||||||
for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++)
|
rxrpc_free_skb(call->tx_pending, rxrpc_skb_cleaned);
|
||||||
rxrpc_free_skb(call->rxtx_buffer[i],
|
|
||||||
(call->tx_phase ? rxrpc_skb_tx_cleaned :
|
|
||||||
rxrpc_skb_rx_cleaned));
|
|
||||||
|
|
||||||
rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned);
|
|
||||||
|
|
||||||
call_rcu(&call->rcu, rxrpc_rcu_destroy_call);
|
call_rcu(&call->rcu, rxrpc_rcu_destroy_call);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1162,3 +1162,47 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet)
|
||||||
|
|
||||||
_leave("");
|
_leave("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up the client connections on a local endpoint.
|
||||||
|
*/
|
||||||
|
void rxrpc_clean_up_local_conns(struct rxrpc_local *local)
|
||||||
|
{
|
||||||
|
struct rxrpc_connection *conn, *tmp;
|
||||||
|
struct rxrpc_net *rxnet = local->rxnet;
|
||||||
|
unsigned int nr_active;
|
||||||
|
LIST_HEAD(graveyard);
|
||||||
|
|
||||||
|
_enter("");
|
||||||
|
|
||||||
|
spin_lock(&rxnet->client_conn_cache_lock);
|
||||||
|
nr_active = rxnet->nr_active_client_conns;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns,
|
||||||
|
cache_link) {
|
||||||
|
if (conn->params.local == local) {
|
||||||
|
ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_IDLE);
|
||||||
|
|
||||||
|
trace_rxrpc_client(conn, -1, rxrpc_client_discard);
|
||||||
|
if (!test_and_clear_bit(RXRPC_CONN_EXPOSED, &conn->flags))
|
||||||
|
BUG();
|
||||||
|
conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE;
|
||||||
|
list_move(&conn->cache_link, &graveyard);
|
||||||
|
nr_active--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rxnet->nr_active_client_conns = nr_active;
|
||||||
|
spin_unlock(&rxnet->client_conn_cache_lock);
|
||||||
|
ASSERTCMP(nr_active, >=, 0);
|
||||||
|
|
||||||
|
while (!list_empty(&graveyard)) {
|
||||||
|
conn = list_entry(graveyard.next,
|
||||||
|
struct rxrpc_connection, cache_link);
|
||||||
|
list_del_init(&conn->cache_link);
|
||||||
|
|
||||||
|
rxrpc_put_connection(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
_leave(" [culled]");
|
||||||
|
}
|
||||||
|
|
|
@ -472,7 +472,7 @@ void rxrpc_process_connection(struct work_struct *work)
|
||||||
/* go through the conn-level event packets, releasing the ref on this
|
/* go through the conn-level event packets, releasing the ref on this
|
||||||
* connection that each one has when we've finished with it */
|
* connection that each one has when we've finished with it */
|
||||||
while ((skb = skb_dequeue(&conn->rx_queue))) {
|
while ((skb = skb_dequeue(&conn->rx_queue))) {
|
||||||
rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
|
rxrpc_see_skb(skb, rxrpc_skb_seen);
|
||||||
ret = rxrpc_process_event(conn, skb, &abort_code);
|
ret = rxrpc_process_event(conn, skb, &abort_code);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case -EPROTO:
|
case -EPROTO:
|
||||||
|
@ -484,7 +484,7 @@ void rxrpc_process_connection(struct work_struct *work)
|
||||||
goto requeue_and_leave;
|
goto requeue_and_leave;
|
||||||
case -ECONNABORTED:
|
case -ECONNABORTED:
|
||||||
default:
|
default:
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,6 +501,6 @@ void rxrpc_process_connection(struct work_struct *work)
|
||||||
protocol_error:
|
protocol_error:
|
||||||
if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
|
if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
|
||||||
goto requeue_and_leave;
|
goto requeue_and_leave;
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,7 +398,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work)
|
||||||
if (conn->state == RXRPC_CONN_SERVICE_PREALLOC)
|
if (conn->state == RXRPC_CONN_SERVICE_PREALLOC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (rxnet->live) {
|
if (rxnet->live && !conn->params.local->dead) {
|
||||||
idle_timestamp = READ_ONCE(conn->idle_timestamp);
|
idle_timestamp = READ_ONCE(conn->idle_timestamp);
|
||||||
expire_at = idle_timestamp + rxrpc_connection_expiry * HZ;
|
expire_at = idle_timestamp + rxrpc_connection_expiry * HZ;
|
||||||
if (conn->params.local->service_closed)
|
if (conn->params.local->service_closed)
|
||||||
|
|
|
@ -233,7 +233,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
||||||
ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK;
|
ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK;
|
||||||
skb = call->rxtx_buffer[ix];
|
skb = call->rxtx_buffer[ix];
|
||||||
annotation = call->rxtx_annotations[ix];
|
annotation = call->rxtx_annotations[ix];
|
||||||
rxrpc_see_skb(skb, rxrpc_skb_tx_rotated);
|
rxrpc_see_skb(skb, rxrpc_skb_rotated);
|
||||||
call->rxtx_buffer[ix] = NULL;
|
call->rxtx_buffer[ix] = NULL;
|
||||||
call->rxtx_annotations[ix] = 0;
|
call->rxtx_annotations[ix] = 0;
|
||||||
skb->next = list;
|
skb->next = list;
|
||||||
|
@ -258,7 +258,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
||||||
skb = list;
|
skb = list;
|
||||||
list = skb->next;
|
list = skb->next;
|
||||||
skb_mark_not_on_list(skb);
|
skb_mark_not_on_list(skb);
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rot_last;
|
return rot_last;
|
||||||
|
@ -347,7 +347,7 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan a jumbo packet to validate its structure and to work out how many
|
* Scan a data packet to validate its structure and to work out how many
|
||||||
* subpackets it contains.
|
* subpackets it contains.
|
||||||
*
|
*
|
||||||
* A jumbo packet is a collection of consecutive packets glued together with
|
* A jumbo packet is a collection of consecutive packets glued together with
|
||||||
|
@ -358,16 +358,21 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
|
||||||
* the last are RXRPC_JUMBO_DATALEN in size. The last subpacket may be of any
|
* the last are RXRPC_JUMBO_DATALEN in size. The last subpacket may be of any
|
||||||
* size.
|
* size.
|
||||||
*/
|
*/
|
||||||
static bool rxrpc_validate_jumbo(struct sk_buff *skb)
|
static bool rxrpc_validate_data(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||||
unsigned int offset = sizeof(struct rxrpc_wire_header);
|
unsigned int offset = sizeof(struct rxrpc_wire_header);
|
||||||
unsigned int len = skb->len;
|
unsigned int len = skb->len;
|
||||||
int nr_jumbo = 1;
|
|
||||||
u8 flags = sp->hdr.flags;
|
u8 flags = sp->hdr.flags;
|
||||||
|
|
||||||
do {
|
for (;;) {
|
||||||
nr_jumbo++;
|
if (flags & RXRPC_REQUEST_ACK)
|
||||||
|
__set_bit(sp->nr_subpackets, sp->rx_req_ack);
|
||||||
|
sp->nr_subpackets++;
|
||||||
|
|
||||||
|
if (!(flags & RXRPC_JUMBO_PACKET))
|
||||||
|
break;
|
||||||
|
|
||||||
if (len - offset < RXRPC_JUMBO_SUBPKTLEN)
|
if (len - offset < RXRPC_JUMBO_SUBPKTLEN)
|
||||||
goto protocol_error;
|
goto protocol_error;
|
||||||
if (flags & RXRPC_LAST_PACKET)
|
if (flags & RXRPC_LAST_PACKET)
|
||||||
|
@ -376,9 +381,10 @@ static bool rxrpc_validate_jumbo(struct sk_buff *skb)
|
||||||
if (skb_copy_bits(skb, offset, &flags, 1) < 0)
|
if (skb_copy_bits(skb, offset, &flags, 1) < 0)
|
||||||
goto protocol_error;
|
goto protocol_error;
|
||||||
offset += sizeof(struct rxrpc_jumbo_header);
|
offset += sizeof(struct rxrpc_jumbo_header);
|
||||||
} while (flags & RXRPC_JUMBO_PACKET);
|
}
|
||||||
|
|
||||||
sp->nr_jumbo = nr_jumbo;
|
if (flags & RXRPC_LAST_PACKET)
|
||||||
|
sp->rx_flags |= RXRPC_SKB_INCL_LAST;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
protocol_error:
|
protocol_error:
|
||||||
|
@ -399,10 +405,10 @@ static bool rxrpc_validate_jumbo(struct sk_buff *skb)
|
||||||
* (that information is encoded in the ACK packet).
|
* (that information is encoded in the ACK packet).
|
||||||
*/
|
*/
|
||||||
static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
|
static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
|
||||||
u8 annotation, bool *_jumbo_bad)
|
bool is_jumbo, bool *_jumbo_bad)
|
||||||
{
|
{
|
||||||
/* Discard normal packets that are duplicates. */
|
/* Discard normal packets that are duplicates. */
|
||||||
if (annotation == 0)
|
if (is_jumbo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Skip jumbo subpackets that are duplicates. When we've had three or
|
/* Skip jumbo subpackets that are duplicates. When we've had three or
|
||||||
|
@ -416,29 +422,30 @@ static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process a DATA packet, adding the packet to the Rx ring.
|
* Process a DATA packet, adding the packet to the Rx ring. The caller's
|
||||||
|
* packet ref must be passed on or discarded.
|
||||||
*/
|
*/
|
||||||
static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||||
enum rxrpc_call_state state;
|
enum rxrpc_call_state state;
|
||||||
unsigned int offset = sizeof(struct rxrpc_wire_header);
|
unsigned int j;
|
||||||
unsigned int ix;
|
|
||||||
rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
|
rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0;
|
||||||
rxrpc_seq_t seq = sp->hdr.seq, hard_ack;
|
rxrpc_seq_t seq0 = sp->hdr.seq, hard_ack;
|
||||||
bool immediate_ack = false, jumbo_bad = false, queued;
|
bool immediate_ack = false, jumbo_bad = false;
|
||||||
u16 len;
|
u8 ack = 0;
|
||||||
u8 ack = 0, flags, annotation = 0;
|
|
||||||
|
|
||||||
_enter("{%u,%u},{%u,%u}",
|
_enter("{%u,%u},{%u,%u}",
|
||||||
call->rx_hard_ack, call->rx_top, skb->len, seq);
|
call->rx_hard_ack, call->rx_top, skb->len, seq0);
|
||||||
|
|
||||||
_proto("Rx DATA %%%u { #%u f=%02x }",
|
_proto("Rx DATA %%%u { #%u f=%02x n=%u }",
|
||||||
sp->hdr.serial, seq, sp->hdr.flags);
|
sp->hdr.serial, seq0, sp->hdr.flags, sp->nr_subpackets);
|
||||||
|
|
||||||
state = READ_ONCE(call->state);
|
state = READ_ONCE(call->state);
|
||||||
if (state >= RXRPC_CALL_COMPLETE)
|
if (state >= RXRPC_CALL_COMPLETE) {
|
||||||
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
|
if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) {
|
||||||
unsigned long timo = READ_ONCE(call->next_req_timo);
|
unsigned long timo = READ_ONCE(call->next_req_timo);
|
||||||
|
@ -463,137 +470,137 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
||||||
!rxrpc_receiving_reply(call))
|
!rxrpc_receiving_reply(call))
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
call->ackr_prev_seq = seq;
|
call->ackr_prev_seq = seq0;
|
||||||
|
|
||||||
hard_ack = READ_ONCE(call->rx_hard_ack);
|
hard_ack = READ_ONCE(call->rx_hard_ack);
|
||||||
if (after(seq, hard_ack + call->rx_winsize)) {
|
|
||||||
ack = RXRPC_ACK_EXCEEDS_WINDOW;
|
|
||||||
ack_serial = serial;
|
|
||||||
goto ack;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = sp->hdr.flags;
|
if (sp->nr_subpackets > 1) {
|
||||||
if (flags & RXRPC_JUMBO_PACKET) {
|
|
||||||
if (call->nr_jumbo_bad > 3) {
|
if (call->nr_jumbo_bad > 3) {
|
||||||
ack = RXRPC_ACK_NOSPACE;
|
ack = RXRPC_ACK_NOSPACE;
|
||||||
ack_serial = serial;
|
ack_serial = serial;
|
||||||
goto ack;
|
goto ack;
|
||||||
}
|
}
|
||||||
annotation = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next_subpacket:
|
for (j = 0; j < sp->nr_subpackets; j++) {
|
||||||
queued = false;
|
rxrpc_serial_t serial = sp->hdr.serial + j;
|
||||||
ix = seq & RXRPC_RXTX_BUFF_MASK;
|
rxrpc_seq_t seq = seq0 + j;
|
||||||
len = skb->len;
|
unsigned int ix = seq & RXRPC_RXTX_BUFF_MASK;
|
||||||
if (flags & RXRPC_JUMBO_PACKET)
|
bool terminal = (j == sp->nr_subpackets - 1);
|
||||||
len = RXRPC_JUMBO_DATALEN;
|
bool last = terminal && (sp->rx_flags & RXRPC_SKB_INCL_LAST);
|
||||||
|
u8 flags, annotation = j;
|
||||||
|
|
||||||
if (flags & RXRPC_LAST_PACKET) {
|
_proto("Rx DATA+%u %%%u { #%x t=%u l=%u }",
|
||||||
if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
|
j, serial, seq, terminal, last);
|
||||||
seq != call->rx_top) {
|
|
||||||
rxrpc_proto_abort("LSN", call, seq);
|
if (last) {
|
||||||
goto unlock;
|
if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
|
||||||
|
seq != call->rx_top) {
|
||||||
|
rxrpc_proto_abort("LSN", call, seq);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
|
||||||
|
after_eq(seq, call->rx_top)) {
|
||||||
|
rxrpc_proto_abort("LSA", call, seq);
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) &&
|
|
||||||
after_eq(seq, call->rx_top)) {
|
|
||||||
rxrpc_proto_abort("LSA", call, seq);
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
|
flags = 0;
|
||||||
if (before_eq(seq, hard_ack)) {
|
if (last)
|
||||||
ack = RXRPC_ACK_DUPLICATE;
|
flags |= RXRPC_LAST_PACKET;
|
||||||
ack_serial = serial;
|
if (!terminal)
|
||||||
goto skip;
|
flags |= RXRPC_JUMBO_PACKET;
|
||||||
}
|
if (test_bit(j, sp->rx_req_ack))
|
||||||
|
flags |= RXRPC_REQUEST_ACK;
|
||||||
|
trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
|
||||||
|
|
||||||
if (flags & RXRPC_REQUEST_ACK && !ack) {
|
if (before_eq(seq, hard_ack)) {
|
||||||
ack = RXRPC_ACK_REQUESTED;
|
|
||||||
ack_serial = serial;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (call->rxtx_buffer[ix]) {
|
|
||||||
rxrpc_input_dup_data(call, seq, annotation, &jumbo_bad);
|
|
||||||
if (ack != RXRPC_ACK_DUPLICATE) {
|
|
||||||
ack = RXRPC_ACK_DUPLICATE;
|
ack = RXRPC_ACK_DUPLICATE;
|
||||||
ack_serial = serial;
|
ack_serial = serial;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
immediate_ack = true;
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Queue the packet. We use a couple of memory barriers here as need
|
if (call->rxtx_buffer[ix]) {
|
||||||
* to make sure that rx_top is perceived to be set after the buffer
|
rxrpc_input_dup_data(call, seq, sp->nr_subpackets > 1,
|
||||||
* pointer and that the buffer pointer is set after the annotation and
|
&jumbo_bad);
|
||||||
* the skb data.
|
if (ack != RXRPC_ACK_DUPLICATE) {
|
||||||
*
|
ack = RXRPC_ACK_DUPLICATE;
|
||||||
* Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
|
ack_serial = serial;
|
||||||
* and also rxrpc_fill_out_ack().
|
}
|
||||||
*/
|
immediate_ack = true;
|
||||||
rxrpc_get_skb(skb, rxrpc_skb_rx_got);
|
continue;
|
||||||
call->rxtx_annotations[ix] = annotation;
|
|
||||||
smp_wmb();
|
|
||||||
call->rxtx_buffer[ix] = skb;
|
|
||||||
if (after(seq, call->rx_top)) {
|
|
||||||
smp_store_release(&call->rx_top, seq);
|
|
||||||
} else if (before(seq, call->rx_top)) {
|
|
||||||
/* Send an immediate ACK if we fill in a hole */
|
|
||||||
if (!ack) {
|
|
||||||
ack = RXRPC_ACK_DELAY;
|
|
||||||
ack_serial = serial;
|
|
||||||
}
|
}
|
||||||
immediate_ack = true;
|
|
||||||
}
|
|
||||||
if (flags & RXRPC_LAST_PACKET) {
|
|
||||||
set_bit(RXRPC_CALL_RX_LAST, &call->flags);
|
|
||||||
trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq);
|
|
||||||
} else {
|
|
||||||
trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq);
|
|
||||||
}
|
|
||||||
queued = true;
|
|
||||||
|
|
||||||
if (after_eq(seq, call->rx_expect_next)) {
|
|
||||||
if (after(seq, call->rx_expect_next)) {
|
|
||||||
_net("OOS %u > %u", seq, call->rx_expect_next);
|
|
||||||
ack = RXRPC_ACK_OUT_OF_SEQUENCE;
|
|
||||||
ack_serial = serial;
|
|
||||||
}
|
|
||||||
call->rx_expect_next = seq + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
skip:
|
|
||||||
offset += len;
|
|
||||||
if (flags & RXRPC_JUMBO_PACKET) {
|
|
||||||
if (skb_copy_bits(skb, offset, &flags, 1) < 0) {
|
|
||||||
rxrpc_proto_abort("XJF", call, seq);
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
offset += sizeof(struct rxrpc_jumbo_header);
|
|
||||||
seq++;
|
|
||||||
serial++;
|
|
||||||
annotation++;
|
|
||||||
if (flags & RXRPC_JUMBO_PACKET)
|
|
||||||
annotation |= RXRPC_RX_ANNO_JLAST;
|
|
||||||
if (after(seq, hard_ack + call->rx_winsize)) {
|
if (after(seq, hard_ack + call->rx_winsize)) {
|
||||||
ack = RXRPC_ACK_EXCEEDS_WINDOW;
|
ack = RXRPC_ACK_EXCEEDS_WINDOW;
|
||||||
ack_serial = serial;
|
ack_serial = serial;
|
||||||
if (!jumbo_bad) {
|
if (flags & RXRPC_JUMBO_PACKET) {
|
||||||
call->nr_jumbo_bad++;
|
if (!jumbo_bad) {
|
||||||
jumbo_bad = true;
|
call->nr_jumbo_bad++;
|
||||||
|
jumbo_bad = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
goto ack;
|
goto ack;
|
||||||
}
|
}
|
||||||
|
|
||||||
_proto("Rx DATA Jumbo %%%u", serial);
|
if (flags & RXRPC_REQUEST_ACK && !ack) {
|
||||||
goto next_subpacket;
|
ack = RXRPC_ACK_REQUESTED;
|
||||||
}
|
ack_serial = serial;
|
||||||
|
}
|
||||||
|
|
||||||
if (queued && flags & RXRPC_LAST_PACKET && !ack) {
|
/* Queue the packet. We use a couple of memory barriers here as need
|
||||||
ack = RXRPC_ACK_DELAY;
|
* to make sure that rx_top is perceived to be set after the buffer
|
||||||
ack_serial = serial;
|
* pointer and that the buffer pointer is set after the annotation and
|
||||||
|
* the skb data.
|
||||||
|
*
|
||||||
|
* Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window()
|
||||||
|
* and also rxrpc_fill_out_ack().
|
||||||
|
*/
|
||||||
|
if (!terminal)
|
||||||
|
rxrpc_get_skb(skb, rxrpc_skb_got);
|
||||||
|
call->rxtx_annotations[ix] = annotation;
|
||||||
|
smp_wmb();
|
||||||
|
call->rxtx_buffer[ix] = skb;
|
||||||
|
if (after(seq, call->rx_top)) {
|
||||||
|
smp_store_release(&call->rx_top, seq);
|
||||||
|
} else if (before(seq, call->rx_top)) {
|
||||||
|
/* Send an immediate ACK if we fill in a hole */
|
||||||
|
if (!ack) {
|
||||||
|
ack = RXRPC_ACK_DELAY;
|
||||||
|
ack_serial = serial;
|
||||||
|
}
|
||||||
|
immediate_ack = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terminal) {
|
||||||
|
/* From this point on, we're not allowed to touch the
|
||||||
|
* packet any longer as its ref now belongs to the Rx
|
||||||
|
* ring.
|
||||||
|
*/
|
||||||
|
skb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last) {
|
||||||
|
set_bit(RXRPC_CALL_RX_LAST, &call->flags);
|
||||||
|
if (!ack) {
|
||||||
|
ack = RXRPC_ACK_DELAY;
|
||||||
|
ack_serial = serial;
|
||||||
|
}
|
||||||
|
trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq);
|
||||||
|
} else {
|
||||||
|
trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (after_eq(seq, call->rx_expect_next)) {
|
||||||
|
if (after(seq, call->rx_expect_next)) {
|
||||||
|
_net("OOS %u > %u", seq, call->rx_expect_next);
|
||||||
|
ack = RXRPC_ACK_OUT_OF_SEQUENCE;
|
||||||
|
ack_serial = serial;
|
||||||
|
}
|
||||||
|
call->rx_expect_next = seq + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ack:
|
ack:
|
||||||
|
@ -606,13 +613,14 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
||||||
false, true,
|
false, true,
|
||||||
rxrpc_propose_ack_input_data);
|
rxrpc_propose_ack_input_data);
|
||||||
|
|
||||||
if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1) {
|
if (seq0 == READ_ONCE(call->rx_hard_ack) + 1) {
|
||||||
trace_rxrpc_notify_socket(call->debug_id, serial);
|
trace_rxrpc_notify_socket(call->debug_id, serial);
|
||||||
rxrpc_notify_socket(call);
|
rxrpc_notify_socket(call);
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
spin_unlock(&call->input_lock);
|
spin_unlock(&call->input_lock);
|
||||||
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
_leave(" [queued]");
|
_leave(" [queued]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,7 +1029,7 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
|
||||||
switch (sp->hdr.type) {
|
switch (sp->hdr.type) {
|
||||||
case RXRPC_PACKET_TYPE_DATA:
|
case RXRPC_PACKET_TYPE_DATA:
|
||||||
rxrpc_input_data(call, skb);
|
rxrpc_input_data(call, skb);
|
||||||
break;
|
goto no_free;
|
||||||
|
|
||||||
case RXRPC_PACKET_TYPE_ACK:
|
case RXRPC_PACKET_TYPE_ACK:
|
||||||
rxrpc_input_ack(call, skb);
|
rxrpc_input_ack(call, skb);
|
||||||
|
@ -1048,6 +1056,8 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
|
no_free:
|
||||||
_leave("");
|
_leave("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,7 +1119,7 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local,
|
||||||
skb_queue_tail(&local->event_queue, skb);
|
skb_queue_tail(&local->event_queue, skb);
|
||||||
rxrpc_queue_local(local);
|
rxrpc_queue_local(local);
|
||||||
} else {
|
} else {
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1124,7 +1134,7 @@ static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb)
|
||||||
skb_queue_tail(&local->reject_queue, skb);
|
skb_queue_tail(&local->reject_queue, skb);
|
||||||
rxrpc_queue_local(local);
|
rxrpc_queue_local(local);
|
||||||
} else {
|
} else {
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1188,7 +1198,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
|
||||||
if (skb->tstamp == 0)
|
if (skb->tstamp == 0)
|
||||||
skb->tstamp = ktime_get_real();
|
skb->tstamp = ktime_get_real();
|
||||||
|
|
||||||
rxrpc_new_skb(skb, rxrpc_skb_rx_received);
|
rxrpc_new_skb(skb, rxrpc_skb_received);
|
||||||
|
|
||||||
skb_pull(skb, sizeof(struct udphdr));
|
skb_pull(skb, sizeof(struct udphdr));
|
||||||
|
|
||||||
|
@ -1205,7 +1215,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
|
||||||
static int lose;
|
static int lose;
|
||||||
if ((lose++ & 7) == 7) {
|
if ((lose++ & 7) == 7) {
|
||||||
trace_rxrpc_rx_lose(sp);
|
trace_rxrpc_rx_lose(sp);
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_lost);
|
rxrpc_free_skb(skb, rxrpc_skb_lost);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1237,9 +1247,26 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
|
||||||
if (sp->hdr.callNumber == 0 ||
|
if (sp->hdr.callNumber == 0 ||
|
||||||
sp->hdr.seq == 0)
|
sp->hdr.seq == 0)
|
||||||
goto bad_message;
|
goto bad_message;
|
||||||
if (sp->hdr.flags & RXRPC_JUMBO_PACKET &&
|
if (!rxrpc_validate_data(skb))
|
||||||
!rxrpc_validate_jumbo(skb))
|
|
||||||
goto bad_message;
|
goto bad_message;
|
||||||
|
|
||||||
|
/* Unshare the packet so that it can be modified for in-place
|
||||||
|
* decryption.
|
||||||
|
*/
|
||||||
|
if (sp->hdr.securityIndex != 0) {
|
||||||
|
struct sk_buff *nskb = skb_unshare(skb, GFP_ATOMIC);
|
||||||
|
if (!nskb) {
|
||||||
|
rxrpc_eaten_skb(skb, rxrpc_skb_unshared_nomem);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nskb != skb) {
|
||||||
|
rxrpc_eaten_skb(skb, rxrpc_skb_received);
|
||||||
|
rxrpc_new_skb(skb, rxrpc_skb_unshared);
|
||||||
|
skb = nskb;
|
||||||
|
sp = rxrpc_skb(skb);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RXRPC_PACKET_TYPE_CHALLENGE:
|
case RXRPC_PACKET_TYPE_CHALLENGE:
|
||||||
|
@ -1373,11 +1400,14 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
|
||||||
mutex_unlock(&call->user_mutex);
|
mutex_unlock(&call->user_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Process a call packet; this either discards or passes on the ref
|
||||||
|
* elsewhere.
|
||||||
|
*/
|
||||||
rxrpc_input_call_packet(call, skb);
|
rxrpc_input_call_packet(call, skb);
|
||||||
goto discard;
|
goto out;
|
||||||
|
|
||||||
discard:
|
discard:
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
out:
|
out:
|
||||||
trace_rxrpc_rx_done(0, 0);
|
trace_rxrpc_rx_done(0, 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -90,7 +90,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local)
|
||||||
if (skb) {
|
if (skb) {
|
||||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||||
|
|
||||||
rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
|
rxrpc_see_skb(skb, rxrpc_skb_seen);
|
||||||
_debug("{%d},{%u}", local->debug_id, sp->hdr.type);
|
_debug("{%d},{%u}", local->debug_id, sp->hdr.type);
|
||||||
|
|
||||||
switch (sp->hdr.type) {
|
switch (sp->hdr.type) {
|
||||||
|
@ -108,7 +108,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
}
|
}
|
||||||
|
|
||||||
_leave("");
|
_leave("");
|
||||||
|
|
|
@ -426,11 +426,14 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local)
|
||||||
|
|
||||||
_enter("%d", local->debug_id);
|
_enter("%d", local->debug_id);
|
||||||
|
|
||||||
|
local->dead = true;
|
||||||
|
|
||||||
mutex_lock(&rxnet->local_mutex);
|
mutex_lock(&rxnet->local_mutex);
|
||||||
list_del_init(&local->link);
|
list_del_init(&local->link);
|
||||||
mutex_unlock(&rxnet->local_mutex);
|
mutex_unlock(&rxnet->local_mutex);
|
||||||
|
|
||||||
ASSERT(RB_EMPTY_ROOT(&local->client_conns));
|
rxrpc_clean_up_local_conns(local);
|
||||||
|
rxrpc_service_connection_reaper(&rxnet->service_conn_reaper);
|
||||||
ASSERT(!local->service);
|
ASSERT(!local->service);
|
||||||
|
|
||||||
if (socket) {
|
if (socket) {
|
||||||
|
|
|
@ -565,7 +565,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
|
||||||
memset(&whdr, 0, sizeof(whdr));
|
memset(&whdr, 0, sizeof(whdr));
|
||||||
|
|
||||||
while ((skb = skb_dequeue(&local->reject_queue))) {
|
while ((skb = skb_dequeue(&local->reject_queue))) {
|
||||||
rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
|
rxrpc_see_skb(skb, rxrpc_skb_seen);
|
||||||
sp = rxrpc_skb(skb);
|
sp = rxrpc_skb(skb);
|
||||||
|
|
||||||
switch (skb->mark) {
|
switch (skb->mark) {
|
||||||
|
@ -581,7 +581,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
|
||||||
ioc = 2;
|
ioc = 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,7 +606,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
|
||||||
rxrpc_tx_point_reject);
|
rxrpc_tx_point_reject);
|
||||||
}
|
}
|
||||||
|
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
}
|
}
|
||||||
|
|
||||||
_leave("");
|
_leave("");
|
||||||
|
|
|
@ -163,11 +163,11 @@ void rxrpc_error_report(struct sock *sk)
|
||||||
_leave("UDP socket errqueue empty");
|
_leave("UDP socket errqueue empty");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rxrpc_new_skb(skb, rxrpc_skb_rx_received);
|
rxrpc_new_skb(skb, rxrpc_skb_received);
|
||||||
serr = SKB_EXT_ERR(skb);
|
serr = SKB_EXT_ERR(skb);
|
||||||
if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) {
|
if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) {
|
||||||
_leave("UDP empty message");
|
_leave("UDP empty message");
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ void rxrpc_error_report(struct sock *sk)
|
||||||
peer = NULL;
|
peer = NULL;
|
||||||
if (!peer) {
|
if (!peer) {
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
_leave(" [no peer]");
|
_leave(" [no peer]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ void rxrpc_error_report(struct sock *sk)
|
||||||
serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
|
serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
|
||||||
rxrpc_adjust_mtu(peer, serr);
|
rxrpc_adjust_mtu(peer, serr);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
rxrpc_put_peer(peer);
|
rxrpc_put_peer(peer);
|
||||||
_leave(" [MTU update]");
|
_leave(" [MTU update]");
|
||||||
return;
|
return;
|
||||||
|
@ -197,7 +197,7 @@ void rxrpc_error_report(struct sock *sk)
|
||||||
|
|
||||||
rxrpc_store_error(peer, serr);
|
rxrpc_store_error(peer, serr);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
rxrpc_put_peer(peer);
|
rxrpc_put_peer(peer);
|
||||||
|
|
||||||
_leave("");
|
_leave("");
|
||||||
|
|
|
@ -89,6 +89,15 @@ struct rxrpc_jumbo_header {
|
||||||
#define RXRPC_JUMBO_DATALEN 1412 /* non-terminal jumbo packet data length */
|
#define RXRPC_JUMBO_DATALEN 1412 /* non-terminal jumbo packet data length */
|
||||||
#define RXRPC_JUMBO_SUBPKTLEN (RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header))
|
#define RXRPC_JUMBO_SUBPKTLEN (RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The maximum number of subpackets that can possibly fit in a UDP packet is:
|
||||||
|
*
|
||||||
|
* ((max_IP - IP_hdr - UDP_hdr) / RXRPC_JUMBO_SUBPKTLEN) + 1
|
||||||
|
* = ((65535 - 28 - 28) / 1416) + 1
|
||||||
|
* = 46 non-terminal packets and 1 terminal packet.
|
||||||
|
*/
|
||||||
|
#define RXRPC_MAX_NR_JUMBO 47
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/*
|
/*
|
||||||
* on-the-wire Rx ACK packet data payload
|
* on-the-wire Rx ACK packet data payload
|
||||||
|
|
|
@ -177,7 +177,8 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
rxrpc_serial_t serial;
|
rxrpc_serial_t serial;
|
||||||
rxrpc_seq_t hard_ack, top;
|
rxrpc_seq_t hard_ack, top;
|
||||||
u8 flags;
|
bool last = false;
|
||||||
|
u8 subpacket;
|
||||||
int ix;
|
int ix;
|
||||||
|
|
||||||
_enter("%d", call->debug_id);
|
_enter("%d", call->debug_id);
|
||||||
|
@ -189,23 +190,25 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
|
||||||
hard_ack++;
|
hard_ack++;
|
||||||
ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
|
ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
|
||||||
skb = call->rxtx_buffer[ix];
|
skb = call->rxtx_buffer[ix];
|
||||||
rxrpc_see_skb(skb, rxrpc_skb_rx_rotated);
|
rxrpc_see_skb(skb, rxrpc_skb_rotated);
|
||||||
sp = rxrpc_skb(skb);
|
sp = rxrpc_skb(skb);
|
||||||
flags = sp->hdr.flags;
|
|
||||||
serial = sp->hdr.serial;
|
subpacket = call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
|
||||||
if (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO)
|
serial = sp->hdr.serial + subpacket;
|
||||||
serial += (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO) - 1;
|
|
||||||
|
if (subpacket == sp->nr_subpackets - 1 &&
|
||||||
|
sp->rx_flags & RXRPC_SKB_INCL_LAST)
|
||||||
|
last = true;
|
||||||
|
|
||||||
call->rxtx_buffer[ix] = NULL;
|
call->rxtx_buffer[ix] = NULL;
|
||||||
call->rxtx_annotations[ix] = 0;
|
call->rxtx_annotations[ix] = 0;
|
||||||
/* Barrier against rxrpc_input_data(). */
|
/* Barrier against rxrpc_input_data(). */
|
||||||
smp_store_release(&call->rx_hard_ack, hard_ack);
|
smp_store_release(&call->rx_hard_ack, hard_ack);
|
||||||
|
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
|
|
||||||
_debug("%u,%u,%02x", hard_ack, top, flags);
|
|
||||||
trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
|
trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
|
||||||
if (flags & RXRPC_LAST_PACKET) {
|
if (last) {
|
||||||
rxrpc_end_rx_phase(call, serial);
|
rxrpc_end_rx_phase(call, serial);
|
||||||
} else {
|
} else {
|
||||||
/* Check to see if there's an ACK that needs sending. */
|
/* Check to see if there's an ACK that needs sending. */
|
||||||
|
@ -233,18 +236,19 @@ static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||||
rxrpc_seq_t seq = sp->hdr.seq;
|
rxrpc_seq_t seq = sp->hdr.seq;
|
||||||
u16 cksum = sp->hdr.cksum;
|
u16 cksum = sp->hdr.cksum;
|
||||||
|
u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
|
||||||
|
|
||||||
_enter("");
|
_enter("");
|
||||||
|
|
||||||
/* For all but the head jumbo subpacket, the security checksum is in a
|
/* For all but the head jumbo subpacket, the security checksum is in a
|
||||||
* jumbo header immediately prior to the data.
|
* jumbo header immediately prior to the data.
|
||||||
*/
|
*/
|
||||||
if ((annotation & RXRPC_RX_ANNO_JUMBO) > 1) {
|
if (subpacket > 0) {
|
||||||
__be16 tmp;
|
__be16 tmp;
|
||||||
if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0)
|
if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0)
|
||||||
BUG();
|
BUG();
|
||||||
cksum = ntohs(tmp);
|
cksum = ntohs(tmp);
|
||||||
seq += (annotation & RXRPC_RX_ANNO_JUMBO) - 1;
|
seq += subpacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
return call->conn->security->verify_packet(call, skb, offset, len,
|
return call->conn->security->verify_packet(call, skb, offset, len,
|
||||||
|
@ -265,19 +269,18 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
u8 *_annotation,
|
u8 *_annotation,
|
||||||
unsigned int *_offset, unsigned int *_len)
|
unsigned int *_offset, unsigned int *_len)
|
||||||
{
|
{
|
||||||
|
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||||
unsigned int offset = sizeof(struct rxrpc_wire_header);
|
unsigned int offset = sizeof(struct rxrpc_wire_header);
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
int ret;
|
int ret;
|
||||||
u8 annotation = *_annotation;
|
u8 annotation = *_annotation;
|
||||||
|
u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET;
|
||||||
|
|
||||||
/* Locate the subpacket */
|
/* Locate the subpacket */
|
||||||
|
offset += subpacket * RXRPC_JUMBO_SUBPKTLEN;
|
||||||
len = skb->len - offset;
|
len = skb->len - offset;
|
||||||
if ((annotation & RXRPC_RX_ANNO_JUMBO) > 0) {
|
if (subpacket < sp->nr_subpackets - 1)
|
||||||
offset += (((annotation & RXRPC_RX_ANNO_JUMBO) - 1) *
|
len = RXRPC_JUMBO_DATALEN;
|
||||||
RXRPC_JUMBO_SUBPKTLEN);
|
|
||||||
len = (annotation & RXRPC_RX_ANNO_JLAST) ?
|
|
||||||
skb->len - offset : RXRPC_JUMBO_SUBPKTLEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) {
|
if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) {
|
||||||
ret = rxrpc_verify_packet(call, skb, annotation, offset, len);
|
ret = rxrpc_verify_packet(call, skb, annotation, offset, len);
|
||||||
|
@ -303,6 +306,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
|
||||||
{
|
{
|
||||||
struct rxrpc_skb_priv *sp;
|
struct rxrpc_skb_priv *sp;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
rxrpc_serial_t serial;
|
||||||
rxrpc_seq_t hard_ack, top, seq;
|
rxrpc_seq_t hard_ack, top, seq;
|
||||||
size_t remain;
|
size_t remain;
|
||||||
bool last;
|
bool last;
|
||||||
|
@ -336,12 +340,15 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
smp_rmb();
|
smp_rmb();
|
||||||
rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
|
rxrpc_see_skb(skb, rxrpc_skb_seen);
|
||||||
sp = rxrpc_skb(skb);
|
sp = rxrpc_skb(skb);
|
||||||
|
|
||||||
if (!(flags & MSG_PEEK))
|
if (!(flags & MSG_PEEK)) {
|
||||||
|
serial = sp->hdr.serial;
|
||||||
|
serial += call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET;
|
||||||
trace_rxrpc_receive(call, rxrpc_receive_front,
|
trace_rxrpc_receive(call, rxrpc_receive_front,
|
||||||
sp->hdr.serial, seq);
|
serial, seq);
|
||||||
|
}
|
||||||
|
|
||||||
if (msg)
|
if (msg)
|
||||||
sock_recv_timestamp(msg, sock->sk, skb);
|
sock_recv_timestamp(msg, sock->sk, skb);
|
||||||
|
|
|
@ -187,10 +187,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
|
||||||
struct rxrpc_skb_priv *sp;
|
struct rxrpc_skb_priv *sp;
|
||||||
struct rxrpc_crypt iv;
|
struct rxrpc_crypt iv;
|
||||||
struct scatterlist sg[16];
|
struct scatterlist sg[16];
|
||||||
struct sk_buff *trailer;
|
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
u16 check;
|
u16 check;
|
||||||
int nsg;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
sp = rxrpc_skb(skb);
|
sp = rxrpc_skb(skb);
|
||||||
|
@ -214,15 +212,14 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
|
||||||
crypto_skcipher_encrypt(req);
|
crypto_skcipher_encrypt(req);
|
||||||
|
|
||||||
/* we want to encrypt the skbuff in-place */
|
/* we want to encrypt the skbuff in-place */
|
||||||
nsg = skb_cow_data(skb, 0, &trailer);
|
err = -EMSGSIZE;
|
||||||
err = -ENOMEM;
|
if (skb_shinfo(skb)->nr_frags > 16)
|
||||||
if (nsg < 0 || nsg > 16)
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
len = data_size + call->conn->size_align - 1;
|
len = data_size + call->conn->size_align - 1;
|
||||||
len &= ~(call->conn->size_align - 1);
|
len &= ~(call->conn->size_align - 1);
|
||||||
|
|
||||||
sg_init_table(sg, nsg);
|
sg_init_table(sg, ARRAY_SIZE(sg));
|
||||||
err = skb_to_sgvec(skb, sg, 0, len);
|
err = skb_to_sgvec(skb, sg, 0, len);
|
||||||
if (unlikely(err < 0))
|
if (unlikely(err < 0))
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -319,11 +316,10 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
struct rxkad_level1_hdr sechdr;
|
struct rxkad_level1_hdr sechdr;
|
||||||
struct rxrpc_crypt iv;
|
struct rxrpc_crypt iv;
|
||||||
struct scatterlist sg[16];
|
struct scatterlist sg[16];
|
||||||
struct sk_buff *trailer;
|
|
||||||
bool aborted;
|
bool aborted;
|
||||||
u32 data_size, buf;
|
u32 data_size, buf;
|
||||||
u16 check;
|
u16 check;
|
||||||
int nsg, ret;
|
int ret;
|
||||||
|
|
||||||
_enter("");
|
_enter("");
|
||||||
|
|
||||||
|
@ -336,11 +332,7 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
/* Decrypt the skbuff in-place. TODO: We really want to decrypt
|
/* Decrypt the skbuff in-place. TODO: We really want to decrypt
|
||||||
* directly into the target buffer.
|
* directly into the target buffer.
|
||||||
*/
|
*/
|
||||||
nsg = skb_cow_data(skb, 0, &trailer);
|
sg_init_table(sg, ARRAY_SIZE(sg));
|
||||||
if (nsg < 0 || nsg > 16)
|
|
||||||
goto nomem;
|
|
||||||
|
|
||||||
sg_init_table(sg, nsg);
|
|
||||||
ret = skb_to_sgvec(skb, sg, offset, 8);
|
ret = skb_to_sgvec(skb, sg, offset, 8);
|
||||||
if (unlikely(ret < 0))
|
if (unlikely(ret < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -388,10 +380,6 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
if (aborted)
|
if (aborted)
|
||||||
rxrpc_send_abort_packet(call);
|
rxrpc_send_abort_packet(call);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
|
|
||||||
nomem:
|
|
||||||
_leave(" = -ENOMEM");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -406,7 +394,6 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
struct rxkad_level2_hdr sechdr;
|
struct rxkad_level2_hdr sechdr;
|
||||||
struct rxrpc_crypt iv;
|
struct rxrpc_crypt iv;
|
||||||
struct scatterlist _sg[4], *sg;
|
struct scatterlist _sg[4], *sg;
|
||||||
struct sk_buff *trailer;
|
|
||||||
bool aborted;
|
bool aborted;
|
||||||
u32 data_size, buf;
|
u32 data_size, buf;
|
||||||
u16 check;
|
u16 check;
|
||||||
|
@ -423,12 +410,11 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
|
||||||
/* Decrypt the skbuff in-place. TODO: We really want to decrypt
|
/* Decrypt the skbuff in-place. TODO: We really want to decrypt
|
||||||
* directly into the target buffer.
|
* directly into the target buffer.
|
||||||
*/
|
*/
|
||||||
nsg = skb_cow_data(skb, 0, &trailer);
|
|
||||||
if (nsg < 0)
|
|
||||||
goto nomem;
|
|
||||||
|
|
||||||
sg = _sg;
|
sg = _sg;
|
||||||
if (unlikely(nsg > 4)) {
|
nsg = skb_shinfo(skb)->nr_frags;
|
||||||
|
if (nsg <= 4) {
|
||||||
|
nsg = 4;
|
||||||
|
} else {
|
||||||
sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO);
|
sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO);
|
||||||
if (!sg)
|
if (!sg)
|
||||||
goto nomem;
|
goto nomem;
|
||||||
|
|
|
@ -176,7 +176,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
|
||||||
skb->tstamp = ktime_get_real();
|
skb->tstamp = ktime_get_real();
|
||||||
|
|
||||||
ix = seq & RXRPC_RXTX_BUFF_MASK;
|
ix = seq & RXRPC_RXTX_BUFF_MASK;
|
||||||
rxrpc_get_skb(skb, rxrpc_skb_tx_got);
|
rxrpc_get_skb(skb, rxrpc_skb_got);
|
||||||
call->rxtx_annotations[ix] = annotation;
|
call->rxtx_annotations[ix] = annotation;
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
call->rxtx_buffer[ix] = skb;
|
call->rxtx_buffer[ix] = skb;
|
||||||
|
@ -248,7 +248,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
_leave(" = %d", ret);
|
_leave(" = %d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
|
||||||
|
|
||||||
skb = call->tx_pending;
|
skb = call->tx_pending;
|
||||||
call->tx_pending = NULL;
|
call->tx_pending = NULL;
|
||||||
rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
|
rxrpc_see_skb(skb, rxrpc_skb_seen);
|
||||||
|
|
||||||
copied = 0;
|
copied = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -336,7 +336,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
|
||||||
if (!skb)
|
if (!skb)
|
||||||
goto maybe_error;
|
goto maybe_error;
|
||||||
|
|
||||||
rxrpc_new_skb(skb, rxrpc_skb_tx_new);
|
sp = rxrpc_skb(skb);
|
||||||
|
sp->rx_flags |= RXRPC_SKB_TX_BUFFER;
|
||||||
|
rxrpc_new_skb(skb, rxrpc_skb_new);
|
||||||
|
|
||||||
_debug("ALLOC SEND %p", skb);
|
_debug("ALLOC SEND %p", skb);
|
||||||
|
|
||||||
|
@ -346,7 +348,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
|
||||||
skb_reserve(skb, call->conn->security_size);
|
skb_reserve(skb, call->conn->security_size);
|
||||||
skb->len += call->conn->security_size;
|
skb->len += call->conn->security_size;
|
||||||
|
|
||||||
sp = rxrpc_skb(skb);
|
|
||||||
sp->remain = chunk;
|
sp->remain = chunk;
|
||||||
if (sp->remain > skb_tailroom(skb))
|
if (sp->remain > skb_tailroom(skb))
|
||||||
sp->remain = skb_tailroom(skb);
|
sp->remain = skb_tailroom(skb);
|
||||||
|
@ -439,7 +440,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
call_terminated:
|
call_terminated:
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_freed);
|
||||||
_leave(" = %d", call->error);
|
_leave(" = %d", call->error);
|
||||||
return call->error;
|
return call->error;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
#include <net/af_rxrpc.h>
|
#include <net/af_rxrpc.h>
|
||||||
#include "ar-internal.h"
|
#include "ar-internal.h"
|
||||||
|
|
||||||
#define select_skb_count(op) (op >= rxrpc_skb_tx_cleaned ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
|
#define is_tx_skb(skb) (rxrpc_skb(skb)->rx_flags & RXRPC_SKB_TX_BUFFER)
|
||||||
|
#define select_skb_count(skb) (is_tx_skb(skb) ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note the allocation or reception of a socket buffer.
|
* Note the allocation or reception of a socket buffer.
|
||||||
|
@ -22,8 +23,9 @@
|
||||||
void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
|
void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
|
||||||
{
|
{
|
||||||
const void *here = __builtin_return_address(0);
|
const void *here = __builtin_return_address(0);
|
||||||
int n = atomic_inc_return(select_skb_count(op));
|
int n = atomic_inc_return(select_skb_count(skb));
|
||||||
trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
|
trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
|
||||||
|
rxrpc_skb(skb)->rx_flags, here);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -33,8 +35,9 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
|
||||||
{
|
{
|
||||||
const void *here = __builtin_return_address(0);
|
const void *here = __builtin_return_address(0);
|
||||||
if (skb) {
|
if (skb) {
|
||||||
int n = atomic_read(select_skb_count(op));
|
int n = atomic_read(select_skb_count(skb));
|
||||||
trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
|
trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
|
||||||
|
rxrpc_skb(skb)->rx_flags, here);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,11 +47,22 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
|
||||||
void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
|
void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
|
||||||
{
|
{
|
||||||
const void *here = __builtin_return_address(0);
|
const void *here = __builtin_return_address(0);
|
||||||
int n = atomic_inc_return(select_skb_count(op));
|
int n = atomic_inc_return(select_skb_count(skb));
|
||||||
trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
|
trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
|
||||||
|
rxrpc_skb(skb)->rx_flags, here);
|
||||||
skb_get(skb);
|
skb_get(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note the dropping of a ref on a socket buffer by the core.
|
||||||
|
*/
|
||||||
|
void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
|
||||||
|
{
|
||||||
|
const void *here = __builtin_return_address(0);
|
||||||
|
int n = atomic_inc_return(&rxrpc_n_rx_skbs);
|
||||||
|
trace_rxrpc_skb(skb, op, 0, n, 0, here);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note the destruction of a socket buffer.
|
* Note the destruction of a socket buffer.
|
||||||
*/
|
*/
|
||||||
|
@ -58,8 +72,9 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
|
||||||
if (skb) {
|
if (skb) {
|
||||||
int n;
|
int n;
|
||||||
CHECK_SLAB_OKAY(&skb->users);
|
CHECK_SLAB_OKAY(&skb->users);
|
||||||
n = atomic_dec_return(select_skb_count(op));
|
n = atomic_dec_return(select_skb_count(skb));
|
||||||
trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
|
trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n,
|
||||||
|
rxrpc_skb(skb)->rx_flags, here);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,9 +87,10 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
|
||||||
const void *here = __builtin_return_address(0);
|
const void *here = __builtin_return_address(0);
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
while ((skb = skb_dequeue((list))) != NULL) {
|
while ((skb = skb_dequeue((list))) != NULL) {
|
||||||
int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged));
|
int n = atomic_dec_return(select_skb_count(skb));
|
||||||
trace_rxrpc_skb(skb, rxrpc_skb_rx_purged,
|
trace_rxrpc_skb(skb, rxrpc_skb_purged,
|
||||||
refcount_read(&skb->users), n, here);
|
refcount_read(&skb->users), n,
|
||||||
|
rxrpc_skb(skb)->rx_flags, here);
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -422,7 +422,7 @@ static __net_init int bpf_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, bpf_net_id);
|
struct tc_action_net *tn = net_generic(net, bpf_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_bpf_ops);
|
return tc_action_net_init(net, tn, &act_bpf_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit bpf_exit_net(struct list_head *net_list)
|
static void __net_exit bpf_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -231,7 +231,7 @@ static __net_init int connmark_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, connmark_net_id);
|
struct tc_action_net *tn = net_generic(net, connmark_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_connmark_ops);
|
return tc_action_net_init(net, tn, &act_connmark_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit connmark_exit_net(struct list_head *net_list)
|
static void __net_exit connmark_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -714,7 +714,7 @@ static __net_init int csum_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, csum_net_id);
|
struct tc_action_net *tn = net_generic(net, csum_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_csum_ops);
|
return tc_action_net_init(net, tn, &act_csum_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit csum_exit_net(struct list_head *net_list)
|
static void __net_exit csum_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -939,7 +939,7 @@ static __net_init int ct_init_net(struct net *net)
|
||||||
tn->labels = true;
|
tn->labels = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tc_action_net_init(&tn->tn, &act_ct_ops);
|
return tc_action_net_init(net, &tn->tn, &act_ct_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit ct_exit_net(struct list_head *net_list)
|
static void __net_exit ct_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -376,7 +376,7 @@ static __net_init int ctinfo_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
|
struct tc_action_net *tn = net_generic(net, ctinfo_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_ctinfo_ops);
|
return tc_action_net_init(net, tn, &act_ctinfo_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit ctinfo_exit_net(struct list_head *net_list)
|
static void __net_exit ctinfo_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -278,7 +278,7 @@ static __net_init int gact_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, gact_net_id);
|
struct tc_action_net *tn = net_generic(net, gact_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_gact_ops);
|
return tc_action_net_init(net, tn, &act_gact_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit gact_exit_net(struct list_head *net_list)
|
static void __net_exit gact_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -890,7 +890,7 @@ static __net_init int ife_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, ife_net_id);
|
struct tc_action_net *tn = net_generic(net, ife_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_ife_ops);
|
return tc_action_net_init(net, tn, &act_ife_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit ife_exit_net(struct list_head *net_list)
|
static void __net_exit ife_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -61,12 +61,13 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ipt_destroy_target(struct xt_entry_target *t)
|
static void ipt_destroy_target(struct xt_entry_target *t, struct net *net)
|
||||||
{
|
{
|
||||||
struct xt_tgdtor_param par = {
|
struct xt_tgdtor_param par = {
|
||||||
.target = t->u.kernel.target,
|
.target = t->u.kernel.target,
|
||||||
.targinfo = t->data,
|
.targinfo = t->data,
|
||||||
.family = NFPROTO_IPV4,
|
.family = NFPROTO_IPV4,
|
||||||
|
.net = net,
|
||||||
};
|
};
|
||||||
if (par.target->destroy != NULL)
|
if (par.target->destroy != NULL)
|
||||||
par.target->destroy(&par);
|
par.target->destroy(&par);
|
||||||
|
@ -78,7 +79,7 @@ static void tcf_ipt_release(struct tc_action *a)
|
||||||
struct tcf_ipt *ipt = to_ipt(a);
|
struct tcf_ipt *ipt = to_ipt(a);
|
||||||
|
|
||||||
if (ipt->tcfi_t) {
|
if (ipt->tcfi_t) {
|
||||||
ipt_destroy_target(ipt->tcfi_t);
|
ipt_destroy_target(ipt->tcfi_t, a->idrinfo->net);
|
||||||
kfree(ipt->tcfi_t);
|
kfree(ipt->tcfi_t);
|
||||||
}
|
}
|
||||||
kfree(ipt->tcfi_tname);
|
kfree(ipt->tcfi_tname);
|
||||||
|
@ -180,7 +181,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
|
||||||
|
|
||||||
spin_lock_bh(&ipt->tcf_lock);
|
spin_lock_bh(&ipt->tcf_lock);
|
||||||
if (ret != ACT_P_CREATED) {
|
if (ret != ACT_P_CREATED) {
|
||||||
ipt_destroy_target(ipt->tcfi_t);
|
ipt_destroy_target(ipt->tcfi_t, net);
|
||||||
kfree(ipt->tcfi_tname);
|
kfree(ipt->tcfi_tname);
|
||||||
kfree(ipt->tcfi_t);
|
kfree(ipt->tcfi_t);
|
||||||
}
|
}
|
||||||
|
@ -350,7 +351,7 @@ static __net_init int ipt_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, ipt_net_id);
|
struct tc_action_net *tn = net_generic(net, ipt_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_ipt_ops);
|
return tc_action_net_init(net, tn, &act_ipt_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit ipt_exit_net(struct list_head *net_list)
|
static void __net_exit ipt_exit_net(struct list_head *net_list)
|
||||||
|
@ -399,7 +400,7 @@ static __net_init int xt_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, xt_net_id);
|
struct tc_action_net *tn = net_generic(net, xt_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_xt_ops);
|
return tc_action_net_init(net, tn, &act_xt_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit xt_exit_net(struct list_head *net_list)
|
static void __net_exit xt_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -453,7 +453,7 @@ static __net_init int mirred_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, mirred_net_id);
|
struct tc_action_net *tn = net_generic(net, mirred_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_mirred_ops);
|
return tc_action_net_init(net, tn, &act_mirred_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit mirred_exit_net(struct list_head *net_list)
|
static void __net_exit mirred_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -375,7 +375,7 @@ static __net_init int mpls_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, mpls_net_id);
|
struct tc_action_net *tn = net_generic(net, mpls_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_mpls_ops);
|
return tc_action_net_init(net, tn, &act_mpls_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit mpls_exit_net(struct list_head *net_list)
|
static void __net_exit mpls_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -327,7 +327,7 @@ static __net_init int nat_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, nat_net_id);
|
struct tc_action_net *tn = net_generic(net, nat_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_nat_ops);
|
return tc_action_net_init(net, tn, &act_nat_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit nat_exit_net(struct list_head *net_list)
|
static void __net_exit nat_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -498,7 +498,7 @@ static __net_init int pedit_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, pedit_net_id);
|
struct tc_action_net *tn = net_generic(net, pedit_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_pedit_ops);
|
return tc_action_net_init(net, tn, &act_pedit_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit pedit_exit_net(struct list_head *net_list)
|
static void __net_exit pedit_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -371,7 +371,7 @@ static __net_init int police_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, police_net_id);
|
struct tc_action_net *tn = net_generic(net, police_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_police_ops);
|
return tc_action_net_init(net, tn, &act_police_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit police_exit_net(struct list_head *net_list)
|
static void __net_exit police_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -102,13 +102,17 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
|
||||||
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
|
goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
|
||||||
s->rate = rate;
|
s->rate = rate;
|
||||||
s->psample_group_num = psample_group_num;
|
s->psample_group_num = psample_group_num;
|
||||||
RCU_INIT_POINTER(s->psample_group, psample_group);
|
rcu_swap_protected(s->psample_group, psample_group,
|
||||||
|
lockdep_is_held(&s->tcf_lock));
|
||||||
|
|
||||||
if (tb[TCA_SAMPLE_TRUNC_SIZE]) {
|
if (tb[TCA_SAMPLE_TRUNC_SIZE]) {
|
||||||
s->truncate = true;
|
s->truncate = true;
|
||||||
s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]);
|
s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]);
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&s->tcf_lock);
|
spin_unlock_bh(&s->tcf_lock);
|
||||||
|
|
||||||
|
if (psample_group)
|
||||||
|
psample_group_put(psample_group);
|
||||||
if (goto_ch)
|
if (goto_ch)
|
||||||
tcf_chain_put_by_act(goto_ch);
|
tcf_chain_put_by_act(goto_ch);
|
||||||
|
|
||||||
|
@ -265,7 +269,7 @@ static __net_init int sample_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, sample_net_id);
|
struct tc_action_net *tn = net_generic(net, sample_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_sample_ops);
|
return tc_action_net_init(net, tn, &act_sample_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit sample_exit_net(struct list_head *net_list)
|
static void __net_exit sample_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -232,7 +232,7 @@ static __net_init int simp_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, simp_net_id);
|
struct tc_action_net *tn = net_generic(net, simp_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_simp_ops);
|
return tc_action_net_init(net, tn, &act_simp_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit simp_exit_net(struct list_head *net_list)
|
static void __net_exit simp_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -336,7 +336,7 @@ static __net_init int skbedit_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
|
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_skbedit_ops);
|
return tc_action_net_init(net, tn, &act_skbedit_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit skbedit_exit_net(struct list_head *net_list)
|
static void __net_exit skbedit_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -287,7 +287,7 @@ static __net_init int skbmod_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, skbmod_net_id);
|
struct tc_action_net *tn = net_generic(net, skbmod_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_skbmod_ops);
|
return tc_action_net_init(net, tn, &act_skbmod_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit skbmod_exit_net(struct list_head *net_list)
|
static void __net_exit skbmod_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -600,7 +600,7 @@ static __net_init int tunnel_key_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
|
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_tunnel_key_ops);
|
return tc_action_net_init(net, tn, &act_tunnel_key_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit tunnel_key_exit_net(struct list_head *net_list)
|
static void __net_exit tunnel_key_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -334,7 +334,7 @@ static __net_init int vlan_init_net(struct net *net)
|
||||||
{
|
{
|
||||||
struct tc_action_net *tn = net_generic(net, vlan_net_id);
|
struct tc_action_net *tn = net_generic(net, vlan_net_id);
|
||||||
|
|
||||||
return tc_action_net_init(tn, &act_vlan_ops);
|
return tc_action_net_init(net, tn, &act_vlan_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __net_exit vlan_exit_net(struct list_head *net_list)
|
static void __net_exit vlan_exit_net(struct list_head *net_list)
|
||||||
|
|
|
@ -181,11 +181,6 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch)
|
||||||
s64 credits;
|
s64 credits;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (atomic64_read(&q->port_rate) == -1) {
|
|
||||||
WARN_ONCE(1, "cbs: dequeue() called with unknown port rate.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (q->credits < 0) {
|
if (q->credits < 0) {
|
||||||
credits = timediff_to_credits(now - q->last, q->idleslope);
|
credits = timediff_to_credits(now - q->last, q->idleslope);
|
||||||
|
|
||||||
|
@ -303,11 +298,19 @@ static int cbs_enable_offload(struct net_device *dev, struct cbs_sched_data *q,
|
||||||
static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q)
|
static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q)
|
||||||
{
|
{
|
||||||
struct ethtool_link_ksettings ecmd;
|
struct ethtool_link_ksettings ecmd;
|
||||||
|
int speed = SPEED_10;
|
||||||
int port_rate = -1;
|
int port_rate = -1;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
|
err = __ethtool_get_link_ksettings(dev, &ecmd);
|
||||||
ecmd.base.speed != SPEED_UNKNOWN)
|
if (err < 0)
|
||||||
port_rate = ecmd.base.speed * 1000 * BYTES_PER_KBIT;
|
goto skip;
|
||||||
|
|
||||||
|
if (ecmd.base.speed != SPEED_UNKNOWN)
|
||||||
|
speed = ecmd.base.speed;
|
||||||
|
|
||||||
|
skip:
|
||||||
|
port_rate = speed * 1000 * BYTES_PER_KBIT;
|
||||||
|
|
||||||
atomic64_set(&q->port_rate, port_rate);
|
atomic64_set(&q->port_rate, port_rate);
|
||||||
netdev_dbg(dev, "cbs: set %s's port_rate to: %lld, linkspeed: %d\n",
|
netdev_dbg(dev, "cbs: set %s's port_rate to: %lld, linkspeed: %d\n",
|
||||||
|
|
|
@ -624,8 +624,12 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc,
|
||||||
|
|
||||||
err = skb_array_produce(q, skb);
|
err = skb_array_produce(q, skb);
|
||||||
|
|
||||||
if (unlikely(err))
|
if (unlikely(err)) {
|
||||||
return qdisc_drop_cpu(skb, qdisc, to_free);
|
if (qdisc_is_percpu_stats(qdisc))
|
||||||
|
return qdisc_drop_cpu(skb, qdisc, to_free);
|
||||||
|
else
|
||||||
|
return qdisc_drop(skb, qdisc, to_free);
|
||||||
|
}
|
||||||
|
|
||||||
qdisc_update_stats_at_enqueue(qdisc, pkt_len);
|
qdisc_update_stats_at_enqueue(qdisc, pkt_len);
|
||||||
return NET_XMIT_SUCCESS;
|
return NET_XMIT_SUCCESS;
|
||||||
|
@ -688,11 +692,14 @@ static void pfifo_fast_reset(struct Qdisc *qdisc)
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
for_each_possible_cpu(i) {
|
if (qdisc_is_percpu_stats(qdisc)) {
|
||||||
struct gnet_stats_queue *q = per_cpu_ptr(qdisc->cpu_qstats, i);
|
for_each_possible_cpu(i) {
|
||||||
|
struct gnet_stats_queue *q;
|
||||||
|
|
||||||
q->backlog = 0;
|
q = per_cpu_ptr(qdisc->cpu_qstats, i);
|
||||||
q->qlen = 0;
|
q->backlog = 0;
|
||||||
|
q->qlen = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -477,11 +477,6 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
|
||||||
u32 gate_mask;
|
u32 gate_mask;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (atomic64_read(&q->picos_per_byte) == -1) {
|
|
||||||
WARN_ONCE(1, "taprio: dequeue() called with unknown picos per byte.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
entry = rcu_dereference(q->current_entry);
|
entry = rcu_dereference(q->current_entry);
|
||||||
/* if there's no entry, it means that the schedule didn't
|
/* if there's no entry, it means that the schedule didn't
|
||||||
|
@ -958,12 +953,20 @@ static void taprio_set_picos_per_byte(struct net_device *dev,
|
||||||
struct taprio_sched *q)
|
struct taprio_sched *q)
|
||||||
{
|
{
|
||||||
struct ethtool_link_ksettings ecmd;
|
struct ethtool_link_ksettings ecmd;
|
||||||
int picos_per_byte = -1;
|
int speed = SPEED_10;
|
||||||
|
int picos_per_byte;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (!__ethtool_get_link_ksettings(dev, &ecmd) &&
|
err = __ethtool_get_link_ksettings(dev, &ecmd);
|
||||||
ecmd.base.speed != SPEED_UNKNOWN)
|
if (err < 0)
|
||||||
picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
|
goto skip;
|
||||||
ecmd.base.speed * 1000 * 1000);
|
|
||||||
|
if (ecmd.base.speed != SPEED_UNKNOWN)
|
||||||
|
speed = ecmd.base.speed;
|
||||||
|
|
||||||
|
skip:
|
||||||
|
picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
|
||||||
|
speed * 1000 * 1000);
|
||||||
|
|
||||||
atomic64_set(&q->picos_per_byte, picos_per_byte);
|
atomic64_set(&q->picos_per_byte, picos_per_byte);
|
||||||
netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n",
|
netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n",
|
||||||
|
@ -1249,6 +1252,10 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt,
|
||||||
*/
|
*/
|
||||||
q->clockid = -1;
|
q->clockid = -1;
|
||||||
|
|
||||||
|
spin_lock(&taprio_list_lock);
|
||||||
|
list_add(&q->taprio_list, &taprio_list);
|
||||||
|
spin_unlock(&taprio_list_lock);
|
||||||
|
|
||||||
if (sch->parent != TC_H_ROOT)
|
if (sch->parent != TC_H_ROOT)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
@ -1266,10 +1273,6 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt,
|
||||||
if (!opt)
|
if (!opt)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock(&taprio_list_lock);
|
|
||||||
list_add(&q->taprio_list, &taprio_list);
|
|
||||||
spin_unlock(&taprio_list_lock);
|
|
||||||
|
|
||||||
for (i = 0; i < dev->num_tx_queues; i++) {
|
for (i = 0; i < dev->num_tx_queues; i++) {
|
||||||
struct netdev_queue *dev_queue;
|
struct netdev_queue *dev_queue;
|
||||||
struct Qdisc *qdisc;
|
struct Qdisc *qdisc;
|
||||||
|
|
|
@ -64,7 +64,7 @@ class SubPlugin(TdcPlugin):
|
||||||
cmdlist.insert(0, self.args.NAMES['NS'])
|
cmdlist.insert(0, self.args.NAMES['NS'])
|
||||||
cmdlist.insert(0, 'exec')
|
cmdlist.insert(0, 'exec')
|
||||||
cmdlist.insert(0, 'netns')
|
cmdlist.insert(0, 'netns')
|
||||||
cmdlist.insert(0, 'ip')
|
cmdlist.insert(0, self.args.NAMES['IP'])
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -78,16 +78,16 @@ class SubPlugin(TdcPlugin):
|
||||||
return command
|
return command
|
||||||
|
|
||||||
def _ports_create(self):
|
def _ports_create(self):
|
||||||
cmd = 'ip link add $DEV0 type veth peer name $DEV1'
|
cmd = '$IP link add $DEV0 type veth peer name $DEV1'
|
||||||
self._exec_cmd('pre', cmd)
|
self._exec_cmd('pre', cmd)
|
||||||
cmd = 'ip link set $DEV0 up'
|
cmd = '$IP link set $DEV0 up'
|
||||||
self._exec_cmd('pre', cmd)
|
self._exec_cmd('pre', cmd)
|
||||||
if not self.args.namespace:
|
if not self.args.namespace:
|
||||||
cmd = 'ip link set $DEV1 up'
|
cmd = '$IP link set $DEV1 up'
|
||||||
self._exec_cmd('pre', cmd)
|
self._exec_cmd('pre', cmd)
|
||||||
|
|
||||||
def _ports_destroy(self):
|
def _ports_destroy(self):
|
||||||
cmd = 'ip link del $DEV0'
|
cmd = '$IP link del $DEV0'
|
||||||
self._exec_cmd('post', cmd)
|
self._exec_cmd('post', cmd)
|
||||||
|
|
||||||
def _ns_create(self):
|
def _ns_create(self):
|
||||||
|
@ -97,16 +97,16 @@ class SubPlugin(TdcPlugin):
|
||||||
'''
|
'''
|
||||||
self._ports_create()
|
self._ports_create()
|
||||||
if self.args.namespace:
|
if self.args.namespace:
|
||||||
cmd = 'ip netns add {}'.format(self.args.NAMES['NS'])
|
cmd = '$IP netns add {}'.format(self.args.NAMES['NS'])
|
||||||
self._exec_cmd('pre', cmd)
|
self._exec_cmd('pre', cmd)
|
||||||
cmd = 'ip link set $DEV1 netns {}'.format(self.args.NAMES['NS'])
|
cmd = '$IP link set $DEV1 netns {}'.format(self.args.NAMES['NS'])
|
||||||
self._exec_cmd('pre', cmd)
|
self._exec_cmd('pre', cmd)
|
||||||
cmd = 'ip -n {} link set $DEV1 up'.format(self.args.NAMES['NS'])
|
cmd = '$IP -n {} link set $DEV1 up'.format(self.args.NAMES['NS'])
|
||||||
self._exec_cmd('pre', cmd)
|
self._exec_cmd('pre', cmd)
|
||||||
if self.args.device:
|
if self.args.device:
|
||||||
cmd = 'ip link set $DEV2 netns {}'.format(self.args.NAMES['NS'])
|
cmd = '$IP link set $DEV2 netns {}'.format(self.args.NAMES['NS'])
|
||||||
self._exec_cmd('pre', cmd)
|
self._exec_cmd('pre', cmd)
|
||||||
cmd = 'ip -n {} link set $DEV2 up'.format(self.args.NAMES['NS'])
|
cmd = '$IP -n {} link set $DEV2 up'.format(self.args.NAMES['NS'])
|
||||||
self._exec_cmd('pre', cmd)
|
self._exec_cmd('pre', cmd)
|
||||||
|
|
||||||
def _ns_destroy(self):
|
def _ns_destroy(self):
|
||||||
|
@ -115,7 +115,7 @@ class SubPlugin(TdcPlugin):
|
||||||
devices as well)
|
devices as well)
|
||||||
'''
|
'''
|
||||||
if self.args.namespace:
|
if self.args.namespace:
|
||||||
cmd = 'ip netns delete {}'.format(self.args.NAMES['NS'])
|
cmd = '$IP netns delete {}'.format(self.args.NAMES['NS'])
|
||||||
self._exec_cmd('post', cmd)
|
self._exec_cmd('post', cmd)
|
||||||
|
|
||||||
def _exec_cmd(self, stage, command):
|
def _exec_cmd(self, stage, command):
|
||||||
|
|
Loading…
Reference in a new issue