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

Merge in the fixes we had queued in case there was another -rc.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2021-11-01 20:05:14 -07:00
commit 8a33dcc2f6
19 changed files with 233 additions and 39 deletions

View File

@ -1331,6 +1331,10 @@
#define MDIO_VEND2_PMA_CDR_CONTROL 0x8056 #define MDIO_VEND2_PMA_CDR_CONTROL 0x8056
#endif #endif
#ifndef MDIO_VEND2_PMA_MISC_CTRL0
#define MDIO_VEND2_PMA_MISC_CTRL0 0x8090
#endif
#ifndef MDIO_CTRL1_SPEED1G #ifndef MDIO_CTRL1_SPEED1G
#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100) #define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
#endif #endif
@ -1389,6 +1393,10 @@
#define XGBE_PMA_RX_RST_0_RESET_ON 0x10 #define XGBE_PMA_RX_RST_0_RESET_ON 0x10
#define XGBE_PMA_RX_RST_0_RESET_OFF 0x00 #define XGBE_PMA_RX_RST_0_RESET_OFF 0x00
#define XGBE_PMA_PLL_CTRL_MASK BIT(15)
#define XGBE_PMA_PLL_CTRL_ENABLE BIT(15)
#define XGBE_PMA_PLL_CTRL_DISABLE 0x0000
/* Bit setting and getting macros /* Bit setting and getting macros
* The get macro will extract the current bit field value from within * The get macro will extract the current bit field value from within
* the variable * the variable

View File

@ -1977,12 +1977,26 @@ static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata)
} }
} }
static void xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable)
{
XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0,
XGBE_PMA_PLL_CTRL_MASK,
enable ? XGBE_PMA_PLL_CTRL_ENABLE
: XGBE_PMA_PLL_CTRL_DISABLE);
/* Wait for command to complete */
usleep_range(100, 200);
}
static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
unsigned int cmd, unsigned int sub_cmd) unsigned int cmd, unsigned int sub_cmd)
{ {
unsigned int s0 = 0; unsigned int s0 = 0;
unsigned int wait; unsigned int wait;
/* Disable PLL re-initialization during FW command processing */
xgbe_phy_pll_ctrl(pdata, false);
/* Log if a previous command did not complete */ /* Log if a previous command did not complete */
if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) {
netif_dbg(pdata, link, pdata->netdev, netif_dbg(pdata, link, pdata->netdev,
@ -2003,7 +2017,7 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
wait = XGBE_RATECHANGE_COUNT; wait = XGBE_RATECHANGE_COUNT;
while (wait--) { while (wait--) {
if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
return; goto reenable_pll;
usleep_range(1000, 2000); usleep_range(1000, 2000);
} }
@ -2013,6 +2027,10 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
/* Reset on error */ /* Reset on error */
xgbe_phy_rx_reset(pdata); xgbe_phy_rx_reset(pdata);
reenable_pll:
/* Enable PLL re-initialization */
xgbe_phy_pll_ctrl(pdata, true);
} }
static void xgbe_phy_rrc(struct xgbe_prv_data *pdata) static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)

View File

@ -1914,8 +1914,6 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
ind_bufp = &tx_scrq->ind_buf; ind_bufp = &tx_scrq->ind_buf;
if (test_bit(0, &adapter->resetting)) { if (test_bit(0, &adapter->resetting)) {
if (!netif_subqueue_stopped(netdev, skb))
netif_stop_subqueue(netdev, queue_num);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
tx_send_failed++; tx_send_failed++;
@ -2757,7 +2755,7 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
if (adapter->state == VNIC_PROBING) { if (adapter->state == VNIC_PROBING) {
netdev_warn(netdev, "Adapter reset during probe\n"); netdev_warn(netdev, "Adapter reset during probe\n");
adapter->init_done_rc = EAGAIN; adapter->init_done_rc = -EAGAIN;
ret = EAGAIN; ret = EAGAIN;
goto err; goto err;
} }
@ -5259,11 +5257,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
*/ */
adapter->login_pending = false; adapter->login_pending = false;
if (!completion_done(&adapter->init_done)) {
complete(&adapter->init_done);
adapter->init_done_rc = -EIO;
}
if (adapter->state == VNIC_DOWN) if (adapter->state == VNIC_DOWN)
rc = ibmvnic_reset(adapter, VNIC_RESET_PASSIVE_INIT); rc = ibmvnic_reset(adapter, VNIC_RESET_PASSIVE_INIT);
else else
@ -5284,6 +5277,13 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
rc); rc);
adapter->failover_pending = false; adapter->failover_pending = false;
} }
if (!completion_done(&adapter->init_done)) {
complete(&adapter->init_done);
if (!adapter->init_done_rc)
adapter->init_done_rc = -EAGAIN;
}
break; break;
case IBMVNIC_CRQ_INIT_COMPLETE: case IBMVNIC_CRQ_INIT_COMPLETE:
dev_info(dev, "Partner initialization complete\n"); dev_info(dev, "Partner initialization complete\n");
@ -5604,6 +5604,9 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter)
crq->cur = 0; crq->cur = 0;
spin_lock_init(&crq->lock); spin_lock_init(&crq->lock);
/* process any CRQs that were queued before we enabled interrupts */
tasklet_schedule(&adapter->tasklet);
return retrc; return retrc;
req_irq_failed: req_irq_failed:
@ -5753,7 +5756,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
} }
rc = ibmvnic_reset_init(adapter, false); rc = ibmvnic_reset_init(adapter, false);
} while (rc == EAGAIN); } while (rc == -EAGAIN);
/* We are ignoring the error from ibmvnic_reset_init() assuming that the /* We are ignoring the error from ibmvnic_reset_init() assuming that the
* partner is not ready. CRQ is not active. When the partner becomes * partner is not ready. CRQ is not active. When the partner becomes

View File

@ -2067,7 +2067,7 @@ static int nfp_net_poll(struct napi_struct *napi, int budget)
if (napi_complete_done(napi, pkts_polled)) if (napi_complete_done(napi, pkts_polled))
nfp_net_irq_unmask(r_vec->nfp_net, r_vec->irq_entry); nfp_net_irq_unmask(r_vec->nfp_net, r_vec->irq_entry);
if (r_vec->nfp_net->rx_coalesce_adapt_on) { if (r_vec->nfp_net->rx_coalesce_adapt_on && r_vec->rx_ring) {
struct dim_sample dim_sample = {}; struct dim_sample dim_sample = {};
unsigned int start; unsigned int start;
u64 pkts, bytes; u64 pkts, bytes;
@ -2082,7 +2082,7 @@ static int nfp_net_poll(struct napi_struct *napi, int budget)
net_dim(&r_vec->rx_dim, dim_sample); net_dim(&r_vec->rx_dim, dim_sample);
} }
if (r_vec->nfp_net->tx_coalesce_adapt_on) { if (r_vec->nfp_net->tx_coalesce_adapt_on && r_vec->tx_ring) {
struct dim_sample dim_sample = {}; struct dim_sample dim_sample = {};
unsigned int start; unsigned int start;
u64 pkts, bytes; u64 pkts, bytes;
@ -3016,10 +3016,8 @@ static void nfp_net_rx_dim_work(struct work_struct *work)
/* copy RX interrupt coalesce parameters */ /* copy RX interrupt coalesce parameters */
value = (moder.pkts << 16) | (factor * moder.usec); value = (moder.pkts << 16) | (factor * moder.usec);
rtnl_lock();
nn_writel(nn, NFP_NET_CFG_RXR_IRQ_MOD(r_vec->rx_ring->idx), value); nn_writel(nn, NFP_NET_CFG_RXR_IRQ_MOD(r_vec->rx_ring->idx), value);
(void)nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD); (void)nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD);
rtnl_unlock();
dim->state = DIM_START_MEASURE; dim->state = DIM_START_MEASURE;
} }
@ -3047,10 +3045,8 @@ static void nfp_net_tx_dim_work(struct work_struct *work)
/* copy TX interrupt coalesce parameters */ /* copy TX interrupt coalesce parameters */
value = (moder.pkts << 16) | (factor * moder.usec); value = (moder.pkts << 16) | (factor * moder.usec);
rtnl_lock();
nn_writel(nn, NFP_NET_CFG_TXR_IRQ_MOD(r_vec->tx_ring->idx), value); nn_writel(nn, NFP_NET_CFG_TXR_IRQ_MOD(r_vec->tx_ring->idx), value);
(void)nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD); (void)nfp_net_reconfig(nn, NFP_NET_CFG_UPDATE_IRQMOD);
rtnl_unlock();
dim->state = DIM_START_MEASURE; dim->state = DIM_START_MEASURE;
} }

View File

@ -1780,7 +1780,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!phylink_test(pl->supported, Asym_Pause) && if (!phylink_test(pl->supported, Asym_Pause) &&
!pause->autoneg && pause->rx_pause != pause->tx_pause) pause->rx_pause != pause->tx_pause)
return -EINVAL; return -EINVAL;
pause_state = 0; pause_state = 0;

View File

@ -287,6 +287,7 @@ enum flow_dissector_key_id {
#define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0) #define FLOW_DISSECTOR_F_PARSE_1ST_FRAG BIT(0)
#define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(1) #define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL BIT(1)
#define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(2) #define FLOW_DISSECTOR_F_STOP_AT_ENCAP BIT(2)
#define FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP BIT(3)
struct flow_dissector_key { struct flow_dissector_key {
enum flow_dissector_key_id key_id; enum flow_dissector_key_id key_id;

View File

@ -626,7 +626,8 @@ static inline __u32 sctp_min_frag_point(struct sctp_sock *sp, __u16 datasize)
static inline int sctp_transport_pl_hlen(struct sctp_transport *t) static inline int sctp_transport_pl_hlen(struct sctp_transport *t)
{ {
return __sctp_mtu_payload(sctp_sk(t->asoc->base.sk), t, 0, 0); return __sctp_mtu_payload(sctp_sk(t->asoc->base.sk), t, 0, 0) -
sizeof(struct sctphdr);
} }
static inline void sctp_transport_pl_reset(struct sctp_transport *t) static inline void sctp_transport_pl_reset(struct sctp_transport *t)
@ -653,12 +654,10 @@ static inline void sctp_transport_pl_update(struct sctp_transport *t)
if (t->pl.state == SCTP_PL_DISABLED) if (t->pl.state == SCTP_PL_DISABLED)
return; return;
if (del_timer(&t->probe_timer))
sctp_transport_put(t);
t->pl.state = SCTP_PL_BASE; t->pl.state = SCTP_PL_BASE;
t->pl.pmtu = SCTP_BASE_PLPMTU; t->pl.pmtu = SCTP_BASE_PLPMTU;
t->pl.probe_size = SCTP_BASE_PLPMTU; t->pl.probe_size = SCTP_BASE_PLPMTU;
sctp_transport_reset_probe_timer(t);
} }
static inline bool sctp_transport_pl_enabled(struct sctp_transport *t) static inline bool sctp_transport_pl_enabled(struct sctp_transport *t)

View File

@ -1893,11 +1893,13 @@ static inline int br_cfm_status_fill_info(struct sk_buff *skb,
static inline int br_cfm_mep_count(struct net_bridge *br, u32 *count) static inline int br_cfm_mep_count(struct net_bridge *br, u32 *count)
{ {
*count = 0;
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int br_cfm_peer_mep_count(struct net_bridge *br, u32 *count) static inline int br_cfm_peer_mep_count(struct net_bridge *br, u32 *count)
{ {
*count = 0;
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
#endif #endif

View File

@ -1306,6 +1306,11 @@ ip_proto_again:
switch (ip_proto) { switch (ip_proto) {
case IPPROTO_GRE: case IPPROTO_GRE:
if (flags & FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP) {
fdret = FLOW_DISSECT_RET_OUT_GOOD;
break;
}
fdret = __skb_flow_dissect_gre(skb, key_control, flow_dissector, fdret = __skb_flow_dissect_gre(skb, key_control, flow_dissector,
target_container, data, target_container, data,
&proto, &nhoff, &hlen, flags); &proto, &nhoff, &hlen, flags);
@ -1363,6 +1368,11 @@ ip_proto_again:
break; break;
} }
case IPPROTO_IPIP: case IPPROTO_IPIP:
if (flags & FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP) {
fdret = FLOW_DISSECT_RET_OUT_GOOD;
break;
}
proto = htons(ETH_P_IP); proto = htons(ETH_P_IP);
key_control->flags |= FLOW_DIS_ENCAPSULATION; key_control->flags |= FLOW_DIS_ENCAPSULATION;
@ -1375,6 +1385,11 @@ ip_proto_again:
break; break;
case IPPROTO_IPV6: case IPPROTO_IPV6:
if (flags & FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP) {
fdret = FLOW_DISSECT_RET_OUT_GOOD;
break;
}
proto = htons(ETH_P_IPV6); proto = htons(ETH_P_IPV6);
key_control->flags |= FLOW_DIS_ENCAPSULATION; key_control->flags |= FLOW_DIS_ENCAPSULATION;

View File

@ -1435,7 +1435,6 @@ do_udp_sendmsg:
if (!fl6.flowi6_oif) if (!fl6.flowi6_oif)
fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
fl6.flowi6_mark = ipc6.sockc.mark;
fl6.flowi6_uid = sk->sk_uid; fl6.flowi6_uid = sk->sk_uid;
if (msg->msg_controllen) { if (msg->msg_controllen) {
@ -1471,6 +1470,7 @@ do_udp_sendmsg:
ipc6.opt = opt; ipc6.opt = opt;
fl6.flowi6_proto = sk->sk_protocol; fl6.flowi6_proto = sk->sk_protocol;
fl6.flowi6_mark = ipc6.sockc.mark;
fl6.daddr = *daddr; fl6.daddr = *daddr;
if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr)) if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
fl6.saddr = np->saddr; fl6.saddr = np->saddr;

View File

@ -329,7 +329,8 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
ARRAY_SIZE(fl_ct_info_to_flower_map), ARRAY_SIZE(fl_ct_info_to_flower_map),
post_ct); post_ct);
skb_flow_dissect_hash(skb, &mask->dissector, &skb_key); skb_flow_dissect_hash(skb, &mask->dissector, &skb_key);
skb_flow_dissect(skb, &mask->dissector, &skb_key, 0); skb_flow_dissect(skb, &mask->dissector, &skb_key,
FLOW_DISSECTOR_F_STOP_BEFORE_ENCAP);
f = fl_mask_lookup(mask, &skb_key); f = fl_mask_lookup(mask, &skb_key);
if (f && !tc_skip_sw(f->flags)) { if (f && !tc_skip_sw(f->flags)) {

View File

@ -581,13 +581,16 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list); chunk = list_entry(packet->chunk_list.next, struct sctp_chunk, list);
sk = chunk->skb->sk; sk = chunk->skb->sk;
/* check gso */
if (packet->size > tp->pathmtu && !packet->ipfragok && !chunk->pmtu_probe) { if (packet->size > tp->pathmtu && !packet->ipfragok && !chunk->pmtu_probe) {
if (!sk_can_gso(sk)) { if (tp->pl.state == SCTP_PL_ERROR) { /* do IP fragmentation if in Error state */
pr_err_once("Trying to GSO but underlying device doesn't support it."); packet->ipfragok = 1;
goto out; } else {
if (!sk_can_gso(sk)) { /* check gso */
pr_err_once("Trying to GSO but underlying device doesn't support it.");
goto out;
}
gso = 1;
} }
gso = 1;
} }
/* alloc head skb */ /* alloc head skb */

View File

@ -269,7 +269,7 @@ bool sctp_transport_pl_send(struct sctp_transport *t)
if (t->pl.probe_size == SCTP_BASE_PLPMTU) { /* BASE_PLPMTU Confirmation Failed */ if (t->pl.probe_size == SCTP_BASE_PLPMTU) { /* BASE_PLPMTU Confirmation Failed */
t->pl.state = SCTP_PL_ERROR; /* Base -> Error */ t->pl.state = SCTP_PL_ERROR; /* Base -> Error */
t->pl.pmtu = SCTP_MIN_PLPMTU; t->pl.pmtu = SCTP_BASE_PLPMTU;
t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t);
sctp_assoc_sync_pmtu(t->asoc); sctp_assoc_sync_pmtu(t->asoc);
} }
@ -366,8 +366,9 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu)
if (pmtu >= SCTP_MIN_PLPMTU && pmtu < SCTP_BASE_PLPMTU) { if (pmtu >= SCTP_MIN_PLPMTU && pmtu < SCTP_BASE_PLPMTU) {
t->pl.state = SCTP_PL_ERROR; /* Base -> Error */ t->pl.state = SCTP_PL_ERROR; /* Base -> Error */
t->pl.pmtu = SCTP_MIN_PLPMTU; t->pl.pmtu = SCTP_BASE_PLPMTU;
t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t);
return true;
} }
} else if (t->pl.state == SCTP_PL_SEARCH) { } else if (t->pl.state == SCTP_PL_SEARCH) {
if (pmtu >= SCTP_BASE_PLPMTU && pmtu < t->pl.pmtu) { if (pmtu >= SCTP_BASE_PLPMTU && pmtu < t->pl.pmtu) {
@ -378,11 +379,10 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu)
t->pl.probe_high = 0; t->pl.probe_high = 0;
t->pl.pmtu = SCTP_BASE_PLPMTU; t->pl.pmtu = SCTP_BASE_PLPMTU;
t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t);
return true;
} else if (pmtu > t->pl.pmtu && pmtu < t->pl.probe_size) { } else if (pmtu > t->pl.pmtu && pmtu < t->pl.probe_size) {
t->pl.probe_size = pmtu; t->pl.probe_size = pmtu;
t->pl.probe_count = 0; t->pl.probe_count = 0;
return false;
} }
} else if (t->pl.state == SCTP_PL_COMPLETE) { } else if (t->pl.state == SCTP_PL_COMPLETE) {
if (pmtu >= SCTP_BASE_PLPMTU && pmtu < t->pl.pmtu) { if (pmtu >= SCTP_BASE_PLPMTU && pmtu < t->pl.pmtu) {
@ -393,10 +393,11 @@ static bool sctp_transport_pl_toobig(struct sctp_transport *t, u32 pmtu)
t->pl.probe_high = 0; t->pl.probe_high = 0;
t->pl.pmtu = SCTP_BASE_PLPMTU; t->pl.pmtu = SCTP_BASE_PLPMTU;
t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t); t->pathmtu = t->pl.pmtu + sctp_transport_pl_hlen(t);
return true;
} }
} }
return true; return false;
} }
bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)

View File

@ -31,3 +31,8 @@ rxtimestamp
timestamping timestamping
txtimestamp txtimestamp
so_netns_cookie so_netns_cookie
test_unix_oob
gro
ioam6_parser
toeplitz
cmsg_so_mark

View File

@ -29,6 +29,7 @@ TEST_PROGS += veth.sh
TEST_PROGS += ioam6.sh TEST_PROGS += ioam6.sh
TEST_PROGS += gro.sh TEST_PROGS += gro.sh
TEST_PROGS += gre_gso.sh TEST_PROGS += gre_gso.sh
TEST_PROGS += cmsg_so_mark.sh
TEST_PROGS_EXTENDED := in_netns.sh TEST_PROGS_EXTENDED := in_netns.sh
TEST_GEN_FILES = socket nettest TEST_GEN_FILES = socket nettest
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any
@ -45,6 +46,7 @@ TEST_GEN_FILES += gro
TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls
TEST_GEN_FILES += toeplitz TEST_GEN_FILES += toeplitz
TEST_GEN_FILES += cmsg_so_mark
TEST_FILES := settings TEST_FILES := settings

View File

@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/types.h>
#include <sys/socket.h>
int main(int argc, const char **argv)
{
char cbuf[CMSG_SPACE(sizeof(__u32))];
struct addrinfo hints, *ai;
struct cmsghdr *cmsg;
struct iovec iov[1];
struct msghdr msg;
int mark;
int err;
int fd;
if (argc != 4) {
fprintf(stderr, "Usage: %s <dst_ip> <port> <mark>\n", argv[0]);
return 1;
}
mark = atoi(argv[3]);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
ai = NULL;
err = getaddrinfo(argv[1], argv[2], &hints, &ai);
if (err) {
fprintf(stderr, "Can't resolve address: %s\n", strerror(errno));
return 1;
}
fd = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0) {
fprintf(stderr, "Can't open socket: %s\n", strerror(errno));
freeaddrinfo(ai);
return 1;
}
iov[0].iov_base = "bla";
iov[0].iov_len = 4;
msg.msg_name = ai->ai_addr;
msg.msg_namelen = ai->ai_addrlen;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = cbuf;
msg.msg_controllen = sizeof(cbuf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SO_MARK;
cmsg->cmsg_len = CMSG_LEN(sizeof(__u32));
*(__u32 *)CMSG_DATA(cmsg) = mark;
err = sendmsg(fd, &msg, 0);
close(fd);
freeaddrinfo(ai);
return err != 4;
}

