* [PATCH v2 4/4] selftests: add a test for bpf_prog_test_run output size
From: Lorenz Bauer @ 2018-11-20 15:43 UTC (permalink / raw)
To: ast, daniel; +Cc: netdev, linux-api, ys114321, Lorenz Bauer
In-Reply-To: <20181120154306.16657-1-lmb@cloudflare.com>
Make sure that bpf_prog_test_run returns the correct length
in the size_out argument and that the kernel respects the
output size hint. Also check that errno indicates ENOSPC.
Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
---
tools/testing/selftests/bpf/test_progs.c | 34 ++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index 299938603cb6..92e48c2ba2c6 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -124,6 +124,39 @@ static void test_pkt_access(void)
bpf_object__close(obj);
}
+static void test_output_size_hint(void)
+{
+ const char *file = "./test_pkt_access.o";
+ struct bpf_object *obj;
+ __u32 retval, size, duration;
+ int err, prog_fd;
+ char buf[10];
+
+ err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
+ if (CHECK(err, "load", "err %d errno %d\n", err, errno))
+ return;
+
+ memset(buf, 0, sizeof(buf));
+
+ size = 5;
+ err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
+ buf, &size, &retval, &duration);
+ CHECK(err != -1 || errno != ENOSPC || retval, "run",
+ "err %d errno %d retval %d\n",
+ err, errno, retval);
+
+ duration = 0;
+
+ CHECK(size != sizeof(pkt_v4), "out_size",
+ "incorrect output size, want %lu have %u\n",
+ sizeof(pkt_v4), size);
+
+ CHECK(buf[5] != 0, "overflow",
+ "prog_test_run ignored size hint\n");
+
+ bpf_object__close(obj);
+}
+
static void test_xdp(void)
{
struct vip key4 = {.protocol = 6, .family = AF_INET};
@@ -1847,6 +1880,7 @@ int main(void)
jit_enabled = is_jit_enabled();
test_pkt_access();
+ test_output_size_hint();
test_xdp();
test_xdp_adjust_tail();
test_l4lb_all();
--
2.17.1
^ permalink raw reply related
* [PATCH net V4 0/5] net/smc: fixes 2018-11-12
From: Ursula Braun @ 2018-11-20 15:46 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
Dave,
here is V4 of some net/smc fixes in different areas for the net tree.
v1->v2:
do not define 8-byte alignment for union smcd_cdc_cursor in
patch 4/5 "net/smc: atomic SMCD cursor handling"
v2->v3:
stay with 8-byte alignment for union smcd_cdc_cursor in
patch 4/5 "net/smc: atomic SMCD cursor handling", but get rid of
__packed for struct smcd_cdc_msg
v3->v4:
get rid of another __packed for struct smc_cdc_msg in
patch 4/5 "net/smc: atomic SMCD cursor handling"
Thanks, Ursula
Hans Wippel (2):
net/smc: abort CLC connection in smc_release
net/smc: add SMC-D shutdown signal
Karsten Graul (1):
net/smc: use queue pair number when matching link group
Ursula Braun (2):
net/smc: atomic SMCD cursor handling
net/smc: use after free fix in smc_wr_tx_put_slot()
net/smc/af_smc.c | 11 ++++++----
net/smc/smc_cdc.c | 26 +++++++++++++----------
net/smc/smc_cdc.h | 60 ++++++++++++++++++++++++++++++++++++++++--------------
net/smc/smc_core.c | 20 ++++++++++++------
net/smc/smc_core.h | 5 +++--
net/smc/smc_ism.c | 43 ++++++++++++++++++++++++++++----------
net/smc/smc_ism.h | 1 +
net/smc/smc_wr.c | 4 +++-
8 files changed, 120 insertions(+), 50 deletions(-)
--
2.16.4
^ permalink raw reply
* [PATCH net V4 1/5] net/smc: abort CLC connection in smc_release
From: Ursula Braun @ 2018-11-20 15:46 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
In-Reply-To: <20181120154643.24111-1-ubraun@linux.ibm.com>
From: Hans Wippel <hwippel@linux.ibm.com>
In case of a non-blocking SMC socket, the initial CLC handshake is
performed over a blocking TCP connection in a worker. If the SMC socket
is released, smc_release has to wait for the blocking CLC socket
operations (e.g., kernel_connect) inside the worker.
This patch aborts a CLC connection when the respective non-blocking SMC
socket is released to avoid waiting on socket operations or timeouts.
Signed-off-by: Hans Wippel <hwippel@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
---
net/smc/af_smc.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 80e2119f1c70..84f67f601838 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -127,6 +127,8 @@ static int smc_release(struct socket *sock)
smc = smc_sk(sk);
/* cleanup for a dangling non-blocking connect */
+ if (smc->connect_info && sk->sk_state == SMC_INIT)
+ tcp_abort(smc->clcsock->sk, ECONNABORTED);
flush_work(&smc->connect_work);
kfree(smc->connect_info);
smc->connect_info = NULL;
--
2.16.4
^ permalink raw reply related
* [PATCH net V4 3/5] net/smc: add SMC-D shutdown signal
From: Ursula Braun @ 2018-11-20 15:46 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
In-Reply-To: <20181120154643.24111-1-ubraun@linux.ibm.com>
From: Hans Wippel <hwippel@linux.ibm.com>
When a SMC-D link group is freed, a shutdown signal should be sent to
the peer to indicate that the link group is invalid. This patch adds the
shutdown signal to the SMC code.
Signed-off-by: Hans Wippel <hwippel@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
---
net/smc/smc_core.c | 10 ++++++++--
net/smc/smc_core.h | 3 ++-
net/smc/smc_ism.c | 43 ++++++++++++++++++++++++++++++++-----------
net/smc/smc_ism.h | 1 +
4 files changed, 43 insertions(+), 14 deletions(-)
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 3c023de58afd..1c9fa7f0261a 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -184,6 +184,8 @@ static void smc_lgr_free_work(struct work_struct *work)
if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
smc_llc_link_inactive(lnk);
+ if (lgr->is_smcd)
+ smc_ism_signal_shutdown(lgr);
smc_lgr_free(lgr);
}
}
@@ -485,7 +487,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
}
/* Called when SMC-D device is terminated or peer is lost */
-void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
+void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
{
struct smc_link_group *lgr, *l;
LIST_HEAD(lgr_free_list);
@@ -495,7 +497,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) {
if (lgr->is_smcd && lgr->smcd == dev &&
(!peer_gid || lgr->peer_gid == peer_gid) &&
- !list_empty(&lgr->list)) {
+ (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
__smc_lgr_terminate(lgr);
list_move(&lgr->list, &lgr_free_list);
}
@@ -506,6 +508,8 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
list_del_init(&lgr->list);
cancel_delayed_work_sync(&lgr->free_work);
+ if (!peer_gid && vlan == VLAN_VID_MASK) /* dev terminated? */
+ smc_ism_signal_shutdown(lgr);
smc_lgr_free(lgr);
}
}
@@ -1026,6 +1030,8 @@ void smc_core_exit(void)
smc_llc_link_inactive(lnk);
}
cancel_delayed_work_sync(&lgr->free_work);
+ if (lgr->is_smcd)
+ smc_ism_signal_shutdown(lgr);
smc_lgr_free(lgr); /* free link group */
}
}
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h
index 5bc6cbaf0ed5..cf98f4d6093e 100644
--- a/net/smc/smc_core.h
+++ b/net/smc/smc_core.h
@@ -247,7 +247,8 @@ void smc_lgr_free(struct smc_link_group *lgr);
void smc_lgr_forget(struct smc_link_group *lgr);
void smc_lgr_terminate(struct smc_link_group *lgr);
void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport);
-void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid);
+void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid,
+ unsigned short vlan);
int smc_buf_create(struct smc_sock *smc, bool is_smcd);
int smc_uncompress_bufsize(u8 compressed);
int smc_rmb_rtoken_handling(struct smc_connection *conn,
diff --git a/net/smc/smc_ism.c b/net/smc/smc_ism.c
index e36f21ce7252..2fff79db1a59 100644
--- a/net/smc/smc_ism.c
+++ b/net/smc/smc_ism.c
@@ -187,22 +187,28 @@ struct smc_ism_event_work {
#define ISM_EVENT_REQUEST 0x0001
#define ISM_EVENT_RESPONSE 0x0002
#define ISM_EVENT_REQUEST_IR 0x00000001
+#define ISM_EVENT_CODE_SHUTDOWN 0x80
#define ISM_EVENT_CODE_TESTLINK 0x83
+union smcd_sw_event_info {
+ u64 info;
+ struct {
+ u8 uid[SMC_LGR_ID_SIZE];
+ unsigned short vlan_id;
+ u16 code;
+ };
+};
+
static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
{
- union {
- u64 info;
- struct {
- u32 uid;
- unsigned short vlanid;
- u16 code;
- };
- } ev_info;
+ union smcd_sw_event_info ev_info;
+ ev_info.info = wrk->event.info;
switch (wrk->event.code) {
+ case ISM_EVENT_CODE_SHUTDOWN: /* Peer shut down DMBs */
+ smc_smcd_terminate(wrk->smcd, wrk->event.tok, ev_info.vlan_id);
+ break;
case ISM_EVENT_CODE_TESTLINK: /* Activity timer */
- ev_info.info = wrk->event.info;
if (ev_info.code == ISM_EVENT_REQUEST) {
ev_info.code = ISM_EVENT_RESPONSE;
wrk->smcd->ops->signal_event(wrk->smcd,
@@ -215,6 +221,21 @@ static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
}
}
+int smc_ism_signal_shutdown(struct smc_link_group *lgr)
+{
+ int rc;
+ union smcd_sw_event_info ev_info;
+
+ memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
+ ev_info.vlan_id = lgr->vlan_id;
+ ev_info.code = ISM_EVENT_REQUEST;
+ rc = lgr->smcd->ops->signal_event(lgr->smcd, lgr->peer_gid,
+ ISM_EVENT_REQUEST_IR,
+ ISM_EVENT_CODE_SHUTDOWN,
+ ev_info.info);
+ return rc;
+}
+
/* worker for SMC-D events */
static void smc_ism_event_work(struct work_struct *work)
{
@@ -223,7 +244,7 @@ static void smc_ism_event_work(struct work_struct *work)
switch (wrk->event.type) {
case ISM_EVENT_GID: /* GID event, token is peer GID */
- smc_smcd_terminate(wrk->smcd, wrk->event.tok);
+ smc_smcd_terminate(wrk->smcd, wrk->event.tok, VLAN_VID_MASK);
break;
case ISM_EVENT_DMB:
break;
@@ -289,7 +310,7 @@ void smcd_unregister_dev(struct smcd_dev *smcd)
spin_unlock(&smcd_dev_list.lock);
flush_workqueue(smcd->event_wq);
destroy_workqueue(smcd->event_wq);
- smc_smcd_terminate(smcd, 0);
+ smc_smcd_terminate(smcd, 0, VLAN_VID_MASK);
device_del(&smcd->dev);
}
diff --git a/net/smc/smc_ism.h b/net/smc/smc_ism.h
index aee45b860b79..4da946cbfa29 100644
--- a/net/smc/smc_ism.h
+++ b/net/smc/smc_ism.h
@@ -45,4 +45,5 @@ int smc_ism_register_dmb(struct smc_link_group *lgr, int buf_size,
int smc_ism_unregister_dmb(struct smcd_dev *dev, struct smc_buf_desc *dmb_desc);
int smc_ism_write(struct smcd_dev *dev, const struct smc_ism_position *pos,
void *data, size_t len);
+int smc_ism_signal_shutdown(struct smc_link_group *lgr);
#endif
--
2.16.4
^ permalink raw reply related
* [PATCH net V4 2/5] net/smc: use queue pair number when matching link group
From: Ursula Braun @ 2018-11-20 15:46 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
In-Reply-To: <20181120154643.24111-1-ubraun@linux.ibm.com>
From: Karsten Graul <kgraul@linux.ibm.com>
When searching for an existing link group the queue pair number is also
to be taken into consideration. When the SMC server sends a new number
in a CLC packet (keeping all other values equal) then a new link group
is to be created on the SMC client side.
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
---
net/smc/af_smc.c | 9 +++++----
net/smc/smc_core.c | 10 ++++++----
net/smc/smc_core.h | 2 +-
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 84f67f601838..5fbaf1901571 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -549,7 +549,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
mutex_lock(&smc_create_lgr_pending);
local_contact = smc_conn_create(smc, false, aclc->hdr.flag, ibdev,
- ibport, &aclc->lcl, NULL, 0);
+ ibport, ntoh24(aclc->qpn), &aclc->lcl,
+ NULL, 0);
if (local_contact < 0) {
if (local_contact == -ENOMEM)
reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/
@@ -620,7 +621,7 @@ static int smc_connect_ism(struct smc_sock *smc,
int rc = 0;
mutex_lock(&smc_create_lgr_pending);
- local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0,
+ local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0, 0,
NULL, ismdev, aclc->gid);
if (local_contact < 0)
return smc_connect_abort(smc, SMC_CLC_DECL_MEM, 0);
@@ -1085,7 +1086,7 @@ static int smc_listen_rdma_init(struct smc_sock *new_smc,
int *local_contact)
{
/* allocate connection / link group */
- *local_contact = smc_conn_create(new_smc, false, 0, ibdev, ibport,
+ *local_contact = smc_conn_create(new_smc, false, 0, ibdev, ibport, 0,
&pclc->lcl, NULL, 0);
if (*local_contact < 0) {
if (*local_contact == -ENOMEM)
@@ -1109,7 +1110,7 @@ static int smc_listen_ism_init(struct smc_sock *new_smc,
struct smc_clc_msg_smcd *pclc_smcd;
pclc_smcd = smc_get_clc_msg_smcd(pclc);
- *local_contact = smc_conn_create(new_smc, true, 0, NULL, 0, NULL,
+ *local_contact = smc_conn_create(new_smc, true, 0, NULL, 0, 0, NULL,
ismdev, pclc_smcd->gid);
if (*local_contact < 0) {
if (*local_contact == -ENOMEM)
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 18daebcef181..3c023de58afd 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -559,7 +559,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id)
static bool smcr_lgr_match(struct smc_link_group *lgr,
struct smc_clc_msg_local *lcl,
- enum smc_lgr_role role)
+ enum smc_lgr_role role, u32 clcqpn)
{
return !memcmp(lgr->peer_systemid, lcl->id_for_peer,
SMC_SYSTEMID_LEN) &&
@@ -567,7 +567,9 @@ static bool smcr_lgr_match(struct smc_link_group *lgr,
SMC_GID_SIZE) &&
!memcmp(lgr->lnk[SMC_SINGLE_LINK].peer_mac, lcl->mac,
sizeof(lcl->mac)) &&
- lgr->role == role;
+ lgr->role == role &&
+ (lgr->role == SMC_SERV ||
+ lgr->lnk[SMC_SINGLE_LINK].peer_qpn == clcqpn);
}
static bool smcd_lgr_match(struct smc_link_group *lgr,
@@ -578,7 +580,7 @@ static bool smcd_lgr_match(struct smc_link_group *lgr,
/* create a new SMC connection (and a new link group if necessary) */
int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
- struct smc_ib_device *smcibdev, u8 ibport,
+ struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
struct smc_clc_msg_local *lcl, struct smcd_dev *smcd,
u64 peer_gid)
{
@@ -603,7 +605,7 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
list_for_each_entry(lgr, &smc_lgr_list.list, list) {
write_lock_bh(&lgr->conns_lock);
if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) :
- smcr_lgr_match(lgr, lcl, role)) &&
+ smcr_lgr_match(lgr, lcl, role, clcqpn)) &&
!lgr->sync_err &&
lgr->vlan_id == vlan_id &&
(role == SMC_CLNT ||
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h
index c156674733c9..5bc6cbaf0ed5 100644
--- a/net/smc/smc_core.h
+++ b/net/smc/smc_core.h
@@ -262,7 +262,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id);
void smc_conn_free(struct smc_connection *conn);
int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
- struct smc_ib_device *smcibdev, u8 ibport,
+ struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
struct smc_clc_msg_local *lcl, struct smcd_dev *smcd,
u64 peer_gid);
void smcd_conn_free(struct smc_connection *conn);
--
2.16.4
^ permalink raw reply related
* [PATCH net V4 5/5] net/smc: use after free fix in smc_wr_tx_put_slot()
From: Ursula Braun @ 2018-11-20 15:46 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
In-Reply-To: <20181120154643.24111-1-ubraun@linux.ibm.com>
From: Ursula Braun <ursula.braun@linux.ibm.com>
In smc_wr_tx_put_slot() field pend->idx is used after being
cleared. That means always idx 0 is cleared in the wr_tx_mask.
This results in a broken administration of available WR send
payload buffers.
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
---
net/smc/smc_wr.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c
index 3c458d279855..c2694750a6a8 100644
--- a/net/smc/smc_wr.c
+++ b/net/smc/smc_wr.c
@@ -215,12 +215,14 @@ int smc_wr_tx_put_slot(struct smc_link *link,
pend = container_of(wr_pend_priv, struct smc_wr_tx_pend, priv);
if (pend->idx < link->wr_tx_cnt) {
+ u32 idx = pend->idx;
+
/* clear the full struct smc_wr_tx_pend including .priv */
memset(&link->wr_tx_pends[pend->idx], 0,
sizeof(link->wr_tx_pends[pend->idx]));
memset(&link->wr_tx_bufs[pend->idx], 0,
sizeof(link->wr_tx_bufs[pend->idx]));
- test_and_clear_bit(pend->idx, link->wr_tx_mask);
+ test_and_clear_bit(idx, link->wr_tx_mask);
return 1;
}
--
2.16.4
^ permalink raw reply related
* Re: netns_id in bpf_sk_lookup_{tcp,udp}
From: David Ahern @ 2018-11-20 15:46 UTC (permalink / raw)
To: nicolas.dichtel, Joe Stringer; +Cc: netdev, daniel
In-Reply-To: <1754196d-67a8-6632-878f-72e0e6c2d917@6wind.com>
On 11/20/18 2:05 AM, Nicolas Dichtel wrote:
> Le 20/11/2018 à 00:46, David Ahern a écrit :
> [snip]
>> That revelation shows another hole:
>> $ ip netns add foo
>> $ ip netns set foo 0xffffffff
> It also works with 0xf0000000 ...
yes, I realized last night I sent a bad example. I meant any negative
number besides -1
>
>> $ ip netns list
>> foo (id: 0)
>>
>> Seems like alloc_netid() should error out if reqid < -1 (-1 being the
>> NETNSA_NSID_NOT_ASSIGNED flag) as opposed to blindly ignoring it.
> alloc_netid() tries to allocate the specified nsid if this nsid is valid, ie >=
> 0, else it allocates a new nsid (actually the lower available).
> This is the expected behavior.
>
> For me, it's more an iproute2 problem, which parses an unsigned and silently
> cast it to a signed value.
so your intention is that any < 0 value means auto generate not just -1.
^ permalink raw reply
* [PATCH net V4 4/5] net/smc: atomic SMCD cursor handling
From: Ursula Braun @ 2018-11-20 15:46 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
In-Reply-To: <20181120154643.24111-1-ubraun@linux.ibm.com>
Running uperf tests with SMCD on LPARs results in corrupted cursors.
SMCD cursors should be treated atomically to fix cursor corruption.
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
---
net/smc/smc_cdc.c | 26 ++++++++++++++----------
net/smc/smc_cdc.h | 60 +++++++++++++++++++++++++++++++++++++++++--------------
2 files changed, 60 insertions(+), 26 deletions(-)
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c
index ed5dcf03fe0b..db83332ac1c8 100644
--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -81,7 +81,7 @@ static inline void smc_cdc_add_pending_send(struct smc_connection *conn,
sizeof(struct smc_cdc_msg) > SMC_WR_BUF_SIZE,
"must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_cdc_msg)");
BUILD_BUG_ON_MSG(
- sizeof(struct smc_cdc_msg) != SMC_WR_TX_SIZE,
+ offsetofend(struct smc_cdc_msg, reserved) > SMC_WR_TX_SIZE,
"must adapt SMC_WR_TX_SIZE to sizeof(struct smc_cdc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()");
BUILD_BUG_ON_MSG(
sizeof(struct smc_cdc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE,
@@ -177,23 +177,24 @@ void smc_cdc_tx_dismiss_slots(struct smc_connection *conn)
int smcd_cdc_msg_send(struct smc_connection *conn)
{
struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
+ union smc_host_cursor curs;
struct smcd_cdc_msg cdc;
int rc, diff;
memset(&cdc, 0, sizeof(cdc));
cdc.common.type = SMC_CDC_MSG_TYPE;
- cdc.prod_wrap = conn->local_tx_ctrl.prod.wrap;
- cdc.prod_count = conn->local_tx_ctrl.prod.count;
-
- cdc.cons_wrap = conn->local_tx_ctrl.cons.wrap;
- cdc.cons_count = conn->local_tx_ctrl.cons.count;
- cdc.prod_flags = conn->local_tx_ctrl.prod_flags;
- cdc.conn_state_flags = conn->local_tx_ctrl.conn_state_flags;
+ curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.prod.acurs);
+ cdc.prod.wrap = curs.wrap;
+ cdc.prod.count = curs.count;
+ curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.cons.acurs);
+ cdc.cons.wrap = curs.wrap;
+ cdc.cons.count = curs.count;
+ cdc.cons.prod_flags = conn->local_tx_ctrl.prod_flags;
+ cdc.cons.conn_state_flags = conn->local_tx_ctrl.conn_state_flags;
rc = smcd_tx_ism_write(conn, &cdc, sizeof(cdc), 0, 1);
if (rc)
return rc;
- smc_curs_copy(&conn->rx_curs_confirmed, &conn->local_tx_ctrl.cons,
- conn);
+ smc_curs_copy(&conn->rx_curs_confirmed, &curs, conn);
/* Calculate transmitted data and increment free send buffer space */
diff = smc_curs_diff(conn->sndbuf_desc->len, &conn->tx_curs_fin,
&conn->tx_curs_sent);
@@ -331,13 +332,16 @@ static void smc_cdc_msg_recv(struct smc_sock *smc, struct smc_cdc_msg *cdc)
static void smcd_cdc_rx_tsklet(unsigned long data)
{
struct smc_connection *conn = (struct smc_connection *)data;
+ struct smcd_cdc_msg *data_cdc;
struct smcd_cdc_msg cdc;
struct smc_sock *smc;
if (!conn)
return;
- memcpy(&cdc, conn->rmb_desc->cpu_addr, sizeof(cdc));
+ data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr;
+ smcd_curs_copy(&cdc.prod, &data_cdc->prod, conn);
+ smcd_curs_copy(&cdc.cons, &data_cdc->cons, conn);
smc = container_of(conn, struct smc_sock, conn);
smc_cdc_msg_recv(smc, (struct smc_cdc_msg *)&cdc);
}
diff --git a/net/smc/smc_cdc.h b/net/smc/smc_cdc.h
index 934df4473a7c..b5bfe38c7f9b 100644
--- a/net/smc/smc_cdc.h
+++ b/net/smc/smc_cdc.h
@@ -48,21 +48,31 @@ struct smc_cdc_msg {
struct smc_cdc_producer_flags prod_flags;
struct smc_cdc_conn_state_flags conn_state_flags;
u8 reserved[18];
-} __packed; /* format defined in RFC7609 */
+};
+
+/* SMC-D cursor format */
+union smcd_cdc_cursor {
+ struct {
+ u16 wrap;
+ u32 count;
+ struct smc_cdc_producer_flags prod_flags;
+ struct smc_cdc_conn_state_flags conn_state_flags;
+ } __packed;
+#ifdef KERNEL_HAS_ATOMIC64
+ atomic64_t acurs; /* for atomic processing */
+#else
+ u64 acurs; /* for atomic processing */
+#endif
+} __aligned(8);
/* CDC message for SMC-D */
struct smcd_cdc_msg {
struct smc_wr_rx_hdr common; /* Type = 0xFE */
u8 res1[7];
- u16 prod_wrap;
- u32 prod_count;
- u8 res2[2];
- u16 cons_wrap;
- u32 cons_count;
- struct smc_cdc_producer_flags prod_flags;
- struct smc_cdc_conn_state_flags conn_state_flags;
+ union smcd_cdc_cursor prod;
+ union smcd_cdc_cursor cons;
u8 res3[8];
-} __packed;
+} __aligned(8);
static inline bool smc_cdc_rxed_any_close(struct smc_connection *conn)
{
@@ -135,6 +145,21 @@ static inline void smc_curs_copy_net(union smc_cdc_cursor *tgt,
#endif
}
+static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt,
+ union smcd_cdc_cursor *src,
+ struct smc_connection *conn)
+{
+#ifndef KERNEL_HAS_ATOMIC64
+ unsigned long flags;
+
+ spin_lock_irqsave(&conn->acurs_lock, flags);
+ tgt->acurs = src->acurs;
+ spin_unlock_irqrestore(&conn->acurs_lock, flags);
+#else
+ atomic64_set(&tgt->acurs, atomic64_read(&src->acurs));
+#endif
+}
+
/* calculate cursor difference between old and new, where old <= new */
static inline int smc_curs_diff(unsigned int size,
union smc_host_cursor *old,
@@ -222,12 +247,17 @@ static inline void smcr_cdc_msg_to_host(struct smc_host_cdc_msg *local,
static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local,
struct smcd_cdc_msg *peer)
{
- local->prod.wrap = peer->prod_wrap;
- local->prod.count = peer->prod_count;
- local->cons.wrap = peer->cons_wrap;
- local->cons.count = peer->cons_count;
- local->prod_flags = peer->prod_flags;
- local->conn_state_flags = peer->conn_state_flags;
+ union smc_host_cursor temp;
+
+ temp.wrap = peer->prod.wrap;
+ temp.count = peer->prod.count;
+ atomic64_set(&local->prod.acurs, atomic64_read(&temp.acurs));
+
+ temp.wrap = peer->cons.wrap;
+ temp.count = peer->cons.count;
+ atomic64_set(&local->cons.acurs, atomic64_read(&temp.acurs));
+ local->prod_flags = peer->cons.prod_flags;
+ local->conn_state_flags = peer->cons.conn_state_flags;
}
static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
--
2.16.4
^ permalink raw reply related
* Re: [RFC v3 3/3] vxlan: handle underlay VRF changes
From: David Ahern @ 2018-11-20 15:48 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: abauvin, netdev, akherbouche
In-Reply-To: <CAJieiUiAho4UGbJP8Zcf-1_ErNu+jq_P6EqOKUQFqONRpsTD9w@mail.gmail.com>
On 11/20/18 8:35 AM, Roopa Prabhu wrote:
> On Tue, Nov 20, 2018 at 7:04 AM David Ahern <dsa@cumulusnetworks.com> wrote:
>>
>> On 11/20/18 7:23 AM, Alexis Bauvin wrote:
>>> When underlay VRF changes, either because the lower device itself changed,
>>> or its VRF changed, this patch releases the current socket of the VXLAN
>>> device and recreates another one in the right VRF. This allows for
>>> on-the-fly change of the underlay VRF of a VXLAN device.
>>>
>>> Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
>>> Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
>>> Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
>>> ---
>>> drivers/net/vxlan.c | 94 +++++++++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 94 insertions(+)
>>>
>>> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
>>> index a3de08122269..1e6ccad6df6a 100644
>>> --- a/drivers/net/vxlan.c
>>> +++ b/drivers/net/vxlan.c
>>> @@ -208,6 +208,18 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
>>> return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
>>> }
>>>
>>> +static int vxlan_is_in_l3mdev_chain(struct net_device *chain,
>>> + struct net_device *dev)
>>> +{
>>> + if (!chain)
>>> + return 0;
>>> +
>>> + if (chain->ifindex == dev->ifindex)
>>> + return 1;
>>> + return vxlan_is_in_l3mdev_chain(netdev_master_upper_dev_get(chain),
>>> + dev);
>>> +}
>>
>> This should return bool and true/false.
>>
>> Also, why l3mdev in the name? None of the checks look at whether it is
>> an l3mdev master.
>>
>> And again here, someone more familiar with the vxlan code should review it.
>>
>
>
> I understand the need for patch 2. But I don't understand the need for
> the complexity this patch introduces (especially implicit down and up
> of the vxlan device).
> Alexis, If your underlay routing changes, you can down and up the
> vxlan device from user-space correct ?. This should be true for any
> tunnel device.
>
I believe this patch handles changes to the VRF association of the bridge.
^ permalink raw reply
* Re: netns_id in bpf_sk_lookup_{tcp,udp}
From: Nicolas Dichtel @ 2018-11-20 16:03 UTC (permalink / raw)
To: David Ahern, Joe Stringer; +Cc: netdev, daniel
In-Reply-To: <954e5e2c-d72d-5a87-e050-3e550273cce0@gmail.com>
Le 20/11/2018 à 16:46, David Ahern a écrit :
> On 11/20/18 2:05 AM, Nicolas Dichtel wrote:
>> Le 20/11/2018 à 00:46, David Ahern a écrit :
[snip]
>>> Seems like alloc_netid() should error out if reqid < -1 (-1 being the
>>> NETNSA_NSID_NOT_ASSIGNED flag) as opposed to blindly ignoring it.
>> alloc_netid() tries to allocate the specified nsid if this nsid is valid, ie >=
>> 0, else it allocates a new nsid (actually the lower available).
>> This is the expected behavior.
>>
>> For me, it's more an iproute2 problem, which parses an unsigned and silently
>> cast it to a signed value.
>
> so your intention is that any < 0 value means auto generate not just -1.
Yes. If a valid value is not provided, the kernel tries to allocate one.
Nicolas
^ permalink raw reply
* Re: [RFC v3 2/3] vxlan: add support for underlay in non-default VRF
From: Alexis Bauvin @ 2018-11-20 16:11 UTC (permalink / raw)
To: David Ahern, roopa; +Cc: netdev, akherbouche
In-Reply-To: <4918e368-5938-3f67-0720-ab558d8bff06@cumulusnetworks.com>
Le 20 nov. 2018 à 15:57, David Ahern <dsa@cumulusnetworks.com> a écrit :
>
> On 11/20/18 7:23 AM, Alexis Bauvin wrote:
>> Creating a VXLAN device with is underlay in the non-default VRF makes
>> egress route lookup fail or incorrect since it will resolve in the
>> default VRF, and ingress fail because the socket listens in the default
>> VRF.
>>
>> This patch binds the underlying UDP tunnel socket to the l3mdev of the
>> lower device of the VXLAN device. This will listen in the proper VRF and
>> output traffic from said l3mdev, matching l3mdev routing rules and
>> looking up the correct routing table.
>>
>> When the VXLAN device does not have a lower device, or the lower device
>> is in the default VRF, the socket will not be bound to any interface,
>> keeping the previous behaviour.
>>
>> The underlay l3mdev is deduced from the VXLAN lower device
>> (IFLA_VXLAN_LINK).
>>
>> The l3mdev_master_upper_ifindex_by_index function has been added to
>> l3mdev. Its goal is to fetch the effective l3mdev of an interface which
>> is not a direct slave of said l3mdev. It handles the following example,
>> properly resolving the l3mdev of eth0 to vrf-blue:
>>
>> +----------+ +---------+
>> | | | |
>> | vrf-blue | | vrf-red |
>> | | | |
>> +----+-----+ +----+----+
>> | |
>> | |
>> +----+-----+ +----+----+
>> | | | |
>> | br-blue | | br-red |
>> | | | |
>> +----+-----+ +---+-+---+
>> | | |
>> | +-----+ +-----+
>> | | |
>> +----+-----+ +------+----+ +----+----+
>> | | lower device | | | |
>> | eth0 | <- - - - - - - | vxlan-red | | tap-red | (... more taps)
>> | | | | | |
>> +----------+ +-----------+ +---------+
>
> same here. Very helpful diagram.
>
>
>> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
>> index 27bd586b94b0..a3de08122269 100644
>> --- a/drivers/net/vxlan.c
>> +++ b/drivers/net/vxlan.c
>
> The vxlan changes look ok to me. It would be good for someone who know
> that code better than I do to review it.
>
> Move the following l3mdev changes to a separate patch - introduce infra
> changes separate from their use:
Sure, will do in next version. Thanks!
>> diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h
>> index 3832099289c5..78fa0ac4613c 100644
>> --- a/include/net/l3mdev.h
>> +++ b/include/net/l3mdev.h
>> @@ -101,6 +101,17 @@ struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
>> return master;
>> }
>>
>> +int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex);
>> +static inline
>> +int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
>> +{
>> + rcu_read_lock();
>> + ifindex = l3mdev_master_upper_ifindex_by_index_rcu(net, ifindex);
>> + rcu_read_unlock();
>> +
>> + return ifindex;
>> +}
>> +
>> u32 l3mdev_fib_table_rcu(const struct net_device *dev);
>> u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
>> static inline u32 l3mdev_fib_table(const struct net_device *dev)
>> @@ -207,6 +218,17 @@ static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
>> return 0;
>> }
>>
>> +static inline
>> +int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
>> +{
>> + return 0;
>> +}
>> +static inline
>> +int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
>> +{
>> + return 0;
>> +}
>> +
>> static inline
>> struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
>> {
>> diff --git a/net/l3mdev/l3mdev.c b/net/l3mdev/l3mdev.c
>> index 8da86ceca33d..309dee76724e 100644
>> --- a/net/l3mdev/l3mdev.c
>> +++ b/net/l3mdev/l3mdev.c
>> @@ -46,6 +46,24 @@ int l3mdev_master_ifindex_rcu(const struct net_device *dev)
>> }
>> EXPORT_SYMBOL_GPL(l3mdev_master_ifindex_rcu);
>>
>> +/**
>> + * l3mdev_master_upper_ifindex_by_index - get index of upper l3 master
>> + * device
>> + * @net: network namespace for device index lookup
>> + * @ifindex: targeted interface
>> + */
>> +int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
>> +{
>> + struct net_device *dev;
>> +
>> + dev = dev_get_by_index_rcu(net, ifindex);
>> + while (dev && !netif_is_l3_master(dev))
>> + dev = netdev_master_upper_dev_get(dev);
>> +
>> + return dev ? dev->ifindex : 0;
>> +}
>> +EXPORT_SYMBOL_GPL(l3mdev_master_upper_ifindex_by_index_rcu);
>> +
>> /**
>> * l3mdev_fib_table - get FIB table id associated with an L3
>> * master interface
^ permalink raw reply
* Re: [RFC v3 3/3] vxlan: handle underlay VRF changes
From: David Ahern @ 2018-11-20 16:13 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: abauvin, netdev, akherbouche
In-Reply-To: <a38ee9a8-bae0-f7b8-7ff0-45de8277c2fc@cumulusnetworks.com>
On 11/20/18 8:48 AM, David Ahern wrote:
> On 11/20/18 8:35 AM, Roopa Prabhu wrote:
>> On Tue, Nov 20, 2018 at 7:04 AM David Ahern <dsa@cumulusnetworks.com> wrote:
>>>
>>> On 11/20/18 7:23 AM, Alexis Bauvin wrote:
>>>> When underlay VRF changes, either because the lower device itself changed,
>>>> or its VRF changed, this patch releases the current socket of the VXLAN
>>>> device and recreates another one in the right VRF. This allows for
>>>> on-the-fly change of the underlay VRF of a VXLAN device.
>>>>
>>>> Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
>>>> Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
>>>> Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
>>>> ---
>>>> drivers/net/vxlan.c | 94 +++++++++++++++++++++++++++++++++++++++++++++
>>>> 1 file changed, 94 insertions(+)
>>>>
>>>> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
>>>> index a3de08122269..1e6ccad6df6a 100644
>>>> --- a/drivers/net/vxlan.c
>>>> +++ b/drivers/net/vxlan.c
>>>> @@ -208,6 +208,18 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
>>>> return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
>>>> }
>>>>
>>>> +static int vxlan_is_in_l3mdev_chain(struct net_device *chain,
>>>> + struct net_device *dev)
>>>> +{
>>>> + if (!chain)
>>>> + return 0;
>>>> +
>>>> + if (chain->ifindex == dev->ifindex)
>>>> + return 1;
>>>> + return vxlan_is_in_l3mdev_chain(netdev_master_upper_dev_get(chain),
>>>> + dev);
>>>> +}
>>>
>>> This should return bool and true/false.
>>>
>>> Also, why l3mdev in the name? None of the checks look at whether it is
>>> an l3mdev master.
>>>
>>> And again here, someone more familiar with the vxlan code should review it.
>>>
>>
>>
>> I understand the need for patch 2. But I don't understand the need for
>> the complexity this patch introduces (especially implicit down and up
>> of the vxlan device).
>> Alexis, If your underlay routing changes, you can down and up the
>> vxlan device from user-space correct ?. This should be true for any
>> tunnel device.
>>
>
> I believe this patch handles changes to the VRF association of the bridge.
>
Re-reading the commit message, this handles changes in VRF association
of the lower device.
If the vxlan socket in general (vrf or not) can be bound to the lower
device instead of the VRF then it simplifies things a lot.
^ permalink raw reply
* Re: [RFC v3 2/3] vxlan: add support for underlay in non-default VRF
From: Alexis Bauvin @ 2018-11-20 16:14 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: David Ahern, netdev, akherbouche
In-Reply-To: <CAJieiUj8ro0p_ykirP3M9JtEiHC=28QyV5xHX3KXAsepNhS+rQ@mail.gmail.com>
Le 20 nov. 2018 à 16:25, Roopa Prabhu <roopa@cumulusnetworks.com> a écrit :
>
> On Tue, Nov 20, 2018 at 6:23 AM Alexis Bauvin <abauvin@scaleway.com> wrote:
>>
>> Creating a VXLAN device with is underlay in the non-default VRF makes
>> egress route lookup fail or incorrect since it will resolve in the
>> default VRF, and ingress fail because the socket listens in the default
>> VRF.
>>
>> This patch binds the underlying UDP tunnel socket to the l3mdev of the
>> lower device of the VXLAN device. This will listen in the proper VRF and
>> output traffic from said l3mdev, matching l3mdev routing rules and
>> looking up the correct routing table.
>>
>> When the VXLAN device does not have a lower device, or the lower device
>> is in the default VRF, the socket will not be bound to any interface,
>> keeping the previous behaviour.
>>
>> The underlay l3mdev is deduced from the VXLAN lower device
>> (IFLA_VXLAN_LINK).
>>
>> The l3mdev_master_upper_ifindex_by_index function has been added to
>> l3mdev. Its goal is to fetch the effective l3mdev of an interface which
>> is not a direct slave of said l3mdev. It handles the following example,
>> properly resolving the l3mdev of eth0 to vrf-blue:
>>
>> +----------+ +---------+
>> | | | |
>> | vrf-blue | | vrf-red |
>> | | | |
>> +----+-----+ +----+----+
>> | |
>> | |
>> +----+-----+ +----+----+
>> | | | |
>> | br-blue | | br-red |
>> | | | |
>> +----+-----+ +---+-+---+
>> | | |
>> | +-----+ +-----+
>> | | |
>> +----+-----+ +------+----+ +----+----+
>> | | lower device | | | |
>> | eth0 | <- - - - - - - | vxlan-red | | tap-red | (... more taps)
>> | | | | | |
>> +----------+ +-----------+ +---------+
>>
>> Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
>> Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
>> Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
>> ---
>> drivers/net/vxlan.c | 32 ++++++++++++++++++++++++--------
>> include/net/l3mdev.h | 22 ++++++++++++++++++++++
>> net/l3mdev/l3mdev.c | 18 ++++++++++++++++++
>> 3 files changed, 64 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
>> index 27bd586b94b0..a3de08122269 100644
>> --- a/drivers/net/vxlan.c
>> +++ b/drivers/net/vxlan.c
>> @@ -212,7 +212,7 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
>> * and enabled unshareable flags.
>> */
>> static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
>> - __be16 port, u32 flags)
>> + __be16 port, u32 flags, int ifindex)
>> {
>> struct vxlan_sock *vs;
>>
>> @@ -221,7 +221,8 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
>> hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
>> if (inet_sk(vs->sock->sk)->inet_sport == port &&
>> vxlan_get_sk_family(vs) == family &&
>> - vs->flags == flags)
>> + vs->flags == flags &&
>> + vs->sock->sk->sk_bound_dev_if == ifindex)
>> return vs;
>> }
>> return NULL;
>> @@ -261,7 +262,7 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, int ifindex,
>> {
>> struct vxlan_sock *vs;
>>
>> - vs = vxlan_find_sock(net, family, port, flags);
>> + vs = vxlan_find_sock(net, family, port, flags, ifindex);
>> if (!vs)
>> return NULL;
>>
>> @@ -2172,6 +2173,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
>> struct rtable *rt;
>> __be16 df = 0;
>>
>> + if (!ifindex)
>> + ifindex = sock4->sock->sk->sk_bound_dev_if;
>> +
>> rt = vxlan_get_route(vxlan, dev, sock4, skb, ifindex, tos,
>> dst->sin.sin_addr.s_addr,
>> &local_ip.sin.sin_addr.s_addr,
>> @@ -2210,6 +2214,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
>> } else {
>> struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
>>
>> + if (!ifindex)
>> + ifindex = sock6->sock->sk->sk_bound_dev_if;
>> +
>> ndst = vxlan6_get_route(vxlan, dev, sock6, skb, ifindex, tos,
>> label, &dst->sin6.sin6_addr,
>> &local_ip.sin6.sin6_addr,
>> @@ -2813,7 +2820,7 @@ static const struct ethtool_ops vxlan_ethtool_ops = {
>> };
>>
>> static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
>> - __be16 port, u32 flags)
>> + __be16 port, u32 flags, int ifindex)
>> {
>> struct socket *sock;
>> struct udp_port_cfg udp_conf;
>> @@ -2831,6 +2838,7 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
>> }
>>
>> udp_conf.local_udp_port = port;
>> + udp_conf.bind_ifindex = ifindex;
>>
>> /* Open UDP socket */
>> err = udp_sock_create(net, &udp_conf, &sock);
>> @@ -2842,7 +2850,8 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
>>
>> /* Create new listen socket if needed */
>> static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
>> - __be16 port, u32 flags)
>> + __be16 port, u32 flags,
>> + int ifindex)
>> {
>> struct vxlan_net *vn = net_generic(net, vxlan_net_id);
>> struct vxlan_sock *vs;
>> @@ -2857,7 +2866,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
>> for (h = 0; h < VNI_HASH_SIZE; ++h)
>> INIT_HLIST_HEAD(&vs->vni_list[h]);
>>
>> - sock = vxlan_create_sock(net, ipv6, port, flags);
>> + sock = vxlan_create_sock(net, ipv6, port, flags, ifindex);
>> if (IS_ERR(sock)) {
>> kfree(vs);
>> return ERR_CAST(sock);
>> @@ -2894,11 +2903,17 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
>> struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
>> struct vxlan_sock *vs = NULL;
>> struct vxlan_dev_node *node;
>> + int l3mdev_index;
>> +
>> + l3mdev_index =
>> + l3mdev_master_upper_ifindex_by_index(vxlan->net,
>> + vxlan->cfg.remote_ifindex);
>
> vxlan->cfg.remote_ifindex is optional, so we can avoid trying to
> derive the l3mdev_ifindex for cases where it is not present
So you do suggest to check first remote_ifindex, and derive
the l3mdev_ifindex only if not zero? If so, I will add it
in next version.
>>
>> if (!vxlan->cfg.no_share) {
>> spin_lock(&vn->sock_lock);
>> vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
>> - vxlan->cfg.dst_port, vxlan->cfg.flags);
>> + vxlan->cfg.dst_port, vxlan->cfg.flags,
>> + l3mdev_index);
>> if (vs && !refcount_inc_not_zero(&vs->refcnt)) {
>> spin_unlock(&vn->sock_lock);
>> return -EBUSY;
>> @@ -2907,7 +2922,8 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
>> }
>> if (!vs)
>> vs = vxlan_socket_create(vxlan->net, ipv6,
>> - vxlan->cfg.dst_port, vxlan->cfg.flags);
>> + vxlan->cfg.dst_port, vxlan->cfg.flags,
>> + l3mdev_index);
>> if (IS_ERR(vs))
>> return PTR_ERR(vs);
>> #if IS_ENABLED(CONFIG_IPV6)
>> diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h
>> index 3832099289c5..78fa0ac4613c 100644
>> --- a/include/net/l3mdev.h
>> +++ b/include/net/l3mdev.h
>> @@ -101,6 +101,17 @@ struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
>> return master;
>> }
>>
>> +int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex);
>> +static inline
>> +int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
>> +{
>> + rcu_read_lock();
>> + ifindex = l3mdev_master_upper_ifindex_by_index_rcu(net, ifindex);
>> + rcu_read_unlock();
>> +
>> + return ifindex;
>> +}
>> +
>> u32 l3mdev_fib_table_rcu(const struct net_device *dev);
>> u32 l3mdev_fib_table_by_index(struct net *net, int ifindex);
>> static inline u32 l3mdev_fib_table(const struct net_device *dev)
>> @@ -207,6 +218,17 @@ static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
>> return 0;
>> }
>>
>> +static inline
>> +int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
>> +{
>> + return 0;
>> +}
>> +static inline
>> +int l3mdev_master_upper_ifindex_by_index(struct net *net, int ifindex)
>> +{
>> + return 0;
>> +}
>> +
>> static inline
>> struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
>> {
>> diff --git a/net/l3mdev/l3mdev.c b/net/l3mdev/l3mdev.c
>> index 8da86ceca33d..309dee76724e 100644
>> --- a/net/l3mdev/l3mdev.c
>> +++ b/net/l3mdev/l3mdev.c
>> @@ -46,6 +46,24 @@ int l3mdev_master_ifindex_rcu(const struct net_device *dev)
>> }
>> EXPORT_SYMBOL_GPL(l3mdev_master_ifindex_rcu);
>>
>> +/**
>> + * l3mdev_master_upper_ifindex_by_index - get index of upper l3 master
>> + * device
>> + * @net: network namespace for device index lookup
>> + * @ifindex: targeted interface
>> + */
>> +int l3mdev_master_upper_ifindex_by_index_rcu(struct net *net, int ifindex)
>> +{
>> + struct net_device *dev;
>> +
>> + dev = dev_get_by_index_rcu(net, ifindex);
>> + while (dev && !netif_is_l3_master(dev))
>> + dev = netdev_master_upper_dev_get(dev);
>> +
>> + return dev ? dev->ifindex : 0;
>> +}
>> +EXPORT_SYMBOL_GPL(l3mdev_master_upper_ifindex_by_index_rcu);
>> +
>> /**
>> * l3mdev_fib_table - get FIB table id associated with an L3
>> * master interface
>> --
^ permalink raw reply
* Re: [RFC v3 3/3] vxlan: handle underlay VRF changes
From: Alexis Bauvin @ 2018-11-20 16:27 UTC (permalink / raw)
To: David Ahern, roopa; +Cc: netdev, akherbouche
In-Reply-To: <e10919dc-8001-af17-f7c1-f9adc420c78a@cumulusnetworks.com>
Le 20 nov. 2018 à 16:04, David Ahern <dsa@cumulusnetworks.com> a écrit :
>
> On 11/20/18 7:23 AM, Alexis Bauvin wrote:
>> When underlay VRF changes, either because the lower device itself changed,
>> or its VRF changed, this patch releases the current socket of the VXLAN
>> device and recreates another one in the right VRF. This allows for
>> on-the-fly change of the underlay VRF of a VXLAN device.
>>
>> Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
>> Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
>> Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
>> ---
>> drivers/net/vxlan.c | 94 +++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 94 insertions(+)
>>
>> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
>> index a3de08122269..1e6ccad6df6a 100644
>> --- a/drivers/net/vxlan.c
>> +++ b/drivers/net/vxlan.c
>> @@ -208,6 +208,18 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
>> return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
>> }
>>
>> +static int vxlan_is_in_l3mdev_chain(struct net_device *chain,
>> + struct net_device *dev)
>> +{
>> + if (!chain)
>> + return 0;
>> +
>> + if (chain->ifindex == dev->ifindex)
>> + return 1;
>> + return vxlan_is_in_l3mdev_chain(netdev_master_upper_dev_get(chain),
>> + dev);
>> +}
>
> This should return bool and true/false.
Will change in v4.
> Also, why l3mdev in the name? None of the checks look at whether it is
> an l3mdev master.
The original intention was to detect if, through a master change, the
l3mdev of the lower device changed. However, it is right it is much more
generic than that. It will tell if dev is a master (direct or indirect)
of chain.
A rename to vxlan_is_upper_master would be preferred, maybe even move
the function to net/core/dev.c, with other master-related functions.
What do you think?
> And again here, someone more familiar with the vxlan code should review it.
>
>> +
>> /* Find VXLAN socket based on network namespace, address family and UDP port
>> * and enabled unshareable flags.
>> */
>> @@ -3720,6 +3732,33 @@ struct net_device *vxlan_dev_create(struct net *net, const char *name,
>> }
>> EXPORT_SYMBOL_GPL(vxlan_dev_create);
>>
>> +static int vxlan_reopen(struct vxlan_net *vn, struct vxlan_dev *vxlan)
>> +{
>> + int ret = 0;
>> +
>> + if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip) &&
>> + !vxlan_group_used(vn, vxlan))
>> + ret = vxlan_igmp_leave(vxlan);
>> + vxlan_sock_release(vxlan);
>> +
>> + if (ret < 0)
>> + return ret;
>> +
>> + ret = vxlan_sock_add(vxlan);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
>> + ret = vxlan_igmp_join(vxlan);
>> + if (ret == -EADDRINUSE)
>> + ret = 0;
>> + if (ret)
>> + vxlan_sock_release(vxlan);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
>> struct net_device *dev)
>> {
>> @@ -3742,6 +3781,55 @@ static void vxlan_handle_lowerdev_unregister(struct vxlan_net *vn,
>> unregister_netdevice_many(&list_kill);
>> }
>>
>> +static void vxlan_handle_change_upper(struct vxlan_net *vn,
>> + struct net_device *dev)
>> +{
>> + struct vxlan_dev *vxlan, *next;
>> +
>> + list_for_each_entry_safe(vxlan, next, &vn->vxlan_list, next) {
>> + struct net_device *lower;
>> + int err;
>> +
>> + lower = __dev_get_by_index(vxlan->net,
>> + vxlan->cfg.remote_ifindex);
>> + if (!vxlan_is_in_l3mdev_chain(lower, dev))
>> + continue;
>> +
>> + err = vxlan_reopen(vn, vxlan);
>> + if (err < 0)
>> + netdev_err(vxlan->dev, "Failed to reopen socket: %d\n",
>> + err);
>> + }
>> +}
>> +
>> +static void vxlan_handle_change(struct vxlan_net *vn, struct net_device *dev)
>> +{
>> + struct vxlan_dev *vxlan = netdev_priv(dev);
>> + struct vxlan_sock *sock;
>> + int l3mdev_index;
>> +
>> +#if IS_ENABLED(CONFIG_IPV6)
>> + bool metadata = vxlan->cfg.flags & VXLAN_F_COLLECT_METADATA;
>> + bool ipv6 = vxlan->cfg.flags & VXLAN_F_IPV6 || metadata;
>> +
>> + sock = ipv6 ? rcu_dereference(vxlan->vn6_sock)
>> + : rcu_dereference(vxlan->vn4_sock);
>> +#else
>> + sock = rcu_dereference(vxlan->vn4_sock);
>> +#endif
>> +
>> + l3mdev_index =
>> + l3mdev_master_upper_ifindex_by_index(vxlan->net,
>> + vxlan->cfg.remote_ifindex);
>> + if (sock->sock->sk->sk_bound_dev_if != l3mdev_index) {
>> + int ret = vxlan_reopen(vn, vxlan);
>> +
>> + if (ret < 0)
>> + netdev_err(vxlan->dev, "Failed to reopen socket: %d\n",
>> + ret);
>> + }
>> +}
>> +
>> static int vxlan_netdevice_event(struct notifier_block *unused,
>> unsigned long event, void *ptr)
>> {
>> @@ -3756,6 +3844,12 @@ static int vxlan_netdevice_event(struct notifier_block *unused,
>> } else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO ||
>> event == NETDEV_UDP_TUNNEL_DROP_INFO) {
>> vxlan_offload_rx_ports(dev, event == NETDEV_UDP_TUNNEL_PUSH_INFO);
>> + } else if (event == NETDEV_CHANGEUPPER) {
>> + vxlan_handle_change_upper(vn, dev);
>> + } else if (event == NETDEV_CHANGE) {
>> + if (dev->rtnl_link_ops &&
>> + !strcmp(dev->rtnl_link_ops->kind, vxlan_link_ops.kind))
>> + vxlan_handle_change(vn, dev);
>> }
>>
>> return NOTIFY_DONE;
^ permalink raw reply
* Re: [RFC PATCH] net: don't keep lonely packets forever in the gro hash
From: Eric Dumazet @ 2018-11-20 16:28 UTC (permalink / raw)
To: Paolo Abeni, netdev; +Cc: David S. Miller, Willem de Bruijn
In-Reply-To: <e4a4bcfaa9f780a0b74ae453bfefd2768d9c8b5f.camel@redhat.com>
On 11/20/2018 07:42 AM, Paolo Abeni wrote:
> Hi,
>
> On Tue, 2018-11-20 at 05:49 -0800, Eric Dumazet wrote:
>>
>> On 11/20/2018 02:17 AM, Paolo Abeni wrote:
>>> Eric noted that with UDP GRO and napi timeout, we could keep a single
>>> UDP packet inside the GRO hash forever, if the related NAPI instance
>>> calls napi_gro_complete() at an higher frequency than the napi timeout.
>>> Willem noted that even TCP packets could be trapped there, till the
>>> next retransmission.
>>> This patch tries to address the issue, flushing the oldest packets before
>>> scheduling the NAPI timeout. The rationale is that such a timeout should be
>>> well below a jiffy and we are not flushing packets eligible for sane GRO.
>>>
>>> Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
>>> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
>>> ---
>>> Sending as RFC, as I fear I'm missing some relevant pieces.
>>> Also I'm unsure if this should considered a fixes for "udp: implement
>>> GRO for plain UDP sockets." or for "net: gro: add a per device gro flush timer"
>
> Thank you for your feedback!
>
>> Truth be told, relying on jiffies change is a bit fragile for HZ=100 or HZ=250 kernels.
>
> Yes, we have higher bound there.
>
>> See recent TCP commit that got rid of tcp_tso_should_defer() dependency on HZ/jiffies
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/commit/?id=a682850a114aef947da5d603f7fd2cfe7eabbd72
>
> I'm unsure I follow correctly. Are you suggesting to use ns precision
> for skb aging in GRO? If so, could that be a separate change? (looks
> more invasive)
I am not suggesting adding ns in your patch.
That can be done later if we care.
I simply warn that some distros have low HZ value and thus the fix wont prevent packet sitting 4 or 10 ms in the queue.
^ permalink raw reply
* [PATCH mac80211-next v4] mac80211-next: rtnetlink wifi simulation device
From: Cody Schuffelen @ 2018-11-21 3:14 UTC (permalink / raw)
To: Johannes Berg
Cc: Kalle Valo, David S . Miller, Sergey Matyukevich,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, kernel-team-z5hGa2qSFaRBDgjK7y7TUQ,
Cody Schuffelen, Alistair Strachan, Greg Hartman,
Tristan Muntsinger
This device takes over an existing network device and produces a
new one that appears like a wireless connection, returning enough canned
responses to nl80211 to satisfy a standard connection manager. If
necessary, it can also be set up one step removed from an existing
network device, such as through a vlan/80211Q or macvlan connection to
not disrupt the existing network interface.
To use it to wrap a bare ethernet connection:
ip link add link eth0 name wlan0 type virt_wifi
You may have to rename or otherwise hide the eth0 from your connection
manager, as the original network link will become unusuable and only
the wireless wrapper will be functional. This can also be combined with
vlan or macvlan links on top of eth0 to share the network between
distinct links, but that requires support outside the machine for
accepting vlan-tagged packets or packets from multiple MAC addresses.
This is being used for Google's Remote Android Virtual Device project,
which runs Android devices in virtual machines. The standard network
interfaces provided inside the virtual machines are all ethernet.
However, Android is not interested in ethernet devices and would rather
connect to a wireless interface. This patch allows the virtual machine
guest to treat one of its network connections as wireless rather than
ethernet, satisfying Android's network connection requirements.
We believe this is a generally useful driver for simulating wireless
network connections in other environments where a wireless connection is
desired by some userspace process but is not available.
This is distinct from other testing efforts such as mac80211_hwsim by
being a cfg80211 device instead of mac80211 device, allowing straight
pass-through on the data plane instead of forcing packaging of ethernet
data into mac80211 frames.
Signed-off-by: A. Cody Schuffelen <schuffelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Acked-by: Alistair Strachan <astrachan-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Acked-by: Greg Hartman <ghartman-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
Acked-by: Tristan Muntsinger <muntsinger-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
---
Thanks for the comments on previous changes. Patch comments are now
addressed in responses to those emails. There will be a slight delay as I
get the appropriate lkml.org link to reference the code review comments to
this new patch.
I apologize for the long delay in creating this new version.
First version: https://lkml.org/lkml/2018/7/27/947
First review: https://lore.kernel.org/lkml/1535460343.5895.56.camel-cdvu00un1VgdHxzADdlk8Q@public.gmane.org/
Second version: https://lore.kernel.org/lkml/20180926194324.71290-1-schuffelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org/
Second review: Comments of https://www.lkml.org/lkml/2018/9/26/1169
Third review: https://lkml.org/lkml/2018/10/4/966
drivers/net/wireless/Kconfig | 7 +
drivers/net/wireless/Makefile | 2 +
drivers/net/wireless/virt_wifi.c | 632 +++++++++++++++++++++++++++++++
3 files changed, 641 insertions(+)
create mode 100644 drivers/net/wireless/virt_wifi.c
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 166920ae23f8..f4e808411634 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -114,4 +114,11 @@ config USB_NET_RNDIS_WLAN
If you choose to build a module, it'll be called rndis_wlan.
+config VIRT_WIFI
+ bool "Wifi wrapper for ethernet drivers"
+ depends on CFG80211
+ ---help---
+ This option adds support for ethernet connections to appear as if they
+ are wifi connections through a special rtnetlink device.
+
endif # WLAN
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 7fc96306712a..6cfe74515c95 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -27,3 +27,5 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o
obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
+
+obj-$(CONFIG_VIRT_WIFI) += virt_wifi.o
diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c
new file mode 100644
index 000000000000..64b218699656
--- /dev/null
+++ b/drivers/net/wireless/virt_wifi.c
@@ -0,0 +1,632 @@
+// SPDX-License-Identifier: GPL-2.0
+/* drivers/net/wireless/virt_wifi.c
+ *
+ * A fake implementation of cfg80211_ops that can be tacked on to an ethernet
+ * net_device to make it appear as a wireless connection.
+ *
+ * Copyright (C) 2018 Google, Inc.
+ *
+ * Author: schuffelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org
+ */
+
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+
+#include <net/cfg80211.h>
+#include <net/rtnetlink.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+
+static struct wiphy *common_wiphy;
+
+struct virt_wifi_wiphy_priv {
+ struct delayed_work scan_result;
+ struct cfg80211_scan_request *scan_request;
+ bool being_deleted;
+};
+
+static struct ieee80211_channel channel_2ghz = {
+ .band = NL80211_BAND_2GHZ,
+ .center_freq = 2432,
+ .hw_value = 2432,
+ .max_power = 20,
+};
+
+static struct ieee80211_rate bitrates_2ghz[] = {
+ { .bitrate = 10 },
+ { .bitrate = 20 },
+ { .bitrate = 55 },
+ { .bitrate = 110 },
+ { .bitrate = 60 },
+ { .bitrate = 120 },
+ { .bitrate = 240 },
+};
+
+static struct ieee80211_supported_band band_2ghz = {
+ .channels = &channel_2ghz,
+ .bitrates = bitrates_2ghz,
+ .band = NL80211_BAND_2GHZ,
+ .n_channels = 1,
+ .n_bitrates = ARRAY_SIZE(bitrates_2ghz),
+ .ht_cap = {
+ .ht_supported = true,
+ .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+ IEEE80211_HT_CAP_GRN_FLD |
+ IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_DSSSCCK40,
+ .ampdu_factor = 0x3,
+ .ampdu_density = 0x6,
+ .mcs = {
+ .rx_mask = {0xff, 0xff},
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
+ },
+ },
+};
+
+static struct ieee80211_channel channel_5ghz = {
+ .band = NL80211_BAND_5GHZ,
+ .center_freq = 5240,
+ .hw_value = 5240,
+ .max_power = 20,
+};
+
+static struct ieee80211_rate bitrates_5ghz[] = {
+ { .bitrate = 60 },
+ { .bitrate = 120 },
+ { .bitrate = 240 },
+};
+
+#define RX_MCS_MAP (IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 6 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 8 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 14)
+
+#define TX_MCS_MAP (IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 6 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 8 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | \
+ IEEE80211_VHT_MCS_SUPPORT_0_9 << 14)
+
+static struct ieee80211_supported_band band_5ghz = {
+ .channels = &channel_5ghz,
+ .bitrates = bitrates_5ghz,
+ .band = NL80211_BAND_5GHZ,
+ .n_channels = 1,
+ .n_bitrates = ARRAY_SIZE(bitrates_5ghz),
+ .ht_cap = {
+ .ht_supported = true,
+ .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+ IEEE80211_HT_CAP_GRN_FLD |
+ IEEE80211_HT_CAP_SGI_20 |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_DSSSCCK40,
+ .ampdu_factor = 0x3,
+ .ampdu_density = 0x6,
+ .mcs = {
+ .rx_mask = {0xff, 0xff},
+ .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
+ },
+ },
+ .vht_cap = {
+ .vht_supported = true,
+ .cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
+ IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
+ IEEE80211_VHT_CAP_RXLDPC |
+ IEEE80211_VHT_CAP_SHORT_GI_80 |
+ IEEE80211_VHT_CAP_SHORT_GI_160 |
+ IEEE80211_VHT_CAP_TXSTBC |
+ IEEE80211_VHT_CAP_RXSTBC_1 |
+ IEEE80211_VHT_CAP_RXSTBC_2 |
+ IEEE80211_VHT_CAP_RXSTBC_3 |
+ IEEE80211_VHT_CAP_RXSTBC_4 |
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,
+ .vht_mcs = {
+ .rx_mcs_map = cpu_to_le16(RX_MCS_MAP),
+ .tx_mcs_map = cpu_to_le16(TX_MCS_MAP),
+ }
+ },
+};
+
+/* Assigned at module init. Guaranteed locally-administered and unicast. */
+static u8 fake_router_bssid[ETH_ALEN] __ro_after_init = {};
+
+/* Called with the rtnl lock held. */
+static int virt_wifi_scan(struct wiphy *wiphy,
+ struct cfg80211_scan_request *request)
+{
+ struct virt_wifi_wiphy_priv *priv = wiphy_priv(wiphy);
+
+ wiphy_debug(wiphy, "scan\n");
+
+ if (priv->scan_request || priv->being_deleted)
+ return -EBUSY;
+
+ priv->scan_request = request;
+ schedule_delayed_work(&priv->scan_result, HZ * 2);
+
+ return 0;
+}
+
+/* Acquires and releases the rdev BSS lock. */
+static void virt_wifi_scan_result(struct work_struct *work)
+{
+ struct {
+ u8 tag;
+ u8 len;
+ u8 ssid[8];
+ } __packed ssid = {
+ .tag = WLAN_EID_SSID, .len = 8, .ssid = "VirtWifi",
+ };
+ struct cfg80211_bss *informed_bss;
+ struct virt_wifi_wiphy_priv *priv =
+ container_of(work, struct virt_wifi_wiphy_priv,
+ scan_result.work);
+ struct wiphy *wiphy = priv_to_wiphy(priv);
+ struct cfg80211_scan_info scan_info = { .aborted = false };
+
+ informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
+ CFG80211_BSS_FTYPE_PRESP,
+ fake_router_bssid,
+ ktime_get_boot_ns(),
+ WLAN_CAPABILITY_ESS, 0,
+ (void *)&ssid, sizeof(ssid),
+ DBM_TO_MBM(-50), GFP_KERNEL);
+ cfg80211_put_bss(wiphy, informed_bss);
+
+ /* Schedules work which acquires and releases the rtnl lock. */
+ cfg80211_scan_done(priv->scan_request, &scan_info);
+ priv->scan_request = NULL;
+}
+
+/* May acquire and release the rdev BSS lock. */
+static void virt_wifi_cancel_scan(struct wiphy *wiphy)
+{
+ struct virt_wifi_wiphy_priv *priv = wiphy_priv(wiphy);
+
+ cancel_delayed_work_sync(&priv->scan_result);
+ /* Clean up dangling callbacks if necessary. */
+ if (priv->scan_request) {
+ struct cfg80211_scan_info scan_info = { .aborted = true };
+ /* Schedules work which acquires and releases the rtnl lock. */
+ cfg80211_scan_done(priv->scan_request, &scan_info);
+ priv->scan_request = NULL;
+ }
+}
+
+struct virt_wifi_netdev_priv {
+ struct delayed_work connect;
+ struct net_device *lowerdev;
+ struct net_device *upperdev;
+ u32 tx_packets;
+ u32 tx_failed;
+ u8 connect_requested_bss[ETH_ALEN];
+ bool is_up;
+ bool is_connected;
+ bool being_deleted;
+};
+
+/* Called with the rtnl lock held. */
+static int virt_wifi_connect(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_connect_params *sme)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(netdev);
+ bool could_schedule;
+
+ if (priv->being_deleted || !priv->is_up)
+ return -EBUSY;
+
+ could_schedule = schedule_delayed_work(&priv->connect, HZ * 2);
+ if (!could_schedule)
+ return -EBUSY;
+
+ if (sme->bssid)
+ ether_addr_copy(priv->connect_requested_bss, sme->bssid);
+ else
+ eth_zero_addr(priv->connect_requested_bss);
+
+ wiphy_debug(wiphy, "connect\n");
+
+ return 0;
+}
+
+/* Acquires and releases the rdev event lock. */
+static void virt_wifi_connect_complete(struct work_struct *work)
+{
+ struct virt_wifi_netdev_priv *priv =
+ container_of(work, struct virt_wifi_netdev_priv, connect.work);
+ u8 *requested_bss = priv->connect_requested_bss;
+ bool has_addr = !is_zero_ether_addr(requested_bss);
+ bool right_addr = ether_addr_equal(requested_bss, fake_router_bssid);
+ u16 status = WLAN_STATUS_SUCCESS;
+
+ if (!priv->is_up || (has_addr && !right_addr))
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ else
+ priv->is_connected = true;
+
+ /* Schedules an event that acquires the rtnl lock. */
+ cfg80211_connect_result(priv->upperdev, requested_bss, NULL, 0, NULL, 0,
+ status, GFP_KERNEL);
+ netif_carrier_on(priv->upperdev);
+}
+
+/* May acquire and release the rdev event lock. */
+static void virt_wifi_cancel_connect(struct net_device *netdev)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(netdev);
+
+ /* If there is work pending, clean up dangling callbacks. */
+ if (cancel_delayed_work_sync(&priv->connect)) {
+ /* Schedules an event that acquires the rtnl lock. */
+ cfg80211_connect_result(priv->upperdev,
+ priv->connect_requested_bss, NULL, 0,
+ NULL, 0,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
+ GFP_KERNEL);
+ }
+}
+
+/* Called with the rtnl lock held. Acquires the rdev event lock. */
+static int virt_wifi_disconnect(struct wiphy *wiphy, struct net_device *netdev,
+ u16 reason_code)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(netdev);
+
+ if (priv->being_deleted)
+ return -EBUSY;
+
+ wiphy_debug(wiphy, "disconnect\n");
+ virt_wifi_cancel_connect(netdev);
+
+ cfg80211_disconnected(netdev, reason_code, NULL, 0, true, GFP_KERNEL);
+ priv->is_connected = false;
+ netif_carrier_off(netdev);
+
+ return 0;
+}
+
+/* Called with the rtnl lock held. */
+static int virt_wifi_get_station(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *mac, struct station_info *sinfo)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+
+ wiphy_debug(wiphy, "get_station\n");
+
+ if (!priv->is_connected || !ether_addr_equal(mac, fake_router_bssid))
+ return -ENOENT;
+
+ sinfo->filled = BIT_ULL(NL80211_STA_INFO_TX_PACKETS) |
+ BIT_ULL(NL80211_STA_INFO_TX_FAILED) |
+ BIT_ULL(NL80211_STA_INFO_SIGNAL) |
+ BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+ sinfo->tx_packets = priv->tx_packets;
+ sinfo->tx_failed = priv->tx_failed;
+ /* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_ */
+ sinfo->signal = -50;
+ sinfo->txrate = (struct rate_info) {
+ .legacy = 10, /* units are 100kbit/s */
+ };
+ return 0;
+}
+
+/* Called with the rtnl lock held. */
+static int virt_wifi_dump_station(struct wiphy *wiphy, struct net_device *dev,
+ int idx, u8 *mac, struct station_info *sinfo)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+
+ wiphy_debug(wiphy, "dump_station\n");
+
+ if (idx != 0 || !priv->is_connected)
+ return -ENOENT;
+
+ ether_addr_copy(mac, fake_router_bssid);
+ return virt_wifi_get_station(wiphy, dev, fake_router_bssid, sinfo);
+}
+
+static const struct cfg80211_ops virt_wifi_cfg80211_ops = {
+ .scan = virt_wifi_scan,
+
+ .connect = virt_wifi_connect,
+ .disconnect = virt_wifi_disconnect,
+
+ .get_station = virt_wifi_get_station,
+ .dump_station = virt_wifi_dump_station,
+};
+
+/* Acquires and releases the rtnl lock. */
+static struct wiphy *virt_wifi_make_wiphy(void)
+{
+ struct wiphy *wiphy;
+ struct virt_wifi_wiphy_priv *priv;
+ int err;
+
+ wiphy = wiphy_new(&virt_wifi_cfg80211_ops, sizeof(*priv));
+
+ if (!wiphy)
+ return NULL;
+
+ wiphy->max_scan_ssids = 4;
+ wiphy->max_scan_ie_len = 1000;
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+ wiphy->bands[NL80211_BAND_2GHZ] = &band_2ghz;
+ wiphy->bands[NL80211_BAND_5GHZ] = &band_5ghz;
+ wiphy->bands[NL80211_BAND_60GHZ] = NULL;
+
+ wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED;
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+ priv = wiphy_priv(wiphy);
+ priv->being_deleted = false;
+ priv->scan_request = NULL;
+ INIT_DELAYED_WORK(&priv->scan_result, virt_wifi_scan_result);
+
+ err = wiphy_register(wiphy);
+ if (err < 0) {
+ wiphy_free(wiphy);
+ return NULL;
+ }
+
+ return wiphy;
+}
+
+/* Acquires and releases the rtnl lock. */
+static void virt_wifi_destroy_wiphy(struct wiphy *wiphy)
+{
+ struct virt_wifi_wiphy_priv *priv;
+
+ WARN(!wiphy, "%s called with null wiphy", __func__);
+ if (!wiphy)
+ return;
+
+ priv = wiphy_priv(wiphy);
+ priv->being_deleted = true;
+ virt_wifi_cancel_scan(wiphy);
+
+ if (wiphy->registered)
+ wiphy_unregister(wiphy);
+ wiphy_free(wiphy);
+}
+
+/* Enters and exits a RCU-bh critical section. */
+static netdev_tx_t virt_wifi_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+
+ priv->tx_packets++;
+ if (!priv->is_connected) {
+ priv->tx_failed++;
+ return NET_XMIT_DROP;
+ }
+
+ skb->dev = priv->lowerdev;
+ return dev_queue_xmit(skb);
+}
+
+/* Called with rtnl lock held. */
+static int virt_wifi_net_device_open(struct net_device *dev)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+
+ priv->is_up = true;
+ return 0;
+}
+
+/* Called with rtnl lock held. */
+static int virt_wifi_net_device_stop(struct net_device *dev)
+{
+ struct virt_wifi_netdev_priv *n_priv = netdev_priv(dev);
+ struct virt_wifi_wiphy_priv *w_priv;
+
+ n_priv->is_up = false;
+
+ if (!dev->ieee80211_ptr)
+ return 0;
+ w_priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
+
+ virt_wifi_cancel_scan(dev->ieee80211_ptr->wiphy);
+ virt_wifi_cancel_connect(dev);
+ netif_carrier_off(dev);
+
+ return 0;
+}
+
+static const struct net_device_ops virt_wifi_ops = {
+ .ndo_start_xmit = virt_wifi_start_xmit,
+ .ndo_open = virt_wifi_net_device_open,
+ .ndo_stop = virt_wifi_net_device_stop,
+};
+
+/* Invoked as part of rtnl lock release. */
+static void virt_wifi_net_device_destructor(struct net_device *dev)
+{
+ /* Delayed past dellink to allow nl80211 to react to the device being
+ * deleted.
+ */
+ kfree(dev->ieee80211_ptr);
+ dev->ieee80211_ptr = NULL;
+ free_netdev(dev);
+}
+
+/* No lock interaction. */
+static void virt_wifi_setup(struct net_device *dev)
+{
+ ether_setup(dev);
+ dev->netdev_ops = &virt_wifi_ops;
+ dev->priv_destructor = virt_wifi_net_device_destructor;
+}
+
+/* Called in a RCU read critical section from netif_receive_skb */
+static rx_handler_result_t virt_wifi_rx_handler(struct sk_buff **pskb)
+{
+ struct sk_buff *skb = *pskb;
+ struct virt_wifi_netdev_priv *priv =
+ rcu_dereference(skb->dev->rx_handler_data);
+
+ if (!priv->is_connected)
+ return RX_HANDLER_PASS;
+
+ /* GFP_ATOMIC because this is a packet interrupt handler. */
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!skb) {
+ dev_err(&priv->upperdev->dev, "can't skb_share_check\n");
+ return RX_HANDLER_CONSUMED;
+ }
+
+ *pskb = skb;
+ skb->dev = priv->upperdev;
+ skb->pkt_type = PACKET_HOST;
+ return RX_HANDLER_ANOTHER;
+}
+
+/* Called with rtnl lock held. */
+static int virt_wifi_newlink(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+ int err;
+
+ if (!tb[IFLA_LINK])
+ return -EINVAL;
+
+ netif_carrier_off(dev);
+
+ priv->upperdev = dev;
+ priv->lowerdev = __dev_get_by_index(src_net,
+ nla_get_u32(tb[IFLA_LINK]));
+
+ if (!priv->lowerdev)
+ return -ENODEV;
+ if (!tb[IFLA_MTU])
+ dev->mtu = priv->lowerdev->mtu;
+ else if (dev->mtu > priv->lowerdev->mtu)
+ return -EINVAL;
+
+ err = netdev_rx_handler_register(priv->lowerdev, virt_wifi_rx_handler,
+ priv);
+ if (err) {
+ dev_err(&priv->lowerdev->dev,
+ "can't netdev_rx_handler_register: %d\n", err);
+ return err;
+ }
+
+ eth_hw_addr_inherit(dev, priv->lowerdev);
+ netif_stacked_transfer_operstate(priv->lowerdev, dev);
+
+ SET_NETDEV_DEV(dev, &priv->lowerdev->dev);
+ dev->ieee80211_ptr = kzalloc(sizeof(*dev->ieee80211_ptr), GFP_KERNEL);
+
+ if (!dev->ieee80211_ptr)
+ goto remove_handler;
+
+ dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
+ dev->ieee80211_ptr->wiphy = common_wiphy;
+
+ err = register_netdevice(dev);
+ if (err) {
+ dev_err(&priv->lowerdev->dev, "can't register_netdevice: %d\n",
+ err);
+ goto free_wireless_dev;
+ }
+
+ err = netdev_upper_dev_link(priv->lowerdev, dev, extack);
+ if (err) {
+ dev_err(&priv->lowerdev->dev, "can't netdev_upper_dev_link: %d\n",
+ err);
+ goto unregister_netdev;
+ }
+
+ priv->being_deleted = false;
+ priv->is_connected = false;
+ priv->is_up = false;
+ INIT_DELAYED_WORK(&priv->connect, virt_wifi_connect_complete);
+
+ return 0;
+unregister_netdev:
+ unregister_netdevice(dev);
+free_wireless_dev:
+ kfree(dev->ieee80211_ptr);
+ dev->ieee80211_ptr = NULL;
+remove_handler:
+ netdev_rx_handler_unregister(priv->lowerdev);
+
+ return err;
+}
+
+/* Called with rtnl lock held. */
+static void virt_wifi_dellink(struct net_device *dev,
+ struct list_head *head)
+{
+ struct virt_wifi_netdev_priv *priv = netdev_priv(dev);
+
+ if (dev->ieee80211_ptr)
+ virt_wifi_cancel_scan(dev->ieee80211_ptr->wiphy);
+
+ priv->being_deleted = true;
+ virt_wifi_cancel_connect(dev);
+ netif_carrier_off(dev);
+
+ netdev_rx_handler_unregister(priv->lowerdev);
+ netdev_upper_dev_unlink(priv->lowerdev, dev);
+
+ unregister_netdevice_queue(dev, head);
+
+ /* Deleting the wiphy is handled in the module destructor. */
+}
+
+static struct rtnl_link_ops virt_wifi_link_ops = {
+ .kind = "virt_wifi",
+ .setup = virt_wifi_setup,
+ .newlink = virt_wifi_newlink,
+ .dellink = virt_wifi_dellink,
+ .priv_size = sizeof(struct virt_wifi_netdev_priv),
+};
+
+/* Acquires and releases the rtnl lock. */
+static int __init virt_wifi_init_module(void)
+{
+ int err;
+
+ /* Guaranteed to be locallly-administered and not multicast. */
+ eth_random_addr(fake_router_bssid);
+
+ common_wiphy = virt_wifi_make_wiphy();
+ if (!common_wiphy)
+ return -ENOMEM;
+
+ err = rtnl_link_register(&virt_wifi_link_ops);
+ if (err)
+ virt_wifi_destroy_wiphy(common_wiphy);
+
+ return err;
+}
+
+/* Acquires and releases the rtnl lock. */
+static void __exit virt_wifi_cleanup_module(void)
+{
+ /* Will delete any devices that depend on the wiphy. */
+ rtnl_link_unregister(&virt_wifi_link_ops);
+ virt_wifi_destroy_wiphy(common_wiphy);
+}
+
+module_init(virt_wifi_init_module);
+module_exit(virt_wifi_cleanup_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Cody Schuffelen <schuffelen-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>");
+MODULE_DESCRIPTION("Driver for a wireless wrapper of ethernet devices");
+MODULE_ALIAS_RTNL_LINK("virt_wifi");
--
2.19.1.1215.g8438c0b245-goog
^ permalink raw reply related
* Re: [PATCH net-next v3] wireless-drivers: rtnetlink wifi simulation device
From: Cody Schuffelen @ 2018-11-21 3:20 UTC (permalink / raw)
To: sergey.matyukevich.os
Cc: Johannes Berg, Kalle Valo, David S. Miller, linux-kernel,
linux-wireless, netdev, kernel-team
In-Reply-To: <20181005143323.ezyd2x6x5ymlb7rg@bars>
> > + informed_bss =
> > + cfg80211_inform_bss_data(wiphy, &mock_inform_bss,
> > + CFG80211_BSS_FTYPE_PRESP,
> > + fake_router_bssid,
> > + mock_inform_bss.boottime_ns,
> > + WLAN_CAPABILITY_ESS, 0, ssid.data,
> > + sizeof(ssid), GFP_KERNEL);
>
> It is possible to simplify this part switching to cfg80211_inform_bss
> function: this function wraps your scan data in into cfg80211_inform_bss
> structure internally using some reasonable defaults, e.g. channel width.
>
> Besides, signal strength for scan entries should be passed in mBm units,
> so use DBM_TO_MBM macro. For instance, with your current code 'iw' tool
> produces the following output:
> $ sudo iw dev wlan0 scan
> ...
> signal: 0.-60 dBm
> ...
Good catch, fixed.
> > +static void virt_wifi_connect_complete(struct work_struct *work)
> > +{
> > + struct virt_wifi_priv *priv =
> > + container_of(work, struct virt_wifi_priv, connect.work);
> > + u8 *requested_bss = priv->connect_requested_bss;
> > + bool has_addr = !is_zero_ether_addr(requested_bss);
> > + bool right_addr = ether_addr_equal(requested_bss, fake_router_bssid);
> > + u16 status = WLAN_STATUS_SUCCESS;
> > +
> > + rtnl_lock();
> > + if (!priv->netdev_is_up || (has_addr && !right_addr))
> > + status = WLAN_STATUS_UNSPECIFIED_FAILURE;
> > + else
> > + priv->is_connected = true;
> > +
> > + cfg80211_connect_result(priv->netdev, requested_bss, NULL, 0, NULL, 0,
> > + status, GFP_KERNEL);
> > + rtnl_unlock();
> > +}
>
> Carrier state for wireless device depends on its connection state.
> E.g., carrier is set when wireless connection succeeds and cleared
> when device disconnects. So use netif_carrier_on/netif_carrier_off
> calls in connect/disconnect handlers to set correct carrier state.
> IIUC the following locations look reasonable:
> - netif_carrier_off on init
> - netif_carrier_on in virt_wifi_connect_complete on success
> - netif_carrier_off in virt_wifi_disconnect
Thanks, added.
> > +static void virt_wifi_disconnect_complete(struct work_struct *work)
> > +{
> > + struct virt_wifi_priv *priv =
> > + container_of(work, struct virt_wifi_priv, disconnect.work);
> > +
> > + cfg80211_disconnected(priv->netdev, priv->disconnect_reason, NULL, 0,
> > + true, GFP_KERNEL);
> > + priv->is_connected = false;
> > +}
>
> Why do you need delayed disconnect processing ? IIUC it can be dropped
> and cfg80211_disconnected call can be moved to virt_wifi_disconnect.
Done.
> > +
> > +static int virt_wifi_get_station(struct wiphy *wiphy,
> > + struct net_device *dev,
> > + const u8 *mac,
> > + struct station_info *sinfo)
> > +{
> > + wiphy_debug(wiphy, "get_station\n");
> > +
> > + if (!ether_addr_equal(mac, fake_router_bssid))
> > + return -ENOENT;
> > +
> > + sinfo->filled = BIT(NL80211_STA_INFO_TX_PACKETS) |
> > + BIT(NL80211_STA_INFO_TX_FAILED) | BIT(NL80211_STA_INFO_SIGNAL) |
> > + BIT(NL80211_STA_INFO_TX_BITRATE);
>
> Recently some of NL80211_STA_INFO_ attribute types has been modified to
> use BIT_ULL macro. Could you please check commit 22d0d2fafca93ba1d92a
> for details and modify your coded if needed.
Thanks for the the reference, updated to use BIT_ULL with the station commands.
> > + sinfo->tx_packets = 1;
>
> Only one packet, really ? Not sure if you plan to use the output of 'iw'
> or any other tool. If yes, then it probably makes sense to use stats
> from the original network link. Otherwise, your 'iw' output is
> going to look like this:
>
> $ iw dev wlan0 station dump
> ...
> tx packets: 1
> ...
>
> > + sinfo->tx_failed = 0;
>
> ...
Added bookkeeping to the net_device packet forwarded to track how many
packets were sent, and how many failed being sent due to no
connection.
> > +static int virt_wifi_dump_station(struct wiphy *wiphy,
> > + struct net_device *dev,
> > + int idx,
> > + u8 *mac,
> > + struct station_info *sinfo)
> > +{
> > + wiphy_debug(wiphy, "dump_station\n");
> > +
> > + if (idx != 0)
> > + return -ENOENT;
> > +
> > + ether_addr_copy(mac, fake_router_bssid);
> > + return virt_wifi_get_station(wiphy, dev, fake_router_bssid, sinfo);
> > +}
>
> Callback dump_station should return AP data only when STA is connected.
> Currently your driver returns fake AP data even when it is not
> connected.
Thanks, fixed.
> > +static const struct cfg80211_ops virt_wifi_cfg80211_ops = {
> > + .scan = virt_wifi_scan,
> > +
> > + .connect = virt_wifi_connect,
> > + .disconnect = virt_wifi_disconnect,
> > +
> > + .get_station = virt_wifi_get_station,
> > + .dump_station = virt_wifi_dump_station,
> > +};
>
> Hey, this minimal cfg80211 implementation works fine with wpa_supplicant
> and open AP config. By the way, if you plan to add more features, then
> I would suggest to consider the following cfg80211 callbacks:
> - change_station, get_channel
> to provide more info in connected state, e.g. compare the output
> of the following commands between your virtual interface and
> actual wireless interface:
> $ iw dev wlan0 link
> $ iw dev wlan0 info
>
> - stubs for add_key, del_key to enable encrypted AP simulation
Thanks for testing it out!
I've uploaded the new version here: https://lkml.org/lkml/2018/11/21/251
^ permalink raw reply
* Re: [RFC v3 3/3] vxlan: handle underlay VRF changes
From: David Ahern @ 2018-11-20 16:54 UTC (permalink / raw)
To: Alexis Bauvin, roopa; +Cc: netdev, akherbouche
In-Reply-To: <A40461AE-44D0-436D-BAA7-A90A05166CE1@scaleway.com>
On 11/20/18 9:27 AM, Alexis Bauvin wrote:
> maybe even move
> the function to net/core/dev.c, with other master-related functions.
> What do you think?
yes, it is a generic function.
^ permalink raw reply
* Re: [RFC v3 3/3] vxlan: handle underlay VRF changes
From: Alexis Bauvin @ 2018-11-20 16:58 UTC (permalink / raw)
To: Roopa Prabhu, David Ahern; +Cc: netdev, akherbouche
In-Reply-To: <CAJieiUiAho4UGbJP8Zcf-1_ErNu+jq_P6EqOKUQFqONRpsTD9w@mail.gmail.com>
Le 20 nov. 2018 à 16:35, Roopa Prabhu <roopa@cumulusnetworks.com> a écrit :
>
> On Tue, Nov 20, 2018 at 7:04 AM David Ahern <dsa@cumulusnetworks.com> wrote:
>>
>> On 11/20/18 7:23 AM, Alexis Bauvin wrote:
>>> When underlay VRF changes, either because the lower device itself changed,
>>> or its VRF changed, this patch releases the current socket of the VXLAN
>>> device and recreates another one in the right VRF. This allows for
>>> on-the-fly change of the underlay VRF of a VXLAN device.
>>>
>>> Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
>>> Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
>>> Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
>>> ---
>>> drivers/net/vxlan.c | 94 +++++++++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 94 insertions(+)
>>>
>>> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
>>> index a3de08122269..1e6ccad6df6a 100644
>>> --- a/drivers/net/vxlan.c
>>> +++ b/drivers/net/vxlan.c
>>> @@ -208,6 +208,18 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
>>> return list_first_entry(&fdb->remotes, struct vxlan_rdst, list);
>>> }
>>>
>>> +static int vxlan_is_in_l3mdev_chain(struct net_device *chain,
>>> + struct net_device *dev)
>>> +{
>>> + if (!chain)
>>> + return 0;
>>> +
>>> + if (chain->ifindex == dev->ifindex)
>>> + return 1;
>>> + return vxlan_is_in_l3mdev_chain(netdev_master_upper_dev_get(chain),
>>> + dev);
>>> +}
>>
>> This should return bool and true/false.
>>
>> Also, why l3mdev in the name? None of the checks look at whether it is
>> an l3mdev master.
>>
>> And again here, someone more familiar with the vxlan code should review it.
>>
>
>
> I understand the need for patch 2. But I don't understand the need for
> the complexity this patch introduces (especially implicit down and up
> of the vxlan device).
> Alexis, If your underlay routing changes, you can down and up the
> vxlan device from user-space correct ?. This should be true for any
> tunnel device.
Yes. Without this patch, down-up the vxlan interface is enough to handle
the underlay VRF change. This patch is more a convenience than a real
need.
Furthermore, an issue with automatic down/up of the interface is a silent
fail when mixing underlays in the default vrf and in specific ones. Say
you are in the following situation:
+----------+
| |
| vrf-blue |
| |
+--+----+--+
| |
+----+ +----+
| |
+----+----+ +----+----+
| | | |
| dummy-a | | dummy-b |
| | | |
+---------+ +---------+
. .
.(lower device).
. .
+---------+ +---------+
| | | |
| vxlan-a | | vxlan-b |
| | | |
+---------+ +---------+
A socket bound to vrf-blue listens on *:4789, thus owning the port. If moving an
underlay to the default vrf (ip link set dummy-b nomaster), a new socket will be
created, unbound to any interface and listening on *:4789. However, because it
will be in the default vrf, it will try to take ownership of port 4789 on ALL
vrfs, and fail because this port is already owned in vrf-blue for vxlan-a.
At least, a manual down/up of the vxlan interface would fail when upping the
interface, and spit out "Address already in use" through netlink to the
responsible ip link set up.
Dropping this patch would be sensible given its implicit actions, or fixing it
to make the vxlan interface really down when such a situation happens.
It may not be the right place to ask, but I don’t know the reason behind this
default vrf behaviour.
^ permalink raw reply
* Re: [PATCH 3/3] selftests: add a test for bpf_prog_test_run output size
From: Y Song @ 2018-11-20 16:58 UTC (permalink / raw)
To: lmb; +Cc: Alexei Starovoitov, Daniel Borkmann, netdev, linux-api
In-Reply-To: <CACAyw99F8L7BoB_TVAS6fvY9yb7cu9sCGXhjYPQ82sFZR=xKYQ@mail.gmail.com>
On Tue, Nov 20, 2018 at 3:35 AM Lorenz Bauer <lmb@cloudflare.com> wrote:
>
> On Sun, 18 Nov 2018 at 05:59, Y Song <ys114321@gmail.com> wrote:
> >
> > On Fri, Nov 16, 2018 at 12:55 PM Lorenz Bauer <lmb@cloudflare.com> wrote:
> > >
> > > Make sure that bpf_prog_test_run returns the correct length
> > > in the size_out argument and that the kernel respects the
> > > output size hint.
> > >
> > > Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
> > > ---
> > > tools/testing/selftests/bpf/test_progs.c | 34 ++++++++++++++++++++++++
> > > 1 file changed, 34 insertions(+)
> > >
> > > diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
> > > index 560d7527b86b..6ab98e10e86f 100644
> > > --- a/tools/testing/selftests/bpf/test_progs.c
> > > +++ b/tools/testing/selftests/bpf/test_progs.c
> > > @@ -124,6 +124,39 @@ static void test_pkt_access(void)
> > > bpf_object__close(obj);
> > > }
> > >
> > > +static void test_output_size_hint(void)
> > > +{
> > > + const char *file = "./test_pkt_access.o";
> > > + struct bpf_object *obj;
> > > + __u32 retval, size, duration;
> > > + int err, prog_fd;
> > > + char buf[10];
> > > +
> > > + err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
> > > + if (err) {
> > > + error_cnt++;
> > > + return;
> > > + }
> > CHECK can also be used here.
> > if (CHECK(...)) {
> > goto done;
> > }
> > where label "done" is right before bpf_object__close.
>
> I just copied this part from test_pkt_access, happy to change it though.
> However, I think "goto done" would lead to freeing an unallocated
> object in this case?
Right, you can just return here.
>
> --
> Lorenz Bauer | Systems Engineer
> 25 Lavington St., London SE1 0NZ
>
> www.cloudflare.com
^ permalink raw reply
* Re: [RFC v3 3/3] vxlan: handle underlay VRF changes
From: David Ahern @ 2018-11-20 17:09 UTC (permalink / raw)
To: Alexis Bauvin, Roopa Prabhu; +Cc: netdev, akherbouche
In-Reply-To: <5A3D06B9-4F1A-4144-A6C4-53740DFD7C46@scaleway.com>
On 11/20/18 9:58 AM, Alexis Bauvin wrote:
> A socket bound to vrf-blue listens on *:4789, thus owning the port. If moving an
> underlay to the default vrf (ip link set dummy-b nomaster), a new socket will be
> created, unbound to any interface and listening on *:4789. However, because it
> will be in the default vrf, it will try to take ownership of port 4789 on ALL
> vrfs, and fail because this port is already owned in vrf-blue for vxlan-a.
SO_REUSEPORT will fix that and incoming traffic through a vrf and
default (non-)vrf will work. The recent changes by Vyatta provide even
better isolation of default vrf and overlapping ports.
^ permalink raw reply
* Re: [PATCH 00/12 net-next,v2] add flow_rule infrastructure
From: David Miller @ 2018-11-20 17:16 UTC (permalink / raw)
To: jiri
Cc: pablo, netdev, thomas.lendacky, f.fainelli, ariel.elior,
michael.chan, santosh, madalin.bucur, yisen.zhuang, salil.mehta,
jeffrey.t.kirsher, tariqt, saeedm, jiri, idosch, jakub.kicinski,
peppe.cavallaro, grygorii.strashko, andrew, vivien.didelot,
alexandre.torgue, joabreu, linux-net-drivers, ganeshgr, ogerlitz
In-Reply-To: <20181120073912.GA2264@nanopsycho>
From: Jiri Pirko <jiri@resnulli.us>
Date: Tue, 20 Nov 2018 08:39:12 +0100
> If later on the netfilter code will use it, through another
> ndo/notifier/whatever, that is side a nice side-effect in my
> opinion.
Netfilter HW offloading is the main motivation of these changes.
You can try to spin it any way you like, but I think this is pretty
clear.
Would the author of these changes be even be remotely interested in
this "cleanup" in areas of code he has never been involved in if that
were not the case?
I think it is very dishonest to portray the situation differently.
Thank you.
^ permalink raw reply
* Re: [net 01/13] net/mlx5: IPSec, Fix the SA context hash key
From: David Miller @ 2018-11-20 17:18 UTC (permalink / raw)
To: sergei.shtylyov; +Cc: saeedm, netdev, raeds
In-Reply-To: <baf7b441-10ac-357e-0425-c4c7e2b44d1c@cogentembedded.com>
From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Date: Tue, 20 Nov 2018 12:25:01 +0300
> Hello!
>
> On 20.11.2018 2:41, Saeed Mahameed wrote:
>
>> From: Raed Salem <raeds@mellanox.com>
>> The commit "net/mlx5: Refactor accel IPSec code" introduced a
>
> You also need to cite the commit ID.
It matches the Fixes: tag commit so it is sufficient to me.
^ permalink raw reply
* Re: [PATCH v2 0/4] Fix unsafe BPF_PROG_TEST_RUN interface
From: Y Song @ 2018-11-20 17:18 UTC (permalink / raw)
To: lmb; +Cc: Alexei Starovoitov, Daniel Borkmann, netdev, linux-api
In-Reply-To: <20181120154306.16657-1-lmb@cloudflare.com>
On Tue, Nov 20, 2018 at 7:43 AM Lorenz Bauer <lmb@cloudflare.com> wrote:
>
> Right now, there is no safe way to use BPF_PROG_TEST_RUN with data_out.
> This is because bpf_test_finish copies the output buffer to user space
> without checking its size. This can lead to the kernel overwriting
> data in user space after the buffer if xdp_adjust_head and friends are
> in play.
>
> Changes in v2:
> * Make the syscall return ENOSPC if data_size_out is too small
> * Make bpf_prog_test_run return EINVAL if size_out is missing
> * Document the new behaviour of data_size_out
>
> Lorenz Bauer (4):
> bpf: respect size hint to BPF_PROG_TEST_RUN if present
> tools: sync uapi/linux/bpf.h
> libbpf: require size hint in bpf_prog_test_run
> selftests: add a test for bpf_prog_test_run output size
For the series, if we decided to take this approach rather than
amending another field
in the uapi as described in https://www.spinics.net/lists/netdev/msg534277.html,
then
Acked-by: Yonghong Song <yhs@fb.com>
^ permalink raw reply
* Re: [PATCH V2 mlx5-next 11/12] {net,IB}/mlx5: Move Page fault EQ and ODP logic to RDMA
From: Jason Gunthorpe @ 2018-11-20 17:30 UTC (permalink / raw)
To: Saeed Mahameed
Cc: Leon Romanovsky, netdev@vger.kernel.org,
linux-rdma@vger.kernel.org
In-Reply-To: <20181119185242.21961-12-saeedm@mellanox.com>
On Mon, Nov 19, 2018 at 10:52:41AM -0800, Saeed Mahameed wrote:
> Use the new generic EQ API to move all ODP RDMA data structures and logic
> form mlx5 core driver into mlx5_ib driver.
>
> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
> Reviewed-by: Leon Romanovsky <leonro@mellanox.com>
> Reviewed-by: Tariq Toukan <tariqt@mellanox.com>
> ---
> drivers/infiniband/hw/mlx5/main.c | 10 +-
> drivers/infiniband/hw/mlx5/mlx5_ib.h | 15 +-
> drivers/infiniband/hw/mlx5/odp.c | 281 +++++++++++++++++-
> drivers/net/ethernet/mellanox/mlx5/core/dev.c | 34 ---
> drivers/net/ethernet/mellanox/mlx5/core/eq.c | 252 ----------------
> .../net/ethernet/mellanox/mlx5/core/lib/eq.h | 8 -
> .../net/ethernet/mellanox/mlx5/core/main.c | 17 +-
> .../ethernet/mellanox/mlx5/core/mlx5_core.h | 2 -
> include/linux/mlx5/driver.h | 49 ---
> include/linux/mlx5/eq.h | 21 ++
> 10 files changed, 308 insertions(+), 381 deletions(-)
Acked-by: Jason Gunthorpe <jgg@mellanox.com>
Can you let me know when these land in the shared branch please?
Thanks,
Jason
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox