mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
Merge tag 'net-6.18-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from Paolo Abeni:
"Including fixes from Bluetooth and Wireless. No known outstanding
regressions.
Current release - regressions:
- eth:
- bonding: fix mii_status when slave is down
- mlx5e: fix missing error assignment in mlx5e_xfrm_add_state()
Previous releases - regressions:
- sched: limit try_bulk_dequeue_skb() batches
- ipv4: route: prevent rt_bind_exception() from rebinding stale fnhe
- af_unix: initialise scc_index in unix_add_edge()
- netpoll: fix incorrect refcount handling causing incorrect cleanup
- bluetooth: don't hold spin lock over sleeping functions
- hsr: Fix supervision frame sending on HSRv0
- sctp: prevent possible shift out-of-bounds
- tipc: fix use-after-free in tipc_mon_reinit_self().
- dsa: tag_brcm: do not mark link local traffic as offloaded
- eth: virtio-net: fix incorrect flags recording in big mode
Previous releases - always broken:
- sched: initialize struct tc_ife to fix kernel-infoleak
- wifi:
- mac80211: reject address change while connecting
- iwlwifi: avoid toggling links due to wrong element use
- bluetooth: cancel mesh send timer when hdev removed
- strparser: fix signed/unsigned mismatch bug
- handshake: fix memory leak in tls_handshake_accept()
Misc:
- selftests: mptcp: fix some flaky tests"
* tag 'net-6.18-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (60 commits)
hsr: Follow standard for HSRv0 supervision frames
hsr: Fix supervision frame sending on HSRv0
virtio-net: fix incorrect flags recording in big mode
ipv4: route: Prevent rt_bind_exception() from rebinding stale fnhe
wifi: iwlwifi: mld: always take beacon ies in link grading
wifi: iwlwifi: mvm: fix beacon template/fixed rate
wifi: iwlwifi: fix aux ROC time event iterator usage
net_sched: limit try_bulk_dequeue_skb() batches
selftests: mptcp: join: properly kill background tasks
selftests: mptcp: connect: trunc: read all recv data
selftests: mptcp: join: userspace: longer transfer
selftests: mptcp: join: endpoints: longer transfer
selftests: mptcp: join: rm: set backup flag
selftests: mptcp: connect: fix fallback note due to OoO
ethtool: fix incorrect kernel-doc style comment in ethtool.h
mlx5: Fix default values in create CQ
Bluetooth: btrtl: Avoid loading the config file on security chips
net/mlx5e: Fix potentially misleading debug message
net/mlx5e: Fix wraparound in rate limiting for values above 255 Gbps
net/mlx5e: Fix maxrate wraparound in threshold between units
...
This commit is contained in:
@@ -13,10 +13,10 @@ Simple CLI
|
|||||||
Kernel comes with a simple CLI tool which should be useful when
|
Kernel comes with a simple CLI tool which should be useful when
|
||||||
developing Netlink related code. The tool is implemented in Python
|
developing Netlink related code. The tool is implemented in Python
|
||||||
and can use a YAML specification to issue Netlink requests
|
and can use a YAML specification to issue Netlink requests
|
||||||
to the kernel. Only Generic Netlink is supported.
|
to the kernel.
|
||||||
|
|
||||||
The tool is located at ``tools/net/ynl/pyynl/cli.py``. It accepts
|
The tool is located at ``tools/net/ynl/pyynl/cli.py``. It accepts
|
||||||
a handul of arguments, the most important ones are:
|
a handful of arguments, the most important ones are:
|
||||||
|
|
||||||
- ``--spec`` - point to the spec file
|
- ``--spec`` - point to the spec file
|
||||||
- ``--do $name`` / ``--dump $name`` - issue request ``$name``
|
- ``--do $name`` / ``--dump $name`` - issue request ``$name``
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
#define RTL_CHIP_SUBVER (&(struct rtl_vendor_cmd) {{0x10, 0x38, 0x04, 0x28, 0x80}})
|
#define RTL_CHIP_SUBVER (&(struct rtl_vendor_cmd) {{0x10, 0x38, 0x04, 0x28, 0x80}})
|
||||||
#define RTL_CHIP_REV (&(struct rtl_vendor_cmd) {{0x10, 0x3A, 0x04, 0x28, 0x80}})
|
#define RTL_CHIP_REV (&(struct rtl_vendor_cmd) {{0x10, 0x3A, 0x04, 0x28, 0x80}})
|
||||||
#define RTL_SEC_PROJ (&(struct rtl_vendor_cmd) {{0x10, 0xA4, 0x0D, 0x00, 0xb0}})
|
#define RTL_SEC_PROJ (&(struct rtl_vendor_cmd) {{0x10, 0xA4, 0xAD, 0x00, 0xb0}})
|
||||||
|
|
||||||
#define RTL_PATCH_SNIPPETS 0x01
|
#define RTL_PATCH_SNIPPETS 0x01
|
||||||
#define RTL_PATCH_DUMMY_HEADER 0x02
|
#define RTL_PATCH_DUMMY_HEADER 0x02
|
||||||
@@ -534,7 +534,6 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
|
|||||||
{
|
{
|
||||||
struct rtl_epatch_header_v2 *hdr;
|
struct rtl_epatch_header_v2 *hdr;
|
||||||
int rc;
|
int rc;
|
||||||
u8 reg_val[2];
|
|
||||||
u8 key_id;
|
u8 key_id;
|
||||||
u32 num_sections;
|
u32 num_sections;
|
||||||
struct rtl_section *section;
|
struct rtl_section *section;
|
||||||
@@ -549,14 +548,7 @@ static int rtlbt_parse_firmware_v2(struct hci_dev *hdev,
|
|||||||
.len = btrtl_dev->fw_len - 7, /* Cut the tail */
|
.len = btrtl_dev->fw_len - 7, /* Cut the tail */
|
||||||
};
|
};
|
||||||
|
|
||||||
rc = btrtl_vendor_read_reg16(hdev, RTL_SEC_PROJ, reg_val);
|
key_id = btrtl_dev->key_id;
|
||||||
if (rc < 0)
|
|
||||||
return -EIO;
|
|
||||||
key_id = reg_val[0];
|
|
||||||
|
|
||||||
rtl_dev_dbg(hdev, "%s: key id %u", __func__, key_id);
|
|
||||||
|
|
||||||
btrtl_dev->key_id = key_id;
|
|
||||||
|
|
||||||
hdr = rtl_iov_pull_data(&iov, sizeof(*hdr));
|
hdr = rtl_iov_pull_data(&iov, sizeof(*hdr));
|
||||||
if (!hdr)
|
if (!hdr)
|
||||||
@@ -1070,6 +1062,8 @@ struct btrtl_device_info *btrtl_initialize(struct hci_dev *hdev,
|
|||||||
u16 hci_rev, lmp_subver;
|
u16 hci_rev, lmp_subver;
|
||||||
u8 hci_ver, lmp_ver, chip_type = 0;
|
u8 hci_ver, lmp_ver, chip_type = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
int rc;
|
||||||
|
u8 key_id;
|
||||||
u8 reg_val[2];
|
u8 reg_val[2];
|
||||||
|
|
||||||
btrtl_dev = kzalloc(sizeof(*btrtl_dev), GFP_KERNEL);
|
btrtl_dev = kzalloc(sizeof(*btrtl_dev), GFP_KERNEL);
|
||||||
@@ -1180,6 +1174,14 @@ next:
|
|||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = btrtl_vendor_read_reg16(hdev, RTL_SEC_PROJ, reg_val);
|
||||||
|
if (rc < 0)
|
||||||
|
goto err_free;
|
||||||
|
|
||||||
|
key_id = reg_val[0];
|
||||||
|
btrtl_dev->key_id = key_id;
|
||||||
|
rtl_dev_info(hdev, "%s: key id %u", __func__, key_id);
|
||||||
|
|
||||||
btrtl_dev->fw_len = -EIO;
|
btrtl_dev->fw_len = -EIO;
|
||||||
if (lmp_subver == RTL_ROM_LMP_8852A && hci_rev == 0x000c) {
|
if (lmp_subver == RTL_ROM_LMP_8852A && hci_rev == 0x000c) {
|
||||||
snprintf(fw_name, sizeof(fw_name), "%s_v2.bin",
|
snprintf(fw_name, sizeof(fw_name), "%s_v2.bin",
|
||||||
@@ -1202,7 +1204,7 @@ next:
|
|||||||
goto err_free;
|
goto err_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (btrtl_dev->ic_info->cfg_name) {
|
if (btrtl_dev->ic_info->cfg_name && !btrtl_dev->key_id) {
|
||||||
if (postfix) {
|
if (postfix) {
|
||||||
snprintf(cfg_name, sizeof(cfg_name), "%s-%s.bin",
|
snprintf(cfg_name, sizeof(cfg_name), "%s-%s.bin",
|
||||||
btrtl_dev->ic_info->cfg_name, postfix);
|
btrtl_dev->ic_info->cfg_name, postfix);
|
||||||
|
|||||||
@@ -4361,6 +4361,11 @@ static void btusb_disconnect(struct usb_interface *intf)
|
|||||||
|
|
||||||
hci_unregister_dev(hdev);
|
hci_unregister_dev(hdev);
|
||||||
|
|
||||||
|
if (data->oob_wake_irq)
|
||||||
|
device_init_wakeup(&data->udev->dev, false);
|
||||||
|
if (data->reset_gpio)
|
||||||
|
gpiod_put(data->reset_gpio);
|
||||||
|
|
||||||
if (intf == data->intf) {
|
if (intf == data->intf) {
|
||||||
if (data->isoc)
|
if (data->isoc)
|
||||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||||
@@ -4371,17 +4376,11 @@ static void btusb_disconnect(struct usb_interface *intf)
|
|||||||
usb_driver_release_interface(&btusb_driver, data->diag);
|
usb_driver_release_interface(&btusb_driver, data->diag);
|
||||||
usb_driver_release_interface(&btusb_driver, data->intf);
|
usb_driver_release_interface(&btusb_driver, data->intf);
|
||||||
} else if (intf == data->diag) {
|
} else if (intf == data->diag) {
|
||||||
usb_driver_release_interface(&btusb_driver, data->intf);
|
|
||||||
if (data->isoc)
|
if (data->isoc)
|
||||||
usb_driver_release_interface(&btusb_driver, data->isoc);
|
usb_driver_release_interface(&btusb_driver, data->isoc);
|
||||||
|
usb_driver_release_interface(&btusb_driver, data->intf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->oob_wake_irq)
|
|
||||||
device_init_wakeup(&data->udev->dev, false);
|
|
||||||
|
|
||||||
if (data->reset_gpio)
|
|
||||||
gpiod_put(data->reset_gpio);
|
|
||||||
|
|
||||||
hci_free_dev(hdev);
|
hci_free_dev(hdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1020,15 +1020,18 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
|
|||||||
if (cq->create_flags & IB_UVERBS_CQ_FLAGS_IGNORE_OVERRUN)
|
if (cq->create_flags & IB_UVERBS_CQ_FLAGS_IGNORE_OVERRUN)
|
||||||
MLX5_SET(cqc, cqc, oi, 1);
|
MLX5_SET(cqc, cqc, oi, 1);
|
||||||
|
|
||||||
|
if (udata) {
|
||||||
|
cq->mcq.comp = mlx5_add_cq_to_tasklet;
|
||||||
|
cq->mcq.tasklet_ctx.comp = mlx5_ib_cq_comp;
|
||||||
|
} else {
|
||||||
|
cq->mcq.comp = mlx5_ib_cq_comp;
|
||||||
|
}
|
||||||
|
|
||||||
err = mlx5_core_create_cq(dev->mdev, &cq->mcq, cqb, inlen, out, sizeof(out));
|
err = mlx5_core_create_cq(dev->mdev, &cq->mcq, cqb, inlen, out, sizeof(out));
|
||||||
if (err)
|
if (err)
|
||||||
goto err_cqb;
|
goto err_cqb;
|
||||||
|
|
||||||
mlx5_ib_dbg(dev, "cqn 0x%x\n", cq->mcq.cqn);
|
mlx5_ib_dbg(dev, "cqn 0x%x\n", cq->mcq.cqn);
|
||||||
if (udata)
|
|
||||||
cq->mcq.tasklet_ctx.comp = mlx5_ib_cq_comp;
|
|
||||||
else
|
|
||||||
cq->mcq.comp = mlx5_ib_cq_comp;
|
|
||||||
cq->mcq.event = mlx5_ib_cq_event;
|
cq->mcq.event = mlx5_ib_cq_event;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&cq->wc_list);
|
INIT_LIST_HEAD(&cq->wc_list);
|
||||||
|
|||||||
@@ -2120,7 +2120,7 @@ skip_mac_set:
|
|||||||
/* check for initial state */
|
/* check for initial state */
|
||||||
new_slave->link = BOND_LINK_NOCHANGE;
|
new_slave->link = BOND_LINK_NOCHANGE;
|
||||||
if (bond->params.miimon) {
|
if (bond->params.miimon) {
|
||||||
if (netif_carrier_ok(slave_dev)) {
|
if (netif_running(slave_dev) && netif_carrier_ok(slave_dev)) {
|
||||||
if (bond->params.updelay) {
|
if (bond->params.updelay) {
|
||||||
bond_set_slave_link_state(new_slave,
|
bond_set_slave_link_state(new_slave,
|
||||||
BOND_LINK_BACK,
|
BOND_LINK_BACK,
|
||||||
@@ -2665,7 +2665,8 @@ static int bond_miimon_inspect(struct bonding *bond)
|
|||||||
bond_for_each_slave_rcu(bond, slave, iter) {
|
bond_for_each_slave_rcu(bond, slave, iter) {
|
||||||
bond_propose_link_state(slave, BOND_LINK_NOCHANGE);
|
bond_propose_link_state(slave, BOND_LINK_NOCHANGE);
|
||||||
|
|
||||||
link_state = netif_carrier_ok(slave->dev);
|
link_state = netif_running(slave->dev) &&
|
||||||
|
netif_carrier_ok(slave->dev);
|
||||||
|
|
||||||
switch (slave->link) {
|
switch (slave->link) {
|
||||||
case BOND_LINK_UP:
|
case BOND_LINK_UP:
|
||||||
|
|||||||
@@ -1835,6 +1835,8 @@ fec_enet_rx_queue(struct net_device *ndev, u16 queue_id, int budget)
|
|||||||
ndev->stats.rx_packets++;
|
ndev->stats.rx_packets++;
|
||||||
pkt_len = fec16_to_cpu(bdp->cbd_datlen);
|
pkt_len = fec16_to_cpu(bdp->cbd_datlen);
|
||||||
ndev->stats.rx_bytes += pkt_len;
|
ndev->stats.rx_bytes += pkt_len;
|
||||||
|
if (fep->quirks & FEC_QUIRK_HAS_RACC)
|
||||||
|
ndev->stats.rx_bytes -= 2;
|
||||||
|
|
||||||
index = fec_enet_get_bd_index(bdp, &rxq->bd);
|
index = fec_enet_get_bd_index(bdp, &rxq->bd);
|
||||||
page = rxq->rx_skb_info[index].page;
|
page = rxq->rx_skb_info[index].page;
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ void mlx5_cq_tasklet_cb(struct tasklet_struct *t)
|
|||||||
tasklet_schedule(&ctx->task);
|
tasklet_schedule(&ctx->task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq,
|
void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq,
|
||||||
struct mlx5_eqe *eqe)
|
struct mlx5_eqe *eqe)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct mlx5_eq_tasklet *tasklet_ctx = cq->tasklet_ctx.priv;
|
struct mlx5_eq_tasklet *tasklet_ctx = cq->tasklet_ctx.priv;
|
||||||
@@ -95,7 +95,15 @@ static void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq,
|
|||||||
if (schedule_tasklet)
|
if (schedule_tasklet)
|
||||||
tasklet_schedule(&tasklet_ctx->task);
|
tasklet_schedule(&tasklet_ctx->task);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(mlx5_add_cq_to_tasklet);
|
||||||
|
|
||||||
|
static void mlx5_core_cq_dummy_cb(struct mlx5_core_cq *cq, struct mlx5_eqe *eqe)
|
||||||
|
{
|
||||||
|
mlx5_core_err(cq->eq->core.dev,
|
||||||
|
"CQ default completion callback, CQ #%u\n", cq->cqn);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MLX5_CQ_INIT_CMD_SN cpu_to_be32(2 << 28)
|
||||||
/* Callers must verify outbox status in case of err */
|
/* Callers must verify outbox status in case of err */
|
||||||
int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
|
int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
|
||||||
u32 *in, int inlen, u32 *out, int outlen)
|
u32 *in, int inlen, u32 *out, int outlen)
|
||||||
@@ -121,10 +129,19 @@ int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
|
|||||||
cq->arm_sn = 0;
|
cq->arm_sn = 0;
|
||||||
cq->eq = eq;
|
cq->eq = eq;
|
||||||
cq->uid = MLX5_GET(create_cq_in, in, uid);
|
cq->uid = MLX5_GET(create_cq_in, in, uid);
|
||||||
|
|
||||||
|
/* Kernel CQs must set the arm_db address prior to calling
|
||||||
|
* this function, allowing for the proper value to be
|
||||||
|
* initialized. User CQs are responsible for their own
|
||||||
|
* initialization since they do not use the arm_db field.
|
||||||
|
*/
|
||||||
|
if (cq->arm_db)
|
||||||
|
*cq->arm_db = MLX5_CQ_INIT_CMD_SN;
|
||||||
|
|
||||||
refcount_set(&cq->refcount, 1);
|
refcount_set(&cq->refcount, 1);
|
||||||
init_completion(&cq->free);
|
init_completion(&cq->free);
|
||||||
if (!cq->comp)
|
if (!cq->comp)
|
||||||
cq->comp = mlx5_add_cq_to_tasklet;
|
cq->comp = mlx5_core_cq_dummy_cb;
|
||||||
/* assuming CQ will be deleted before the EQ */
|
/* assuming CQ will be deleted before the EQ */
|
||||||
cq->tasklet_ctx.priv = &eq->tasklet_ctx;
|
cq->tasklet_ctx.priv = &eq->tasklet_ctx;
|
||||||
INIT_LIST_HEAD(&cq->tasklet_ctx.list);
|
INIT_LIST_HEAD(&cq->tasklet_ctx.list);
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ static int mlx5_devlink_num_doorbells_validate(struct devlink *devlink, u32 id,
|
|||||||
max_num_channels = mlx5e_get_max_num_channels(mdev);
|
max_num_channels = mlx5e_get_max_num_channels(mdev);
|
||||||
if (val32 > max_num_channels) {
|
if (val32 > max_num_channels) {
|
||||||
NL_SET_ERR_MSG_FMT_MOD(extack,
|
NL_SET_ERR_MSG_FMT_MOD(extack,
|
||||||
"Requested num_doorbells (%u) exceeds maximum number of channels (%u)",
|
"Requested num_doorbells (%u) exceeds max number of channels (%u)",
|
||||||
val32, max_num_channels);
|
val32, max_num_channels);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -804,7 +804,8 @@ static int mlx5e_xfrm_add_state(struct net_device *dev,
|
|||||||
goto err_xfrm;
|
goto err_xfrm;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mlx5_eswitch_block_mode(priv->mdev))
|
err = mlx5_eswitch_block_mode(priv->mdev);
|
||||||
|
if (err)
|
||||||
goto unblock_ipsec;
|
goto unblock_ipsec;
|
||||||
|
|
||||||
if (x->props.mode == XFRM_MODE_TUNNEL &&
|
if (x->props.mode == XFRM_MODE_TUNNEL &&
|
||||||
|
|||||||
@@ -595,32 +595,55 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
|
|||||||
struct mlx5_core_dev *mdev = priv->mdev;
|
struct mlx5_core_dev *mdev = priv->mdev;
|
||||||
u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
|
u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
|
||||||
u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
|
u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
|
||||||
__u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB);
|
__u64 upper_limit_mbps;
|
||||||
|
__u64 upper_limit_gbps;
|
||||||
int i;
|
int i;
|
||||||
|
struct {
|
||||||
|
int scale;
|
||||||
|
const char *units_str;
|
||||||
|
} units[] = {
|
||||||
|
[MLX5_100_MBPS_UNIT] = {
|
||||||
|
.scale = 100,
|
||||||
|
.units_str = "Mbps",
|
||||||
|
},
|
||||||
|
[MLX5_GBPS_UNIT] = {
|
||||||
|
.scale = 1,
|
||||||
|
.units_str = "Gbps",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
memset(max_bw_value, 0, sizeof(max_bw_value));
|
memset(max_bw_value, 0, sizeof(max_bw_value));
|
||||||
memset(max_bw_unit, 0, sizeof(max_bw_unit));
|
memset(max_bw_unit, 0, sizeof(max_bw_unit));
|
||||||
|
upper_limit_mbps = 255 * MLX5E_100MB;
|
||||||
|
upper_limit_gbps = 255 * MLX5E_1GB;
|
||||||
|
|
||||||
for (i = 0; i <= mlx5_max_tc(mdev); i++) {
|
for (i = 0; i <= mlx5_max_tc(mdev); i++) {
|
||||||
if (!maxrate->tc_maxrate[i]) {
|
if (!maxrate->tc_maxrate[i]) {
|
||||||
max_bw_unit[i] = MLX5_BW_NO_LIMIT;
|
max_bw_unit[i] = MLX5_BW_NO_LIMIT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (maxrate->tc_maxrate[i] < upper_limit_mbps) {
|
if (maxrate->tc_maxrate[i] <= upper_limit_mbps) {
|
||||||
max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
|
max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
|
||||||
MLX5E_100MB);
|
MLX5E_100MB);
|
||||||
max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1;
|
max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1;
|
||||||
max_bw_unit[i] = MLX5_100_MBPS_UNIT;
|
max_bw_unit[i] = MLX5_100_MBPS_UNIT;
|
||||||
} else {
|
} else if (max_bw_value[i] <= upper_limit_gbps) {
|
||||||
max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
|
max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
|
||||||
MLX5E_1GB);
|
MLX5E_1GB);
|
||||||
max_bw_unit[i] = MLX5_GBPS_UNIT;
|
max_bw_unit[i] = MLX5_GBPS_UNIT;
|
||||||
|
} else {
|
||||||
|
netdev_err(netdev,
|
||||||
|
"tc_%d maxrate %llu Kbps exceeds limit %llu\n",
|
||||||
|
i, maxrate->tc_maxrate[i],
|
||||||
|
upper_limit_gbps);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
|
||||||
netdev_dbg(netdev, "%s: tc_%d <=> max_bw %d Gbps\n",
|
netdev_dbg(netdev, "%s: tc_%d <=> max_bw %u %s\n", __func__, i,
|
||||||
__func__, i, max_bw_value[i]);
|
max_bw_value[i] * units[max_bw_unit[i]].scale,
|
||||||
|
units[max_bw_unit[i]].units_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
|
return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
|
||||||
|
|||||||
@@ -2219,7 +2219,6 @@ static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev,
|
|||||||
mcq->set_ci_db = cq->wq_ctrl.db.db;
|
mcq->set_ci_db = cq->wq_ctrl.db.db;
|
||||||
mcq->arm_db = cq->wq_ctrl.db.db + 1;
|
mcq->arm_db = cq->wq_ctrl.db.db + 1;
|
||||||
*mcq->set_ci_db = 0;
|
*mcq->set_ci_db = 0;
|
||||||
*mcq->arm_db = 0;
|
|
||||||
mcq->vector = param->eq_ix;
|
mcq->vector = param->eq_ix;
|
||||||
mcq->comp = mlx5e_completion_event;
|
mcq->comp = mlx5e_completion_event;
|
||||||
mcq->event = mlx5e_cq_error_event;
|
mcq->event = mlx5e_cq_error_event;
|
||||||
|
|||||||
@@ -421,6 +421,13 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
|
|||||||
__be64 *pas;
|
__be64 *pas;
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
|
conn->cq.mcq.cqe_sz = 64;
|
||||||
|
conn->cq.mcq.set_ci_db = conn->cq.wq_ctrl.db.db;
|
||||||
|
conn->cq.mcq.arm_db = conn->cq.wq_ctrl.db.db + 1;
|
||||||
|
*conn->cq.mcq.set_ci_db = 0;
|
||||||
|
conn->cq.mcq.vector = 0;
|
||||||
|
conn->cq.mcq.comp = mlx5_fpga_conn_cq_complete;
|
||||||
|
|
||||||
cq_size = roundup_pow_of_two(cq_size);
|
cq_size = roundup_pow_of_two(cq_size);
|
||||||
MLX5_SET(cqc, temp_cqc, log_cq_size, ilog2(cq_size));
|
MLX5_SET(cqc, temp_cqc, log_cq_size, ilog2(cq_size));
|
||||||
|
|
||||||
@@ -468,15 +475,7 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
|
|||||||
if (err)
|
if (err)
|
||||||
goto err_cqwq;
|
goto err_cqwq;
|
||||||
|
|
||||||
conn->cq.mcq.cqe_sz = 64;
|
|
||||||
conn->cq.mcq.set_ci_db = conn->cq.wq_ctrl.db.db;
|
|
||||||
conn->cq.mcq.arm_db = conn->cq.wq_ctrl.db.db + 1;
|
|
||||||
*conn->cq.mcq.set_ci_db = 0;
|
|
||||||
*conn->cq.mcq.arm_db = 0;
|
|
||||||
conn->cq.mcq.vector = 0;
|
|
||||||
conn->cq.mcq.comp = mlx5_fpga_conn_cq_complete;
|
|
||||||
tasklet_setup(&conn->cq.tasklet, mlx5_fpga_conn_cq_tasklet);
|
tasklet_setup(&conn->cq.tasklet, mlx5_fpga_conn_cq_tasklet);
|
||||||
|
|
||||||
mlx5_fpga_dbg(fdev, "Created CQ #0x%x\n", conn->cq.mcq.cqn);
|
mlx5_fpga_dbg(fdev, "Created CQ #0x%x\n", conn->cq.mcq.cqn);
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@@ -873,12 +873,6 @@ err_free_sqc:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hws_cq_complete(struct mlx5_core_cq *mcq,
|
|
||||||
struct mlx5_eqe *eqe)
|
|
||||||
{
|
|
||||||
pr_err("CQ completion CQ: #%u\n", mcq->cqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hws_send_ring_alloc_cq(struct mlx5_core_dev *mdev,
|
static int hws_send_ring_alloc_cq(struct mlx5_core_dev *mdev,
|
||||||
int numa_node,
|
int numa_node,
|
||||||
struct mlx5hws_send_engine *queue,
|
struct mlx5hws_send_engine *queue,
|
||||||
@@ -901,7 +895,6 @@ static int hws_send_ring_alloc_cq(struct mlx5_core_dev *mdev,
|
|||||||
mcq->cqe_sz = 64;
|
mcq->cqe_sz = 64;
|
||||||
mcq->set_ci_db = cq->wq_ctrl.db.db;
|
mcq->set_ci_db = cq->wq_ctrl.db.db;
|
||||||
mcq->arm_db = cq->wq_ctrl.db.db + 1;
|
mcq->arm_db = cq->wq_ctrl.db.db + 1;
|
||||||
mcq->comp = hws_cq_complete;
|
|
||||||
|
|
||||||
for (i = 0; i < mlx5_cqwq_get_size(&cq->wq); i++) {
|
for (i = 0; i < mlx5_cqwq_get_size(&cq->wq); i++) {
|
||||||
cqe = mlx5_cqwq_get_wqe(&cq->wq, i);
|
cqe = mlx5_cqwq_get_wqe(&cq->wq, i);
|
||||||
|
|||||||
@@ -1049,12 +1049,6 @@ static int dr_prepare_qp_to_rts(struct mlx5dr_domain *dmn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dr_cq_complete(struct mlx5_core_cq *mcq,
|
|
||||||
struct mlx5_eqe *eqe)
|
|
||||||
{
|
|
||||||
pr_err("CQ completion CQ: #%u\n", mcq->cqn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
|
static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
|
||||||
struct mlx5_uars_page *uar,
|
struct mlx5_uars_page *uar,
|
||||||
size_t ncqe)
|
size_t ncqe)
|
||||||
@@ -1089,6 +1083,13 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
|
|||||||
cqe->op_own = MLX5_CQE_INVALID << 4 | MLX5_CQE_OWNER_MASK;
|
cqe->op_own = MLX5_CQE_INVALID << 4 | MLX5_CQE_OWNER_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cq->mcq.cqe_sz = 64;
|
||||||
|
cq->mcq.set_ci_db = cq->wq_ctrl.db.db;
|
||||||
|
cq->mcq.arm_db = cq->wq_ctrl.db.db + 1;
|
||||||
|
*cq->mcq.set_ci_db = 0;
|
||||||
|
cq->mcq.vector = 0;
|
||||||
|
cq->mdev = mdev;
|
||||||
|
|
||||||
inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
|
inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
|
||||||
sizeof(u64) * cq->wq_ctrl.buf.npages;
|
sizeof(u64) * cq->wq_ctrl.buf.npages;
|
||||||
in = kvzalloc(inlen, GFP_KERNEL);
|
in = kvzalloc(inlen, GFP_KERNEL);
|
||||||
@@ -1112,27 +1113,12 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
|
|||||||
pas = (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas);
|
pas = (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas);
|
||||||
mlx5_fill_page_frag_array(&cq->wq_ctrl.buf, pas);
|
mlx5_fill_page_frag_array(&cq->wq_ctrl.buf, pas);
|
||||||
|
|
||||||
cq->mcq.comp = dr_cq_complete;
|
|
||||||
|
|
||||||
err = mlx5_core_create_cq(mdev, &cq->mcq, in, inlen, out, sizeof(out));
|
err = mlx5_core_create_cq(mdev, &cq->mcq, in, inlen, out, sizeof(out));
|
||||||
kvfree(in);
|
kvfree(in);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto err_cqwq;
|
goto err_cqwq;
|
||||||
|
|
||||||
cq->mcq.cqe_sz = 64;
|
|
||||||
cq->mcq.set_ci_db = cq->wq_ctrl.db.db;
|
|
||||||
cq->mcq.arm_db = cq->wq_ctrl.db.db + 1;
|
|
||||||
*cq->mcq.set_ci_db = 0;
|
|
||||||
|
|
||||||
/* set no-zero value, in order to avoid the HW to run db-recovery on
|
|
||||||
* CQ that used in polling mode.
|
|
||||||
*/
|
|
||||||
*cq->mcq.arm_db = cpu_to_be32(2 << 28);
|
|
||||||
|
|
||||||
cq->mcq.vector = 0;
|
|
||||||
cq->mdev = mdev;
|
|
||||||
|
|
||||||
return cq;
|
return cq;
|
||||||
|
|
||||||
err_cqwq:
|
err_cqwq:
|
||||||
|
|||||||
@@ -276,9 +276,31 @@ static int am65_cpsw_iet_set_verify_timeout_count(struct am65_cpsw_port *port)
|
|||||||
/* The number of wireside clocks contained in the verify
|
/* The number of wireside clocks contained in the verify
|
||||||
* timeout counter. The default is 0x1312d0
|
* timeout counter. The default is 0x1312d0
|
||||||
* (10ms at 125Mhz in 1G mode).
|
* (10ms at 125Mhz in 1G mode).
|
||||||
|
* The frequency of the clock depends on the link speed
|
||||||
|
* and the PHY interface.
|
||||||
*/
|
*/
|
||||||
val = 125 * HZ_PER_MHZ; /* assuming 125MHz wireside clock */
|
switch (port->slave.phy_if) {
|
||||||
|
case PHY_INTERFACE_MODE_RGMII:
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||||
|
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||||
|
if (port->qos.link_speed == SPEED_1000)
|
||||||
|
val = 125 * HZ_PER_MHZ; /* 125 MHz at 1000Mbps*/
|
||||||
|
else if (port->qos.link_speed == SPEED_100)
|
||||||
|
val = 25 * HZ_PER_MHZ; /* 25 MHz at 100Mbps*/
|
||||||
|
else
|
||||||
|
val = (25 * HZ_PER_MHZ) / 10; /* 2.5 MHz at 10Mbps*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PHY_INTERFACE_MODE_QSGMII:
|
||||||
|
case PHY_INTERFACE_MODE_SGMII:
|
||||||
|
val = 125 * HZ_PER_MHZ; /* 125 MHz */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
netdev_err(port->ndev, "selected mode does not supported IET\n");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
val /= MILLIHZ_PER_HZ; /* count per ms timeout */
|
val /= MILLIHZ_PER_HZ; /* count per ms timeout */
|
||||||
val *= verify_time_ms; /* count for timeout ms */
|
val *= verify_time_ms; /* count for timeout ms */
|
||||||
|
|
||||||
@@ -295,20 +317,21 @@ static int am65_cpsw_iet_verify_wait(struct am65_cpsw_port *port)
|
|||||||
u32 ctrl, status;
|
u32 ctrl, status;
|
||||||
int try;
|
int try;
|
||||||
|
|
||||||
try = 20;
|
try = 3;
|
||||||
|
|
||||||
|
/* Reset the verify state machine by writing 1
|
||||||
|
* to LINKFAIL
|
||||||
|
*/
|
||||||
|
ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
|
||||||
|
ctrl |= AM65_CPSW_PN_IET_MAC_LINKFAIL;
|
||||||
|
writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
|
||||||
|
|
||||||
|
/* Clear MAC_LINKFAIL bit to start Verify. */
|
||||||
|
ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
|
||||||
|
ctrl &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL;
|
||||||
|
writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Reset the verify state machine by writing 1
|
|
||||||
* to LINKFAIL
|
|
||||||
*/
|
|
||||||
ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
|
|
||||||
ctrl |= AM65_CPSW_PN_IET_MAC_LINKFAIL;
|
|
||||||
writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
|
|
||||||
|
|
||||||
/* Clear MAC_LINKFAIL bit to start Verify. */
|
|
||||||
ctrl = readl(port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
|
|
||||||
ctrl &= ~AM65_CPSW_PN_IET_MAC_LINKFAIL;
|
|
||||||
writel(ctrl, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
|
|
||||||
|
|
||||||
msleep(port->qos.iet.verify_time_ms);
|
msleep(port->qos.iet.verify_time_ms);
|
||||||
|
|
||||||
status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS);
|
status = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS);
|
||||||
@@ -330,7 +353,7 @@ static int am65_cpsw_iet_verify_wait(struct am65_cpsw_port *port)
|
|||||||
netdev_dbg(port->ndev, "MAC Merge verify error\n");
|
netdev_dbg(port->ndev, "MAC Merge verify error\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
} while (try-- > 0);
|
} while (--try > 0);
|
||||||
|
|
||||||
netdev_dbg(port->ndev, "MAC Merge verify timeout\n");
|
netdev_dbg(port->ndev, "MAC Merge verify timeout\n");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
|||||||
@@ -73,8 +73,11 @@ int mdiobus_register_device(struct mdio_device *mdiodev)
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = mdiobus_register_reset(mdiodev);
|
err = mdiobus_register_reset(mdiodev);
|
||||||
if (err)
|
if (err) {
|
||||||
|
gpiod_put(mdiodev->reset_gpio);
|
||||||
|
mdiodev->reset_gpio = NULL;
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Assert the reset signal */
|
/* Assert the reset signal */
|
||||||
mdio_device_reset(mdiodev, 1);
|
mdio_device_reset(mdiodev, 1);
|
||||||
|
|||||||
@@ -4380,12 +4380,6 @@ static int lan8814_config_init(struct phy_device *phydev)
|
|||||||
{
|
{
|
||||||
struct kszphy_priv *lan8814 = phydev->priv;
|
struct kszphy_priv *lan8814 = phydev->priv;
|
||||||
|
|
||||||
/* Reset the PHY */
|
|
||||||
lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
|
|
||||||
LAN8814_QSGMII_SOFT_RESET,
|
|
||||||
LAN8814_QSGMII_SOFT_RESET_BIT,
|
|
||||||
LAN8814_QSGMII_SOFT_RESET_BIT);
|
|
||||||
|
|
||||||
/* Disable ANEG with QSGMII PCS Host side */
|
/* Disable ANEG with QSGMII PCS Host side */
|
||||||
lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS,
|
lanphy_modify_page_reg(phydev, LAN8814_PAGE_PORT_REGS,
|
||||||
LAN8814_QSGMII_PCS1G_ANEG_CONFIG,
|
LAN8814_QSGMII_PCS1G_ANEG_CONFIG,
|
||||||
@@ -4471,6 +4465,12 @@ static int lan8814_probe(struct phy_device *phydev)
|
|||||||
addr, sizeof(struct lan8814_shared_priv));
|
addr, sizeof(struct lan8814_shared_priv));
|
||||||
|
|
||||||
if (phy_package_init_once(phydev)) {
|
if (phy_package_init_once(phydev)) {
|
||||||
|
/* Reset the PHY */
|
||||||
|
lanphy_modify_page_reg(phydev, LAN8814_PAGE_COMMON_REGS,
|
||||||
|
LAN8814_QSGMII_SOFT_RESET,
|
||||||
|
LAN8814_QSGMII_SOFT_RESET_BIT,
|
||||||
|
LAN8814_QSGMII_SOFT_RESET_BIT);
|
||||||
|
|
||||||
err = lan8814_release_coma_mode(phydev);
|
err = lan8814_release_coma_mode(phydev);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@@ -2631,22 +2631,28 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 1. Save the flags early, as the XDP program might overwrite them.
|
/* About the flags below:
|
||||||
|
* 1. Save the flags early, as the XDP program might overwrite them.
|
||||||
* These flags ensure packets marked as VIRTIO_NET_HDR_F_DATA_VALID
|
* These flags ensure packets marked as VIRTIO_NET_HDR_F_DATA_VALID
|
||||||
* stay valid after XDP processing.
|
* stay valid after XDP processing.
|
||||||
* 2. XDP doesn't work with partially checksummed packets (refer to
|
* 2. XDP doesn't work with partially checksummed packets (refer to
|
||||||
* virtnet_xdp_set()), so packets marked as
|
* virtnet_xdp_set()), so packets marked as
|
||||||
* VIRTIO_NET_HDR_F_NEEDS_CSUM get dropped during XDP processing.
|
* VIRTIO_NET_HDR_F_NEEDS_CSUM get dropped during XDP processing.
|
||||||
*/
|
*/
|
||||||
flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags;
|
|
||||||
|
|
||||||
if (vi->mergeable_rx_bufs)
|
if (vi->mergeable_rx_bufs) {
|
||||||
|
flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags;
|
||||||
skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit,
|
skb = receive_mergeable(dev, vi, rq, buf, ctx, len, xdp_xmit,
|
||||||
stats);
|
stats);
|
||||||
else if (vi->big_packets)
|
} else if (vi->big_packets) {
|
||||||
|
void *p = page_address((struct page *)buf);
|
||||||
|
|
||||||
|
flags = ((struct virtio_net_common_hdr *)p)->hdr.flags;
|
||||||
skb = receive_big(dev, vi, rq, buf, len, stats);
|
skb = receive_big(dev, vi, rq, buf, len, stats);
|
||||||
else
|
} else {
|
||||||
|
flags = ((struct virtio_net_common_hdr *)buf)->hdr.flags;
|
||||||
skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit, stats);
|
skb = receive_small(dev, vi, rq, buf, ctx, len, xdp_xmit, stats);
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5961,6 +5961,9 @@ static int wmi_process_mgmt_tx_comp(struct ath11k *ar,
|
|||||||
dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||||
|
|
||||||
info = IEEE80211_SKB_CB(msdu);
|
info = IEEE80211_SKB_CB(msdu);
|
||||||
|
memset(&info->status, 0, sizeof(info->status));
|
||||||
|
info->status.rates[0].idx = -1;
|
||||||
|
|
||||||
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) &&
|
if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) &&
|
||||||
!tx_compl_param->status) {
|
!tx_compl_param->status) {
|
||||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||||
|
|||||||
@@ -708,18 +708,13 @@ static int
|
|||||||
iwl_mld_get_chan_load_from_element(struct iwl_mld *mld,
|
iwl_mld_get_chan_load_from_element(struct iwl_mld *mld,
|
||||||
struct ieee80211_bss_conf *link_conf)
|
struct ieee80211_bss_conf *link_conf)
|
||||||
{
|
{
|
||||||
struct ieee80211_vif *vif = link_conf->vif;
|
|
||||||
const struct cfg80211_bss_ies *ies;
|
const struct cfg80211_bss_ies *ies;
|
||||||
const struct element *bss_load_elem = NULL;
|
const struct element *bss_load_elem = NULL;
|
||||||
const struct ieee80211_bss_load_elem *bss_load;
|
const struct ieee80211_bss_load_elem *bss_load;
|
||||||
|
|
||||||
guard(rcu)();
|
guard(rcu)();
|
||||||
|
|
||||||
if (ieee80211_vif_link_active(vif, link_conf->link_id))
|
ies = rcu_dereference(link_conf->bss->beacon_ies);
|
||||||
ies = rcu_dereference(link_conf->bss->beacon_ies);
|
|
||||||
else
|
|
||||||
ies = rcu_dereference(link_conf->bss->ies);
|
|
||||||
|
|
||||||
if (ies)
|
if (ies)
|
||||||
bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD,
|
bss_load_elem = cfg80211_find_elem(WLAN_EID_QBSS_LOAD,
|
||||||
ies->data, ies->len);
|
ies->data, ies->len);
|
||||||
|
|||||||
@@ -938,19 +938,12 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct iwl_mvm *mvm,
|
|||||||
|
|
||||||
u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
|
u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
|
||||||
{
|
{
|
||||||
|
u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
|
||||||
bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
|
bool is_new_rate = iwl_fw_lookup_cmd_ver(fw, BEACON_TEMPLATE_CMD, 0) > 10;
|
||||||
u16 flags, cck_flag;
|
|
||||||
|
|
||||||
if (is_new_rate) {
|
|
||||||
flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
|
|
||||||
cck_flag = IWL_MAC_BEACON_CCK;
|
|
||||||
} else {
|
|
||||||
cck_flag = IWL_MAC_BEACON_CCK_V1;
|
|
||||||
flags = iwl_fw_rate_idx_to_plcp(rate_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rate_idx <= IWL_LAST_CCK_RATE)
|
if (rate_idx <= IWL_LAST_CCK_RATE)
|
||||||
flags |= cck_flag;
|
flags |= is_new_rate ? IWL_MAC_BEACON_CCK
|
||||||
|
: IWL_MAC_BEACON_CCK_V1;
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -463,7 +463,7 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
|
|||||||
if (!aux_roc_te) /* Not a Aux ROC time event */
|
if (!aux_roc_te) /* Not a Aux ROC time event */
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
iwl_mvm_te_check_trigger(mvm, notif, te_data);
|
iwl_mvm_te_check_trigger(mvm, notif, aux_roc_te);
|
||||||
|
|
||||||
IWL_DEBUG_TE(mvm,
|
IWL_DEBUG_TE(mvm,
|
||||||
"Aux ROC time event notification - UID = 0x%x action %d (error = %d)\n",
|
"Aux ROC time event notification - UID = 0x%x action %d (error = %d)\n",
|
||||||
@@ -475,14 +475,14 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
|
|||||||
/* End TE, notify mac80211 */
|
/* End TE, notify mac80211 */
|
||||||
ieee80211_remain_on_channel_expired(mvm->hw);
|
ieee80211_remain_on_channel_expired(mvm->hw);
|
||||||
iwl_mvm_roc_finished(mvm); /* flush aux queue */
|
iwl_mvm_roc_finished(mvm); /* flush aux queue */
|
||||||
list_del(&te_data->list); /* remove from list */
|
list_del(&aux_roc_te->list); /* remove from list */
|
||||||
te_data->running = false;
|
aux_roc_te->running = false;
|
||||||
te_data->vif = NULL;
|
aux_roc_te->vif = NULL;
|
||||||
te_data->uid = 0;
|
aux_roc_te->uid = 0;
|
||||||
te_data->id = TE_MAX;
|
aux_roc_te->id = TE_MAX;
|
||||||
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
|
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
|
||||||
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
|
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
|
||||||
te_data->running = true;
|
aux_roc_te->running = true;
|
||||||
ieee80211_ready_on_channel(mvm->hw); /* Start TE */
|
ieee80211_ready_on_channel(mvm->hw); /* Start TE */
|
||||||
} else {
|
} else {
|
||||||
IWL_DEBUG_TE(mvm,
|
IWL_DEBUG_TE(mvm,
|
||||||
|
|||||||
@@ -159,9 +159,15 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
|||||||
|
|
||||||
u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)
|
u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)
|
||||||
{
|
{
|
||||||
return (rate_idx >= IWL_FIRST_OFDM_RATE ?
|
if (iwl_fw_lookup_cmd_ver(fw, TX_CMD, 0) > 8)
|
||||||
rate_idx - IWL_FIRST_OFDM_RATE :
|
/* In the new rate legacy rates are indexed:
|
||||||
rate_idx);
|
* 0 - 3 for CCK and 0 - 7 for OFDM.
|
||||||
|
*/
|
||||||
|
return (rate_idx >= IWL_FIRST_OFDM_RATE ?
|
||||||
|
rate_idx - IWL_FIRST_OFDM_RATE :
|
||||||
|
rate_idx);
|
||||||
|
|
||||||
|
return iwl_fw_rate_idx_to_plcp(rate_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)
|
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)
|
||||||
|
|||||||
@@ -2966,6 +2966,51 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask)
|
|||||||
/*
|
/*
|
||||||
* CMD_SET_BEACON.
|
* CMD_SET_BEACON.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static bool mwl8k_beacon_has_ds_params(const u8 *buf, int len)
|
||||||
|
{
|
||||||
|
const struct ieee80211_mgmt *mgmt = (const void *)buf;
|
||||||
|
int ies_len;
|
||||||
|
|
||||||
|
if (len <= offsetof(struct ieee80211_mgmt, u.beacon.variable))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ies_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||||
|
|
||||||
|
return cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable,
|
||||||
|
ies_len) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mwl8k_beacon_copy_inject_ds_params(struct ieee80211_hw *hw,
|
||||||
|
u8 *buf_dst, const u8 *buf_src,
|
||||||
|
int src_len)
|
||||||
|
{
|
||||||
|
const struct ieee80211_mgmt *mgmt = (const void *)buf_src;
|
||||||
|
static const u8 before_ds_params[] = {
|
||||||
|
WLAN_EID_SSID,
|
||||||
|
WLAN_EID_SUPP_RATES,
|
||||||
|
};
|
||||||
|
const u8 *ies;
|
||||||
|
int hdr_len, left, offs, pos;
|
||||||
|
|
||||||
|
ies = mgmt->u.beacon.variable;
|
||||||
|
hdr_len = offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||||
|
|
||||||
|
offs = ieee80211_ie_split(ies, src_len - hdr_len, before_ds_params,
|
||||||
|
ARRAY_SIZE(before_ds_params), 0);
|
||||||
|
|
||||||
|
pos = hdr_len + offs;
|
||||||
|
left = src_len - pos;
|
||||||
|
|
||||||
|
memcpy(buf_dst, buf_src, pos);
|
||||||
|
|
||||||
|
/* Inject a DSSS Parameter Set after SSID + Supp Rates */
|
||||||
|
buf_dst[pos + 0] = WLAN_EID_DS_PARAMS;
|
||||||
|
buf_dst[pos + 1] = 1;
|
||||||
|
buf_dst[pos + 2] = hw->conf.chandef.chan->hw_value;
|
||||||
|
|
||||||
|
memcpy(buf_dst + pos + 3, buf_src + pos, left);
|
||||||
|
}
|
||||||
struct mwl8k_cmd_set_beacon {
|
struct mwl8k_cmd_set_beacon {
|
||||||
struct mwl8k_cmd_pkt_hdr header;
|
struct mwl8k_cmd_pkt_hdr header;
|
||||||
__le16 beacon_len;
|
__le16 beacon_len;
|
||||||
@@ -2975,17 +3020,33 @@ struct mwl8k_cmd_set_beacon {
|
|||||||
static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
|
static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif, u8 *beacon, int len)
|
struct ieee80211_vif *vif, u8 *beacon, int len)
|
||||||
{
|
{
|
||||||
|
bool ds_params_present = mwl8k_beacon_has_ds_params(beacon, len);
|
||||||
struct mwl8k_cmd_set_beacon *cmd;
|
struct mwl8k_cmd_set_beacon *cmd;
|
||||||
int rc;
|
int rc, final_len = len;
|
||||||
|
|
||||||
cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL);
|
if (!ds_params_present) {
|
||||||
|
/*
|
||||||
|
* mwl8k firmware requires a DS Params IE with the current
|
||||||
|
* channel in AP beacons. If mac80211/hostapd does not
|
||||||
|
* include it, inject one here. IE ID + length + channel
|
||||||
|
* number = 3 bytes.
|
||||||
|
*/
|
||||||
|
final_len += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = kzalloc(sizeof(*cmd) + final_len, GFP_KERNEL);
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON);
|
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON);
|
||||||
cmd->header.length = cpu_to_le16(sizeof(*cmd) + len);
|
cmd->header.length = cpu_to_le16(sizeof(*cmd) + final_len);
|
||||||
cmd->beacon_len = cpu_to_le16(len);
|
cmd->beacon_len = cpu_to_le16(final_len);
|
||||||
memcpy(cmd->beacon, beacon, len);
|
|
||||||
|
if (ds_params_present)
|
||||||
|
memcpy(cmd->beacon, beacon, len);
|
||||||
|
else
|
||||||
|
mwl8k_beacon_copy_inject_ds_params(hw, cmd->beacon, beacon,
|
||||||
|
len);
|
||||||
|
|
||||||
rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
|
rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
|
||||||
kfree(cmd);
|
kfree(cmd);
|
||||||
|
|||||||
@@ -2003,8 +2003,14 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
|||||||
struct ieee80211_sta *sta = control->sta;
|
struct ieee80211_sta *sta = control->sta;
|
||||||
struct ieee80211_bss_conf *bss_conf;
|
struct ieee80211_bss_conf *bss_conf;
|
||||||
|
|
||||||
|
/* This can happen in case of monitor injection */
|
||||||
|
if (!vif) {
|
||||||
|
ieee80211_free_txskb(hw, skb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (link != IEEE80211_LINK_UNSPECIFIED) {
|
if (link != IEEE80211_LINK_UNSPECIFIED) {
|
||||||
bss_conf = rcu_dereference(txi->control.vif->link_conf[link]);
|
bss_conf = rcu_dereference(vif->link_conf[link]);
|
||||||
if (sta)
|
if (sta)
|
||||||
link_sta = rcu_dereference(sta->link[link]);
|
link_sta = rcu_dereference(sta->link[link]);
|
||||||
} else {
|
} else {
|
||||||
@@ -2065,13 +2071,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txi->control.vif)
|
if (vif)
|
||||||
hwsim_check_magic(txi->control.vif);
|
hwsim_check_magic(vif);
|
||||||
if (control->sta)
|
if (control->sta)
|
||||||
hwsim_check_sta_magic(control->sta);
|
hwsim_check_sta_magic(control->sta);
|
||||||
|
|
||||||
if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE))
|
if (ieee80211_hw_check(hw, SUPPORTS_RC_TABLE))
|
||||||
ieee80211_get_tx_rates(txi->control.vif, control->sta, skb,
|
ieee80211_get_tx_rates(vif, control->sta, skb,
|
||||||
txi->control.rates,
|
txi->control.rates,
|
||||||
ARRAY_SIZE(txi->control.rates));
|
ARRAY_SIZE(txi->control.rates));
|
||||||
|
|
||||||
|
|||||||
@@ -573,6 +573,8 @@ static int cq_create(struct mlx5_vdpa_net *ndev, u16 idx, u32 num_ent)
|
|||||||
vcq->mcq.set_ci_db = vcq->db.db;
|
vcq->mcq.set_ci_db = vcq->db.db;
|
||||||
vcq->mcq.arm_db = vcq->db.db + 1;
|
vcq->mcq.arm_db = vcq->db.db + 1;
|
||||||
vcq->mcq.cqe_sz = 64;
|
vcq->mcq.cqe_sz = 64;
|
||||||
|
vcq->mcq.comp = mlx5_vdpa_cq_comp;
|
||||||
|
vcq->cqe = num_ent;
|
||||||
|
|
||||||
err = cq_frag_buf_alloc(ndev, &vcq->buf, num_ent);
|
err = cq_frag_buf_alloc(ndev, &vcq->buf, num_ent);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -612,10 +614,6 @@ static int cq_create(struct mlx5_vdpa_net *ndev, u16 idx, u32 num_ent)
|
|||||||
if (err)
|
if (err)
|
||||||
goto err_vec;
|
goto err_vec;
|
||||||
|
|
||||||
vcq->mcq.comp = mlx5_vdpa_cq_comp;
|
|
||||||
vcq->cqe = num_ent;
|
|
||||||
vcq->mcq.set_ci_db = vcq->db.db;
|
|
||||||
vcq->mcq.arm_db = vcq->db.db + 1;
|
|
||||||
mlx5_cq_arm(&mvq->cq.mcq, MLX5_CQ_DB_REQ_NOT, uar_page, mvq->cq.mcq.cons_index);
|
mlx5_cq_arm(&mvq->cq.mcq, MLX5_CQ_DB_REQ_NOT, uar_page, mvq->cq.mcq.cons_index);
|
||||||
kfree(in);
|
kfree(in);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ struct ethtool_pause_stats {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define ETHTOOL_MAX_LANES 8
|
#define ETHTOOL_MAX_LANES 8
|
||||||
/**
|
/*
|
||||||
* IEEE 802.3ck/df defines 16 bins for FEC histogram plus one more for
|
* IEEE 802.3ck/df defines 16 bins for FEC histogram plus one more for
|
||||||
* the end-of-list marker, total 17 items
|
* the end-of-list marker, total 17 items
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -183,6 +183,7 @@ static inline void mlx5_cq_put(struct mlx5_core_cq *cq)
|
|||||||
complete(&cq->free);
|
complete(&cq->free);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mlx5_add_cq_to_tasklet(struct mlx5_core_cq *cq, struct mlx5_eqe *eqe);
|
||||||
int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
|
int mlx5_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
|
||||||
u32 *in, int inlen, u32 *out, int outlen);
|
u32 *in, int inlen, u32 *out, int outlen);
|
||||||
int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
|
int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
|
||||||
|
|||||||
@@ -2783,6 +2783,11 @@ struct hci_ev_le_per_adv_report {
|
|||||||
__u8 data[];
|
__u8 data[];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define HCI_EV_LE_PA_SYNC_LOST 0x10
|
||||||
|
struct hci_ev_le_pa_sync_lost {
|
||||||
|
__le16 handle;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
#define LE_PA_DATA_COMPLETE 0x00
|
#define LE_PA_DATA_COMPLETE 0x00
|
||||||
#define LE_PA_DATA_MORE_TO_COME 0x01
|
#define LE_PA_DATA_MORE_TO_COME 0x01
|
||||||
#define LE_PA_DATA_TRUNCATED 0x02
|
#define LE_PA_DATA_TRUNCATED 0x02
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ static bool enable_6lowpan;
|
|||||||
static struct l2cap_chan *listen_chan;
|
static struct l2cap_chan *listen_chan;
|
||||||
static DEFINE_MUTEX(set_lock);
|
static DEFINE_MUTEX(set_lock);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LOWPAN_PEER_CLOSING,
|
||||||
|
LOWPAN_PEER_MAXBITS
|
||||||
|
};
|
||||||
|
|
||||||
struct lowpan_peer {
|
struct lowpan_peer {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct rcu_head rcu;
|
struct rcu_head rcu;
|
||||||
@@ -61,6 +66,8 @@ struct lowpan_peer {
|
|||||||
/* peer addresses in various formats */
|
/* peer addresses in various formats */
|
||||||
unsigned char lladdr[ETH_ALEN];
|
unsigned char lladdr[ETH_ALEN];
|
||||||
struct in6_addr peer_addr;
|
struct in6_addr peer_addr;
|
||||||
|
|
||||||
|
DECLARE_BITMAP(flags, LOWPAN_PEER_MAXBITS);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lowpan_btle_dev {
|
struct lowpan_btle_dev {
|
||||||
@@ -289,6 +296,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
|
|||||||
local_skb->pkt_type = PACKET_HOST;
|
local_skb->pkt_type = PACKET_HOST;
|
||||||
local_skb->dev = dev;
|
local_skb->dev = dev;
|
||||||
|
|
||||||
|
skb_reset_mac_header(local_skb);
|
||||||
skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
|
skb_set_transport_header(local_skb, sizeof(struct ipv6hdr));
|
||||||
|
|
||||||
if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) {
|
if (give_skb_to_upper(local_skb, dev) != NET_RX_SUCCESS) {
|
||||||
@@ -919,7 +927,9 @@ static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type)
|
|||||||
|
|
||||||
BT_DBG("peer %p chan %p", peer, peer->chan);
|
BT_DBG("peer %p chan %p", peer, peer->chan);
|
||||||
|
|
||||||
|
l2cap_chan_lock(peer->chan);
|
||||||
l2cap_chan_close(peer->chan, ENOENT);
|
l2cap_chan_close(peer->chan, ENOENT);
|
||||||
|
l2cap_chan_unlock(peer->chan);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -956,10 +966,11 @@ static struct l2cap_chan *bt_6lowpan_listen(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type,
|
static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type,
|
||||||
struct l2cap_conn **conn)
|
struct l2cap_conn **conn, bool disconnect)
|
||||||
{
|
{
|
||||||
struct hci_conn *hcon;
|
struct hci_conn *hcon;
|
||||||
struct hci_dev *hdev;
|
struct hci_dev *hdev;
|
||||||
|
int le_addr_type;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu",
|
n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu",
|
||||||
@@ -970,13 +981,32 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type,
|
|||||||
if (n < 7)
|
if (n < 7)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (disconnect) {
|
||||||
|
/* The "disconnect" debugfs command has used different address
|
||||||
|
* type constants than "connect" since 2015. Let's retain that
|
||||||
|
* for now even though it's obviously buggy...
|
||||||
|
*/
|
||||||
|
*addr_type += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*addr_type) {
|
||||||
|
case BDADDR_LE_PUBLIC:
|
||||||
|
le_addr_type = ADDR_LE_DEV_PUBLIC;
|
||||||
|
break;
|
||||||
|
case BDADDR_LE_RANDOM:
|
||||||
|
le_addr_type = ADDR_LE_DEV_RANDOM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
/* The LE_PUBLIC address type is ignored because of BDADDR_ANY */
|
/* The LE_PUBLIC address type is ignored because of BDADDR_ANY */
|
||||||
hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC);
|
hdev = hci_get_route(addr, BDADDR_ANY, BDADDR_LE_PUBLIC);
|
||||||
if (!hdev)
|
if (!hdev)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type);
|
hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type);
|
||||||
hci_dev_unlock(hdev);
|
hci_dev_unlock(hdev);
|
||||||
hci_dev_put(hdev);
|
hci_dev_put(hdev);
|
||||||
|
|
||||||
@@ -993,41 +1023,52 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type,
|
|||||||
static void disconnect_all_peers(void)
|
static void disconnect_all_peers(void)
|
||||||
{
|
{
|
||||||
struct lowpan_btle_dev *entry;
|
struct lowpan_btle_dev *entry;
|
||||||
struct lowpan_peer *peer, *tmp_peer, *new_peer;
|
struct lowpan_peer *peer;
|
||||||
struct list_head peers;
|
int nchans;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&peers);
|
/* l2cap_chan_close() cannot be called from RCU, and lock ordering
|
||||||
|
* chan->lock > devices_lock prevents taking write side lock, so copy
|
||||||
/* We make a separate list of peers as the close_cb() will
|
* then close.
|
||||||
* modify the device peers list so it is better not to mess
|
|
||||||
* with the same list at the same time.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list)
|
||||||
list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
|
list_for_each_entry_rcu(peer, &entry->peers, list)
|
||||||
list_for_each_entry_rcu(peer, &entry->peers, list) {
|
clear_bit(LOWPAN_PEER_CLOSING, peer->flags);
|
||||||
new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC);
|
|
||||||
if (!new_peer)
|
|
||||||
break;
|
|
||||||
|
|
||||||
new_peer->chan = peer->chan;
|
|
||||||
INIT_LIST_HEAD(&new_peer->list);
|
|
||||||
|
|
||||||
list_add(&new_peer->list, &peers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
spin_lock(&devices_lock);
|
do {
|
||||||
list_for_each_entry_safe(peer, tmp_peer, &peers, list) {
|
struct l2cap_chan *chans[32];
|
||||||
l2cap_chan_close(peer->chan, ENOENT);
|
int i;
|
||||||
|
|
||||||
list_del_rcu(&peer->list);
|
nchans = 0;
|
||||||
kfree_rcu(peer, rcu);
|
|
||||||
}
|
spin_lock(&devices_lock);
|
||||||
spin_unlock(&devices_lock);
|
|
||||||
|
list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
|
||||||
|
list_for_each_entry_rcu(peer, &entry->peers, list) {
|
||||||
|
if (test_and_set_bit(LOWPAN_PEER_CLOSING,
|
||||||
|
peer->flags))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
l2cap_chan_hold(peer->chan);
|
||||||
|
chans[nchans++] = peer->chan;
|
||||||
|
|
||||||
|
if (nchans >= ARRAY_SIZE(chans))
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
spin_unlock(&devices_lock);
|
||||||
|
|
||||||
|
for (i = 0; i < nchans; ++i) {
|
||||||
|
l2cap_chan_lock(chans[i]);
|
||||||
|
l2cap_chan_close(chans[i], ENOENT);
|
||||||
|
l2cap_chan_unlock(chans[i]);
|
||||||
|
l2cap_chan_put(chans[i]);
|
||||||
|
}
|
||||||
|
} while (nchans);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct set_enable {
|
struct set_enable {
|
||||||
@@ -1050,7 +1091,9 @@ static void do_enable_set(struct work_struct *work)
|
|||||||
|
|
||||||
mutex_lock(&set_lock);
|
mutex_lock(&set_lock);
|
||||||
if (listen_chan) {
|
if (listen_chan) {
|
||||||
|
l2cap_chan_lock(listen_chan);
|
||||||
l2cap_chan_close(listen_chan, 0);
|
l2cap_chan_close(listen_chan, 0);
|
||||||
|
l2cap_chan_unlock(listen_chan);
|
||||||
l2cap_chan_put(listen_chan);
|
l2cap_chan_put(listen_chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1103,13 +1146,15 @@ static ssize_t lowpan_control_write(struct file *fp,
|
|||||||
buf[buf_size] = '\0';
|
buf[buf_size] = '\0';
|
||||||
|
|
||||||
if (memcmp(buf, "connect ", 8) == 0) {
|
if (memcmp(buf, "connect ", 8) == 0) {
|
||||||
ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn);
|
ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn, false);
|
||||||
if (ret == -EINVAL)
|
if (ret == -EINVAL)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
mutex_lock(&set_lock);
|
mutex_lock(&set_lock);
|
||||||
if (listen_chan) {
|
if (listen_chan) {
|
||||||
|
l2cap_chan_lock(listen_chan);
|
||||||
l2cap_chan_close(listen_chan, 0);
|
l2cap_chan_close(listen_chan, 0);
|
||||||
|
l2cap_chan_unlock(listen_chan);
|
||||||
l2cap_chan_put(listen_chan);
|
l2cap_chan_put(listen_chan);
|
||||||
listen_chan = NULL;
|
listen_chan = NULL;
|
||||||
}
|
}
|
||||||
@@ -1140,7 +1185,7 @@ static ssize_t lowpan_control_write(struct file *fp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(buf, "disconnect ", 11) == 0) {
|
if (memcmp(buf, "disconnect ", 11) == 0) {
|
||||||
ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn);
|
ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn, true);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -1271,7 +1316,9 @@ static void __exit bt_6lowpan_exit(void)
|
|||||||
debugfs_remove(lowpan_control_debugfs);
|
debugfs_remove(lowpan_control_debugfs);
|
||||||
|
|
||||||
if (listen_chan) {
|
if (listen_chan) {
|
||||||
|
l2cap_chan_lock(listen_chan);
|
||||||
l2cap_chan_close(listen_chan, 0);
|
l2cap_chan_close(listen_chan, 0);
|
||||||
|
l2cap_chan_unlock(listen_chan);
|
||||||
l2cap_chan_put(listen_chan);
|
l2cap_chan_put(listen_chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -769,21 +769,23 @@ static void find_bis(struct hci_conn *conn, void *data)
|
|||||||
d->count++;
|
d->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *conn)
|
static int hci_le_big_terminate(struct hci_dev *hdev, struct hci_conn *conn)
|
||||||
{
|
{
|
||||||
struct iso_list_data *d;
|
struct iso_list_data *d;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", big, conn->sync_handle);
|
bt_dev_dbg(hdev, "hcon %p big 0x%2.2x sync_handle 0x%4.4x", conn,
|
||||||
|
conn->iso_qos.bcast.big, conn->sync_handle);
|
||||||
|
|
||||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||||
if (!d)
|
if (!d)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
d->big = big;
|
d->big = conn->iso_qos.bcast.big;
|
||||||
d->sync_handle = conn->sync_handle;
|
d->sync_handle = conn->sync_handle;
|
||||||
|
|
||||||
if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
|
if (conn->type == PA_LINK &&
|
||||||
|
test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
|
||||||
hci_conn_hash_list_flag(hdev, find_bis, PA_LINK,
|
hci_conn_hash_list_flag(hdev, find_bis, PA_LINK,
|
||||||
HCI_CONN_PA_SYNC, d);
|
HCI_CONN_PA_SYNC, d);
|
||||||
|
|
||||||
@@ -801,6 +803,9 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c
|
|||||||
d->big_sync_term = true;
|
d->big_sync_term = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!d->pa_sync_term && !d->big_sync_term)
|
||||||
|
return 0;
|
||||||
|
|
||||||
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
|
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
|
||||||
terminate_big_destroy);
|
terminate_big_destroy);
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -852,8 +857,7 @@ static void bis_cleanup(struct hci_conn *conn)
|
|||||||
|
|
||||||
hci_le_terminate_big(hdev, conn);
|
hci_le_terminate_big(hdev, conn);
|
||||||
} else {
|
} else {
|
||||||
hci_le_big_terminate(hdev, conn->iso_qos.bcast.big,
|
hci_le_big_terminate(hdev, conn);
|
||||||
conn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -994,19 +998,20 @@ static struct hci_conn *__hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t
|
|||||||
conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
|
conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
|
||||||
break;
|
break;
|
||||||
case CIS_LINK:
|
case CIS_LINK:
|
||||||
case BIS_LINK:
|
|
||||||
case PA_LINK:
|
|
||||||
/* conn->src should reflect the local identity address */
|
/* conn->src should reflect the local identity address */
|
||||||
hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
|
hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
|
||||||
|
|
||||||
/* set proper cleanup function */
|
if (conn->role == HCI_ROLE_MASTER)
|
||||||
if (!bacmp(dst, BDADDR_ANY))
|
|
||||||
conn->cleanup = bis_cleanup;
|
|
||||||
else if (conn->role == HCI_ROLE_MASTER)
|
|
||||||
conn->cleanup = cis_cleanup;
|
conn->cleanup = cis_cleanup;
|
||||||
|
|
||||||
conn->mtu = hdev->iso_mtu ? hdev->iso_mtu :
|
conn->mtu = hdev->iso_mtu;
|
||||||
hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
|
break;
|
||||||
|
case PA_LINK:
|
||||||
|
case BIS_LINK:
|
||||||
|
/* conn->src should reflect the local identity address */
|
||||||
|
hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
|
||||||
|
conn->cleanup = bis_cleanup;
|
||||||
|
conn->mtu = hdev->iso_mtu;
|
||||||
break;
|
break;
|
||||||
case SCO_LINK:
|
case SCO_LINK:
|
||||||
if (lmp_esco_capable(hdev))
|
if (lmp_esco_capable(hdev))
|
||||||
|
|||||||
@@ -5843,6 +5843,29 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, void *data,
|
|||||||
le16_to_cpu(ev->supervision_timeout));
|
le16_to_cpu(ev->supervision_timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hci_le_pa_sync_lost_evt(struct hci_dev *hdev, void *data,
|
||||||
|
struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct hci_ev_le_pa_sync_lost *ev = data;
|
||||||
|
u16 handle = le16_to_cpu(ev->handle);
|
||||||
|
struct hci_conn *conn;
|
||||||
|
|
||||||
|
bt_dev_dbg(hdev, "sync handle 0x%4.4x", handle);
|
||||||
|
|
||||||
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
|
/* Delete the pa sync connection */
|
||||||
|
conn = hci_conn_hash_lookup_pa_sync_handle(hdev, handle);
|
||||||
|
if (conn) {
|
||||||
|
clear_bit(HCI_CONN_BIG_SYNC, &conn->flags);
|
||||||
|
clear_bit(HCI_CONN_PA_SYNC, &conn->flags);
|
||||||
|
hci_disconn_cfm(conn, HCI_ERROR_REMOTE_USER_TERM);
|
||||||
|
hci_conn_del(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
hci_dev_unlock(hdev);
|
||||||
|
}
|
||||||
|
|
||||||
static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data,
|
static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
@@ -7001,14 +7024,9 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev->status != 0x42) {
|
if (ev->status != 0x42)
|
||||||
/* Mark PA sync as established */
|
/* Mark PA sync as established */
|
||||||
set_bit(HCI_CONN_PA_SYNC, &bis->flags);
|
set_bit(HCI_CONN_PA_SYNC, &bis->flags);
|
||||||
/* Reset cleanup callback of PA Sync so it doesn't
|
|
||||||
* terminate the sync when deleting the connection.
|
|
||||||
*/
|
|
||||||
conn->cleanup = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bis->sync_handle = conn->sync_handle;
|
bis->sync_handle = conn->sync_handle;
|
||||||
bis->iso_qos.bcast.big = ev->handle;
|
bis->iso_qos.bcast.big = ev->handle;
|
||||||
@@ -7051,29 +7069,24 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data,
|
|||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct hci_evt_le_big_sync_lost *ev = data;
|
struct hci_evt_le_big_sync_lost *ev = data;
|
||||||
struct hci_conn *bis, *conn;
|
struct hci_conn *bis;
|
||||||
bool mgmt_conn;
|
bool mgmt_conn = false;
|
||||||
|
|
||||||
bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle);
|
bt_dev_dbg(hdev, "big handle 0x%2.2x", ev->handle);
|
||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
/* Delete the pa sync connection */
|
|
||||||
bis = hci_conn_hash_lookup_pa_sync_big_handle(hdev, ev->handle);
|
|
||||||
if (bis) {
|
|
||||||
conn = hci_conn_hash_lookup_pa_sync_handle(hdev,
|
|
||||||
bis->sync_handle);
|
|
||||||
if (conn)
|
|
||||||
hci_conn_del(conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete each bis connection */
|
/* Delete each bis connection */
|
||||||
while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle,
|
while ((bis = hci_conn_hash_lookup_big_state(hdev, ev->handle,
|
||||||
BT_CONNECTED,
|
BT_CONNECTED,
|
||||||
HCI_ROLE_SLAVE))) {
|
HCI_ROLE_SLAVE))) {
|
||||||
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &bis->flags);
|
if (!mgmt_conn) {
|
||||||
mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type,
|
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED,
|
||||||
ev->reason, mgmt_conn);
|
&bis->flags);
|
||||||
|
mgmt_device_disconnected(hdev, &bis->dst, bis->type,
|
||||||
|
bis->dst_type, ev->reason,
|
||||||
|
mgmt_conn);
|
||||||
|
}
|
||||||
|
|
||||||
clear_bit(HCI_CONN_BIG_SYNC, &bis->flags);
|
clear_bit(HCI_CONN_BIG_SYNC, &bis->flags);
|
||||||
hci_disconn_cfm(bis, ev->reason);
|
hci_disconn_cfm(bis, ev->reason);
|
||||||
@@ -7187,6 +7200,9 @@ static const struct hci_le_ev {
|
|||||||
hci_le_per_adv_report_evt,
|
hci_le_per_adv_report_evt,
|
||||||
sizeof(struct hci_ev_le_per_adv_report),
|
sizeof(struct hci_ev_le_per_adv_report),
|
||||||
HCI_MAX_EVENT_SIZE),
|
HCI_MAX_EVENT_SIZE),
|
||||||
|
/* [0x10 = HCI_EV_LE_PA_SYNC_LOST] */
|
||||||
|
HCI_LE_EV(HCI_EV_LE_PA_SYNC_LOST, hci_le_pa_sync_lost_evt,
|
||||||
|
sizeof(struct hci_ev_le_pa_sync_lost)),
|
||||||
/* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */
|
/* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */
|
||||||
HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt,
|
HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt,
|
||||||
sizeof(struct hci_evt_le_ext_adv_set_term)),
|
sizeof(struct hci_evt_le_ext_adv_set_term)),
|
||||||
|
|||||||
@@ -6999,7 +6999,7 @@ static void create_pa_complete(struct hci_dev *hdev, void *data, int err)
|
|||||||
|
|
||||||
hci_dev_lock(hdev);
|
hci_dev_lock(hdev);
|
||||||
|
|
||||||
if (!hci_conn_valid(hdev, conn))
|
if (hci_conn_valid(hdev, conn))
|
||||||
clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
|
clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
|
|||||||
@@ -497,6 +497,7 @@ void l2cap_chan_hold(struct l2cap_chan *c)
|
|||||||
|
|
||||||
kref_get(&c->kref);
|
kref_get(&c->kref);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(l2cap_chan_hold);
|
||||||
|
|
||||||
struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
|
struct l2cap_chan *l2cap_chan_hold_unless_zero(struct l2cap_chan *c)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9497,6 +9497,7 @@ void mgmt_index_removed(struct hci_dev *hdev)
|
|||||||
cancel_delayed_work_sync(&hdev->discov_off);
|
cancel_delayed_work_sync(&hdev->discov_off);
|
||||||
cancel_delayed_work_sync(&hdev->service_cache);
|
cancel_delayed_work_sync(&hdev->service_cache);
|
||||||
cancel_delayed_work_sync(&hdev->rpa_expired);
|
cancel_delayed_work_sync(&hdev->rpa_expired);
|
||||||
|
cancel_delayed_work_sync(&hdev->mesh_send_done);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mgmt_power_on(struct hci_dev *hdev, int err)
|
void mgmt_power_on(struct hci_dev *hdev, int err)
|
||||||
|
|||||||
@@ -811,6 +811,10 @@ static void __netpoll_cleanup(struct netpoll *np)
|
|||||||
if (!npinfo)
|
if (!npinfo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* At this point, there is a single npinfo instance per netdevice, and
|
||||||
|
* its refcnt tracks how many netpoll structures are linked to it. We
|
||||||
|
* only perform npinfo cleanup when the refcnt decrements to zero.
|
||||||
|
*/
|
||||||
if (refcount_dec_and_test(&npinfo->refcnt)) {
|
if (refcount_dec_and_test(&npinfo->refcnt)) {
|
||||||
const struct net_device_ops *ops;
|
const struct net_device_ops *ops;
|
||||||
|
|
||||||
@@ -820,8 +824,7 @@ static void __netpoll_cleanup(struct netpoll *np)
|
|||||||
|
|
||||||
RCU_INIT_POINTER(np->dev->npinfo, NULL);
|
RCU_INIT_POINTER(np->dev->npinfo, NULL);
|
||||||
call_rcu(&npinfo->rcu, rcu_cleanup_netpoll_info);
|
call_rcu(&npinfo->rcu, rcu_cleanup_netpoll_info);
|
||||||
} else
|
}
|
||||||
RCU_INIT_POINTER(np->dev->npinfo, NULL);
|
|
||||||
|
|
||||||
skb_pool_flush(np);
|
skb_pool_flush(np);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,7 +176,8 @@ static struct sk_buff *brcm_tag_rcv_ll(struct sk_buff *skb,
|
|||||||
/* Remove Broadcom tag and update checksum */
|
/* Remove Broadcom tag and update checksum */
|
||||||
skb_pull_rcsum(skb, BRCM_TAG_LEN);
|
skb_pull_rcsum(skb, BRCM_TAG_LEN);
|
||||||
|
|
||||||
dsa_default_offload_fwd_mark(skb);
|
if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest)))
|
||||||
|
dsa_default_offload_fwd_mark(skb);
|
||||||
|
|
||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
@@ -250,7 +251,8 @@ static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
|
|||||||
/* Remove Broadcom tag and update checksum */
|
/* Remove Broadcom tag and update checksum */
|
||||||
skb_pull_rcsum(skb, len);
|
skb_pull_rcsum(skb, len);
|
||||||
|
|
||||||
dsa_default_offload_fwd_mark(skb);
|
if (likely(!is_link_local_ether_addr(eth_hdr(skb)->h_dest)))
|
||||||
|
dsa_default_offload_fwd_mark(skb);
|
||||||
|
|
||||||
dsa_strip_etype_header(skb, len);
|
dsa_strip_etype_header(skb, len);
|
||||||
|
|
||||||
|
|||||||
@@ -259,6 +259,7 @@ static int tls_handshake_accept(struct handshake_req *req,
|
|||||||
|
|
||||||
out_cancel:
|
out_cancel:
|
||||||
genlmsg_cancel(msg, hdr);
|
genlmsg_cancel(msg, hdr);
|
||||||
|
nlmsg_free(msg);
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -320,6 +320,9 @@ static void send_hsr_supervision_frame(struct hsr_port *port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag));
|
hsr_stag = skb_put(skb, sizeof(struct hsr_sup_tag));
|
||||||
|
skb_set_network_header(skb, ETH_HLEN + HSR_HLEN);
|
||||||
|
skb_reset_mac_len(skb);
|
||||||
|
|
||||||
set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf));
|
set_hsr_stag_path(hsr_stag, (hsr->prot_version ? 0x0 : 0xf));
|
||||||
set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version);
|
set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version);
|
||||||
|
|
||||||
@@ -334,7 +337,7 @@ static void send_hsr_supervision_frame(struct hsr_port *port,
|
|||||||
}
|
}
|
||||||
|
|
||||||
hsr_stag->tlv.HSR_TLV_type = type;
|
hsr_stag->tlv.HSR_TLV_type = type;
|
||||||
/* TODO: Why 12 in HSRv0? */
|
/* HSRv0 has 6 unused bytes after the MAC */
|
||||||
hsr_stag->tlv.HSR_TLV_length = hsr->prot_version ?
|
hsr_stag->tlv.HSR_TLV_length = hsr->prot_version ?
|
||||||
sizeof(struct hsr_sup_payload) : 12;
|
sizeof(struct hsr_sup_payload) : 12;
|
||||||
|
|
||||||
|
|||||||
@@ -262,15 +262,23 @@ static struct sk_buff *prp_fill_rct(struct sk_buff *skb,
|
|||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hsr_set_path_id(struct hsr_ethhdr *hsr_ethhdr,
|
static void hsr_set_path_id(struct hsr_frame_info *frame,
|
||||||
|
struct hsr_ethhdr *hsr_ethhdr,
|
||||||
struct hsr_port *port)
|
struct hsr_port *port)
|
||||||
{
|
{
|
||||||
int path_id;
|
int path_id;
|
||||||
|
|
||||||
if (port->type == HSR_PT_SLAVE_A)
|
if (port->hsr->prot_version) {
|
||||||
path_id = 0;
|
if (port->type == HSR_PT_SLAVE_A)
|
||||||
else
|
path_id = 0;
|
||||||
path_id = 1;
|
else
|
||||||
|
path_id = 1;
|
||||||
|
} else {
|
||||||
|
if (frame->is_supervision)
|
||||||
|
path_id = 0xf;
|
||||||
|
else
|
||||||
|
path_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
set_hsr_tag_path(&hsr_ethhdr->hsr_tag, path_id);
|
set_hsr_tag_path(&hsr_ethhdr->hsr_tag, path_id);
|
||||||
}
|
}
|
||||||
@@ -304,7 +312,7 @@ static struct sk_buff *hsr_fill_tag(struct sk_buff *skb,
|
|||||||
else
|
else
|
||||||
hsr_ethhdr = (struct hsr_ethhdr *)pc;
|
hsr_ethhdr = (struct hsr_ethhdr *)pc;
|
||||||
|
|
||||||
hsr_set_path_id(hsr_ethhdr, port);
|
hsr_set_path_id(frame, hsr_ethhdr, port);
|
||||||
set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size);
|
set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size);
|
||||||
hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr);
|
hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr);
|
||||||
hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto;
|
hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto;
|
||||||
@@ -330,7 +338,7 @@ struct sk_buff *hsr_create_tagged_frame(struct hsr_frame_info *frame,
|
|||||||
(struct hsr_ethhdr *)skb_mac_header(frame->skb_hsr);
|
(struct hsr_ethhdr *)skb_mac_header(frame->skb_hsr);
|
||||||
|
|
||||||
/* set the lane id properly */
|
/* set the lane id properly */
|
||||||
hsr_set_path_id(hsr_ethhdr, port);
|
hsr_set_path_id(frame, hsr_ethhdr, port);
|
||||||
return skb_clone(frame->skb_hsr, GFP_ATOMIC);
|
return skb_clone(frame->skb_hsr, GFP_ATOMIC);
|
||||||
} else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) {
|
} else if (port->dev->features & NETIF_F_HW_HSR_TAG_INS) {
|
||||||
return skb_clone(frame->skb_std, GFP_ATOMIC);
|
return skb_clone(frame->skb_std, GFP_ATOMIC);
|
||||||
|
|||||||
@@ -607,6 +607,11 @@ static void fnhe_remove_oldest(struct fnhe_hash_bucket *hash)
|
|||||||
oldest_p = fnhe_p;
|
oldest_p = fnhe_p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear oldest->fnhe_daddr to prevent this fnhe from being
|
||||||
|
* rebound with new dsts in rt_bind_exception().
|
||||||
|
*/
|
||||||
|
oldest->fnhe_daddr = 0;
|
||||||
fnhe_flush_routes(oldest);
|
fnhe_flush_routes(oldest);
|
||||||
*oldest_p = oldest->fnhe_next;
|
*oldest_p = oldest->fnhe_next;
|
||||||
kfree_rcu(oldest, rcu);
|
kfree_rcu(oldest, rcu);
|
||||||
|
|||||||
@@ -223,6 +223,10 @@ static int ieee80211_can_powered_addr_change(struct ieee80211_sub_if_data *sdata
|
|||||||
if (netif_carrier_ok(sdata->dev))
|
if (netif_carrier_ok(sdata->dev))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
/* if any stations are set known (so they know this vif too), reject */
|
||||||
|
if (sta_info_get_by_idx(sdata, 0))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
/* First check no ROC work is happening on this iface */
|
/* First check no ROC work is happening on this iface */
|
||||||
list_for_each_entry(roc, &local->roc_list, list) {
|
list_for_each_entry(roc, &local->roc_list, list) {
|
||||||
if (roc->sdata != sdata)
|
if (roc->sdata != sdata)
|
||||||
@@ -242,12 +246,16 @@ static int ieee80211_can_powered_addr_change(struct ieee80211_sub_if_data *sdata
|
|||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* More interface types could be added here but changing the
|
||||||
|
* address while powered makes the most sense in client modes.
|
||||||
|
*/
|
||||||
switch (sdata->vif.type) {
|
switch (sdata->vif.type) {
|
||||||
case NL80211_IFTYPE_STATION:
|
case NL80211_IFTYPE_STATION:
|
||||||
case NL80211_IFTYPE_P2P_CLIENT:
|
case NL80211_IFTYPE_P2P_CLIENT:
|
||||||
/* More interface types could be added here but changing the
|
/* refuse while connecting */
|
||||||
* address while powered makes the most sense in client modes.
|
if (sdata->u.mgd.auth_data || sdata->u.mgd.assoc_data)
|
||||||
*/
|
return -EBUSY;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EOPNOTSUPP;
|
ret = -EOPNOTSUPP;
|
||||||
|
|||||||
@@ -5360,10 +5360,14 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
|
|||||||
if (WARN_ON(!local->started))
|
if (WARN_ON(!local->started))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) {
|
if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC) &&
|
||||||
|
!(status->flag & RX_FLAG_NO_PSDU &&
|
||||||
|
status->zero_length_psdu_type ==
|
||||||
|
IEEE80211_RADIOTAP_ZERO_LEN_PSDU_NOT_CAPTURED))) {
|
||||||
/*
|
/*
|
||||||
* Validate the rate, unless a PLCP error means that
|
* Validate the rate, unless there was a PLCP error which may
|
||||||
* we probably can't have a valid rate here anyway.
|
* have an invalid rate or the PSDU was not capture and may be
|
||||||
|
* missing rate information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
switch (status->encoding) {
|
switch (status->encoding) {
|
||||||
|
|||||||
@@ -195,13 +195,15 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
|
|||||||
const struct tcf_connmark_info *ci = to_connmark(a);
|
const struct tcf_connmark_info *ci = to_connmark(a);
|
||||||
unsigned char *b = skb_tail_pointer(skb);
|
unsigned char *b = skb_tail_pointer(skb);
|
||||||
const struct tcf_connmark_parms *parms;
|
const struct tcf_connmark_parms *parms;
|
||||||
struct tc_connmark opt = {
|
struct tc_connmark opt;
|
||||||
.index = ci->tcf_index,
|
|
||||||
.refcnt = refcount_read(&ci->tcf_refcnt) - ref,
|
|
||||||
.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind,
|
|
||||||
};
|
|
||||||
struct tcf_t t;
|
struct tcf_t t;
|
||||||
|
|
||||||
|
memset(&opt, 0, sizeof(opt));
|
||||||
|
|
||||||
|
opt.index = ci->tcf_index;
|
||||||
|
opt.refcnt = refcount_read(&ci->tcf_refcnt) - ref;
|
||||||
|
opt.bindcnt = atomic_read(&ci->tcf_bindcnt) - bind;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
parms = rcu_dereference(ci->parms);
|
parms = rcu_dereference(ci->parms);
|
||||||
|
|
||||||
|
|||||||
@@ -644,13 +644,15 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind,
|
|||||||
unsigned char *b = skb_tail_pointer(skb);
|
unsigned char *b = skb_tail_pointer(skb);
|
||||||
struct tcf_ife_info *ife = to_ife(a);
|
struct tcf_ife_info *ife = to_ife(a);
|
||||||
struct tcf_ife_params *p;
|
struct tcf_ife_params *p;
|
||||||
struct tc_ife opt = {
|
struct tc_ife opt;
|
||||||
.index = ife->tcf_index,
|
|
||||||
.refcnt = refcount_read(&ife->tcf_refcnt) - ref,
|
|
||||||
.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind,
|
|
||||||
};
|
|
||||||
struct tcf_t t;
|
struct tcf_t t;
|
||||||
|
|
||||||
|
memset(&opt, 0, sizeof(opt));
|
||||||
|
|
||||||
|
opt.index = ife->tcf_index,
|
||||||
|
opt.refcnt = refcount_read(&ife->tcf_refcnt) - ref,
|
||||||
|
opt.bindcnt = atomic_read(&ife->tcf_bindcnt) - bind,
|
||||||
|
|
||||||
spin_lock_bh(&ife->tcf_lock);
|
spin_lock_bh(&ife->tcf_lock);
|
||||||
opt.action = ife->tcf_action;
|
opt.action = ife->tcf_action;
|
||||||
p = rcu_dereference_protected(ife->params,
|
p = rcu_dereference_protected(ife->params,
|
||||||
|
|||||||
@@ -1599,6 +1599,11 @@ static int __tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
|
|||||||
NL_SET_ERR_MSG(extack, "Failed to find specified qdisc");
|
NL_SET_ERR_MSG(extack, "Failed to find specified qdisc");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
if (p->flags & TCQ_F_INGRESS) {
|
||||||
|
NL_SET_ERR_MSG(extack,
|
||||||
|
"Cannot add children to ingress/clsact qdisc");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
q = qdisc_leaf(p, clid, extack);
|
q = qdisc_leaf(p, clid, extack);
|
||||||
if (IS_ERR(q))
|
if (IS_ERR(q))
|
||||||
return PTR_ERR(q);
|
return PTR_ERR(q);
|
||||||
|
|||||||
@@ -180,9 +180,10 @@ static inline void dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q)
|
|||||||
static void try_bulk_dequeue_skb(struct Qdisc *q,
|
static void try_bulk_dequeue_skb(struct Qdisc *q,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
const struct netdev_queue *txq,
|
const struct netdev_queue *txq,
|
||||||
int *packets)
|
int *packets, int budget)
|
||||||
{
|
{
|
||||||
int bytelimit = qdisc_avail_bulklimit(txq) - skb->len;
|
int bytelimit = qdisc_avail_bulklimit(txq) - skb->len;
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
while (bytelimit > 0) {
|
while (bytelimit > 0) {
|
||||||
struct sk_buff *nskb = q->dequeue(q);
|
struct sk_buff *nskb = q->dequeue(q);
|
||||||
@@ -193,8 +194,10 @@ static void try_bulk_dequeue_skb(struct Qdisc *q,
|
|||||||
bytelimit -= nskb->len; /* covers GSO len */
|
bytelimit -= nskb->len; /* covers GSO len */
|
||||||
skb->next = nskb;
|
skb->next = nskb;
|
||||||
skb = nskb;
|
skb = nskb;
|
||||||
(*packets)++; /* GSO counts as one pkt */
|
if (++cnt >= budget)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
(*packets) += cnt;
|
||||||
skb_mark_not_on_list(skb);
|
skb_mark_not_on_list(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +231,7 @@ static void try_bulk_dequeue_skb_slow(struct Qdisc *q,
|
|||||||
* A requeued skb (via q->gso_skb) can also be a SKB list.
|
* A requeued skb (via q->gso_skb) can also be a SKB list.
|
||||||
*/
|
*/
|
||||||
static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
|
static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
|
||||||
int *packets)
|
int *packets, int budget)
|
||||||
{
|
{
|
||||||
const struct netdev_queue *txq = q->dev_queue;
|
const struct netdev_queue *txq = q->dev_queue;
|
||||||
struct sk_buff *skb = NULL;
|
struct sk_buff *skb = NULL;
|
||||||
@@ -295,7 +298,7 @@ validate:
|
|||||||
if (skb) {
|
if (skb) {
|
||||||
bulk:
|
bulk:
|
||||||
if (qdisc_may_bulk(q))
|
if (qdisc_may_bulk(q))
|
||||||
try_bulk_dequeue_skb(q, skb, txq, packets);
|
try_bulk_dequeue_skb(q, skb, txq, packets, budget);
|
||||||
else
|
else
|
||||||
try_bulk_dequeue_skb_slow(q, skb, packets);
|
try_bulk_dequeue_skb_slow(q, skb, packets);
|
||||||
}
|
}
|
||||||
@@ -387,7 +390,7 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
|
|||||||
* >0 - queue is not empty.
|
* >0 - queue is not empty.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static inline bool qdisc_restart(struct Qdisc *q, int *packets)
|
static inline bool qdisc_restart(struct Qdisc *q, int *packets, int budget)
|
||||||
{
|
{
|
||||||
spinlock_t *root_lock = NULL;
|
spinlock_t *root_lock = NULL;
|
||||||
struct netdev_queue *txq;
|
struct netdev_queue *txq;
|
||||||
@@ -396,7 +399,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets)
|
|||||||
bool validate;
|
bool validate;
|
||||||
|
|
||||||
/* Dequeue packet */
|
/* Dequeue packet */
|
||||||
skb = dequeue_skb(q, &validate, packets);
|
skb = dequeue_skb(q, &validate, packets, budget);
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -414,7 +417,7 @@ void __qdisc_run(struct Qdisc *q)
|
|||||||
int quota = READ_ONCE(net_hotdata.dev_tx_weight);
|
int quota = READ_ONCE(net_hotdata.dev_tx_weight);
|
||||||
int packets;
|
int packets;
|
||||||
|
|
||||||
while (qdisc_restart(q, &packets)) {
|
while (qdisc_restart(q, &packets, quota)) {
|
||||||
quota -= packets;
|
quota -= packets;
|
||||||
if (quota <= 0) {
|
if (quota <= 0) {
|
||||||
if (q->flags & TCQ_F_NOLOCK)
|
if (q->flags & TCQ_F_NOLOCK)
|
||||||
|
|||||||
@@ -486,6 +486,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
|
|||||||
|
|
||||||
if (tp->rttvar || tp->srtt) {
|
if (tp->rttvar || tp->srtt) {
|
||||||
struct net *net = tp->asoc->base.net;
|
struct net *net = tp->asoc->base.net;
|
||||||
|
unsigned int rto_beta, rto_alpha;
|
||||||
/* 6.3.1 C3) When a new RTT measurement R' is made, set
|
/* 6.3.1 C3) When a new RTT measurement R' is made, set
|
||||||
* RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'|
|
* RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'|
|
||||||
* SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R'
|
* SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R'
|
||||||
@@ -497,10 +498,14 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
|
|||||||
* For example, assuming the default value of RTO.Alpha of
|
* For example, assuming the default value of RTO.Alpha of
|
||||||
* 1/8, rto_alpha would be expressed as 3.
|
* 1/8, rto_alpha would be expressed as 3.
|
||||||
*/
|
*/
|
||||||
tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta)
|
rto_beta = READ_ONCE(net->sctp.rto_beta);
|
||||||
+ (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta);
|
if (rto_beta < 32)
|
||||||
tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha)
|
tp->rttvar = tp->rttvar - (tp->rttvar >> rto_beta)
|
||||||
+ (rtt >> net->sctp.rto_alpha);
|
+ (((__u32)abs((__s64)tp->srtt - (__s64)rtt)) >> rto_beta);
|
||||||
|
rto_alpha = READ_ONCE(net->sctp.rto_alpha);
|
||||||
|
if (rto_alpha < 32)
|
||||||
|
tp->srtt = tp->srtt - (tp->srtt >> rto_alpha)
|
||||||
|
+ (rtt >> rto_alpha);
|
||||||
} else {
|
} else {
|
||||||
/* 6.3.1 C2) When the first RTT measurement R is made, set
|
/* 6.3.1 C2) When the first RTT measurement R is made, set
|
||||||
* SRTT <- R, RTTVAR <- R/2.
|
* SRTT <- R, RTTVAR <- R/2.
|
||||||
|
|||||||
@@ -890,6 +890,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
|
|||||||
return SMC_CLC_DECL_CNFERR;
|
return SMC_CLC_DECL_CNFERR;
|
||||||
}
|
}
|
||||||
pclc_base->hdr.typev1 = SMC_TYPE_N;
|
pclc_base->hdr.typev1 = SMC_TYPE_N;
|
||||||
|
ini->smc_type_v1 = SMC_TYPE_N;
|
||||||
} else {
|
} else {
|
||||||
pclc_base->iparea_offset = htons(sizeof(*pclc_smcd));
|
pclc_base->iparea_offset = htons(sizeof(*pclc_smcd));
|
||||||
plen += sizeof(*pclc_prfx) +
|
plen += sizeof(*pclc_prfx) +
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
|
|||||||
strp_parser_err(strp, -EMSGSIZE, desc);
|
strp_parser_err(strp, -EMSGSIZE, desc);
|
||||||
break;
|
break;
|
||||||
} else if (len <= (ssize_t)head->len -
|
} else if (len <= (ssize_t)head->len -
|
||||||
skb->len - stm->strp.offset) {
|
(ssize_t)skb->len - stm->strp.offset) {
|
||||||
/* Length must be into new skb (and also
|
/* Length must be into new skb (and also
|
||||||
* greater than zero)
|
* greater than zero)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -145,7 +145,9 @@ void tipc_net_finalize_work(struct work_struct *work)
|
|||||||
{
|
{
|
||||||
struct tipc_net *tn = container_of(work, struct tipc_net, work);
|
struct tipc_net *tn = container_of(work, struct tipc_net, work);
|
||||||
|
|
||||||
|
rtnl_lock();
|
||||||
tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr);
|
tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr);
|
||||||
|
rtnl_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tipc_net_stop(struct net *net)
|
void tipc_net_stop(struct net *net)
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ enum unix_vertex_index {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static unsigned long unix_vertex_unvisited_index = UNIX_VERTEX_INDEX_MARK1;
|
static unsigned long unix_vertex_unvisited_index = UNIX_VERTEX_INDEX_MARK1;
|
||||||
|
static unsigned long unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START;
|
||||||
|
|
||||||
static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge)
|
static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge)
|
||||||
{
|
{
|
||||||
@@ -153,6 +154,7 @@ static void unix_add_edge(struct scm_fp_list *fpl, struct unix_edge *edge)
|
|||||||
if (!vertex) {
|
if (!vertex) {
|
||||||
vertex = list_first_entry(&fpl->vertices, typeof(*vertex), entry);
|
vertex = list_first_entry(&fpl->vertices, typeof(*vertex), entry);
|
||||||
vertex->index = unix_vertex_unvisited_index;
|
vertex->index = unix_vertex_unvisited_index;
|
||||||
|
vertex->scc_index = ++unix_vertex_max_scc_index;
|
||||||
vertex->out_degree = 0;
|
vertex->out_degree = 0;
|
||||||
INIT_LIST_HEAD(&vertex->edges);
|
INIT_LIST_HEAD(&vertex->edges);
|
||||||
INIT_LIST_HEAD(&vertex->scc_entry);
|
INIT_LIST_HEAD(&vertex->scc_entry);
|
||||||
@@ -489,10 +491,15 @@ prev_vertex:
|
|||||||
scc_dead = unix_vertex_dead(v);
|
scc_dead = unix_vertex_dead(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scc_dead)
|
if (scc_dead) {
|
||||||
unix_collect_skb(&scc, hitlist);
|
unix_collect_skb(&scc, hitlist);
|
||||||
else if (!unix_graph_maybe_cyclic)
|
} else {
|
||||||
unix_graph_maybe_cyclic = unix_scc_cyclic(&scc);
|
if (unix_vertex_max_scc_index < vertex->scc_index)
|
||||||
|
unix_vertex_max_scc_index = vertex->scc_index;
|
||||||
|
|
||||||
|
if (!unix_graph_maybe_cyclic)
|
||||||
|
unix_graph_maybe_cyclic = unix_scc_cyclic(&scc);
|
||||||
|
}
|
||||||
|
|
||||||
list_del(&scc);
|
list_del(&scc);
|
||||||
}
|
}
|
||||||
@@ -507,6 +514,7 @@ static void unix_walk_scc(struct sk_buff_head *hitlist)
|
|||||||
unsigned long last_index = UNIX_VERTEX_INDEX_START;
|
unsigned long last_index = UNIX_VERTEX_INDEX_START;
|
||||||
|
|
||||||
unix_graph_maybe_cyclic = false;
|
unix_graph_maybe_cyclic = false;
|
||||||
|
unix_vertex_max_scc_index = UNIX_VERTEX_INDEX_START;
|
||||||
|
|
||||||
/* Visit every vertex exactly once.
|
/* Visit every vertex exactly once.
|
||||||
* __unix_walk_scc() moves visited vertices to unix_visited_vertices.
|
* __unix_walk_scc() moves visited vertices to unix_visited_vertices.
|
||||||
|
|||||||
@@ -861,6 +861,18 @@ class TypeIndexedArray(Type):
|
|||||||
return [f"{member} = {self.c_name};",
|
return [f"{member} = {self.c_name};",
|
||||||
f"{presence} = n_{self.c_name};"]
|
f"{presence} = n_{self.c_name};"]
|
||||||
|
|
||||||
|
def free_needs_iter(self):
|
||||||
|
return self.sub_type == 'nest'
|
||||||
|
|
||||||
|
def _free_lines(self, ri, var, ref):
|
||||||
|
lines = []
|
||||||
|
if self.sub_type == 'nest':
|
||||||
|
lines += [
|
||||||
|
f"for (i = 0; i < {var}->{ref}_count.{self.c_name}; i++)",
|
||||||
|
f'{self.nested_render_name}_free(&{var}->{ref}{self.c_name}[i]);',
|
||||||
|
]
|
||||||
|
lines += f"free({var}->{ref}{self.c_name});",
|
||||||
|
return lines
|
||||||
|
|
||||||
class TypeNestTypeValue(Type):
|
class TypeNestTypeValue(Type):
|
||||||
def _complex_member_type(self, ri):
|
def _complex_member_type(self, ri):
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ TEST_PROGS := \
|
|||||||
netcons_fragmented_msg.sh \
|
netcons_fragmented_msg.sh \
|
||||||
netcons_overflow.sh \
|
netcons_overflow.sh \
|
||||||
netcons_sysdata.sh \
|
netcons_sysdata.sh \
|
||||||
|
netcons_torture.sh \
|
||||||
netpoll_basic.py \
|
netpoll_basic.py \
|
||||||
ping.py \
|
ping.py \
|
||||||
psp.py \
|
psp.py \
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ TEST_PROGS := \
|
|||||||
dev_addr_lists.sh \
|
dev_addr_lists.sh \
|
||||||
mode-1-recovery-updelay.sh \
|
mode-1-recovery-updelay.sh \
|
||||||
mode-2-recovery-updelay.sh \
|
mode-2-recovery-updelay.sh \
|
||||||
|
netcons_over_bonding.sh \
|
||||||
# end of TEST_PROGS
|
# end of TEST_PROGS
|
||||||
|
|
||||||
TEST_FILES := \
|
TEST_FILES := \
|
||||||
@@ -24,6 +25,7 @@ TEST_FILES := \
|
|||||||
|
|
||||||
TEST_INCLUDES := \
|
TEST_INCLUDES := \
|
||||||
../../../net/lib.sh \
|
../../../net/lib.sh \
|
||||||
|
../lib/sh/lib_netcons.sh \
|
||||||
../../../net/forwarding/lib.sh \
|
../../../net/forwarding/lib.sh \
|
||||||
# end of TEST_INCLUDES
|
# end of TEST_INCLUDES
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
CONFIG_BONDING=y
|
CONFIG_BONDING=y
|
||||||
CONFIG_BRIDGE=y
|
CONFIG_BRIDGE=y
|
||||||
|
CONFIG_CONFIGFS_FS=y
|
||||||
CONFIG_DUMMY=y
|
CONFIG_DUMMY=y
|
||||||
CONFIG_INET_ESP=y
|
CONFIG_INET_ESP=y
|
||||||
CONFIG_INET_ESP_OFFLOAD=y
|
CONFIG_INET_ESP_OFFLOAD=y
|
||||||
@@ -9,6 +10,9 @@ CONFIG_MACVLAN=y
|
|||||||
CONFIG_NET_ACT_GACT=y
|
CONFIG_NET_ACT_GACT=y
|
||||||
CONFIG_NET_CLS_FLOWER=y
|
CONFIG_NET_CLS_FLOWER=y
|
||||||
CONFIG_NET_CLS_MATCHALL=m
|
CONFIG_NET_CLS_MATCHALL=m
|
||||||
|
CONFIG_NETCONSOLE=m
|
||||||
|
CONFIG_NETCONSOLE_DYNAMIC=y
|
||||||
|
CONFIG_NETCONSOLE_EXTENDED_LOG=y
|
||||||
CONFIG_NETDEVSIM=m
|
CONFIG_NETDEVSIM=m
|
||||||
CONFIG_NET_SCH_INGRESS=y
|
CONFIG_NET_SCH_INGRESS=y
|
||||||
CONFIG_NLMON=y
|
CONFIG_NLMON=y
|
||||||
|
|||||||
361
tools/testing/selftests/drivers/net/bonding/netcons_over_bonding.sh
Executable file
361
tools/testing/selftests/drivers/net/bonding/netcons_over_bonding.sh
Executable file
@@ -0,0 +1,361 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
#
|
||||||
|
# This selftest exercises trying to have multiple netpoll users at the same
|
||||||
|
# time.
|
||||||
|
#
|
||||||
|
# This selftest has multiple smalls test inside, and the goal is to
|
||||||
|
# get interfaces with bonding and netconsole in different orders in order
|
||||||
|
# to catch any possible issue.
|
||||||
|
#
|
||||||
|
# The main test composes of four interfaces being created using netdevsim; two
|
||||||
|
# of them are bonded to serve as the netconsole's transmit interface. The
|
||||||
|
# remaining two interfaces are similarly bonded and assigned to a separate
|
||||||
|
# network namespace, which acts as the receive interface, where socat monitors
|
||||||
|
# for incoming messages.
|
||||||
|
#
|
||||||
|
# A netconsole message is then sent to ensure it is properly received across
|
||||||
|
# this configuration.
|
||||||
|
#
|
||||||
|
# Later, run a few other tests, to make sure that bonding and netconsole
|
||||||
|
# cannot coexist.
|
||||||
|
#
|
||||||
|
# The test's objective is to exercise netpoll usage when managed simultaneously
|
||||||
|
# by multiple subsystems (netconsole and bonding).
|
||||||
|
#
|
||||||
|
# Author: Breno Leitao <leitao@debian.org>
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
|
||||||
|
|
||||||
|
source "${SCRIPTDIR}"/../lib/sh/lib_netcons.sh
|
||||||
|
|
||||||
|
modprobe netdevsim 2> /dev/null || true
|
||||||
|
modprobe netconsole 2> /dev/null || true
|
||||||
|
modprobe bonding 2> /dev/null || true
|
||||||
|
modprobe veth 2> /dev/null || true
|
||||||
|
|
||||||
|
# The content of kmsg will be save to the following file
|
||||||
|
OUTPUT_FILE="/tmp/${TARGET}"
|
||||||
|
|
||||||
|
# Check for basic system dependency and exit if not found
|
||||||
|
check_for_dependencies
|
||||||
|
# Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5)
|
||||||
|
echo "6 5" > /proc/sys/kernel/printk
|
||||||
|
# Remove the namespace, interfaces and netconsole target on exit
|
||||||
|
trap cleanup_bond EXIT
|
||||||
|
|
||||||
|
FORMAT="extended"
|
||||||
|
IP_VERSION="ipv4"
|
||||||
|
VETH0="veth"$(( RANDOM % 256))
|
||||||
|
VETH1="veth"$((256 + RANDOM % 256))
|
||||||
|
TXNS=""
|
||||||
|
RXNS=""
|
||||||
|
|
||||||
|
# Create "bond_tx_XX" and "bond_rx_XX" interfaces, and set DSTIF and SRCIF with
|
||||||
|
# the bonding interfaces
|
||||||
|
function setup_bonding_ifaces() {
|
||||||
|
local RAND=$(( RANDOM % 100 ))
|
||||||
|
BOND_TX_MAIN_IF="bond_tx_$RAND"
|
||||||
|
BOND_RX_MAIN_IF="bond_rx_$RAND"
|
||||||
|
|
||||||
|
# Setup TX
|
||||||
|
if ! ip -n "${TXNS}" link add "${BOND_TX_MAIN_IF}" type bond mode balance-rr
|
||||||
|
then
|
||||||
|
echo "Failed to create bond TX interface. Is CONFIG_BONDING set?" >&2
|
||||||
|
# only clean nsim ifaces and namespace. Nothing else has been
|
||||||
|
# initialized
|
||||||
|
cleanup_bond_nsim
|
||||||
|
trap - EXIT
|
||||||
|
exit "${ksft_skip}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# create_netdevsim() got the interface up, but it needs to be down
|
||||||
|
# before being enslaved.
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX1_SLAVE_IF}" down
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX2_SLAVE_IF}" down
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX1_SLAVE_IF}" master "${BOND_TX_MAIN_IF}"
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX2_SLAVE_IF}" master "${BOND_TX_MAIN_IF}"
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX_MAIN_IF}" up
|
||||||
|
|
||||||
|
# Setup RX
|
||||||
|
ip -n "${RXNS}" \
|
||||||
|
link add "${BOND_RX_MAIN_IF}" type bond mode balance-rr
|
||||||
|
ip -n "${RXNS}" \
|
||||||
|
link set "${BOND_RX1_SLAVE_IF}" down
|
||||||
|
ip -n "${RXNS}" \
|
||||||
|
link set "${BOND_RX2_SLAVE_IF}" down
|
||||||
|
ip -n "${RXNS}" \
|
||||||
|
link set "${BOND_RX1_SLAVE_IF}" master "${BOND_RX_MAIN_IF}"
|
||||||
|
ip -n "${RXNS}" \
|
||||||
|
link set "${BOND_RX2_SLAVE_IF}" master "${BOND_RX_MAIN_IF}"
|
||||||
|
ip -n "${RXNS}" \
|
||||||
|
link set "${BOND_RX_MAIN_IF}" up
|
||||||
|
|
||||||
|
export DSTIF="${BOND_RX_MAIN_IF}"
|
||||||
|
export SRCIF="${BOND_TX_MAIN_IF}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create 4 netdevsim interfaces. Two of them will be bound to TX bonding iface
|
||||||
|
# and the other two will be bond to the RX interface (on the other namespace)
|
||||||
|
function create_ifaces_bond() {
|
||||||
|
BOND_TX1_SLAVE_IF=$(create_netdevsim "${NSIM_BOND_TX_1}" "${TXNS}")
|
||||||
|
BOND_TX2_SLAVE_IF=$(create_netdevsim "${NSIM_BOND_TX_2}" "${TXNS}")
|
||||||
|
BOND_RX1_SLAVE_IF=$(create_netdevsim "${NSIM_BOND_RX_1}" "${RXNS}")
|
||||||
|
BOND_RX2_SLAVE_IF=$(create_netdevsim "${NSIM_BOND_RX_2}" "${RXNS}")
|
||||||
|
}
|
||||||
|
|
||||||
|
# netdevsim link BOND_TX to BOND_RX interfaces
|
||||||
|
function link_ifaces_bond() {
|
||||||
|
local BOND_TX1_SLAVE_IFIDX
|
||||||
|
local BOND_TX2_SLAVE_IFIDX
|
||||||
|
local BOND_RX1_SLAVE_IFIDX
|
||||||
|
local BOND_RX2_SLAVE_IFIDX
|
||||||
|
local TXNS_FD
|
||||||
|
local RXNS_FD
|
||||||
|
|
||||||
|
BOND_TX1_SLAVE_IFIDX=$(ip netns exec "${TXNS}" \
|
||||||
|
cat /sys/class/net/"$BOND_TX1_SLAVE_IF"/ifindex)
|
||||||
|
BOND_TX2_SLAVE_IFIDX=$(ip netns exec "${TXNS}" \
|
||||||
|
cat /sys/class/net/"$BOND_TX2_SLAVE_IF"/ifindex)
|
||||||
|
BOND_RX1_SLAVE_IFIDX=$(ip netns exec "${RXNS}" \
|
||||||
|
cat /sys/class/net/"$BOND_RX1_SLAVE_IF"/ifindex)
|
||||||
|
BOND_RX2_SLAVE_IFIDX=$(ip netns exec "${RXNS}" \
|
||||||
|
cat /sys/class/net/"$BOND_RX2_SLAVE_IF"/ifindex)
|
||||||
|
|
||||||
|
exec {TXNS_FD}</var/run/netns/"${TXNS}"
|
||||||
|
exec {RXNS_FD}</var/run/netns/"${RXNS}"
|
||||||
|
|
||||||
|
# Linking TX ifaces to the RX ones (on the other namespace)
|
||||||
|
echo "${TXNS_FD}:$BOND_TX1_SLAVE_IFIDX $RXNS_FD:$BOND_RX1_SLAVE_IFIDX" \
|
||||||
|
> "$NSIM_DEV_SYS_LINK"
|
||||||
|
echo "${TXNS_FD}:$BOND_TX2_SLAVE_IFIDX $RXNS_FD:$BOND_RX2_SLAVE_IFIDX" \
|
||||||
|
> "$NSIM_DEV_SYS_LINK"
|
||||||
|
|
||||||
|
exec {TXNS_FD}<&-
|
||||||
|
exec {RXNS_FD}<&-
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_all_ifaces() {
|
||||||
|
# setup_ns function is coming from lib.sh
|
||||||
|
setup_ns TXNS RXNS
|
||||||
|
export NAMESPACE="${RXNS}"
|
||||||
|
|
||||||
|
# Create two interfaces for RX and two for TX
|
||||||
|
create_ifaces_bond
|
||||||
|
# Link netlink ifaces
|
||||||
|
link_ifaces_bond
|
||||||
|
}
|
||||||
|
|
||||||
|
# configure DSTIF and SRCIF IPs
|
||||||
|
function configure_ifaces_ips() {
|
||||||
|
local IP_VERSION=${1:-"ipv4"}
|
||||||
|
select_ipv4_or_ipv6 "${IP_VERSION}"
|
||||||
|
|
||||||
|
ip -n "${RXNS}" addr add "${DSTIP}"/24 dev "${DSTIF}"
|
||||||
|
ip -n "${RXNS}" link set "${DSTIF}" up
|
||||||
|
|
||||||
|
ip -n "${TXNS}" addr add "${SRCIP}"/24 dev "${SRCIF}"
|
||||||
|
ip -n "${TXNS}" link set "${SRCIF}" up
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_enable_netpoll_on_enslaved_iface() {
|
||||||
|
echo 0 > "${NETCONS_PATH}"/enabled
|
||||||
|
|
||||||
|
# At this stage, BOND_TX1_SLAVE_IF is enslaved to BOND_TX_MAIN_IF, and
|
||||||
|
# linked to BOND_RX1_SLAVE_IF inside the namespace.
|
||||||
|
echo "${BOND_TX1_SLAVE_IF}" > "${NETCONS_PATH}"/dev_name
|
||||||
|
|
||||||
|
# This should fail with the following message in dmesg:
|
||||||
|
# netpoll: netconsole: ethX is a slave device, aborting
|
||||||
|
set +e
|
||||||
|
enable_netcons_ns 2> /dev/null
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 1 ]]
|
||||||
|
then
|
||||||
|
echo "test failed: Bonding and netpoll cannot co-exists." >&2
|
||||||
|
exit "${ksft_fail}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_delete_bond_and_reenable_target() {
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link delete "${BOND_TX_MAIN_IF}" type bond
|
||||||
|
|
||||||
|
# BOND_TX1_SLAVE_IF is not attached to a bond interface anymore
|
||||||
|
# netpoll can be plugged in there
|
||||||
|
echo "${BOND_TX1_SLAVE_IF}" > "${NETCONS_PATH}"/dev_name
|
||||||
|
|
||||||
|
# this should work, since the interface is not enslaved
|
||||||
|
enable_netcons_ns
|
||||||
|
|
||||||
|
if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 0 ]]
|
||||||
|
then
|
||||||
|
echo "test failed: Unable to start netpoll on an unbond iface." >&2
|
||||||
|
exit "${ksft_fail}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Send a netconsole message to the netconsole target
|
||||||
|
function test_send_netcons_msg_through_bond_iface() {
|
||||||
|
# Listen for netconsole port inside the namespace and
|
||||||
|
# destination interface
|
||||||
|
listen_port_and_save_to "${OUTPUT_FILE}" "${IP_VERSION}" &
|
||||||
|
# Wait for socat to start and listen to the port.
|
||||||
|
wait_for_port "${RXNS}" "${PORT}" "${IP_VERSION}"
|
||||||
|
# Send the message
|
||||||
|
echo "${MSG}: ${TARGET}" > /dev/kmsg
|
||||||
|
# Wait until socat saves the file to disk
|
||||||
|
busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}"
|
||||||
|
# Make sure the message was received in the dst part
|
||||||
|
# and exit
|
||||||
|
validate_result "${OUTPUT_FILE}" "${FORMAT}"
|
||||||
|
# kill socat in case it is still running
|
||||||
|
pkill_socat
|
||||||
|
}
|
||||||
|
|
||||||
|
# BOND_TX1_SLAVE_IF has netconsole enabled on it, bind it to BOND_TX_MAIN_IF.
|
||||||
|
# Given BOND_TX_MAIN_IF was deleted, recreate it first
|
||||||
|
function test_enslave_netcons_enabled_iface {
|
||||||
|
# netconsole got disabled while the interface was down
|
||||||
|
if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 0 ]]
|
||||||
|
then
|
||||||
|
echo "test failed: netconsole expected to be enabled against BOND_TX1_SLAVE_IF" >&2
|
||||||
|
exit "${ksft_fail}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# recreate the bonding iface. it got deleted by previous
|
||||||
|
# test (test_delete_bond_and_reenable_target)
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link add "${BOND_TX_MAIN_IF}" type bond mode balance-rr
|
||||||
|
|
||||||
|
# sub-interface need to be down before attaching to bonding
|
||||||
|
# This will also disable netconsole.
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX1_SLAVE_IF}" down
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX1_SLAVE_IF}" master "${BOND_TX_MAIN_IF}"
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX_MAIN_IF}" up
|
||||||
|
|
||||||
|
# netconsole got disabled while the interface was down
|
||||||
|
if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 1 ]]
|
||||||
|
then
|
||||||
|
echo "test failed: Device is part of a bond iface, cannot have netcons enabled" >&2
|
||||||
|
exit "${ksft_fail}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get netconsole enabled on a bonding interface and attach a second
|
||||||
|
# sub-interface.
|
||||||
|
function test_enslave_iface_to_bond {
|
||||||
|
# BOND_TX_MAIN_IF has only BOND_TX1_SLAVE_IF right now
|
||||||
|
echo "${BOND_TX_MAIN_IF}" > "${NETCONS_PATH}"/dev_name
|
||||||
|
enable_netcons_ns
|
||||||
|
|
||||||
|
# netcons is attached to bond0 and BOND_TX1_SLAVE_IF is
|
||||||
|
# part of BOND_TX_MAIN_IF. Attach BOND_TX2_SLAVE_IF to BOND_TX_MAIN_IF.
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link set "${BOND_TX2_SLAVE_IF}" master "${BOND_TX_MAIN_IF}"
|
||||||
|
if [[ $(cat "${NETCONS_PATH}"/enabled) -eq 0 ]]
|
||||||
|
then
|
||||||
|
echo "test failed: Netconsole should be enabled on bonding interface. Failed" >&2
|
||||||
|
exit "${ksft_fail}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_enslave_iff_disabled_netpoll_iface {
|
||||||
|
local ret
|
||||||
|
|
||||||
|
# Create two interfaces. veth interfaces it known to have
|
||||||
|
# IFF_DISABLE_NETPOLL set
|
||||||
|
if ! ip link add "${VETH0}" type veth peer name "${VETH1}"
|
||||||
|
then
|
||||||
|
echo "Failed to create veth TX interface. Is CONFIG_VETH set?" >&2
|
||||||
|
exit "${ksft_skip}"
|
||||||
|
fi
|
||||||
|
set +e
|
||||||
|
# This will print RTNETLINK answers: Device or resource busy
|
||||||
|
ip link set "${VETH0}" master "${BOND_TX_MAIN_IF}" 2> /dev/null
|
||||||
|
ret=$?
|
||||||
|
set -e
|
||||||
|
if [[ $ret -eq 0 ]]
|
||||||
|
then
|
||||||
|
echo "test failed: veth interface could not be enslaved"
|
||||||
|
exit "${ksft_fail}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Given that netconsole picks the current net namespace, we need to enable it
|
||||||
|
# from inside the TXNS namespace
|
||||||
|
function enable_netcons_ns() {
|
||||||
|
ip netns exec "${TXNS}" sh -c \
|
||||||
|
"mount -t configfs configfs /sys/kernel/config && echo 1 > $NETCONS_PATH/enabled"
|
||||||
|
}
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Tests start here #
|
||||||
|
####################
|
||||||
|
|
||||||
|
# Create regular interfaces using netdevsim and link them
|
||||||
|
create_all_ifaces
|
||||||
|
|
||||||
|
# Setup the bonding interfaces
|
||||||
|
# BOND_RX_MAIN_IF has BOND_RX{1,2}_SLAVE_IF
|
||||||
|
# BOND_TX_MAIN_IF has BOND_TX{1,2}_SLAVE_IF
|
||||||
|
setup_bonding_ifaces
|
||||||
|
|
||||||
|
# Configure the ips as BOND_RX1_SLAVE_IF and BOND_TX1_SLAVE_IF
|
||||||
|
configure_ifaces_ips "${IP_VERSION}"
|
||||||
|
|
||||||
|
_create_dynamic_target "${FORMAT}" "${NETCONS_PATH}"
|
||||||
|
enable_netcons_ns
|
||||||
|
set_user_data
|
||||||
|
|
||||||
|
# Test #1 : Create an bonding interface and attach netpoll into
|
||||||
|
# the bonding interface. Netconsole/netpoll should work on
|
||||||
|
# the bonding interface.
|
||||||
|
test_send_netcons_msg_through_bond_iface
|
||||||
|
echo "test #1: netpoll on bonding interface worked. Test passed" >&2
|
||||||
|
|
||||||
|
# Test #2: Attach netpoll to an enslaved interface
|
||||||
|
# Try to attach netpoll to an enslaved sub-interface (while still being part of
|
||||||
|
# a bonding interface), which shouldn't be allowed
|
||||||
|
test_enable_netpoll_on_enslaved_iface
|
||||||
|
echo "test #2: netpoll correctly rejected enslaved interface (expected behavior). Test passed." >&2
|
||||||
|
|
||||||
|
# Test #3: Unplug the sub-interface from bond and enable netconsole
|
||||||
|
# Detach the interface from a bonding interface and attach netpoll again
|
||||||
|
test_delete_bond_and_reenable_target
|
||||||
|
echo "test #3: Able to attach to an unbound interface. Test passed." >&2
|
||||||
|
|
||||||
|
# Test #4: Enslave a sub-interface that had netconsole enabled
|
||||||
|
# Try to enslave an interface that has netconsole/netpoll enabled.
|
||||||
|
# Previous test has netconsole enabled in BOND_TX1_SLAVE_IF, try to enslave it
|
||||||
|
test_enslave_netcons_enabled_iface
|
||||||
|
echo "test #4: Enslaving an interface with netpoll attached. Test passed." >&2
|
||||||
|
|
||||||
|
# Test #5: Enslave a sub-interface to a bonding interface
|
||||||
|
# Enslave an interface to a bond interface that has netpoll attached
|
||||||
|
# At this stage, BOND_TX_MAIN_IF is created and BOND_TX1_SLAVE_IF is part of
|
||||||
|
# it. Netconsole is currently disabled
|
||||||
|
test_enslave_iface_to_bond
|
||||||
|
echo "test #5: Enslaving an interface to bond+netpoll. Test passed." >&2
|
||||||
|
|
||||||
|
# Test #6: Enslave a IFF_DISABLE_NETPOLL sub-interface to a bonding interface
|
||||||
|
# At this stage, BOND_TX_MAIN_IF has both sub interface and netconsole is
|
||||||
|
# enabled. This test will try to enslave an a veth (IFF_DISABLE_NETPOLL) interface
|
||||||
|
# and it should fail, with netpoll: veth0 doesn't support polling
|
||||||
|
test_enslave_iff_disabled_netpoll_iface
|
||||||
|
echo "test #6: Enslaving IFF_DISABLE_NETPOLL ifaces to bond iface is not supported. Test passed." >&2
|
||||||
|
|
||||||
|
cleanup_bond
|
||||||
|
trap - EXIT
|
||||||
|
exit "${EXIT_STATUS}"
|
||||||
@@ -11,9 +11,11 @@ set -euo pipefail
|
|||||||
LIBDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
|
LIBDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
|
||||||
|
|
||||||
SRCIF="" # to be populated later
|
SRCIF="" # to be populated later
|
||||||
|
SRCIP="" # to be populated later
|
||||||
SRCIP4="192.0.2.1"
|
SRCIP4="192.0.2.1"
|
||||||
SRCIP6="fc00::1"
|
SRCIP6="fc00::1"
|
||||||
DSTIF="" # to be populated later
|
DSTIF="" # to be populated later
|
||||||
|
DSTIP="" # to be populated later
|
||||||
DSTIP4="192.0.2.2"
|
DSTIP4="192.0.2.2"
|
||||||
DSTIP6="fc00::2"
|
DSTIP6="fc00::2"
|
||||||
|
|
||||||
@@ -28,17 +30,23 @@ NETCONS_PATH="${NETCONS_CONFIGFS}"/"${TARGET}"
|
|||||||
# NAMESPACE will be populated by setup_ns with a random value
|
# NAMESPACE will be populated by setup_ns with a random value
|
||||||
NAMESPACE=""
|
NAMESPACE=""
|
||||||
|
|
||||||
# IDs for netdevsim
|
# IDs for netdevsim. We either use NSIM_DEV_{1,2}_ID for standard test
|
||||||
|
# or NSIM_BOND_{T,R}X_{1,2} for the bonding tests. Not both at the
|
||||||
|
# same time.
|
||||||
NSIM_DEV_1_ID=$((256 + RANDOM % 256))
|
NSIM_DEV_1_ID=$((256 + RANDOM % 256))
|
||||||
NSIM_DEV_2_ID=$((512 + RANDOM % 256))
|
NSIM_DEV_2_ID=$((512 + RANDOM % 256))
|
||||||
|
NSIM_BOND_TX_1=$((768 + RANDOM % 256))
|
||||||
|
NSIM_BOND_TX_2=$((1024 + RANDOM % 256))
|
||||||
|
NSIM_BOND_RX_1=$((1280 + RANDOM % 256))
|
||||||
|
NSIM_BOND_RX_2=$((1536 + RANDOM % 256))
|
||||||
NSIM_DEV_SYS_NEW="/sys/bus/netdevsim/new_device"
|
NSIM_DEV_SYS_NEW="/sys/bus/netdevsim/new_device"
|
||||||
|
NSIM_DEV_SYS_LINK="/sys/bus/netdevsim/link_device"
|
||||||
|
|
||||||
# Used to create and delete namespaces
|
# Used to create and delete namespaces
|
||||||
source "${LIBDIR}"/../../../../net/lib.sh
|
source "${LIBDIR}"/../../../../net/lib.sh
|
||||||
|
|
||||||
# Create netdevsim interfaces
|
# Create netdevsim interfaces
|
||||||
create_ifaces() {
|
create_ifaces() {
|
||||||
|
|
||||||
echo "$NSIM_DEV_2_ID" > "$NSIM_DEV_SYS_NEW"
|
echo "$NSIM_DEV_2_ID" > "$NSIM_DEV_SYS_NEW"
|
||||||
echo "$NSIM_DEV_1_ID" > "$NSIM_DEV_SYS_NEW"
|
echo "$NSIM_DEV_1_ID" > "$NSIM_DEV_SYS_NEW"
|
||||||
udevadm settle 2> /dev/null || true
|
udevadm settle 2> /dev/null || true
|
||||||
@@ -113,31 +121,38 @@ function set_network() {
|
|||||||
configure_ip
|
configure_ip
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_dynamic_target() {
|
function _create_dynamic_target() {
|
||||||
local FORMAT=${1:-"extended"}
|
local FORMAT="${1:?FORMAT parameter required}"
|
||||||
|
local NCPATH="${2:?NCPATH parameter required}"
|
||||||
|
|
||||||
DSTMAC=$(ip netns exec "${NAMESPACE}" \
|
DSTMAC=$(ip netns exec "${NAMESPACE}" \
|
||||||
ip link show "${DSTIF}" | awk '/ether/ {print $2}')
|
ip link show "${DSTIF}" | awk '/ether/ {print $2}')
|
||||||
|
|
||||||
# Create a dynamic target
|
# Create a dynamic target
|
||||||
mkdir "${NETCONS_PATH}"
|
mkdir "${NCPATH}"
|
||||||
|
|
||||||
echo "${DSTIP}" > "${NETCONS_PATH}"/remote_ip
|
echo "${DSTIP}" > "${NCPATH}"/remote_ip
|
||||||
echo "${SRCIP}" > "${NETCONS_PATH}"/local_ip
|
echo "${SRCIP}" > "${NCPATH}"/local_ip
|
||||||
echo "${DSTMAC}" > "${NETCONS_PATH}"/remote_mac
|
echo "${DSTMAC}" > "${NCPATH}"/remote_mac
|
||||||
echo "${SRCIF}" > "${NETCONS_PATH}"/dev_name
|
echo "${SRCIF}" > "${NCPATH}"/dev_name
|
||||||
|
|
||||||
if [ "${FORMAT}" == "basic" ]
|
if [ "${FORMAT}" == "basic" ]
|
||||||
then
|
then
|
||||||
# Basic target does not support release
|
# Basic target does not support release
|
||||||
echo 0 > "${NETCONS_PATH}"/release
|
echo 0 > "${NCPATH}"/release
|
||||||
echo 0 > "${NETCONS_PATH}"/extended
|
echo 0 > "${NCPATH}"/extended
|
||||||
elif [ "${FORMAT}" == "extended" ]
|
elif [ "${FORMAT}" == "extended" ]
|
||||||
then
|
then
|
||||||
echo 1 > "${NETCONS_PATH}"/extended
|
echo 1 > "${NCPATH}"/extended
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
echo 1 > "${NETCONS_PATH}"/enabled
|
function create_dynamic_target() {
|
||||||
|
local FORMAT=${1:-"extended"}
|
||||||
|
local NCPATH=${2:-"$NETCONS_PATH"}
|
||||||
|
_create_dynamic_target "${FORMAT}" "${NCPATH}"
|
||||||
|
|
||||||
|
echo 1 > "${NCPATH}"/enabled
|
||||||
|
|
||||||
# This will make sure that the kernel was able to
|
# This will make sure that the kernel was able to
|
||||||
# load the netconsole driver configuration. The console message
|
# load the netconsole driver configuration. The console message
|
||||||
@@ -185,14 +200,26 @@ function do_cleanup() {
|
|||||||
echo "${DEFAULT_PRINTK_VALUES}" > /proc/sys/kernel/printk
|
echo "${DEFAULT_PRINTK_VALUES}" > /proc/sys/kernel/printk
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup_netcons() {
|
||||||
# delete netconsole dynamic reconfiguration
|
# delete netconsole dynamic reconfiguration
|
||||||
echo 0 > "${NETCONS_PATH}"/enabled
|
# do not fail if the target is already disabled
|
||||||
|
if [[ ! -d "${NETCONS_PATH}" ]]
|
||||||
|
then
|
||||||
|
# in some cases this is called before netcons path is created
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ $(cat "${NETCONS_PATH}"/enabled) != 0 ]]
|
||||||
|
then
|
||||||
|
echo 0 > "${NETCONS_PATH}"/enabled || true
|
||||||
|
fi
|
||||||
# Remove all the keys that got created during the selftest
|
# Remove all the keys that got created during the selftest
|
||||||
find "${NETCONS_PATH}/userdata/" -mindepth 1 -type d -delete
|
find "${NETCONS_PATH}/userdata/" -mindepth 1 -type d -delete
|
||||||
# Remove the configfs entry
|
# Remove the configfs entry
|
||||||
rmdir "${NETCONS_PATH}"
|
rmdir "${NETCONS_PATH}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
cleanup_netcons
|
||||||
do_cleanup
|
do_cleanup
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,3 +396,24 @@ function wait_for_port() {
|
|||||||
# more frequently on IPv6
|
# more frequently on IPv6
|
||||||
sleep 1
|
sleep 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Clean up netdevsim ifaces created for bonding test
|
||||||
|
function cleanup_bond_nsim() {
|
||||||
|
ip -n "${TXNS}" \
|
||||||
|
link delete "${BOND_TX_MAIN_IF}" type bond || true
|
||||||
|
ip -n "${RXNS}" \
|
||||||
|
link delete "${BOND_RX_MAIN_IF}" type bond || true
|
||||||
|
|
||||||
|
cleanup_netdevsim "$NSIM_BOND_TX_1"
|
||||||
|
cleanup_netdevsim "$NSIM_BOND_TX_2"
|
||||||
|
cleanup_netdevsim "$NSIM_BOND_RX_1"
|
||||||
|
cleanup_netdevsim "$NSIM_BOND_RX_2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# cleanup tests that use bonding interfaces
|
||||||
|
function cleanup_bond() {
|
||||||
|
cleanup_netcons
|
||||||
|
cleanup_bond_nsim
|
||||||
|
cleanup_all_ns
|
||||||
|
ip link delete "${VETH0}" || true
|
||||||
|
}
|
||||||
|
|||||||
130
tools/testing/selftests/drivers/net/netcons_torture.sh
Executable file
130
tools/testing/selftests/drivers/net/netcons_torture.sh
Executable file
@@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
# Repeatedly send kernel messages, toggles netconsole targets on and off,
|
||||||
|
# creates and deletes targets in parallel, and toggles the source interface to
|
||||||
|
# simulate stress conditions.
|
||||||
|
#
|
||||||
|
# This test aims to verify the robustness of netconsole under dynamic
|
||||||
|
# configurations and concurrent operations.
|
||||||
|
#
|
||||||
|
# The major goal is to run this test with LOCKDEP, Kmemleak and KASAN to make
|
||||||
|
# sure no issues is reported.
|
||||||
|
#
|
||||||
|
# Author: Breno Leitao <leitao@debian.org>
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
|
||||||
|
|
||||||
|
source "${SCRIPTDIR}"/lib/sh/lib_netcons.sh
|
||||||
|
|
||||||
|
# Number of times the main loop run
|
||||||
|
ITERATIONS=${1:-150}
|
||||||
|
|
||||||
|
# Only test extended format
|
||||||
|
FORMAT="extended"
|
||||||
|
# And ipv6 only
|
||||||
|
IP_VERSION="ipv6"
|
||||||
|
|
||||||
|
# Create, enable and delete some targets.
|
||||||
|
create_and_delete_random_target() {
|
||||||
|
COUNT=2
|
||||||
|
RND_PREFIX=$(mktemp -u netcons_rnd_XXXX_)
|
||||||
|
|
||||||
|
if [ -d "${NETCONS_CONFIGFS}/${RND_PREFIX}${COUNT}" ] || \
|
||||||
|
[ -d "${NETCONS_CONFIGFS}/${RND_PREFIX}0" ]; then
|
||||||
|
echo "Function didn't finish yet, skipping it." >&2
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# enable COUNT targets
|
||||||
|
for i in $(seq ${COUNT})
|
||||||
|
do
|
||||||
|
RND_TARGET="${RND_PREFIX}"${i}
|
||||||
|
RND_TARGET_PATH="${NETCONS_CONFIGFS}"/"${RND_TARGET}"
|
||||||
|
|
||||||
|
# Basic population so the target can come up
|
||||||
|
_create_dynamic_target "${FORMAT}" "${RND_TARGET_PATH}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "netconsole selftest: ${COUNT} additional targets were created" > /dev/kmsg
|
||||||
|
# disable them all
|
||||||
|
for i in $(seq ${COUNT})
|
||||||
|
do
|
||||||
|
RND_TARGET="${RND_PREFIX}"${i}
|
||||||
|
RND_TARGET_PATH="${NETCONS_CONFIGFS}"/"${RND_TARGET}"
|
||||||
|
if [[ $(cat "${RND_TARGET_PATH}/enabled") -eq 1 ]]
|
||||||
|
then
|
||||||
|
echo 0 > "${RND_TARGET_PATH}"/enabled
|
||||||
|
fi
|
||||||
|
rmdir "${RND_TARGET_PATH}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Disable and enable the target mid-air, while messages
|
||||||
|
# are being transmitted.
|
||||||
|
toggle_netcons_target() {
|
||||||
|
for i in $(seq 2)
|
||||||
|
do
|
||||||
|
if [ ! -d "${NETCONS_PATH}" ]
|
||||||
|
then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo 0 > "${NETCONS_PATH}"/enabled 2> /dev/null || true
|
||||||
|
# Try to enable a bit harder, given it might fail to enable
|
||||||
|
# Write to `enabled` might fail depending on the lock, which is
|
||||||
|
# highly contentious here
|
||||||
|
for _ in $(seq 5)
|
||||||
|
do
|
||||||
|
echo 1 > "${NETCONS_PATH}"/enabled 2> /dev/null || true
|
||||||
|
done
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle_iface(){
|
||||||
|
ip link set "${SRCIF}" down
|
||||||
|
ip link set "${SRCIF}" up
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start here
|
||||||
|
|
||||||
|
modprobe netdevsim 2> /dev/null || true
|
||||||
|
modprobe netconsole 2> /dev/null || true
|
||||||
|
|
||||||
|
# Check for basic system dependency and exit if not found
|
||||||
|
check_for_dependencies
|
||||||
|
# Set current loglevel to KERN_INFO(6), and default to KERN_NOTICE(5)
|
||||||
|
echo "6 5" > /proc/sys/kernel/printk
|
||||||
|
# Remove the namespace, interfaces and netconsole target on exit
|
||||||
|
trap cleanup EXIT
|
||||||
|
# Create one namespace and two interfaces
|
||||||
|
set_network "${IP_VERSION}"
|
||||||
|
# Create a dynamic target for netconsole
|
||||||
|
create_dynamic_target "${FORMAT}"
|
||||||
|
|
||||||
|
for i in $(seq "$ITERATIONS")
|
||||||
|
do
|
||||||
|
for _ in $(seq 10)
|
||||||
|
do
|
||||||
|
echo "${MSG}: ${TARGET} ${i}" > /dev/kmsg
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
|
||||||
|
if (( i % 30 == 0 )); then
|
||||||
|
toggle_netcons_target &
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( i % 50 == 0 )); then
|
||||||
|
# create some targets, enable them, send msg and disable
|
||||||
|
# all in a parallel thread
|
||||||
|
create_and_delete_random_target &
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( i % 70 == 0 )); then
|
||||||
|
toggle_iface &
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
|
||||||
|
exit "${EXIT_STATUS}"
|
||||||
@@ -176,6 +176,8 @@ run_test()
|
|||||||
local rcv_dmac=$(mac_get $rcv_if_name)
|
local rcv_dmac=$(mac_get $rcv_if_name)
|
||||||
local should_receive
|
local should_receive
|
||||||
|
|
||||||
|
setup_wait
|
||||||
|
|
||||||
tcpdump_start $rcv_if_name
|
tcpdump_start $rcv_if_name
|
||||||
|
|
||||||
mc_route_prepare $send_if_name
|
mc_route_prepare $send_if_name
|
||||||
|
|||||||
@@ -710,8 +710,14 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd,
|
|||||||
|
|
||||||
bw = do_rnd_write(peerfd, winfo->buf + winfo->off, winfo->len);
|
bw = do_rnd_write(peerfd, winfo->buf + winfo->off, winfo->len);
|
||||||
if (bw < 0) {
|
if (bw < 0) {
|
||||||
if (cfg_rcv_trunc)
|
/* expected reset, continue to read */
|
||||||
return 0;
|
if (cfg_rcv_trunc &&
|
||||||
|
(errno == ECONNRESET ||
|
||||||
|
errno == EPIPE)) {
|
||||||
|
fds.events &= ~POLLOUT;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
perror("write");
|
perror("write");
|
||||||
return 111;
|
return 111;
|
||||||
}
|
}
|
||||||
@@ -737,8 +743,10 @@ static int copyfd_io_poll(int infd, int peerfd, int outfd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fds.revents & (POLLERR | POLLNVAL)) {
|
if (fds.revents & (POLLERR | POLLNVAL)) {
|
||||||
if (cfg_rcv_trunc)
|
if (cfg_rcv_trunc) {
|
||||||
return 0;
|
fds.events &= ~(POLLERR | POLLNVAL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
fprintf(stderr, "Unexpected revents: "
|
fprintf(stderr, "Unexpected revents: "
|
||||||
"POLLERR/POLLNVAL(%x)\n", fds.revents);
|
"POLLERR/POLLNVAL(%x)\n", fds.revents);
|
||||||
return 5;
|
return 5;
|
||||||
@@ -1433,7 +1441,7 @@ static void parse_opts(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
if (cfg_truncate < 0) {
|
if (cfg_truncate < 0) {
|
||||||
cfg_rcv_trunc = true;
|
cfg_rcv_trunc = true;
|
||||||
signal(SIGPIPE, handle_signal);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ do_transfer()
|
|||||||
"than expected (${expect_synrx})"
|
"than expected (${expect_synrx})"
|
||||||
retc=1
|
retc=1
|
||||||
fi
|
fi
|
||||||
if [ ${stat_ackrx_now_l} -lt ${expect_ackrx} ] && [ ${stat_ooo_now} -eq 0 ]; then
|
if [ ${stat_ackrx_now_l} -lt ${expect_ackrx} ]; then
|
||||||
if [ ${stat_ooo_now} -eq 0 ]; then
|
if [ ${stat_ooo_now} -eq 0 ]; then
|
||||||
mptcp_lib_pr_fail "lower MPC ACK rx (${stat_ackrx_now_l})" \
|
mptcp_lib_pr_fail "lower MPC ACK rx (${stat_ackrx_now_l})" \
|
||||||
"than expected (${expect_ackrx})"
|
"than expected (${expect_ackrx})"
|
||||||
|
|||||||
@@ -2532,7 +2532,7 @@ remove_tests()
|
|||||||
if reset "remove single subflow"; then
|
if reset "remove single subflow"; then
|
||||||
pm_nl_set_limits $ns1 0 1
|
pm_nl_set_limits $ns1 0 1
|
||||||
pm_nl_set_limits $ns2 0 1
|
pm_nl_set_limits $ns2 0 1
|
||||||
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
|
||||||
addr_nr_ns2=-1 speed=slow \
|
addr_nr_ns2=-1 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 1 1 1
|
chk_join_nr 1 1 1
|
||||||
@@ -2545,8 +2545,8 @@ remove_tests()
|
|||||||
if reset "remove multiple subflows"; then
|
if reset "remove multiple subflows"; then
|
||||||
pm_nl_set_limits $ns1 0 2
|
pm_nl_set_limits $ns1 0 2
|
||||||
pm_nl_set_limits $ns2 0 2
|
pm_nl_set_limits $ns2 0 2
|
||||||
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,backup
|
||||||
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
|
||||||
addr_nr_ns2=-2 speed=slow \
|
addr_nr_ns2=-2 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 2 2 2
|
chk_join_nr 2 2 2
|
||||||
@@ -2557,7 +2557,7 @@ remove_tests()
|
|||||||
# single address, remove
|
# single address, remove
|
||||||
if reset "remove single address"; then
|
if reset "remove single address"; then
|
||||||
pm_nl_set_limits $ns1 0 1
|
pm_nl_set_limits $ns1 0 1
|
||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup
|
||||||
pm_nl_set_limits $ns2 1 1
|
pm_nl_set_limits $ns2 1 1
|
||||||
addr_nr_ns1=-1 speed=slow \
|
addr_nr_ns1=-1 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
@@ -2570,9 +2570,9 @@ remove_tests()
|
|||||||
# subflow and signal, remove
|
# subflow and signal, remove
|
||||||
if reset "remove subflow and signal"; then
|
if reset "remove subflow and signal"; then
|
||||||
pm_nl_set_limits $ns1 0 2
|
pm_nl_set_limits $ns1 0 2
|
||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup
|
||||||
pm_nl_set_limits $ns2 1 2
|
pm_nl_set_limits $ns2 1 2
|
||||||
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
|
||||||
addr_nr_ns1=-1 addr_nr_ns2=-1 speed=slow \
|
addr_nr_ns1=-1 addr_nr_ns2=-1 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 2 2 2
|
chk_join_nr 2 2 2
|
||||||
@@ -2584,10 +2584,10 @@ remove_tests()
|
|||||||
# subflows and signal, remove
|
# subflows and signal, remove
|
||||||
if reset "remove subflows and signal"; then
|
if reset "remove subflows and signal"; then
|
||||||
pm_nl_set_limits $ns1 0 3
|
pm_nl_set_limits $ns1 0 3
|
||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup
|
||||||
pm_nl_set_limits $ns2 1 3
|
pm_nl_set_limits $ns2 1 3
|
||||||
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
|
||||||
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow,backup
|
||||||
addr_nr_ns1=-1 addr_nr_ns2=-2 speed=10 \
|
addr_nr_ns1=-1 addr_nr_ns2=-2 speed=10 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 3 3 3
|
chk_join_nr 3 3 3
|
||||||
@@ -2599,9 +2599,9 @@ remove_tests()
|
|||||||
# addresses remove
|
# addresses remove
|
||||||
if reset "remove addresses"; then
|
if reset "remove addresses"; then
|
||||||
pm_nl_set_limits $ns1 3 3
|
pm_nl_set_limits $ns1 3 3
|
||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal id 250
|
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup id 250
|
||||||
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal,backup
|
||||||
pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.4.1 flags signal,backup
|
||||||
pm_nl_set_limits $ns2 3 3
|
pm_nl_set_limits $ns2 3 3
|
||||||
addr_nr_ns1=-3 speed=10 \
|
addr_nr_ns1=-3 speed=10 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
@@ -2614,10 +2614,10 @@ remove_tests()
|
|||||||
# invalid addresses remove
|
# invalid addresses remove
|
||||||
if reset "remove invalid addresses"; then
|
if reset "remove invalid addresses"; then
|
||||||
pm_nl_set_limits $ns1 3 3
|
pm_nl_set_limits $ns1 3 3
|
||||||
pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.12.1 flags signal,backup
|
||||||
# broadcast IP: no packet for this address will be received on ns1
|
# broadcast IP: no packet for this address will be received on ns1
|
||||||
pm_nl_add_endpoint $ns1 224.0.0.1 flags signal
|
pm_nl_add_endpoint $ns1 224.0.0.1 flags signal,backup
|
||||||
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal,backup
|
||||||
pm_nl_set_limits $ns2 2 2
|
pm_nl_set_limits $ns2 2 2
|
||||||
addr_nr_ns1=-3 speed=10 \
|
addr_nr_ns1=-3 speed=10 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
@@ -2631,10 +2631,10 @@ remove_tests()
|
|||||||
# subflows and signal, flush
|
# subflows and signal, flush
|
||||||
if reset "flush subflows and signal"; then
|
if reset "flush subflows and signal"; then
|
||||||
pm_nl_set_limits $ns1 0 3
|
pm_nl_set_limits $ns1 0 3
|
||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup
|
||||||
pm_nl_set_limits $ns2 1 3
|
pm_nl_set_limits $ns2 1 3
|
||||||
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
|
||||||
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow,backup
|
||||||
addr_nr_ns1=-8 addr_nr_ns2=-8 speed=slow \
|
addr_nr_ns1=-8 addr_nr_ns2=-8 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 3 3 3
|
chk_join_nr 3 3 3
|
||||||
@@ -2647,9 +2647,9 @@ remove_tests()
|
|||||||
if reset "flush subflows"; then
|
if reset "flush subflows"; then
|
||||||
pm_nl_set_limits $ns1 3 3
|
pm_nl_set_limits $ns1 3 3
|
||||||
pm_nl_set_limits $ns2 3 3
|
pm_nl_set_limits $ns2 3 3
|
||||||
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow id 150
|
pm_nl_add_endpoint $ns2 10.0.2.2 flags subflow,backup id 150
|
||||||
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.3.2 flags subflow,backup
|
||||||
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.4.2 flags subflow,backup
|
||||||
addr_nr_ns1=-8 addr_nr_ns2=-8 speed=slow \
|
addr_nr_ns1=-8 addr_nr_ns2=-8 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
chk_join_nr 3 3 3
|
chk_join_nr 3 3 3
|
||||||
@@ -2666,9 +2666,9 @@ remove_tests()
|
|||||||
# addresses flush
|
# addresses flush
|
||||||
if reset "flush addresses"; then
|
if reset "flush addresses"; then
|
||||||
pm_nl_set_limits $ns1 3 3
|
pm_nl_set_limits $ns1 3 3
|
||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal id 250
|
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal,backup id 250
|
||||||
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal,backup
|
||||||
pm_nl_add_endpoint $ns1 10.0.4.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.4.1 flags signal,backup
|
||||||
pm_nl_set_limits $ns2 3 3
|
pm_nl_set_limits $ns2 3 3
|
||||||
addr_nr_ns1=-8 addr_nr_ns2=-8 speed=slow \
|
addr_nr_ns1=-8 addr_nr_ns2=-8 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
@@ -2681,9 +2681,9 @@ remove_tests()
|
|||||||
# invalid addresses flush
|
# invalid addresses flush
|
||||||
if reset "flush invalid addresses"; then
|
if reset "flush invalid addresses"; then
|
||||||
pm_nl_set_limits $ns1 3 3
|
pm_nl_set_limits $ns1 3 3
|
||||||
pm_nl_add_endpoint $ns1 10.0.12.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.12.1 flags signal,backup
|
||||||
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.3.1 flags signal,backup
|
||||||
pm_nl_add_endpoint $ns1 10.0.14.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.14.1 flags signal,backup
|
||||||
pm_nl_set_limits $ns2 3 3
|
pm_nl_set_limits $ns2 3 3
|
||||||
addr_nr_ns1=-8 speed=slow \
|
addr_nr_ns1=-8 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1
|
run_tests $ns1 $ns2 10.0.1.1
|
||||||
@@ -3806,7 +3806,7 @@ userspace_tests()
|
|||||||
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
||||||
set_userspace_pm $ns1
|
set_userspace_pm $ns1
|
||||||
pm_nl_set_limits $ns2 2 2
|
pm_nl_set_limits $ns2 2 2
|
||||||
{ speed=5 \
|
{ test_linkfail=128 speed=5 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
wait_mpj $ns1
|
wait_mpj $ns1
|
||||||
@@ -3831,7 +3831,7 @@ userspace_tests()
|
|||||||
chk_mptcp_info subflows 0 subflows 0
|
chk_mptcp_info subflows 0 subflows 0
|
||||||
chk_subflows_total 1 1
|
chk_subflows_total 1 1
|
||||||
kill_events_pids
|
kill_events_pids
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# userspace pm create destroy subflow
|
# userspace pm create destroy subflow
|
||||||
@@ -3839,7 +3839,7 @@ userspace_tests()
|
|||||||
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
||||||
set_userspace_pm $ns2
|
set_userspace_pm $ns2
|
||||||
pm_nl_set_limits $ns1 0 1
|
pm_nl_set_limits $ns1 0 1
|
||||||
{ speed=5 \
|
{ test_linkfail=128 speed=5 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
wait_mpj $ns2
|
wait_mpj $ns2
|
||||||
@@ -3859,7 +3859,7 @@ userspace_tests()
|
|||||||
chk_mptcp_info subflows 0 subflows 0
|
chk_mptcp_info subflows 0 subflows 0
|
||||||
chk_subflows_total 1 1
|
chk_subflows_total 1 1
|
||||||
kill_events_pids
|
kill_events_pids
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# userspace pm create id 0 subflow
|
# userspace pm create id 0 subflow
|
||||||
@@ -3867,7 +3867,7 @@ userspace_tests()
|
|||||||
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
||||||
set_userspace_pm $ns2
|
set_userspace_pm $ns2
|
||||||
pm_nl_set_limits $ns1 0 1
|
pm_nl_set_limits $ns1 0 1
|
||||||
{ speed=5 \
|
{ test_linkfail=128 speed=5 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
wait_mpj $ns2
|
wait_mpj $ns2
|
||||||
@@ -3880,7 +3880,7 @@ userspace_tests()
|
|||||||
chk_mptcp_info subflows 1 subflows 1
|
chk_mptcp_info subflows 1 subflows 1
|
||||||
chk_subflows_total 2 2
|
chk_subflows_total 2 2
|
||||||
kill_events_pids
|
kill_events_pids
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# userspace pm remove initial subflow
|
# userspace pm remove initial subflow
|
||||||
@@ -3888,7 +3888,7 @@ userspace_tests()
|
|||||||
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
||||||
set_userspace_pm $ns2
|
set_userspace_pm $ns2
|
||||||
pm_nl_set_limits $ns1 0 1
|
pm_nl_set_limits $ns1 0 1
|
||||||
{ speed=5 \
|
{ test_linkfail=128 speed=5 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
wait_mpj $ns2
|
wait_mpj $ns2
|
||||||
@@ -3904,7 +3904,7 @@ userspace_tests()
|
|||||||
chk_mptcp_info subflows 1 subflows 1
|
chk_mptcp_info subflows 1 subflows 1
|
||||||
chk_subflows_total 1 1
|
chk_subflows_total 1 1
|
||||||
kill_events_pids
|
kill_events_pids
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# userspace pm send RM_ADDR for ID 0
|
# userspace pm send RM_ADDR for ID 0
|
||||||
@@ -3912,7 +3912,7 @@ userspace_tests()
|
|||||||
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
continue_if mptcp_lib_has_file '/proc/sys/net/mptcp/pm_type'; then
|
||||||
set_userspace_pm $ns1
|
set_userspace_pm $ns1
|
||||||
pm_nl_set_limits $ns2 1 1
|
pm_nl_set_limits $ns2 1 1
|
||||||
{ speed=5 \
|
{ test_linkfail=128 speed=5 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
wait_mpj $ns1
|
wait_mpj $ns1
|
||||||
@@ -3930,7 +3930,7 @@ userspace_tests()
|
|||||||
chk_mptcp_info subflows 1 subflows 1
|
chk_mptcp_info subflows 1 subflows 1
|
||||||
chk_subflows_total 1 1
|
chk_subflows_total 1 1
|
||||||
kill_events_pids
|
kill_events_pids
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3943,7 +3943,7 @@ endpoint_tests()
|
|||||||
pm_nl_set_limits $ns1 2 2
|
pm_nl_set_limits $ns1 2 2
|
||||||
pm_nl_set_limits $ns2 2 2
|
pm_nl_set_limits $ns2 2 2
|
||||||
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
pm_nl_add_endpoint $ns1 10.0.2.1 flags signal
|
||||||
{ speed=slow \
|
{ test_linkfail=128 speed=slow \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
|
|
||||||
@@ -3960,7 +3960,7 @@ endpoint_tests()
|
|||||||
pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
|
pm_nl_add_endpoint $ns2 10.0.2.2 flags signal
|
||||||
pm_nl_check_endpoint "modif is allowed" \
|
pm_nl_check_endpoint "modif is allowed" \
|
||||||
$ns2 10.0.2.2 id 1 flags signal
|
$ns2 10.0.2.2 id 1 flags signal
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT &&
|
if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT &&
|
||||||
@@ -3970,7 +3970,7 @@ endpoint_tests()
|
|||||||
pm_nl_set_limits $ns2 0 3
|
pm_nl_set_limits $ns2 0 3
|
||||||
pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.1.2 id 1 dev ns2eth1 flags subflow
|
||||||
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.2.2 id 2 dev ns2eth2 flags subflow
|
||||||
{ test_linkfail=4 speed=5 \
|
{ test_linkfail=128 speed=5 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
|
|
||||||
@@ -4015,7 +4015,7 @@ endpoint_tests()
|
|||||||
chk_mptcp_info subflows 3 subflows 3
|
chk_mptcp_info subflows 3 subflows 3
|
||||||
done
|
done
|
||||||
|
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
|
|
||||||
kill_events_pids
|
kill_events_pids
|
||||||
chk_evt_nr ns1 MPTCP_LIB_EVENT_LISTENER_CREATED 1
|
chk_evt_nr ns1 MPTCP_LIB_EVENT_LISTENER_CREATED 1
|
||||||
@@ -4048,7 +4048,7 @@ endpoint_tests()
|
|||||||
# broadcast IP: no packet for this address will be received on ns1
|
# broadcast IP: no packet for this address will be received on ns1
|
||||||
pm_nl_add_endpoint $ns1 224.0.0.1 id 2 flags signal
|
pm_nl_add_endpoint $ns1 224.0.0.1 id 2 flags signal
|
||||||
pm_nl_add_endpoint $ns1 10.0.1.1 id 42 flags signal
|
pm_nl_add_endpoint $ns1 10.0.1.1 id 42 flags signal
|
||||||
{ test_linkfail=4 speed=5 \
|
{ test_linkfail=128 speed=5 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
|
|
||||||
@@ -4089,7 +4089,7 @@ endpoint_tests()
|
|||||||
wait_mpj $ns2
|
wait_mpj $ns2
|
||||||
chk_subflow_nr "after re-re-add ID 0" 3
|
chk_subflow_nr "after re-re-add ID 0" 3
|
||||||
chk_mptcp_info subflows 3 subflows 3
|
chk_mptcp_info subflows 3 subflows 3
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
|
|
||||||
kill_events_pids
|
kill_events_pids
|
||||||
chk_evt_nr ns1 MPTCP_LIB_EVENT_LISTENER_CREATED 1
|
chk_evt_nr ns1 MPTCP_LIB_EVENT_LISTENER_CREATED 1
|
||||||
@@ -4121,7 +4121,7 @@ endpoint_tests()
|
|||||||
# broadcast IP: no packet for this address will be received on ns1
|
# broadcast IP: no packet for this address will be received on ns1
|
||||||
pm_nl_add_endpoint $ns1 224.0.0.1 id 2 flags signal
|
pm_nl_add_endpoint $ns1 224.0.0.1 id 2 flags signal
|
||||||
pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow
|
pm_nl_add_endpoint $ns2 10.0.3.2 id 3 flags subflow
|
||||||
{ test_linkfail=4 speed=20 \
|
{ test_linkfail=128 speed=20 \
|
||||||
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
run_tests $ns1 $ns2 10.0.1.1 & } 2>/dev/null
|
||||||
local tests_pid=$!
|
local tests_pid=$!
|
||||||
|
|
||||||
@@ -4137,7 +4137,7 @@ endpoint_tests()
|
|||||||
wait_mpj $ns2
|
wait_mpj $ns2
|
||||||
pm_nl_add_endpoint $ns1 10.0.3.1 id 2 flags signal
|
pm_nl_add_endpoint $ns1 10.0.3.1 id 2 flags signal
|
||||||
wait_mpj $ns2
|
wait_mpj $ns2
|
||||||
mptcp_lib_kill_wait $tests_pid
|
mptcp_lib_kill_group_wait $tests_pid
|
||||||
|
|
||||||
join_syn_tx=3 join_connect_err=1 \
|
join_syn_tx=3 join_connect_err=1 \
|
||||||
chk_join_nr 2 2 2
|
chk_join_nr 2 2 2
|
||||||
|
|||||||
@@ -350,6 +350,27 @@ mptcp_lib_kill_wait() {
|
|||||||
wait "${1}" 2>/dev/null
|
wait "${1}" 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# $1: PID
|
||||||
|
mptcp_lib_pid_list_children() {
|
||||||
|
local curr="${1}"
|
||||||
|
# evoke 'ps' only once
|
||||||
|
local pids="${2:-"$(ps o pid,ppid)"}"
|
||||||
|
|
||||||
|
echo "${curr}"
|
||||||
|
|
||||||
|
local pid
|
||||||
|
for pid in $(echo "${pids}" | awk "\$2 == ${curr} { print \$1 }"); do
|
||||||
|
mptcp_lib_pid_list_children "${pid}" "${pids}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1: PID
|
||||||
|
mptcp_lib_kill_group_wait() {
|
||||||
|
# Some users might not have procps-ng: cannot use "kill -- -PID"
|
||||||
|
mptcp_lib_pid_list_children "${1}" | xargs -r kill &>/dev/null
|
||||||
|
wait "${1}" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
# $1: IP address
|
# $1: IP address
|
||||||
mptcp_lib_is_v6() {
|
mptcp_lib_is_v6() {
|
||||||
[ -z "${1##*:*}" ]
|
[ -z "${1##*:*}" ]
|
||||||
|
|||||||
@@ -961,5 +961,49 @@
|
|||||||
"teardown": [
|
"teardown": [
|
||||||
"$TC qdisc del dev $DUMMY root"
|
"$TC qdisc del dev $DUMMY root"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4989",
|
||||||
|
"name": "Try to add an fq child to an ingress qdisc",
|
||||||
|
"category": [
|
||||||
|
"qdisc",
|
||||||
|
"ingress"
|
||||||
|
],
|
||||||
|
"plugins": {
|
||||||
|
"requires": "nsPlugin"
|
||||||
|
},
|
||||||
|
"setup": [
|
||||||
|
"$TC qdisc add dev $DUMMY handle ffff:0 ingress"
|
||||||
|
],
|
||||||
|
"cmdUnderTest": "$TC qdisc add dev $DUMMY parent ffff:0 handle ffe0:0 fq",
|
||||||
|
"expExitCode": "2",
|
||||||
|
"verifyCmd": "$TC -j qdisc ls dev $DUMMY handle ffe0:",
|
||||||
|
"matchJSON": [],
|
||||||
|
"matchCount": "1",
|
||||||
|
"teardown": [
|
||||||
|
"$TC qdisc del dev $DUMMY ingress"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "c2b0",
|
||||||
|
"name": "Try to add an fq child to a clsact qdisc",
|
||||||
|
"category": [
|
||||||
|
"qdisc",
|
||||||
|
"ingress"
|
||||||
|
],
|
||||||
|
"plugins": {
|
||||||
|
"requires": "nsPlugin"
|
||||||
|
},
|
||||||
|
"setup": [
|
||||||
|
"$TC qdisc add dev $DUMMY handle ffff:0 clsact"
|
||||||
|
],
|
||||||
|
"cmdUnderTest": "$TC qdisc add dev $DUMMY parent ffff:0 handle ffe0:0 fq",
|
||||||
|
"expExitCode": "2",
|
||||||
|
"verifyCmd": "$TC -j qdisc ls dev $DUMMY handle ffe0:",
|
||||||
|
"matchJSON": [],
|
||||||
|
"matchCount": "1",
|
||||||
|
"teardown": [
|
||||||
|
"$TC qdisc del dev $DUMMY clsact"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user