View File

@ -0,0 +1,61 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
NS=ns
IP4=172.16.0.1/24
TGT4=172.16.0.2
IP6=2001:db8:1::1/64
TGT6=2001:db8:1::2
MARK=1000
cleanup()
{
ip netns del $NS
}
trap cleanup EXIT
# Namespaces
ip netns add $NS
# Connectivity
ip -netns $NS link add type dummy
ip -netns $NS link set dev dummy0 up
ip -netns $NS addr add $IP4 dev dummy0
ip -netns $NS addr add $IP6 dev dummy0
ip -netns $NS rule add fwmark $MARK lookup 300
ip -6 -netns $NS rule add fwmark $MARK lookup 300
ip -netns $NS route add prohibit any table 300
ip -6 -netns $NS route add prohibit any table 300
# Test
BAD=0
TOTAL=0
check_result() {
((TOTAL++))
if [ $1 -ne $2 ]; then
echo " Case $3 returned $1, expected $2"
((BAD++))
fi
}
ip netns exec $NS ./cmsg_so_mark $TGT4 1234 $((MARK + 1))
check_result $? 0 "IPv4 pass"
ip netns exec $NS ./cmsg_so_mark $TGT6 1234 $((MARK + 1))
check_result $? 0 "IPv6 pass"
ip netns exec $NS ./cmsg_so_mark $TGT4 1234 $MARK
check_result $? 1 "IPv4 rejection"
ip netns exec $NS ./cmsg_so_mark $TGT6 1234 $MARK
check_result $? 1 "IPv6 rejection"
# Summary
if [ $BAD -ne 0 ]; then
echo "FAIL - $BAD/$TOTAL cases failed"
exit 1
else
echo "OK"
exit 0
fi

View File

@ -482,10 +482,15 @@ v3exc_timeout_test()
local X=("192.0.2.20" "192.0.2.30") local X=("192.0.2.20" "192.0.2.30")
# GMI should be 3 seconds # GMI should be 3 seconds
ip link set dev br0 type bridge mcast_query_interval 100 mcast_query_response_interval 100 ip link set dev br0 type bridge mcast_query_interval 100 \
mcast_query_response_interval 100 \
mcast_membership_interval 300
v3exclude_prepare $h1 $ALL_MAC $ALL_GROUP v3exclude_prepare $h1 $ALL_MAC $ALL_GROUP
ip link set dev br0 type bridge mcast_query_interval 500 mcast_query_response_interval 500 ip link set dev br0 type bridge mcast_query_interval 500 \
mcast_query_response_interval 500 \
mcast_membership_interval 1500
$MZ $h1 -c 1 -b $ALL_MAC -B $ALL_GROUP -t ip "proto=2,p=$MZPKT_ALLOW2" -q $MZ $h1 -c 1 -b $ALL_MAC -B $ALL_GROUP -t ip "proto=2,p=$MZPKT_ALLOW2" -q
sleep 3 sleep 3
bridge -j -d -s mdb show dev br0 \ bridge -j -d -s mdb show dev br0 \
@ -517,7 +522,8 @@ v3exc_timeout_test()
log_test "IGMPv3 group $TEST_GROUP exclude timeout" log_test "IGMPv3 group $TEST_GROUP exclude timeout"
ip link set dev br0 type bridge mcast_query_interval 12500 \ ip link set dev br0 type bridge mcast_query_interval 12500 \
mcast_query_response_interval 1000 mcast_query_response_interval 1000 \
mcast_membership_interval 26000
v3cleanup $swp1 $TEST_GROUP v3cleanup $swp1 $TEST_GROUP
} }

