Commit d7e78951 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'net-6.11-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net

Pull networking fixes from Paolo Abeni:
 "Including fixes from netfilter.

  Notably this includes fixes for a s390 build breakage.

  Current release - new code bugs:

   - eth: fbnic: fix s390 build

   - eth: airoha: fix NULL pointer dereference in
     airoha_qdma_cleanup_rx_queue()

  Previous releases - regressions:

   - flow_dissector: use DEBUG_NET_WARN_ON_ONCE

   - ipv4: fix incorrect TOS in route get reply

   - dsa: fix chip-wide frame size config in some drivers

  Previous releases - always broken:

   - netfilter: nf_set_pipapo: fix initial map fill

   - eth: gve: fix XDP TX completion handling when counters overflow"

* tag 'net-6.11-rc0' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net:
  eth: fbnic: don't build the driver when skb has more than 21 frags
  net: dsa: b53: Limit chip-wide jumbo frame config to CPU ports
  net: dsa: mv88e6xxx: Limit chip-wide frame size config to CPU ports
  net: airoha: Fix NULL pointer dereference in airoha_qdma_cleanup_rx_queue()
  net: wwan: t7xx: add support for Dell DW5933e
  ipv4: Fix incorrect TOS in fibmatch route get reply
  ipv4: Fix incorrect TOS in route get reply
  net: flow_dissector: use DEBUG_NET_WARN_ON_ONCE
  driver core: auxiliary bus: Fix documentation of auxiliary_device
  net: airoha: fix error branch in airoha_dev_xmit and airoha_set_gdm_ports
  gve: Fix XDP TX completion handling when counters overflow
  ipvs: properly dereference pe in ip_vs_add_service
  selftests: netfilter: add test case for recent mismatch bug
  netfilter: nf_set_pipapo: fix initial map fill
  netfilter: ctnetlink: use helper function to calculate expect ID
  eth: fbnic: fix s390 build.