View File

@ -479,10 +479,15 @@ mldv2exc_timeout_test()
local X=("2001:db8:1::20" "2001:db8:1::30") local X=("2001:db8:1::20" "2001:db8:1::30")
# GMI should be 3 seconds # GMI should be 3 seconds
ip link set dev br0 type bridge mcast_query_interval 100 mcast_query_response_interval 100 ip link set dev br0 type bridge mcast_query_interval 100 \
mcast_query_response_interval 100 \
mcast_membership_interval 300
mldv2exclude_prepare $h1 mldv2exclude_prepare $h1
ip link set dev br0 type bridge mcast_query_interval 500 mcast_query_response_interval 500 ip link set dev br0 type bridge mcast_query_interval 500 \
mcast_query_response_interval 500 \
mcast_membership_interval 1500
$MZ $h1 -c 1 $MZPKT_ALLOW2 -q $MZ $h1 -c 1 $MZPKT_ALLOW2 -q
sleep 3 sleep 3
bridge -j -d -s mdb show dev br0 \ bridge -j -d -s mdb show dev br0 \
@ -514,7 +519,8 @@ mldv2exc_timeout_test()
log_test "MLDv2 group $TEST_GROUP exclude timeout" log_test "MLDv2 group $TEST_GROUP exclude timeout"
ip link set dev br0 type bridge mcast_query_interval 12500 \ ip link set dev br0 type bridge mcast_query_interval 12500 \
mcast_query_response_interval 1000 mcast_query_response_interval 1000 \
mcast_membership_interval 26000
mldv2cleanup $swp1 mldv2cleanup $swp1
} }