parents 53a5182c 43598361
...@@ -2256,6 +2256,9 @@ static int b53_change_mtu(struct dsa_switch *ds, int port, int mtu) ...@@ -2256,6 +2256,9 @@ static int b53_change_mtu(struct dsa_switch *ds, int port, int mtu)
if (is5325(dev) || is5365(dev)) if (is5325(dev) || is5365(dev))
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!dsa_is_cpu_port(ds, port))
return 0;
enable_jumbo = (mtu >= JMS_MIN_SIZE); enable_jumbo = (mtu >= JMS_MIN_SIZE);
allow_10_100 = (dev->chip_id == BCM583XX_DEVICE_ID); allow_10_100 = (dev->chip_id == BCM583XX_DEVICE_ID);
......
...@@ -3626,7 +3626,8 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) ...@@ -3626,7 +3626,8 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
mv88e6xxx_reg_lock(chip); mv88e6xxx_reg_lock(chip);
if (chip->info->ops->port_set_jumbo_size) if (chip->info->ops->port_set_jumbo_size)
ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu); ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu);
else if (chip->info->ops->set_max_frame_size) else if (chip->info->ops->set_max_frame_size &&
dsa_is_cpu_port(ds, port))
ret = chip->info->ops->set_max_frame_size(chip, new_mtu); ret = chip->info->ops->set_max_frame_size(chip, new_mtu);
mv88e6xxx_reg_unlock(chip); mv88e6xxx_reg_unlock(chip);
......
...@@ -158,15 +158,16 @@ static int gve_clean_xdp_done(struct gve_priv *priv, struct gve_tx_ring *tx, ...@@ -158,15 +158,16 @@ static int gve_clean_xdp_done(struct gve_priv *priv, struct gve_tx_ring *tx,
u32 to_do) u32 to_do)
{ {
struct gve_tx_buffer_state *info; struct gve_tx_buffer_state *info;
u32 clean_end = tx->done + to_do;
u64 pkts = 0, bytes = 0; u64 pkts = 0, bytes = 0;
size_t space_freed = 0; size_t space_freed = 0;
u32 xsk_complete = 0; u32 xsk_complete = 0;
u32 idx; u32 idx;
int i;
for (; tx->done < clean_end; tx->done++) { for (i = 0; i < to_do; i++) {
idx = tx->done & tx->mask; idx = tx->done & tx->mask;
info = &tx->info[idx]; info = &tx->info[idx];
tx->done++;
if (unlikely(!info->xdp.size)) if (unlikely(!info->xdp.size))
continue; continue;
......
...@@ -977,7 +977,7 @@ static int airoha_set_gdm_ports(struct airoha_eth *eth, bool enable) ...@@ -977,7 +977,7 @@ static int airoha_set_gdm_ports(struct airoha_eth *eth, bool enable)
return 0; return 0;
error: error:
for (i--; i >= 0; i++) for (i--; i >= 0; i--)
airoha_set_gdm_port(eth, port_list[i], false); airoha_set_gdm_port(eth, port_list[i], false);
return err; return err;
...@@ -1585,7 +1585,6 @@ static int airoha_qdma_init_rx_queue(struct airoha_eth *eth, ...@@ -1585,7 +1585,6 @@ static int airoha_qdma_init_rx_queue(struct airoha_eth *eth,
static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
{ {
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
struct airoha_eth *eth = q->eth; struct airoha_eth *eth = q->eth;
while (q->queued) { while (q->queued) {
...@@ -1593,7 +1592,7 @@ static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) ...@@ -1593,7 +1592,7 @@ static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
struct page *page = virt_to_head_page(e->buf); struct page *page = virt_to_head_page(e->buf);
dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len, dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len,
dir); page_pool_get_dma_dir(q->page_pool));
page_pool_put_full_page(q->page_pool, page, false); page_pool_put_full_page(q->page_pool, page, false);
q->tail = (q->tail + 1) % q->ndesc; q->tail = (q->tail + 1) % q->ndesc;
q->queued--; q->queued--;
...@@ -2431,9 +2430,11 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, ...@@ -2431,9 +2430,11 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
return NETDEV_TX_OK; return NETDEV_TX_OK;
error_unmap: error_unmap:
for (i--; i >= 0; i++) for (i--; i >= 0; i--) {
dma_unmap_single(dev->dev.parent, q->entry[i].dma_addr, index = (q->head + i) % q->ndesc;
q->entry[i].dma_len, DMA_TO_DEVICE); dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr,
q->entry[index].dma_len, DMA_TO_DEVICE);
}
spin_unlock_bh(&q->lock); spin_unlock_bh(&q->lock);
error: error:
......
...@@ -20,6 +20,8 @@ if NET_VENDOR_META ...@@ -20,6 +20,8 @@ if NET_VENDOR_META
config FBNIC config FBNIC
tristate "Meta Platforms Host Network Interface" tristate "Meta Platforms Host Network Interface"
depends on X86_64 || COMPILE_TEST depends on X86_64 || COMPILE_TEST
depends on S390=n
depends on MAX_SKB_FRAGS < 22
depends on PCI_MSI depends on PCI_MSI
select PHYLINK select PHYLINK
help help
......
...@@ -852,6 +852,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev) ...@@ -852,6 +852,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev)
static const struct pci_device_id t7xx_pci_table[] = { static const struct pci_device_id t7xx_pci_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x4d75) }, { PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x4d75) },
{ PCI_DEVICE(0x14c0, 0x4d75) }, // Dell DW5933e
{ } { }
}; };
MODULE_DEVICE_TABLE(pci, t7xx_pci_table); MODULE_DEVICE_TABLE(pci, t7xx_pci_table);
......
...@@ -58,9 +58,10 @@ ...@@ -58,9 +58,10 @@
* in * in
* @name: Match name found by the auxiliary device driver, * @name: Match name found by the auxiliary device driver,
* @id: unique identitier if multiple devices of the same name are exported, * @id: unique identitier if multiple devices of the same name are exported,
* @irqs: irqs xarray contains irq indices which are used by the device, * @sysfs: embedded struct which hold all sysfs related fields,
* @lock: Synchronize irq sysfs creation, * @sysfs.irqs: irqs xarray contains irq indices which are used by the device,
* @irq_dir_exists: whether "irqs" directory exists, * @sysfs.lock: Synchronize irq sysfs creation,
* @sysfs.irq_dir_exists: whether "irqs" directory exists,
* *
* An auxiliary_device represents a part of its parent device's functionality. * An auxiliary_device represents a part of its parent device's functionality.
* It is given a name that, combined with the registering drivers * It is given a name that, combined with the registering drivers
......
...@@ -173,6 +173,7 @@ struct fib_result { ...@@ -173,6 +173,7 @@ struct fib_result {
unsigned char type; unsigned char type;
unsigned char scope; unsigned char scope;
u32 tclassid; u32 tclassid;
dscp_t dscp;
struct fib_nh_common *nhc; struct fib_nh_common *nhc;
struct fib_info *fi; struct fib_info *fi;
struct fib_table *table; struct fib_table *table;
......
...@@ -1117,7 +1117,7 @@ bool __skb_flow_dissect(const struct net *net, ...@@ -1117,7 +1117,7 @@ bool __skb_flow_dissect(const struct net *net,
} }
} }
WARN_ON_ONCE(!net); DEBUG_NET_WARN_ON_ONCE(!net);
if (net) { if (net) {
enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR; enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR;
struct bpf_prog_array *run_array; struct bpf_prog_array *run_array;
......
...@@ -1629,6 +1629,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, ...@@ -1629,6 +1629,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
res->nhc = nhc; res->nhc = nhc;
res->type = fa->fa_type; res->type = fa->fa_type;
res->scope = fi->fib_scope; res->scope = fi->fib_scope;
res->dscp = fa->fa_dscp;
res->fi = fi; res->fi = fi;
res->table = tb; res->table = tb;
res->fa_head = &n->leaf; res->fa_head = &n->leaf;
......
...@@ -2867,9 +2867,9 @@ EXPORT_SYMBOL_GPL(ip_route_output_flow); ...@@ -2867,9 +2867,9 @@ EXPORT_SYMBOL_GPL(ip_route_output_flow);
/* called with rcu_read_lock held */ /* called with rcu_read_lock held */
static int rt_fill_info(struct net *net, __be32 dst, __be32 src, static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
struct rtable *rt, u32 table_id, struct flowi4 *fl4, struct rtable *rt, u32 table_id, dscp_t dscp,
struct sk_buff *skb, u32 portid, u32 seq, struct flowi4 *fl4, struct sk_buff *skb, u32 portid,
unsigned int flags) u32 seq, unsigned int flags)
{ {
struct rtmsg *r; struct rtmsg *r;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
...@@ -2885,7 +2885,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, ...@@ -2885,7 +2885,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
r->rtm_family = AF_INET; r->rtm_family = AF_INET;
r->rtm_dst_len = 32; r->rtm_dst_len = 32;
r->rtm_src_len = 0; r->rtm_src_len = 0;
r->rtm_tos = fl4 ? fl4->flowi4_tos : 0; r->rtm_tos = inet_dscp_to_dsfield(dscp);
r->rtm_table = table_id < 256 ? table_id : RT_TABLE_COMPAT; r->rtm_table = table_id < 256 ? table_id : RT_TABLE_COMPAT;
if (nla_put_u32(skb, RTA_TABLE, table_id)) if (nla_put_u32(skb, RTA_TABLE, table_id))
goto nla_put_failure; goto nla_put_failure;
...@@ -3035,7 +3035,7 @@ static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb, ...@@ -3035,7 +3035,7 @@ static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb,
goto next; goto next;
err = rt_fill_info(net, fnhe->fnhe_daddr, 0, rt, err = rt_fill_info(net, fnhe->fnhe_daddr, 0, rt,
table_id, NULL, skb, table_id, 0, NULL, skb,
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, flags); cb->nlh->nlmsg_seq, flags);
if (err) if (err)
...@@ -3331,7 +3331,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, ...@@ -3331,7 +3331,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
fri.tb_id = table_id; fri.tb_id = table_id;
fri.dst = res.prefix; fri.dst = res.prefix;
fri.dst_len = res.prefixlen; fri.dst_len = res.prefixlen;
fri.dscp = inet_dsfield_to_dscp(fl4.flowi4_tos); fri.dscp = res.dscp;
fri.type = rt->rt_type; fri.type = rt->rt_type;
fri.offload = 0; fri.offload = 0;
fri.trap = 0; fri.trap = 0;
...@@ -3358,8 +3358,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, ...@@ -3358,8 +3358,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
err = fib_dump_info(skb, NETLINK_CB(in_skb).portid, err = fib_dump_info(skb, NETLINK_CB(in_skb).portid,
nlh->nlmsg_seq, RTM_NEWROUTE, &fri, 0); nlh->nlmsg_seq, RTM_NEWROUTE, &fri, 0);
} else { } else {
err = rt_fill_info(net, dst, src, rt, table_id, &fl4, skb, err = rt_fill_info(net, dst, src, rt, table_id, res.dscp, &fl4,
NETLINK_CB(in_skb).portid, skb, NETLINK_CB(in_skb).portid,
nlh->nlmsg_seq, 0); nlh->nlmsg_seq, 0);
} }
if (err < 0) if (err < 0)
......
...@@ -1459,18 +1459,18 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, ...@@ -1459,18 +1459,18 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
if (ret < 0) if (ret < 0)
goto out_err; goto out_err;
/* Bind the ct retriever */
RCU_INIT_POINTER(svc->pe, pe);
pe = NULL;
/* Update the virtual service counters */ /* Update the virtual service counters */
if (svc->port == FTPPORT) if (svc->port == FTPPORT)
atomic_inc(&ipvs->ftpsvc_counter); atomic_inc(&ipvs->ftpsvc_counter);
else if (svc->port == 0) else if (svc->port == 0)
atomic_inc(&ipvs->nullsvc_counter); atomic_inc(&ipvs->nullsvc_counter);
if (svc->pe && svc->pe->conn_out) if (pe && pe->conn_out)
atomic_inc(&ipvs->conn_out_counter); atomic_inc(&ipvs->conn_out_counter);
/* Bind the ct retriever */
RCU_INIT_POINTER(svc->pe, pe);
pe = NULL;
/* Count only IPv4 services for old get/setsockopt interface */ /* Count only IPv4 services for old get/setsockopt interface */
if (svc->af == AF_INET) if (svc->af == AF_INET)
ipvs->num_services++; ipvs->num_services++;
......
...@@ -3420,7 +3420,8 @@ static int ctnetlink_del_expect(struct sk_buff *skb, ...@@ -3420,7 +3420,8 @@ static int ctnetlink_del_expect(struct sk_buff *skb,
if (cda[CTA_EXPECT_ID]) { if (cda[CTA_EXPECT_ID]) {
__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]); __be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
if (ntohl(id) != (u32)(unsigned long)exp) {
if (id != nf_expect_get_id(exp)) {
nf_ct_expect_put(exp); nf_ct_expect_put(exp);
return -ENOENT; return -ENOENT;
} }
......
...@@ -434,7 +434,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set, ...@@ -434,7 +434,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
res_map = scratch->map + (map_index ? m->bsize_max : 0); res_map = scratch->map + (map_index ? m->bsize_max : 0);
fill_map = scratch->map + (map_index ? 0 : m->bsize_max); fill_map = scratch->map + (map_index ? 0 : m->bsize_max);
memset(res_map, 0xff, m->bsize_max * sizeof(*res_map)); pipapo_resmap_init(m, res_map);
nft_pipapo_for_each_field(f, i, m) { nft_pipapo_for_each_field(f, i, m) {
bool last = i == m->field_count - 1; bool last = i == m->field_count - 1;
...@@ -542,7 +542,7 @@ static struct nft_pipapo_elem *pipapo_get(const struct net *net, ...@@ -542,7 +542,7 @@ static struct nft_pipapo_elem *pipapo_get(const struct net *net,
goto out; goto out;
} }
memset(res_map, 0xff, m->bsize_max * sizeof(*res_map)); pipapo_resmap_init(m, res_map);
nft_pipapo_for_each_field(f, i, m) { nft_pipapo_for_each_field(f, i, m) {
bool last = i == m->field_count - 1; bool last = i == m->field_count - 1;
......
...@@ -278,4 +278,25 @@ static u64 pipapo_estimate_size(const struct nft_set_desc *desc) ...@@ -278,4 +278,25 @@ static u64 pipapo_estimate_size(const struct nft_set_desc *desc)
return size; return size;
} }
/**
* pipapo_resmap_init() - Initialise result map before first use
* @m: Matching data, including mapping table
* @res_map: Result map
*
* Initialize all bits covered by the first field to one, so that after
* the first step, only the matching bits of the first bit group remain.
*
* If other fields have a large bitmap, set remainder of res_map to 0.
*/
static inline void pipapo_resmap_init(const struct nft_pipapo_match *m, unsigned long *res_map)
{
const struct nft_pipapo_field *f = m->f;
int i;
for (i = 0; i < f->bsize; i++)
res_map[i] = ULONG_MAX;
for (i = f->bsize; i < m->bsize_max; i++)
res_map[i] = 0ul;
}
#endif /* _NFT_SET_PIPAPO_H */ #endif /* _NFT_SET_PIPAPO_H */
...@@ -1036,6 +1036,7 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill, ...@@ -1036,6 +1036,7 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
/** /**
* nft_pipapo_avx2_lookup_slow() - Fallback function for uncommon field sizes * nft_pipapo_avx2_lookup_slow() - Fallback function for uncommon field sizes
* @mdata: Matching data, including mapping table
* @map: Previous match result, used as initial bitmap * @map: Previous match result, used as initial bitmap
* @fill: Destination bitmap to be filled with current match result * @fill: Destination bitmap to be filled with current match result
* @f: Field, containing lookup and mapping tables * @f: Field, containing lookup and mapping tables
...@@ -1051,7 +1052,8 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill, ...@@ -1051,7 +1052,8 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
* Return: -1 on no match, rule index of match if @last, otherwise first long * Return: -1 on no match, rule index of match if @last, otherwise first long
* word index to be checked next (i.e. first filled word). * word index to be checked next (i.e. first filled word).
*/ */
static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill, static int nft_pipapo_avx2_lookup_slow(const struct nft_pipapo_match *mdata,
unsigned long *map, unsigned long *fill,
const struct nft_pipapo_field *f, const struct nft_pipapo_field *f,
int offset, const u8 *pkt, int offset, const u8 *pkt,
bool first, bool last) bool first, bool last)
...@@ -1060,7 +1062,7 @@ static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill, ...@@ -1060,7 +1062,7 @@ static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill,
int i, ret = -1, b; int i, ret = -1, b;
if (first) if (first)
memset(map, 0xff, bsize * sizeof(*map)); pipapo_resmap_init(mdata, map);
for (i = offset; i < bsize; i++) { for (i = offset; i < bsize; i++) {
if (f->bb == 8) if (f->bb == 8)
...@@ -1186,7 +1188,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, ...@@ -1186,7 +1188,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
} else if (f->groups == 16) { } else if (f->groups == 16) {
NFT_SET_PIPAPO_AVX2_LOOKUP(8, 16); NFT_SET_PIPAPO_AVX2_LOOKUP(8, 16);
} else { } else {
ret = nft_pipapo_avx2_lookup_slow(res, fill, f, ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f,
ret, rp, ret, rp,
first, last); first, last);
} }
...@@ -1202,7 +1204,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set, ...@@ -1202,7 +1204,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
} else if (f->groups == 32) { } else if (f->groups == 32) {
NFT_SET_PIPAPO_AVX2_LOOKUP(4, 32); NFT_SET_PIPAPO_AVX2_LOOKUP(4, 32);
} else { } else {
ret = nft_pipapo_avx2_lookup_slow(res, fill, f, ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f,
ret, rp, ret, rp,
first, last); first, last);
} }
......
...@@ -1737,53 +1737,53 @@ ipv4_rt_dsfield() ...@@ -1737,53 +1737,53 @@ ipv4_rt_dsfield()
# DSCP 0x10 should match the specific route, no matter the ECN bits # DSCP 0x10 should match the specific route, no matter the ECN bits
$IP route get fibmatch 172.16.102.1 dsfield 0x10 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x10 | \
grep -q "via 172.16.103.2" grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT" log_test $? 0 "IPv4 route with DSCP and ECN:Not-ECT"
$IP route get fibmatch 172.16.102.1 dsfield 0x11 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x11 | \
grep -q "via 172.16.103.2" grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)" log_test $? 0 "IPv4 route with DSCP and ECN:ECT(1)"
$IP route get fibmatch 172.16.102.1 dsfield 0x12 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x12 | \
grep -q "via 172.16.103.2" grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)" log_test $? 0 "IPv4 route with DSCP and ECN:ECT(0)"
$IP route get fibmatch 172.16.102.1 dsfield 0x13 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x13 | \
grep -q "via 172.16.103.2" grep -q "172.16.102.0/24 tos 0x10 via 172.16.103.2"
log_test $? 0 "IPv4 route with DSCP and ECN:CE" log_test $? 0 "IPv4 route with DSCP and ECN:CE"
# Unknown DSCP should match the generic route, no matter the ECN bits # Unknown DSCP should match the generic route, no matter the ECN bits
$IP route get fibmatch 172.16.102.1 dsfield 0x14 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x14 | \
grep -q "via 172.16.101.2" grep -q "172.16.102.0/24 via 172.16.101.2"
log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT" log_test $? 0 "IPv4 route with unknown DSCP and ECN:Not-ECT"
$IP route get fibmatch 172.16.102.1 dsfield 0x15 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x15 | \
grep -q "via 172.16.101.2" grep -q "172.16.102.0/24 via 172.16.101.2"
log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)" log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(1)"
$IP route get fibmatch 172.16.102.1 dsfield 0x16 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x16 | \
grep -q "via 172.16.101.2" grep -q "172.16.102.0/24 via 172.16.101.2"
log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)" log_test $? 0 "IPv4 route with unknown DSCP and ECN:ECT(0)"
$IP route get fibmatch 172.16.102.1 dsfield 0x17 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x17 | \
grep -q "via 172.16.101.2" grep -q "172.16.102.0/24 via 172.16.101.2"
log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE" log_test $? 0 "IPv4 route with unknown DSCP and ECN:CE"
# Null DSCP should match the generic route, no matter the ECN bits # Null DSCP should match the generic route, no matter the ECN bits
$IP route get fibmatch 172.16.102.1 dsfield 0x00 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x00 | \
grep -q "via 172.16.101.2" grep -q "172.16.102.0/24 via 172.16.101.2"
log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT" log_test $? 0 "IPv4 route with no DSCP and ECN:Not-ECT"
$IP route get fibmatch 172.16.102.1 dsfield 0x01 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x01 | \
grep -q "via 172.16.101.2" grep -q "172.16.102.0/24 via 172.16.101.2"
log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)" log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(1)"
$IP route get fibmatch 172.16.102.1 dsfield 0x02 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x02 | \
grep -q "via 172.16.101.2" grep -q "172.16.102.0/24 via 172.16.101.2"
log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)" log_test $? 0 "IPv4 route with no DSCP and ECN:ECT(0)"
$IP route get fibmatch 172.16.102.1 dsfield 0x03 | \ $IP route get fibmatch 172.16.102.1 dsfield 0x03 | \
grep -q "via 172.16.101.2" grep -q "172.16.102.0/24 via 172.16.101.2"
log_test $? 0 "IPv4 route with no DSCP and ECN:CE" log_test $? 0 "IPv4 route with no DSCP and ECN:CE"
} }
......
...@@ -27,7 +27,7 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto ...@@ -27,7 +27,7 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto
net6_port_net6_port net_port_mac_proto_net" net6_port_net6_port net_port_mac_proto_net"
# Reported bugs, also described by TYPE_ variables below # Reported bugs, also described by TYPE_ variables below
BUGS="flush_remove_add reload" BUGS="flush_remove_add reload net_port_proto_match"
# List of possible paths to pktgen script from kernel tree for performance tests # List of possible paths to pktgen script from kernel tree for performance tests
PKTGEN_SCRIPT_PATHS=" PKTGEN_SCRIPT_PATHS="
...@@ -371,6 +371,22 @@ race_repeat 0 ...@@ -371,6 +371,22 @@ race_repeat 0
perf_duration 0 perf_duration 0
" "
TYPE_net_port_proto_match="
display net,port,proto
type_spec ipv4_addr . inet_service . inet_proto
chain_spec ip daddr . udp dport . meta l4proto
dst addr4 port proto
src
start 1
count 9
src_delta 9
tools sendip bash
proto udp
race_repeat 0
perf_duration 0
"
# Set template for all tests, types and rules are filled in depending on test # Set template for all tests, types and rules are filled in depending on test
set_template=' set_template='
flush ruleset flush ruleset
...@@ -1555,6 +1571,64 @@ test_bug_reload() { ...@@ -1555,6 +1571,64 @@ test_bug_reload() {
nft flush ruleset nft flush ruleset
} }
# - add ranged element, check that packets match it
# - delete element again, check it is gone
test_bug_net_port_proto_match() {
setup veth send_"${proto}" set || return ${ksft_skip}
rstart=${start}
range_size=1
for i in $(seq 1 10); do
for j in $(seq 1 20) ; do
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
nft "add element inet filter test { $elem }" || return 1
nft "get element inet filter test { $elem }" | grep -q "$elem"
if [ $? -ne 0 ];then
local got=$(nft "get element inet filter test { $elem }")
err "post-add: should have returned $elem but got $got"
return 1
fi
done
done
# recheck after set was filled
for i in $(seq 1 10); do
for j in $(seq 1 20) ; do
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
nft "get element inet filter test { $elem }" | grep -q "$elem"
if [ $? -ne 0 ];then
local got=$(nft "get element inet filter test { $elem }")
err "post-fill: should have returned $elem but got $got"
return 1
fi
done
done
# random del and re-fetch
for i in $(seq 1 10); do
for j in $(seq 1 20) ; do
local rnd=$((RANDOM%10))
local got=""
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
if [ $rnd -gt 0 ];then
continue
fi
nft "delete element inet filter test { $elem }"
got=$(nft "get element inet filter test { $elem }" 2>/dev/null)
if [ $? -eq 0 ];then
err "post-delete: query for $elem returned $got instead of error."
return 1
fi
done
done
nft flush ruleset
}
test_reported_issues() { test_reported_issues() {
eval test_bug_"${subtest}" eval test_bug_"${subtest}"
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment