* [PATCH bpf] xdp: fix possible cq entry leak
From: Ilya Maximets @ 2019-07-04 14:25 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, bpf, xdp-newbies, David S. Miller,
Björn Töpel, Magnus Karlsson, Jonathan Lemon,
Jakub Kicinski, Alexei Starovoitov, Daniel Borkmann,
Ilya Maximets
In-Reply-To: <CGME20190704142509eucas1p268eb9ca87bcc0bffb60891f88f3f6642@eucas1p2.samsung.com>
Completion queue address reservation could not be undone.
In case of bad 'queue_id' or skb allocation failure, reserved entry
will be leaked reducing the total capacity of completion queue.
Fix that by moving reservation to the point where failure is not
possible. Additionally, 'queue_id' checking moved out from the loop
since there is no point to check it there.
Fixes: 35fcde7f8deb ("xsk: support for Tx")
Signed-off-by: Ilya Maximets <i.maximets@samsung.com>
---
net/xdp/xsk.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
index f53a6ef7c155..703cf5ea448b 100644
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -226,6 +226,9 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
mutex_lock(&xs->mutex);
+ if (xs->queue_id >= xs->dev->real_num_tx_queues)
+ goto out;
+
while (xskq_peek_desc(xs->tx, &desc)) {
char *buffer;
u64 addr;
@@ -236,12 +239,6 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
goto out;
}
- if (xskq_reserve_addr(xs->umem->cq))
- goto out;
-
- if (xs->queue_id >= xs->dev->real_num_tx_queues)
- goto out;
-
len = desc.len;
skb = sock_alloc_send_skb(sk, len, 1, &err);
if (unlikely(!skb)) {
@@ -253,7 +250,7 @@ static int xsk_generic_xmit(struct sock *sk, struct msghdr *m,
addr = desc.addr;
buffer = xdp_umem_get_data(xs->umem, addr);
err = skb_store_bits(skb, 0, buffer, len);
- if (unlikely(err)) {
+ if (unlikely(err) || xskq_reserve_addr(xs->umem->cq)) {
kfree_skb(skb);
goto out;
}
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v6 5/5] selftests: tc-tests: actions: add MPLS tests
From: John Hurley @ 2019-07-04 14:16 UTC (permalink / raw)
To: netdev
Cc: davem, jiri, xiyou.wangcong, dsahern, willemdebruijn.kernel,
dcaratti, simon.horman, jakub.kicinski, oss-drivers, John Hurley
In-Reply-To: <1562249802-24937-1-git-send-email-john.hurley@netronome.com>
Add a new series of selftests to verify the functionality of act_mpls in
TC.
Signed-off-by: John Hurley <john.hurley@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
tools/testing/selftests/tc-testing/config | 1 +
.../tc-testing/tc-tests/actions/mpls.json | 812 +++++++++++++++++++++
2 files changed, 813 insertions(+)
create mode 100644 tools/testing/selftests/tc-testing/tc-tests/actions/mpls.json
diff --git a/tools/testing/selftests/tc-testing/config b/tools/testing/selftests/tc-testing/config
index 1adc4f9..7c55196 100644
--- a/tools/testing/selftests/tc-testing/config
+++ b/tools/testing/selftests/tc-testing/config
@@ -42,6 +42,7 @@ CONFIG_NET_ACT_CTINFO=m
CONFIG_NET_ACT_SKBMOD=m
CONFIG_NET_ACT_IFE=m
CONFIG_NET_ACT_TUNNEL_KEY=m
+CONFIG_NET_ACT_MPLS=m
CONFIG_NET_IFE_SKBMARK=m
CONFIG_NET_IFE_SKBPRIO=m
CONFIG_NET_IFE_SKBTCINDEX=m
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/mpls.json b/tools/testing/selftests/tc-testing/tc-tests/actions/mpls.json
new file mode 100644
index 0000000..d46180a
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/mpls.json
@@ -0,0 +1,812 @@
+[
+ {
+ "id": "a933",
+ "name": "Add MPLS dec_ttl action with pipe opcode",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl pipe index 8",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*pipe.*index 8 ref",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "08d1",
+ "name": "Add mpls dec_ttl action with pass opcode",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl pass index 8",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions get action mpls index 8",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*pass.*index 8 ref",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "d786",
+ "name": "Add mpls dec_ttl action with drop opcode",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl drop index 8",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions get action mpls index 8",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*drop.*index 8 ref",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "f334",
+ "name": "Add mpls dec_ttl action with reclassify opcode",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl reclassify index 8",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions get action mpls index 8",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*reclassify.*index 8 ref",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "29bd",
+ "name": "Add mpls dec_ttl action with continue opcode",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl continue index 8",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions get action mpls index 8",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*continue.*index 8 ref",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "48df",
+ "name": "Add mpls dec_ttl action with jump opcode",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl jump 10 index 8",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*jump 10.*index 8 ref",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "62eb",
+ "name": "Add mpls dec_ttl action with trap opcode",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl trap index 8",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl trap.*index 8 ref",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "9118",
+ "name": "Add mpls dec_ttl action with invalid opcode",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl foo index 8",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*foo.*index 8 ref",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "6ce1",
+ "name": "Add mpls dec_ttl action with label (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl label 20",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*label.*20.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "352f",
+ "name": "Add mpls dec_ttl action with tc (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl tc 3",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*tc.*3.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "fa1c",
+ "name": "Add mpls dec_ttl action with ttl (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl ttl 20",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*ttl.*20.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "6b79",
+ "name": "Add mpls dec_ttl action with bos (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls dec_ttl bos 1",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*dec_ttl.*bos.*1.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "d4c4",
+ "name": "Add mpls pop action with ip proto",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls pop protocol ipv4",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*pop.*protocol.*ip.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "92fe",
+ "name": "Add mpls pop action with mpls proto",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls pop protocol mpls_mc",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*pop.*protocol.*mpls_mc.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "7e23",
+ "name": "Add mpls pop action with no protocol (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls pop",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*pop.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "6182",
+ "name": "Add mpls pop action with label (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls pop protocol ipv4 label 20",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*pop.*label.*20.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "6475",
+ "name": "Add mpls pop action with tc (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls pop protocol ipv4 tc 3",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*pop.*tc.*3.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "067b",
+ "name": "Add mpls pop action with ttl (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls pop protocol ipv4 ttl 20",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*pop.*ttl.*20.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "7316",
+ "name": "Add mpls pop action with bos (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls pop protocol ipv4 bos 1",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*pop.*bos.*1.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "38cc",
+ "name": "Add mpls push action with label",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push label 20",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*label.*20.*ttl.*[0-9]+.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "c281",
+ "name": "Add mpls push action with mpls_mc protocol",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push protocol mpls_mc label 20",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_mc.*label.*20.*ttl.*[0-9]+.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "5db4",
+ "name": "Add mpls push action with label, tc and ttl",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push label 20 tc 3 ttl 128",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*label.*20.*tc.*3.*ttl.*128.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "16eb",
+ "name": "Add mpls push action with label and bos",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push label 20 bos 1",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*label.*20.*bos.*1.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "d69d",
+ "name": "Add mpls push action with no label (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "e8e4",
+ "name": "Add mpls push action with ipv4 protocol (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push protocol ipv4 label 20",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*label.*20.*ttl.*[0-9]+.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "ecd0",
+ "name": "Add mpls push action with out of range label (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push label 1048576",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*label.*1048576.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "d303",
+ "name": "Add mpls push action with out of range tc (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push label 20 tc 8",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*label.*20.*tc.*8.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "fd6e",
+ "name": "Add mpls push action with ttl of 0 (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls push label 20 ttl 0",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*label.*20.*ttl.*0.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "19e9",
+ "name": "Add mpls mod action with mpls label",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls mod label 20",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*modify.*label.*20.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "04b5",
+ "name": "Add mpls mod action with mpls tc",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls mod tc 3",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*modify.*tc.*3.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "6ed5",
+ "name": "Add mpls mod action with mpls label",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls mod ttl 128",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*modify.*ttl.*128.*pipe",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "db7c",
+ "name": "Add mpls mod action with protocol (invalid)",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ]
+ ],
+ "cmdUnderTest": "$TC actions add action mpls mod protocol ipv4",
+ "expExitCode": "255",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*modify.*protocol.*ip.*pipe",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "b070",
+ "name": "Replace existing mpls push action with new ID",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ],
+ "$TC actions add action mpls push label 20 pipe index 12"
+ ],
+ "cmdUnderTest": "$TC actions replace action mpls push label 30 pipe index 12",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions get action mpls index 12",
+ "matchPattern": "action order [0-9]+: mpls.*push.*protocol.*mpls_uc.*label.*30.*pipe.*index 12 ref",
+ "matchCount": "1",
+ "teardown": [
+ "$TC actions flush action mpls"
+ ]
+ },
+ {
+ "id": "6cce",
+ "name": "Delete mpls pop action",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ],
+ "$TC actions add action mpls pop protocol ipv4 index 44"
+ ],
+ "cmdUnderTest": "$TC actions del action mpls index 44",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*pop.*index 44 ref",
+ "matchCount": "0",
+ "teardown": []
+ },
+ {
+ "id": "d138",
+ "name": "Flush mpls actions",
+ "category": [
+ "actions",
+ "mpls"
+ ],
+ "setup": [
+ [
+ "$TC actions flush action mpls",
+ 0,
+ 1,
+ 255
+ ],
+ "$TC actions add action mpls push label 10 index 10",
+ "$TC actions add action mpls push label 20 index 20",
+ "$TC actions add action mpls push label 30 index 30",
+ "$TC actions add action mpls push label 40 index 40"
+ ],
+ "cmdUnderTest": "$TC actions flush action mpls",
+ "expExitCode": "0",
+ "verifyCmd": "$TC actions list action mpls",
+ "matchPattern": "action order [0-9]+: mpls.*push.*",
+ "matchCount": "0",
+ "teardown": []
+ }
+]
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v6 4/5] net: sched: add mpls manipulation actions to TC
From: John Hurley @ 2019-07-04 14:16 UTC (permalink / raw)
To: netdev
Cc: davem, jiri, xiyou.wangcong, dsahern, willemdebruijn.kernel,
dcaratti, simon.horman, jakub.kicinski, oss-drivers, John Hurley
In-Reply-To: <1562249802-24937-1-git-send-email-john.hurley@netronome.com>
Currently, TC offers the ability to match on the MPLS fields of a packet
through the use of the flow_dissector_key_mpls struct. However, as yet, TC
actions do not allow the modification or manipulation of such fields.
Add a new module that registers TC action ops to allow manipulation of
MPLS. This includes the ability to push and pop headers as well as modify
the contents of new or existing headers. A further action to decrement the
TTL field of an MPLS header is also provided with a new helper added to
support this.
Examples of the usage of the new action with flower rules to push and pop
MPLS labels are:
tc filter add dev eth0 protocol ip parent ffff: flower \
action mpls push protocol mpls_uc label 123 \
action mirred egress redirect dev eth1
tc filter add dev eth0 protocol mpls_uc parent ffff: flower \
action mpls pop protocol ipv4 \
action mirred egress redirect dev eth1
Signed-off-by: John Hurley <john.hurley@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
---
include/linux/skbuff.h | 1 +
include/net/tc_act/tc_mpls.h | 30 +++
include/uapi/linux/pkt_cls.h | 3 +-
include/uapi/linux/tc_act/tc_mpls.h | 33 +++
net/core/skbuff.c | 30 +++
net/sched/Kconfig | 11 +
net/sched/Makefile | 1 +
net/sched/act_mpls.c | 406 ++++++++++++++++++++++++++++++++++++
8 files changed, 514 insertions(+), 1 deletion(-)
create mode 100644 include/net/tc_act/tc_mpls.h
create mode 100644 include/uapi/linux/tc_act/tc_mpls.h
create mode 100644 net/sched/act_mpls.c
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 1545c4c..a9f8ff9 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3449,6 +3449,7 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto);
int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto);
int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse);
+int skb_mpls_dec_ttl(struct sk_buff *skb);
struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
gfp_t gfp);
diff --git a/include/net/tc_act/tc_mpls.h b/include/net/tc_act/tc_mpls.h
new file mode 100644
index 0000000..4bc3d92
--- /dev/null
+++ b/include/net/tc_act/tc_mpls.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/* Copyright (C) 2019 Netronome Systems, Inc. */
+
+#ifndef __NET_TC_MPLS_H
+#define __NET_TC_MPLS_H
+
+#include <linux/tc_act/tc_mpls.h>
+#include <net/act_api.h>
+
+struct tcf_mpls_params {
+ int tcfm_action;
+ u32 tcfm_label;
+ u8 tcfm_tc;
+ u8 tcfm_ttl;
+ u8 tcfm_bos;
+ __be16 tcfm_proto;
+ struct rcu_head rcu;
+};
+
+#define ACT_MPLS_TC_NOT_SET 0xff
+#define ACT_MPLS_BOS_NOT_SET 0xff
+#define ACT_MPLS_LABEL_NOT_SET 0xffffffff
+
+struct tcf_mpls {
+ struct tc_action common;
+ struct tcf_mpls_params __rcu *mpls_p;
+};
+#define to_mpls(a) ((struct tcf_mpls *)a)
+
+#endif /* __NET_TC_MPLS_H */
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 8cc6b67..e22ef4a 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -104,8 +104,9 @@ enum tca_id {
TCA_ID_SIMP = TCA_ACT_SIMP,
TCA_ID_IFE = TCA_ACT_IFE,
TCA_ID_SAMPLE = TCA_ACT_SAMPLE,
- /* other actions go here */
TCA_ID_CTINFO,
+ TCA_ID_MPLS,
+ /* other actions go here */
__TCA_ID_MAX = 255
};
diff --git a/include/uapi/linux/tc_act/tc_mpls.h b/include/uapi/linux/tc_act/tc_mpls.h
new file mode 100644
index 0000000..9360e95
--- /dev/null
+++ b/include/uapi/linux/tc_act/tc_mpls.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* Copyright (C) 2019 Netronome Systems, Inc. */
+
+#ifndef __LINUX_TC_MPLS_H
+#define __LINUX_TC_MPLS_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_MPLS_ACT_POP 1
+#define TCA_MPLS_ACT_PUSH 2
+#define TCA_MPLS_ACT_MODIFY 3
+#define TCA_MPLS_ACT_DEC_TTL 4
+
+struct tc_mpls {
+ tc_gen; /* generic TC action fields. */
+ int m_action; /* action of type TCA_MPLS_ACT_*. */
+};
+
+enum {
+ TCA_MPLS_UNSPEC,
+ TCA_MPLS_TM, /* struct tcf_t; time values associated with action. */
+ TCA_MPLS_PARMS, /* struct tc_mpls; action type and general TC fields. */
+ TCA_MPLS_PAD,
+ TCA_MPLS_PROTO, /* be16; eth_type of pushed or next (for pop) header. */
+ TCA_MPLS_LABEL, /* u32; MPLS label. Lower 20 bits are used. */
+ TCA_MPLS_TC, /* u8; MPLS TC field. Lower 3 bits are used. */
+ TCA_MPLS_TTL, /* u8; MPLS TTL field. Must not be 0. */
+ TCA_MPLS_BOS, /* u8; MPLS BOS field. Either 1 or 0. */
+ __TCA_MPLS_MAX,
+};
+#define TCA_MPLS_MAX (__TCA_MPLS_MAX - 1)
+
+#endif
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 46da15c..34ee236 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -59,6 +59,7 @@
#include <linux/errqueue.h>
#include <linux/prefetch.h>
#include <linux/if_vlan.h>
+#include <linux/mpls.h>
#include <net/protocol.h>
#include <net/dst.h>
@@ -5466,6 +5467,35 @@ int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse)
EXPORT_SYMBOL_GPL(skb_mpls_update_lse);
/**
+ * skb_mpls_dec_ttl() - decrement the TTL of the outermost MPLS header
+ *
+ * @skb: buffer
+ *
+ * Expects skb->data at mac header.
+ *
+ * Returns 0 on success, -errno otherwise.
+ */
+int skb_mpls_dec_ttl(struct sk_buff *skb)
+{
+ u32 lse;
+ u8 ttl;
+
+ if (unlikely(!eth_p_mpls(skb->protocol)))
+ return -EINVAL;
+
+ lse = be32_to_cpu(mpls_hdr(skb)->label_stack_entry);
+ ttl = (lse & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT;
+ if (!--ttl)
+ return -EINVAL;
+
+ lse &= ~MPLS_LS_TTL_MASK;
+ lse |= ttl << MPLS_LS_TTL_SHIFT;
+
+ return skb_mpls_update_lse(skb, cpu_to_be32(lse));
+}
+EXPORT_SYMBOL_GPL(skb_mpls_dec_ttl);
+
+/**
* alloc_skb_with_frags - allocate skb with page frags
*
* @header_len: size of linear part
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 360fdd3..731f5fb 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -842,6 +842,17 @@ config NET_ACT_CSUM
To compile this code as a module, choose M here: the
module will be called act_csum.
+config NET_ACT_MPLS
+ tristate "MPLS manipulation"
+ depends on NET_CLS_ACT
+ help
+ Say Y here to push or pop MPLS headers.
+
+ If unsure, say N.
+
+ To compile this code as a module, choose M here: the
+ module will be called act_mpls.
+
config NET_ACT_VLAN
tristate "Vlan manipulation"
depends on NET_CLS_ACT
diff --git a/net/sched/Makefile b/net/sched/Makefile
index d54bfcb..c266036 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o
obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o
obj-$(CONFIG_NET_ACT_SKBEDIT) += act_skbedit.o
obj-$(CONFIG_NET_ACT_CSUM) += act_csum.o
+obj-$(CONFIG_NET_ACT_MPLS) += act_mpls.o
obj-$(CONFIG_NET_ACT_VLAN) += act_vlan.o
obj-$(CONFIG_NET_ACT_BPF) += act_bpf.o
obj-$(CONFIG_NET_ACT_CONNMARK) += act_connmark.o
diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c
new file mode 100644
index 0000000..ca2597c
--- /dev/null
+++ b/net/sched/act_mpls.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/* Copyright (C) 2019 Netronome Systems, Inc. */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mpls.h>
+#include <linux/rtnetlink.h>
+#include <linux/skbuff.h>
+#include <linux/tc_act/tc_mpls.h>
+#include <net/mpls.h>
+#include <net/netlink.h>
+#include <net/pkt_sched.h>
+#include <net/pkt_cls.h>
+#include <net/tc_act/tc_mpls.h>
+
+static unsigned int mpls_net_id;
+static struct tc_action_ops act_mpls_ops;
+
+#define ACT_MPLS_TTL_DEFAULT 255
+
+static __be32 tcf_mpls_get_lse(struct mpls_shim_hdr *lse,
+ struct tcf_mpls_params *p, bool set_bos)
+{
+ u32 new_lse = 0;
+
+ if (lse)
+ new_lse = be32_to_cpu(lse->label_stack_entry);
+
+ if (p->tcfm_label != ACT_MPLS_LABEL_NOT_SET) {
+ new_lse &= ~MPLS_LS_LABEL_MASK;
+ new_lse |= p->tcfm_label << MPLS_LS_LABEL_SHIFT;
+ }
+ if (p->tcfm_ttl) {
+ new_lse &= ~MPLS_LS_TTL_MASK;
+ new_lse |= p->tcfm_ttl << MPLS_LS_TTL_SHIFT;
+ }
+ if (p->tcfm_tc != ACT_MPLS_TC_NOT_SET) {
+ new_lse &= ~MPLS_LS_TC_MASK;
+ new_lse |= p->tcfm_tc << MPLS_LS_TC_SHIFT;
+ }
+ if (p->tcfm_bos != ACT_MPLS_BOS_NOT_SET) {
+ new_lse &= ~MPLS_LS_S_MASK;
+ new_lse |= p->tcfm_bos << MPLS_LS_S_SHIFT;
+ } else if (set_bos) {
+ new_lse |= 1 << MPLS_LS_S_SHIFT;
+ }
+
+ return cpu_to_be32(new_lse);
+}
+
+static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a,
+ struct tcf_result *res)
+{
+ struct tcf_mpls *m = to_mpls(a);
+ struct tcf_mpls_params *p;
+ __be32 new_lse;
+ int ret;
+
+ tcf_lastuse_update(&m->tcf_tm);
+ bstats_cpu_update(this_cpu_ptr(m->common.cpu_bstats), skb);
+
+ /* Ensure 'data' points at mac_header prior calling mpls manipulating
+ * functions.
+ */
+ if (skb_at_tc_ingress(skb))
+ skb_push_rcsum(skb, skb->mac_len);
+
+ ret = READ_ONCE(m->tcf_action);
+
+ p = rcu_dereference_bh(m->mpls_p);
+
+ switch (p->tcfm_action) {
+ case TCA_MPLS_ACT_POP:
+ if (skb_mpls_pop(skb, p->tcfm_proto))
+ goto drop;
+ break;
+ case TCA_MPLS_ACT_PUSH:
+ new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb->protocol));
+ if (skb_mpls_push(skb, new_lse, p->tcfm_proto))
+ goto drop;
+ break;
+ case TCA_MPLS_ACT_MODIFY:
+ new_lse = tcf_mpls_get_lse(mpls_hdr(skb), p, false);
+ if (skb_mpls_update_lse(skb, new_lse))
+ goto drop;
+ break;
+ case TCA_MPLS_ACT_DEC_TTL:
+ if (skb_mpls_dec_ttl(skb))
+ goto drop;
+ break;
+ }
+
+ if (skb_at_tc_ingress(skb))
+ skb_pull_rcsum(skb, skb->mac_len);
+
+ return ret;
+
+drop:
+ qstats_drop_inc(this_cpu_ptr(m->common.cpu_qstats));
+ return TC_ACT_SHOT;
+}
+
+static int valid_label(const struct nlattr *attr,
+ struct netlink_ext_ack *extack)
+{
+ const u32 *label = nla_data(attr);
+
+ if (*label & ~MPLS_LABEL_MASK || *label == MPLS_LABEL_IMPLNULL) {
+ NL_SET_ERR_MSG_MOD(extack, "MPLS label out of range");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct nla_policy mpls_policy[TCA_MPLS_MAX + 1] = {
+ [TCA_MPLS_UNSPEC] = { .strict_start_type = TCA_MPLS_UNSPEC + 1 },
+ [TCA_MPLS_PARMS] = NLA_POLICY_EXACT_LEN(sizeof(struct tc_mpls)),
+ [TCA_MPLS_PROTO] = { .type = NLA_U16 },
+ [TCA_MPLS_LABEL] = NLA_POLICY_VALIDATE_FN(NLA_U32, valid_label),
+ [TCA_MPLS_TC] = NLA_POLICY_RANGE(NLA_U8, 0, 7),
+ [TCA_MPLS_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
+ [TCA_MPLS_BOS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
+};
+
+static int tcf_mpls_init(struct net *net, struct nlattr *nla,
+ struct nlattr *est, struct tc_action **a,
+ int ovr, int bind, bool rtnl_held,
+ struct tcf_proto *tp, struct netlink_ext_ack *extack)
+{
+ struct tc_action_net *tn = net_generic(net, mpls_net_id);
+ struct nlattr *tb[TCA_MPLS_MAX + 1];
+ struct tcf_chain *goto_ch = NULL;
+ struct tcf_mpls_params *p;
+ struct tc_mpls *parm;
+ bool exists = false;
+ struct tcf_mpls *m;
+ int ret = 0, err;
+ u8 mpls_ttl = 0;
+
+ if (!nla) {
+ NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes");
+ return -EINVAL;
+ }
+
+ err = nla_parse_nested(tb, TCA_MPLS_MAX, nla, mpls_policy, extack);
+ if (err < 0)
+ return err;
+
+ if (!tb[TCA_MPLS_PARMS]) {
+ NL_SET_ERR_MSG_MOD(extack, "No MPLS params");
+ return -EINVAL;
+ }
+ parm = nla_data(tb[TCA_MPLS_PARMS]);
+
+ /* Verify parameters against action type. */
+ switch (parm->m_action) {
+ case TCA_MPLS_ACT_POP:
+ if (!tb[TCA_MPLS_PROTO]) {
+ NL_SET_ERR_MSG_MOD(extack, "Protocol must be set for MPLS pop");
+ return -EINVAL;
+ }
+ if (!eth_proto_is_802_3(nla_get_be16(tb[TCA_MPLS_PROTO]))) {
+ NL_SET_ERR_MSG_MOD(extack, "Invalid protocol type for MPLS pop");
+ return -EINVAL;
+ }
+ if (tb[TCA_MPLS_LABEL] || tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] ||
+ tb[TCA_MPLS_BOS]) {
+ NL_SET_ERR_MSG_MOD(extack, "Label, TTL, TC or BOS cannot be used with MPLS pop");
+ return -EINVAL;
+ }
+ break;
+ case TCA_MPLS_ACT_DEC_TTL:
+ if (tb[TCA_MPLS_PROTO] || tb[TCA_MPLS_LABEL] ||
+ tb[TCA_MPLS_TTL] || tb[TCA_MPLS_TC] || tb[TCA_MPLS_BOS]) {
+ NL_SET_ERR_MSG_MOD(extack, "Label, TTL, TC, BOS or protocol cannot be used with MPLS dec_ttl");
+ return -EINVAL;
+ }
+ break;
+ case TCA_MPLS_ACT_PUSH:
+ if (!tb[TCA_MPLS_LABEL]) {
+ NL_SET_ERR_MSG_MOD(extack, "Label is required for MPLS push");
+ return -EINVAL;
+ }
+ if (tb[TCA_MPLS_PROTO] &&
+ !eth_p_mpls(nla_get_be16(tb[TCA_MPLS_PROTO]))) {
+ NL_SET_ERR_MSG_MOD(extack, "Protocol must be an MPLS type for MPLS push");
+ return -EPROTONOSUPPORT;
+ }
+ /* Push needs a TTL - if not specified, set a default value. */
+ if (!tb[TCA_MPLS_TTL]) {
+#if IS_ENABLED(CONFIG_MPLS)
+ mpls_ttl = net->mpls.default_ttl ?
+ net->mpls.default_ttl : ACT_MPLS_TTL_DEFAULT;
+#else
+ mpls_ttl = ACT_MPLS_TTL_DEFAULT;
+#endif
+ }
+ break;
+ case TCA_MPLS_ACT_MODIFY:
+ if (tb[TCA_MPLS_PROTO]) {
+ NL_SET_ERR_MSG_MOD(extack, "Protocol cannot be used with MPLS modify");
+ return -EINVAL;
+ }
+ break;
+ default:
+ NL_SET_ERR_MSG_MOD(extack, "Unknown MPLS action");
+ return -EINVAL;
+ }
+
+ err = tcf_idr_check_alloc(tn, &parm->index, a, bind);
+ if (err < 0)
+ return err;
+ exists = err;
+ if (exists && bind)
+ return 0;
+
+ if (!exists) {
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_mpls_ops, bind, true);
+ if (ret) {
+ tcf_idr_cleanup(tn, parm->index);
+ return ret;
+ }
+
+ ret = ACT_P_CREATED;
+ } else if (!ovr) {
+ tcf_idr_release(*a, bind);
+ return -EEXIST;
+ }
+
+ err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
+ if (err < 0)
+ goto release_idr;
+
+ m = to_mpls(*a);
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ err = -ENOMEM;
+ goto put_chain;
+ }
+
+ p->tcfm_action = parm->m_action;
+ p->tcfm_label = tb[TCA_MPLS_LABEL] ? nla_get_u32(tb[TCA_MPLS_LABEL]) :
+ ACT_MPLS_LABEL_NOT_SET;
+ p->tcfm_tc = tb[TCA_MPLS_TC] ? nla_get_u8(tb[TCA_MPLS_TC]) :
+ ACT_MPLS_TC_NOT_SET;
+ p->tcfm_ttl = tb[TCA_MPLS_TTL] ? nla_get_u8(tb[TCA_MPLS_TTL]) :
+ mpls_ttl;
+ p->tcfm_bos = tb[TCA_MPLS_BOS] ? nla_get_u8(tb[TCA_MPLS_BOS]) :
+ ACT_MPLS_BOS_NOT_SET;
+ p->tcfm_proto = tb[TCA_MPLS_PROTO] ? nla_get_be16(tb[TCA_MPLS_PROTO]) :
+ htons(ETH_P_MPLS_UC);
+
+ spin_lock_bh(&m->tcf_lock);
+ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
+ rcu_swap_protected(m->mpls_p, p, lockdep_is_held(&m->tcf_lock));
+ spin_unlock_bh(&m->tcf_lock);
+
+ if (goto_ch)
+ tcf_chain_put_by_act(goto_ch);
+ if (p)
+ kfree_rcu(p, rcu);
+
+ if (ret == ACT_P_CREATED)
+ tcf_idr_insert(tn, *a);
+ return ret;
+put_chain:
+ if (goto_ch)
+ tcf_chain_put_by_act(goto_ch);
+release_idr:
+ tcf_idr_release(*a, bind);
+ return err;
+}
+
+static void tcf_mpls_cleanup(struct tc_action *a)
+{
+ struct tcf_mpls *m = to_mpls(a);
+ struct tcf_mpls_params *p;
+
+ p = rcu_dereference_protected(m->mpls_p, 1);
+ if (p)
+ kfree_rcu(p, rcu);
+}
+
+static int tcf_mpls_dump(struct sk_buff *skb, struct tc_action *a,
+ int bind, int ref)
+{
+ unsigned char *b = skb_tail_pointer(skb);
+ struct tcf_mpls *m = to_mpls(a);
+ struct tcf_mpls_params *p;
+ struct tc_mpls opt = {
+ .index = m->tcf_index,
+ .refcnt = refcount_read(&m->tcf_refcnt) - ref,
+ .bindcnt = atomic_read(&m->tcf_bindcnt) - bind,
+ };
+ struct tcf_t t;
+
+ spin_lock_bh(&m->tcf_lock);
+ opt.action = m->tcf_action;
+ p = rcu_dereference_protected(m->mpls_p, lockdep_is_held(&m->tcf_lock));
+ opt.m_action = p->tcfm_action;
+
+ if (nla_put(skb, TCA_MPLS_PARMS, sizeof(opt), &opt))
+ goto nla_put_failure;
+
+ if (p->tcfm_label != ACT_MPLS_LABEL_NOT_SET &&
+ nla_put_u32(skb, TCA_MPLS_LABEL, p->tcfm_label))
+ goto nla_put_failure;
+
+ if (p->tcfm_tc != ACT_MPLS_TC_NOT_SET &&
+ nla_put_u8(skb, TCA_MPLS_TC, p->tcfm_tc))
+ goto nla_put_failure;
+
+ if (p->tcfm_ttl && nla_put_u8(skb, TCA_MPLS_TTL, p->tcfm_ttl))
+ goto nla_put_failure;
+
+ if (p->tcfm_bos != ACT_MPLS_BOS_NOT_SET &&
+ nla_put_u8(skb, TCA_MPLS_BOS, p->tcfm_bos))
+ goto nla_put_failure;
+
+ if (nla_put_be16(skb, TCA_MPLS_PROTO, p->tcfm_proto))
+ goto nla_put_failure;
+
+ tcf_tm_dump(&t, &m->tcf_tm);
+
+ if (nla_put_64bit(skb, TCA_MPLS_TM, sizeof(t), &t, TCA_MPLS_PAD))
+ goto nla_put_failure;
+
+ spin_unlock_bh(&m->tcf_lock);
+
+ return skb->len;
+
+nla_put_failure:
+ spin_unlock_bh(&m->tcf_lock);
+ nlmsg_trim(skb, b);
+ return -EMSGSIZE;
+}
+
+static int tcf_mpls_walker(struct net *net, struct sk_buff *skb,
+ struct netlink_callback *cb, int type,
+ const struct tc_action_ops *ops,
+ struct netlink_ext_ack *extack)
+{
+ struct tc_action_net *tn = net_generic(net, mpls_net_id);
+
+ return tcf_generic_walker(tn, skb, cb, type, ops, extack);
+}
+
+static int tcf_mpls_search(struct net *net, struct tc_action **a, u32 index)
+{
+ struct tc_action_net *tn = net_generic(net, mpls_net_id);
+
+ return tcf_idr_search(tn, a, index);
+}
+
+static struct tc_action_ops act_mpls_ops = {
+ .kind = "mpls",
+ .id = TCA_ID_MPLS,
+ .owner = THIS_MODULE,
+ .act = tcf_mpls_act,
+ .dump = tcf_mpls_dump,
+ .init = tcf_mpls_init,
+ .cleanup = tcf_mpls_cleanup,
+ .walk = tcf_mpls_walker,
+ .lookup = tcf_mpls_search,
+ .size = sizeof(struct tcf_mpls),
+};
+
+static __net_init int mpls_init_net(struct net *net)
+{
+ struct tc_action_net *tn = net_generic(net, mpls_net_id);
+
+ return tc_action_net_init(tn, &act_mpls_ops);
+}
+
+static void __net_exit mpls_exit_net(struct list_head *net_list)
+{
+ tc_action_net_exit(net_list, mpls_net_id);
+}
+
+static struct pernet_operations mpls_net_ops = {
+ .init = mpls_init_net,
+ .exit_batch = mpls_exit_net,
+ .id = &mpls_net_id,
+ .size = sizeof(struct tc_action_net),
+};
+
+static int __init mpls_init_module(void)
+{
+ return tcf_register_action(&act_mpls_ops, &mpls_net_ops);
+}
+
+static void __exit mpls_cleanup_module(void)
+{
+ tcf_unregister_action(&act_mpls_ops, &mpls_net_ops);
+}
+
+module_init(mpls_init_module);
+module_exit(mpls_cleanup_module);
+
+MODULE_AUTHOR("Netronome Systems <oss-drivers@netronome.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MPLS manipulation actions");
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v6 3/5] net: core: add MPLS update core helper and use in OvS
From: John Hurley @ 2019-07-04 14:16 UTC (permalink / raw)
To: netdev
Cc: davem, jiri, xiyou.wangcong, dsahern, willemdebruijn.kernel,
dcaratti, simon.horman, jakub.kicinski, oss-drivers, John Hurley
In-Reply-To: <1562249802-24937-1-git-send-email-john.hurley@netronome.com>
Open vSwitch allows the updating of an existing MPLS header on a packet.
In preparation for supporting similar functionality in TC, move this to a
common skb helper function.
Signed-off-by: John Hurley <john.hurley@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
---
include/linux/skbuff.h | 1 +
net/core/skbuff.c | 33 +++++++++++++++++++++++++++++++++
net/openvswitch/actions.c | 13 +++----------
3 files changed, 37 insertions(+), 10 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 89d5c43..1545c4c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3448,6 +3448,7 @@ int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto);
int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto);
+int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse);
struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
gfp_t gfp);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index ce30989..46da15c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -5433,6 +5433,39 @@ int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto)
EXPORT_SYMBOL_GPL(skb_mpls_pop);
/**
+ * skb_mpls_update_lse() - modify outermost MPLS header and update csum
+ *
+ * @skb: buffer
+ * @mpls_lse: new MPLS label stack entry to update to
+ *
+ * Expects skb->data at mac header.
+ *
+ * Returns 0 on success, -errno otherwise.
+ */
+int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse)
+{
+ int err;
+
+ if (unlikely(!eth_p_mpls(skb->protocol)))
+ return -EINVAL;
+
+ err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
+ if (unlikely(err))
+ return err;
+
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ __be32 diff[] = { ~mpls_hdr(skb)->label_stack_entry, mpls_lse };
+
+ skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
+ }
+
+ mpls_hdr(skb)->label_stack_entry = mpls_lse;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(skb_mpls_update_lse);
+
+/**
* alloc_skb_with_frags - allocate skb with page frags
*
* @header_len: size of linear part
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 62715bb..3572e11 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -193,19 +193,12 @@ static int set_mpls(struct sk_buff *skb, struct sw_flow_key *flow_key,
__be32 lse;
int err;
- err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
- if (unlikely(err))
- return err;
-
stack = mpls_hdr(skb);
lse = OVS_MASKED(stack->label_stack_entry, *mpls_lse, *mask);
- if (skb->ip_summed == CHECKSUM_COMPLETE) {
- __be32 diff[] = { ~(stack->label_stack_entry), lse };
-
- skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
- }
+ err = skb_mpls_update_lse(skb, lse);
+ if (err)
+ return err;
- stack->label_stack_entry = lse;
flow_key->mpls.top_lse = lse;
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v6 2/5] net: core: move pop MPLS functionality from OvS to core helper
From: John Hurley @ 2019-07-04 14:16 UTC (permalink / raw)
To: netdev
Cc: davem, jiri, xiyou.wangcong, dsahern, willemdebruijn.kernel,
dcaratti, simon.horman, jakub.kicinski, oss-drivers, John Hurley
In-Reply-To: <1562249802-24937-1-git-send-email-john.hurley@netronome.com>
Open vSwitch provides code to pop an MPLS header to a packet. In
preparation for supporting this in TC, move the pop code to an skb helper
that can be reused.
Remove the, now unused, update_ethertype static function from OvS.
Signed-off-by: John Hurley <john.hurley@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
---
include/linux/skbuff.h | 1 +
net/core/skbuff.c | 42 ++++++++++++++++++++++++++++++++++++++++++
net/openvswitch/actions.c | 37 ++-----------------------------------
3 files changed, 45 insertions(+), 35 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 0112256..89d5c43 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3447,6 +3447,7 @@ int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci);
int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto);
+int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto);
struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
gfp_t gfp);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f1d1e47..ce30989 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -5391,6 +5391,48 @@ int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto)
EXPORT_SYMBOL_GPL(skb_mpls_push);
/**
+ * skb_mpls_pop() - pop the outermost MPLS header
+ *
+ * @skb: buffer
+ * @next_proto: ethertype of header after popped MPLS header
+ *
+ * Expects skb->data at mac header.
+ *
+ * Returns 0 on success, -errno otherwise.
+ */
+int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto)
+{
+ int err;
+
+ if (unlikely(!eth_p_mpls(skb->protocol)))
+ return -EINVAL;
+
+ err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
+ if (unlikely(err))
+ return err;
+
+ skb_postpull_rcsum(skb, mpls_hdr(skb), MPLS_HLEN);
+ memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb),
+ skb->mac_len);
+
+ __skb_pull(skb, MPLS_HLEN);
+ skb_reset_mac_header(skb);
+ skb_set_network_header(skb, skb->mac_len);
+
+ if (skb->dev && skb->dev->type == ARPHRD_ETHER) {
+ struct ethhdr *hdr;
+
+ /* use mpls_hdr() to get ethertype to account for VLANs. */
+ hdr = (struct ethhdr *)((void *)mpls_hdr(skb) - ETH_HLEN);
+ skb_mod_eth_type(skb, hdr, next_proto);
+ }
+ skb->protocol = next_proto;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(skb_mpls_pop);
+
+/**
* alloc_skb_with_frags - allocate skb with page frags
*
* @header_len: size of linear part
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index a9a6c9c..62715bb 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -160,18 +160,6 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
struct sw_flow_key *key,
const struct nlattr *attr, int len);
-static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr,
- __be16 ethertype)
-{
- if (skb->ip_summed == CHECKSUM_COMPLETE) {
- __be16 diff[] = { ~(hdr->h_proto), ethertype };
-
- skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
- }
-
- hdr->h_proto = ethertype;
-}
-
static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
const struct ovs_action_push_mpls *mpls)
{
@@ -190,31 +178,10 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
{
int err;
- err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
- if (unlikely(err))
+ err = skb_mpls_pop(skb, ethertype);
+ if (err)
return err;
- skb_postpull_rcsum(skb, mpls_hdr(skb), MPLS_HLEN);
-
- memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb),
- skb->mac_len);
-
- __skb_pull(skb, MPLS_HLEN);
- skb_reset_mac_header(skb);
- skb_set_network_header(skb, skb->mac_len);
-
- if (ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET) {
- struct ethhdr *hdr;
-
- /* mpls_hdr() is used to locate the ethertype field correctly in the
- * presence of VLAN tags.
- */
- hdr = (struct ethhdr *)((void *)mpls_hdr(skb) - ETH_HLEN);
- update_ethertype(skb, hdr, ethertype);
- }
- if (eth_p_mpls(skb->protocol))
- skb->protocol = ethertype;
-
invalidate_flow_key(key);
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v6 1/5] net: core: move push MPLS functionality from OvS to core helper
From: John Hurley @ 2019-07-04 14:16 UTC (permalink / raw)
To: netdev
Cc: davem, jiri, xiyou.wangcong, dsahern, willemdebruijn.kernel,
dcaratti, simon.horman, jakub.kicinski, oss-drivers, John Hurley
In-Reply-To: <1562249802-24937-1-git-send-email-john.hurley@netronome.com>
Open vSwitch provides code to push an MPLS header to a packet. In
preparation for supporting this in TC, move the push code to an skb helper
that can be reused.
Signed-off-by: John Hurley <john.hurley@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
---
include/linux/skbuff.h | 1 +
net/core/skbuff.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++
net/openvswitch/actions.c | 31 +++--------------------
3 files changed, 69 insertions(+), 27 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b5d427b..0112256 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3446,6 +3446,7 @@ int skb_ensure_writable(struct sk_buff *skb, int write_len);
int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci);
int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
+int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto);
struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
gfp_t gfp);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5323441..f1d1e47 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -66,6 +66,7 @@
#include <net/checksum.h>
#include <net/ip6_checksum.h>
#include <net/xfrm.h>
+#include <net/mpls.h>
#include <linux/uaccess.h>
#include <trace/events/skb.h>
@@ -5326,6 +5327,69 @@ int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
}
EXPORT_SYMBOL(skb_vlan_push);
+/* Update the ethertype of hdr and the skb csum value if required. */
+static void skb_mod_eth_type(struct sk_buff *skb, struct ethhdr *hdr,
+ __be16 ethertype)
+{
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+ __be16 diff[] = { ~hdr->h_proto, ethertype };
+
+ skb->csum = csum_partial((char *)diff, sizeof(diff), skb->csum);
+ }
+
+ hdr->h_proto = ethertype;
+}
+
+/**
+ * skb_mpls_push() - push a new MPLS header after the mac header
+ *
+ * @skb: buffer
+ * @mpls_lse: MPLS label stack entry to push
+ * @mpls_proto: ethertype of the new MPLS header (expects 0x8847 or 0x8848)
+ *
+ * Expects skb->data at mac header.
+ *
+ * Returns 0 on success, -errno otherwise.
+ */
+int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto)
+{
+ struct mpls_shim_hdr *lse;
+ int err;
+
+ if (unlikely(!eth_p_mpls(mpls_proto)))
+ return -EINVAL;
+
+ /* Networking stack does not allow simultaneous Tunnel and MPLS GSO. */
+ if (skb->encapsulation)
+ return -EINVAL;
+
+ err = skb_cow_head(skb, MPLS_HLEN);
+ if (unlikely(err))
+ return err;
+
+ if (!skb->inner_protocol) {
+ skb_set_inner_network_header(skb, skb->mac_len);
+ skb_set_inner_protocol(skb, skb->protocol);
+ }
+
+ skb_push(skb, MPLS_HLEN);
+ memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
+ skb->mac_len);
+ skb_reset_mac_header(skb);
+ skb_set_network_header(skb, skb->mac_len);
+
+ lse = mpls_hdr(skb);
+ lse->label_stack_entry = mpls_lse;
+ skb_postpush_rcsum(skb, lse, MPLS_HLEN);
+
+ if (skb->dev && skb->dev->type == ARPHRD_ETHER)
+ skb_mod_eth_type(skb, eth_hdr(skb), mpls_proto);
+ skb->protocol = mpls_proto;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(skb_mpls_push);
+
/**
* alloc_skb_with_frags - allocate skb with page frags
*
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index bd13146..a9a6c9c 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -175,34 +175,11 @@ static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr,
static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
const struct ovs_action_push_mpls *mpls)
{
- struct mpls_shim_hdr *new_mpls_lse;
-
- /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */
- if (skb->encapsulation)
- return -ENOTSUPP;
-
- if (skb_cow_head(skb, MPLS_HLEN) < 0)
- return -ENOMEM;
-
- if (!skb->inner_protocol) {
- skb_set_inner_network_header(skb, skb->mac_len);
- skb_set_inner_protocol(skb, skb->protocol);
- }
-
- skb_push(skb, MPLS_HLEN);
- memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
- skb->mac_len);
- skb_reset_mac_header(skb);
- skb_set_network_header(skb, skb->mac_len);
-
- new_mpls_lse = mpls_hdr(skb);
- new_mpls_lse->label_stack_entry = mpls->mpls_lse;
-
- skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);
+ int err;
- if (ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET)
- update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype);
- skb->protocol = mpls->mpls_ethertype;
+ err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype);
+ if (err)
+ return err;
invalidate_flow_key(key);
return 0;
--
2.7.4
^ permalink raw reply related
* [PATCH net-next v6 0/5] Add MPLS actions to TC
From: John Hurley @ 2019-07-04 14:16 UTC (permalink / raw)
To: netdev
Cc: davem, jiri, xiyou.wangcong, dsahern, willemdebruijn.kernel,
dcaratti, simon.horman, jakub.kicinski, oss-drivers, John Hurley
This patchset introduces a new TC action module that allows the
manipulation of the MPLS headers of packets. The code impliments
functionality including push, pop, and modify.
Also included are tests for the new funtionality. Note that these will
require iproute2 changes to be submitted soon.
NOTE: these patches are applied to net-next along with the patch:
[PATCH net 1/1] net: openvswitch: fix csum updates for MPLS actions
This patch has been accepted into net but, at time of posting, is not yet
in net-next.
v5-v6:
- add CONFIG_NET_ACT_MPLS to tc-testing config file - patch 5
(Davide Caratti)
v4-v5:
- move mpls_hdr() call to after skb_ensure_writable - patch 3
(Willem de Bruijn)
- move mpls_dec_ttl to helper - patch 4 (Willem de Bruijn)
- add iproute2 usage example to commit msg - patch 4 (David Ahern)
- align label validation with mpls core code - patch 4 (David Ahern)
- improve extack message for no proto in mpls pop - patch 4 (David Ahern)
v3-v4:
- refactor and reuse OvS code (Cong Wang)
- use csum API rather than skb_post*rscum to update skb->csum (Cong Wang)
- remove unnecessary warning (Cong Wang)
- add comments to uapi attributes (David Ahern)
- set strict type policy check for TCA_MPLS_UNSPEC (David Ahern)
- expand/improve extack messages (David Ahern)
- add option to manually set BOS
v2-v3:
- remove a few unnecessary line breaks (Jiri Pirko)
- retract hw offload patch from set (resubmit with driver changes) (Jiri)
v1->v2:
- ensure TCA_ID_MPLS does not conflict with TCA_ID_CTINFO (Davide Caratti)
John Hurley (5):
net: core: move push MPLS functionality from OvS to core helper
net: core: move pop MPLS functionality from OvS to core helper
net: core: add MPLS update core helper and use in OvS
net: sched: add mpls manipulation actions to TC
selftests: tc-tests: actions: add MPLS tests
include/linux/skbuff.h | 4 +
include/net/tc_act/tc_mpls.h | 30 +
include/uapi/linux/pkt_cls.h | 3 +-
include/uapi/linux/tc_act/tc_mpls.h | 33 +
net/core/skbuff.c | 169 +++++
net/openvswitch/actions.c | 81 +-
net/sched/Kconfig | 11 +
net/sched/Makefile | 1 +
net/sched/act_mpls.c | 406 +++++++++++
tools/testing/selftests/tc-testing/config | 1 +
.../tc-testing/tc-tests/actions/mpls.json | 812 +++++++++++++++++++++
11 files changed, 1478 insertions(+), 73 deletions(-)
create mode 100644 include/net/tc_act/tc_mpls.h
create mode 100644 include/uapi/linux/tc_act/tc_mpls.h
create mode 100644 net/sched/act_mpls.c
create mode 100644 tools/testing/selftests/tc-testing/tc-tests/actions/mpls.json
--
2.7.4
^ permalink raw reply
* [PATCH] net: netsec: Sync dma for device on buffer allocation
From: Ilias Apalodimas @ 2019-07-04 14:11 UTC (permalink / raw)
To: netdev, jaswinder.singh; +Cc: ard.biesheuvel, arnd, Ilias Apalodimas
Quoting Arnd,
We have to do a sync_single_for_device /somewhere/ before the
buffer is given to the device. On a non-cache-coherent machine with
a write-back cache, there may be dirty cache lines that get written back
after the device DMA's data into it (e.g. from a previous memset
from before the buffer got freed), so you absolutely need to flush any
dirty cache lines on it first.
Since the coherency is configurable in this device make sure we cover
all configurations by explicitly syncing the allocated buffer for the
device before refilling it's descriptors
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
drivers/net/ethernet/socionext/netsec.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 5544a722543f..e05a7191336d 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -727,6 +727,7 @@ static void *netsec_alloc_rx_data(struct netsec_priv *priv,
{
struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
+ enum dma_data_direction dma_dir;
struct page *page;
page = page_pool_dev_alloc_pages(dring->page_pool);
@@ -742,6 +743,10 @@ static void *netsec_alloc_rx_data(struct netsec_priv *priv,
* cases and reserve enough space for headroom + skb_shared_info
*/
*desc_len = PAGE_SIZE - NETSEC_RX_BUF_NON_DATA;
+ dma_dir = page_pool_get_dma_dir(dring->page_pool);
+ dma_sync_single_for_device(priv->dev,
+ *dma_handle - NETSEC_RXBUF_HEADROOM,
+ PAGE_SIZE, dma_dir);
return page_address(page);
}
--
2.20.1
^ permalink raw reply related
* [PATCH net-next 1/9] net: hns3: enable broadcast promisc mode when initializing VF
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Jian Shen, Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
For revision 0x20, the broadcast promisc is enabled by firmware,
it's unnecessary to enable it when initializing VF.
For revision 0x21, it's necessary to enable broadcast promisc mode
when initializing or re-initializing VF, otherwise, it will be
unable to send and receive promisc packets.
Fixes: f01f5559cac8 ("net: hns3: don't allow vf to enable promisc mode")
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index 42006cc..ff7e8cb 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -2589,6 +2589,12 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
return ret;
}
+ if (pdev->revision >= 0x21) {
+ ret = hclgevf_set_promisc_mode(hdev, true);
+ if (ret)
+ return ret;
+ }
+
dev_info(&hdev->pdev->dev, "Reset done\n");
return 0;
@@ -2668,9 +2674,11 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
* firmware makes sure broadcast packets can be accepted.
* For revision 0x21, default to enable broadcast promisc mode.
*/
- ret = hclgevf_set_promisc_mode(hdev, true);
- if (ret)
- goto err_config;
+ if (pdev->revision >= 0x21) {
+ ret = hclgevf_set_promisc_mode(hdev, true);
+ if (ret)
+ goto err_config;
+ }
/* Initialize RSS for this VF */
ret = hclgevf_rss_init_hw(hdev);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 3/9] net: hns3: fix port capbility updating issue
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Jian Shen, Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
Currently, the driver queries the media port information, and
updates the port capability periodically. But it sets an error
mac->speed_type value, which stops update port capability.
Fixes: 88d10bd6f730 ("net: hns3: add support for multiple media type")
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 2ecc10a..94c94e1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -2663,6 +2663,7 @@ static int hclge_get_sfp_info(struct hclge_dev *hdev, struct hclge_mac *mac)
mac->speed_ability = le32_to_cpu(resp->speed_ability);
mac->autoneg = resp->autoneg;
mac->support_autoneg = resp->autoneg_ability;
+ mac->speed_type = QUERY_ACTIVE_SPEED;
if (!resp->active_fec)
mac->fec_mode = 0;
else
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 2/9] net: hns3: fix flow control configure issue for fibre port
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Jian Shen, Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
Flow control autoneg is unsupported for fibre port. It takes no
effect for flow control when restart autoneg. This patch fixes
it, return -EOPNOTSUPP when user tries to enable flow control
autoneg.
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 62c6263..2ecc10a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -8179,8 +8179,9 @@ static void hclge_get_pauseparam(struct hnae3_handle *handle, u32 *auto_neg,
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back;
+ struct phy_device *phydev = hdev->hw.mac.phydev;
- *auto_neg = hclge_get_autoneg(handle);
+ *auto_neg = phydev ? hclge_get_autoneg(handle) : 0;
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) {
*rx_en = 0;
@@ -8211,11 +8212,13 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
struct phy_device *phydev = hdev->hw.mac.phydev;
u32 fc_autoneg;
- fc_autoneg = hclge_get_autoneg(handle);
- if (auto_neg != fc_autoneg) {
- dev_info(&hdev->pdev->dev,
- "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
- return -EOPNOTSUPP;
+ if (phydev) {
+ fc_autoneg = hclge_get_autoneg(handle);
+ if (auto_neg != fc_autoneg) {
+ dev_info(&hdev->pdev->dev,
+ "To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
+ return -EOPNOTSUPP;
+ }
}
if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) {
@@ -8226,16 +8229,13 @@ static int hclge_set_pauseparam(struct hnae3_handle *handle, u32 auto_neg,
hclge_set_flowctrl_adv(hdev, rx_en, tx_en);
- if (!fc_autoneg)
+ if (!auto_neg)
return hclge_cfg_pauseparam(hdev, rx_en, tx_en);
if (phydev)
return phy_start_aneg(phydev);
- if (hdev->pdev->revision == 0x20)
- return -EOPNOTSUPP;
-
- return hclge_restart_autoneg(handle);
+ return -EOPNOTSUPP;
}
static void hclge_get_ksettings_an_result(struct hnae3_handle *handle,
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 7/9] net: hns3: add default value for tc_size and tc_offset
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Peng Li <lipeng321@huawei.com>
This patch adds default value for tc_size and tc_offset, or it may
get random value and used later.
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 94c94e1..2abd5f5 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -4092,11 +4092,11 @@ int hclge_rss_init_hw(struct hclge_dev *hdev)
struct hclge_vport *vport = hdev->vport;
u8 *rss_indir = vport[0].rss_indirection_tbl;
u16 rss_size = vport[0].alloc_rss_size;
+ u16 tc_offset[HCLGE_MAX_TC_NUM] = {0};
+ u16 tc_size[HCLGE_MAX_TC_NUM] = {0};
u8 *key = vport[0].rss_hash_key;
u8 hfunc = vport[0].rss_algo;
- u16 tc_offset[HCLGE_MAX_TC_NUM];
u16 tc_valid[HCLGE_MAX_TC_NUM];
- u16 tc_size[HCLGE_MAX_TC_NUM];
u16 roundup_size;
unsigned int i;
int ret;
@@ -9036,12 +9036,12 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
{
struct hclge_vport *vport = hclge_get_vport(handle);
struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+ u16 tc_offset[HCLGE_MAX_TC_NUM] = {0};
struct hclge_dev *hdev = vport->back;
+ u16 tc_size[HCLGE_MAX_TC_NUM] = {0};
int cur_rss_size = kinfo->rss_size;
int cur_tqps = kinfo->num_tqps;
- u16 tc_offset[HCLGE_MAX_TC_NUM];
u16 tc_valid[HCLGE_MAX_TC_NUM];
- u16 tc_size[HCLGE_MAX_TC_NUM];
u16 roundup_size;
u32 *rss_indir;
unsigned int i;
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 9/9] net: hns3: set maximum length to resp_data_len for exceptional case
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Peng Li <lipeng321@huawei.com>
If HCLGE_MBX_MAX_RESP_DATA_SIZE > HCLGE_MBX_MAX_RESP_DATA_SIZE,
the memcpy will cause out of memory. So this patch just set
resp_data_len to the maximum length for this case.
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
index 9adeba9..a38ac7c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
@@ -29,6 +29,10 @@ static int hclge_gen_resp_to_vf(struct hclge_vport *vport,
"PF fail to gen resp to VF len %d exceeds max len %d\n",
resp_data_len,
HCLGE_MBX_MAX_RESP_DATA_SIZE);
+ /* If resp_data_len is too long, set the value to max length
+ * and return the msg to VF
+ */
+ resp_data_len = HCLGE_MBX_MAX_RESP_DATA_SIZE;
}
hclge_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_PF_TO_VF, false);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 8/9] net: hns3: bitwise operator should use unsigned type
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Yonglong Liu, Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Yonglong Liu <liuyonglong@huawei.com>
There are some bitwise operator used signed type, this patch fixes
them with unsigned type.
Signed-off-by: Yonglong Liu <liuyonglong@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 9 +++--
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 +-
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 43 ++++++++++++----------
3 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index ab5a339..310afa70 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -951,8 +951,9 @@ static int hns3_set_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
static void hns3_set_txbd_baseinfo(u16 *bdtp_fe_sc_vld_ra_ri, int frag_end)
{
/* Config bd buffer end */
- hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_FE_B, !!frag_end);
- hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B, 1);
+ if (!!frag_end)
+ hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_FE_B, 1U);
+ hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B, 1U);
}
static int hns3_fill_desc_vtags(struct sk_buff *skb,
@@ -2575,7 +2576,7 @@ static bool hns3_parse_vlan_tag(struct hns3_enet_ring *ring,
}
}
-static int hns3_alloc_skb(struct hns3_enet_ring *ring, int length,
+static int hns3_alloc_skb(struct hns3_enet_ring *ring, unsigned int length,
unsigned char *va)
{
#define HNS3_NEED_ADD_FRAG 1
@@ -2818,8 +2819,8 @@ static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
struct sk_buff *skb = ring->skb;
struct hns3_desc_cb *desc_cb;
struct hns3_desc *desc;
+ unsigned int length;
u32 bd_base_info;
- int length;
int ret;
desc = &ring->desc[ring->next_to_clean];
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
index a2b73d6..848b866 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
@@ -610,7 +610,7 @@ static inline bool hns3_nic_resetting(struct net_device *netdev)
#define hnae3_buf_size(_ring) ((_ring)->buf_size)
#define hnae3_page_order(_ring) (get_order(hnae3_buf_size(_ring)))
-#define hnae3_page_size(_ring) (PAGE_SIZE << hnae3_page_order(_ring))
+#define hnae3_page_size(_ring) (PAGE_SIZE << (u32)hnae3_page_order(_ring))
/* iterator for handling rings in ring group */
#define hns3_for_each_ring(pos, head) \
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 2abd5f5..3fde5471 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -1360,8 +1360,9 @@ static int hclge_map_tqps_to_func(struct hclge_dev *hdev, u16 func_id,
req = (struct hclge_tqp_map_cmd *)desc.data;
req->tqp_id = cpu_to_le16(tqp_pid);
req->tqp_vf = func_id;
- req->tqp_flag = !is_pf << HCLGE_TQP_MAP_TYPE_B |
- 1 << HCLGE_TQP_MAP_EN_B;
+ req->tqp_flag = 1U << HCLGE_TQP_MAP_EN_B;
+ if (!is_pf)
+ req->tqp_flag |= 1U << HCLGE_TQP_MAP_TYPE_B;
req->tqp_vid = cpu_to_le16(tqp_vid);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -2320,7 +2321,8 @@ static int hclge_set_autoneg_en(struct hclge_dev *hdev, bool enable)
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_AN_MODE, false);
req = (struct hclge_config_auto_neg_cmd *)desc.data;
- hnae3_set_bit(flag, HCLGE_MAC_CFG_AN_EN_B, !!enable);
+ if (enable)
+ hnae3_set_bit(flag, HCLGE_MAC_CFG_AN_EN_B, 1U);
req->cfg_an_cmd_flag = cpu_to_le32(flag);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -5935,20 +5937,20 @@ static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_MAC_MODE, false);
- hnae3_set_bit(loop_en, HCLGE_MAC_TX_EN_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_RX_EN_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_PAD_TX_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_PAD_RX_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_1588_TX_B, 0);
- hnae3_set_bit(loop_en, HCLGE_MAC_1588_RX_B, 0);
- hnae3_set_bit(loop_en, HCLGE_MAC_APP_LP_B, 0);
- hnae3_set_bit(loop_en, HCLGE_MAC_LINE_LP_B, 0);
- hnae3_set_bit(loop_en, HCLGE_MAC_FCS_TX_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_RX_FCS_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_RX_FCS_STRIP_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B, enable);
- hnae3_set_bit(loop_en, HCLGE_MAC_TX_UNDER_MIN_ERR_B, enable);
+
+ if (enable) {
+ hnae3_set_bit(loop_en, HCLGE_MAC_TX_EN_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_RX_EN_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_PAD_TX_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_PAD_RX_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_FCS_TX_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_RX_FCS_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_RX_FCS_STRIP_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_TX_OVERSIZE_TRUNCATE_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_RX_OVERSIZE_TRUNCATE_B, 1U);
+ hnae3_set_bit(loop_en, HCLGE_MAC_TX_UNDER_MIN_ERR_B, 1U);
+ }
+
req->txrx_pad_fcs_loop_en = cpu_to_le32(loop_en);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -6310,8 +6312,8 @@ static int hclge_update_desc_vfid(struct hclge_desc *desc, int vfid, bool clr)
{
#define HCLGE_VF_NUM_IN_FIRST_DESC 192
- int word_num;
- int bit_num;
+ unsigned int word_num;
+ unsigned int bit_num;
if (vfid > 255 || vfid < 0)
return -EIO;
@@ -7972,7 +7974,8 @@ static int hclge_send_reset_tqp_cmd(struct hclge_dev *hdev, u16 queue_id,
req = (struct hclge_reset_tqp_queue_cmd *)desc.data;
req->tqp_id = cpu_to_le16(queue_id & HCLGE_RING_ID_MASK);
- hnae3_set_bit(req->reset_req, HCLGE_TQP_RESET_B, enable);
+ if (enable)
+ hnae3_set_bit(req->reset_req, HCLGE_TQP_RESET_B, 1U);
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) {
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 4/9] net: hns3: add all IMP return code
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Peng Li <lipeng321@huawei.com>
Currently, the HNS3 driver just defines part of IMP return code,
This patch supplements all the remaining IMP return code, and adds
a function to convert this code to the error number.
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 43 +++++++++++++++++-----
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 8 ++++
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c | 38 ++++++++++++++++---
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 14 +++++--
4 files changed, 85 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
index 667c3be..22f6acd 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -188,12 +188,43 @@ static bool hclge_is_special_opcode(u16 opcode)
return false;
}
+static int hclge_cmd_convert_err_code(u16 desc_ret)
+{
+ switch (desc_ret) {
+ case HCLGE_CMD_EXEC_SUCCESS:
+ return 0;
+ case HCLGE_CMD_NO_AUTH:
+ return -EPERM;
+ case HCLGE_CMD_NOT_SUPPORTED:
+ return -EOPNOTSUPP;
+ case HCLGE_CMD_QUEUE_FULL:
+ return -EXFULL;
+ case HCLGE_CMD_NEXT_ERR:
+ return -ENOSR;
+ case HCLGE_CMD_UNEXE_ERR:
+ return -ENOTBLK;
+ case HCLGE_CMD_PARA_ERR:
+ return -EINVAL;
+ case HCLGE_CMD_RESULT_ERR:
+ return -ERANGE;
+ case HCLGE_CMD_TIMEOUT:
+ return -ETIME;
+ case HCLGE_CMD_HILINK_ERR:
+ return -ENOLINK;
+ case HCLGE_CMD_QUEUE_ILLEGAL:
+ return -ENXIO;
+ case HCLGE_CMD_INVALID:
+ return -EBADR;
+ default:
+ return -EIO;
+ }
+}
+
static int hclge_cmd_check_retval(struct hclge_hw *hw, struct hclge_desc *desc,
int num, int ntc)
{
u16 opcode, desc_ret;
int handle;
- int retval;
opcode = le16_to_cpu(desc[0].opcode);
for (handle = 0; handle < num; handle++) {
@@ -207,17 +238,9 @@ static int hclge_cmd_check_retval(struct hclge_hw *hw, struct hclge_desc *desc,
else
desc_ret = le16_to_cpu(desc[0].retval);
- if (desc_ret == HCLGE_CMD_EXEC_SUCCESS)
- retval = 0;
- else if (desc_ret == HCLGE_CMD_NO_AUTH)
- retval = -EPERM;
- else if (desc_ret == HCLGE_CMD_NOT_SUPPORTED)
- retval = -EOPNOTSUPP;
- else
- retval = -EIO;
hw->cmq.last_status = desc_ret;
- return retval;
+ return hclge_cmd_convert_err_code(desc_ret);
}
/**
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index d23ab2b..96840d8 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -41,6 +41,14 @@ enum hclge_cmd_return_status {
HCLGE_CMD_NO_AUTH = 1,
HCLGE_CMD_NOT_SUPPORTED = 2,
HCLGE_CMD_QUEUE_FULL = 3,
+ HCLGE_CMD_NEXT_ERR = 4,
+ HCLGE_CMD_UNEXE_ERR = 5,
+ HCLGE_CMD_PARA_ERR = 6,
+ HCLGE_CMD_RESULT_ERR = 7,
+ HCLGE_CMD_TIMEOUT = 8,
+ HCLGE_CMD_HILINK_ERR = 9,
+ HCLGE_CMD_QUEUE_ILLEGAL = 10,
+ HCLGE_CMD_INVALID = 11,
};
enum hclge_cmd_status {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
index 31db6d6..652b796 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
@@ -177,6 +177,38 @@ void hclgevf_cmd_setup_basic_desc(struct hclgevf_desc *desc,
desc->flag &= cpu_to_le16(~HCLGEVF_CMD_FLAG_WR);
}
+static int hclgevf_cmd_convert_err_code(u16 desc_ret)
+{
+ switch (desc_ret) {
+ case HCLGEVF_CMD_EXEC_SUCCESS:
+ return 0;
+ case HCLGEVF_CMD_NO_AUTH:
+ return -EPERM;
+ case HCLGEVF_CMD_NOT_SUPPORTED:
+ return -EOPNOTSUPP;
+ case HCLGEVF_CMD_QUEUE_FULL:
+ return -EXFULL;
+ case HCLGEVF_CMD_NEXT_ERR:
+ return -ENOSR;
+ case HCLGEVF_CMD_UNEXE_ERR:
+ return -ENOTBLK;
+ case HCLGEVF_CMD_PARA_ERR:
+ return -EINVAL;
+ case HCLGEVF_CMD_RESULT_ERR:
+ return -ERANGE;
+ case HCLGEVF_CMD_TIMEOUT:
+ return -ETIME;
+ case HCLGEVF_CMD_HILINK_ERR:
+ return -ENOLINK;
+ case HCLGEVF_CMD_QUEUE_ILLEGAL:
+ return -ENXIO;
+ case HCLGEVF_CMD_INVALID:
+ return -EBADR;
+ default:
+ return -EIO;
+ }
+}
+
/* hclgevf_cmd_send - send command to command queue
* @hw: pointer to the hw struct
* @desc: prefilled descriptor for describing the command
@@ -259,11 +291,7 @@ int hclgevf_cmd_send(struct hclgevf_hw *hw, struct hclgevf_desc *desc, int num)
else
retval = le16_to_cpu(desc[0].retval);
- if ((enum hclgevf_cmd_return_status)retval ==
- HCLGEVF_CMD_EXEC_SUCCESS)
- status = 0;
- else
- status = -EIO;
+ status = hclgevf_cmd_convert_err_code(retval);
hw->cmq.last_status = (enum hclgevf_cmd_status)retval;
ntc++;
handle++;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h
index 47030b4..127a434 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h
@@ -46,9 +46,17 @@ struct hclgevf_cmq_ring {
enum hclgevf_cmd_return_status {
HCLGEVF_CMD_EXEC_SUCCESS = 0,
- HCLGEVF_CMD_NO_AUTH = 1,
- HCLGEVF_CMD_NOT_EXEC = 2,
- HCLGEVF_CMD_QUEUE_FULL = 3,
+ HCLGEVF_CMD_NO_AUTH = 1,
+ HCLGEVF_CMD_NOT_SUPPORTED = 2,
+ HCLGEVF_CMD_QUEUE_FULL = 3,
+ HCLGEVF_CMD_NEXT_ERR = 4,
+ HCLGEVF_CMD_UNEXE_ERR = 5,
+ HCLGEVF_CMD_PARA_ERR = 6,
+ HCLGEVF_CMD_RESULT_ERR = 7,
+ HCLGEVF_CMD_TIMEOUT = 8,
+ HCLGEVF_CMD_HILINK_ERR = 9,
+ HCLGEVF_CMD_QUEUE_ILLEGAL = 10,
+ HCLGEVF_CMD_INVALID = 11,
};
enum hclgevf_cmd_status {
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 6/9] net: hns3: check msg_data before memcpy in hclgevf_send_mbx_msg
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Weihang Li, Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Weihang Li <liweihang@hisilicon.com>
The value of msg_data may be NULL in some cases, which will cause
errors reported by some compiler.
So this patch adds a check to fix it.
Signed-off-by: Weihang Li <liweihang@hisilicon.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
index 30f2e93..f60b80b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
@@ -102,7 +102,8 @@ int hclgevf_send_mbx_msg(struct hclgevf_dev *hdev, u16 code, u16 subcode,
~HCLGE_MBX_NEED_RESP_BIT;
req->msg[0] = code;
req->msg[1] = subcode;
- memcpy(&req->msg[2], msg_data, msg_len);
+ if (msg_data)
+ memcpy(&req->msg[2], msg_data, msg_len);
/* synchronous send */
if (need_resp) {
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 5/9] net: hns3: set default value for param "type" in hclgevf_bind_ring_to_vector
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Peng Li, Huazhong Tan
In-Reply-To: <1562249068-40176-1-git-send-email-tanhuazhong@huawei.com>
From: Peng Li <lipeng321@huawei.com>
The value of param type is always not changed in
hclgevf_bind_ring_to_vector, move the assignment to
front of "for {}" can reduce the redundant assignment.
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index ff7e8cb..a13a0e1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -994,6 +994,8 @@ static int hclgevf_bind_ring_to_vector(struct hnae3_handle *handle, bool en,
u8 type;
req = (struct hclge_mbx_vf_to_pf_cmd *)desc.data;
+ type = en ? HCLGE_MBX_MAP_RING_TO_VECTOR :
+ HCLGE_MBX_UNMAP_RING_TO_VECTOR;
for (node = ring_chain; node; node = node->next) {
int idx_offset = HCLGE_MBX_RING_MAP_BASIC_MSG_NUM +
@@ -1003,9 +1005,6 @@ static int hclgevf_bind_ring_to_vector(struct hnae3_handle *handle, bool en,
hclgevf_cmd_setup_basic_desc(&desc,
HCLGEVF_OPC_MBX_VF_TO_PF,
false);
- type = en ?
- HCLGE_MBX_MAP_RING_TO_VECTOR :
- HCLGE_MBX_UNMAP_RING_TO_VECTOR;
req->msg[0] = type;
req->msg[1] = vector_id;
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 0/9] net: hns3: some cleanups & bugfixes
From: Huazhong Tan @ 2019-07-04 14:04 UTC (permalink / raw)
To: davem
Cc: netdev, linux-kernel, salil.mehta, yisen.zhuang, linuxarm,
Huazhong Tan
This patch-set includes cleanups and bugfixes for
the HNS3 ethernet controller driver.
[patch 1/9] fixes VF's broadcast promisc mode not enabled after
initializing.
[patch 2/9] adds hints for fibre port not support flow control.
[patch 3/9] fixes a port capbility updating issue.
[patch 4/9 - 9/9] adds some cleanups for HNS3 driver.
Jian Shen (3):
net: hns3: enable broadcast promisc mode when initializing VF
net: hns3: fix flow control configure issue for fibre port
net: hns3: fix port capbility updating issue
Peng Li (4):
net: hns3: add all IMP return code
net: hns3: set default value for param "type" in
hclgevf_bind_ring_to_vector
net: hns3: add default value for tc_size and tc_offset
net: hns3: set maximum length to resp_data_len for exceptional case
Weihang Li (1):
net: hns3: check msg_data before memcpy in hclgevf_send_mbx_msg
Yonglong Liu (1):
net: hns3: bitwise operator should use unsigned type
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 9 +--
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 43 ++++++++++---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 8 +++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 74 ++++++++++++----------
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 4 ++
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c | 38 +++++++++--
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 14 +++-
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 19 ++++--
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c | 3 +-
10 files changed, 149 insertions(+), 65 deletions(-)
--
2.7.4
^ permalink raw reply
* Re: [PATCH v1 net-next] net: stmmac: enable clause 45 mdio support
From: Andrew Lunn @ 2019-07-04 13:54 UTC (permalink / raw)
To: Voon, Weifeng
Cc: David S. Miller, Maxime Coquelin, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, Jose Abreu, Giuseppe Cavallaro,
Florian Fainelli, Alexandre Torgue, biao huang, Ong, Boon Leong,
Kweh, Hock Leong
In-Reply-To: <D6759987A7968C4889FDA6FA91D5CBC81473862D@PGSMSX103.gar.corp.intel.com>
On Thu, Jul 04, 2019 at 06:05:23AM +0000, Voon, Weifeng wrote:
> > > > > @@ -155,22 +171,26 @@ static int stmmac_mdio_read(struct mii_bus
> > > > > *bus,
> > > > int phyaddr, int phyreg)
> > > > > struct stmmac_priv *priv = netdev_priv(ndev);
> > > > > unsigned int mii_address = priv->hw->mii.addr;
> > > > > unsigned int mii_data = priv->hw->mii.data;
> > > > > - u32 v;
> > > > > - int data;
> > > > > u32 value = MII_BUSY;
> > > > > + int data = 0;
> > > > > + u32 v;
> > > > >
> > > > > value |= (phyaddr << priv->hw->mii.addr_shift)
> > > > > & priv->hw->mii.addr_mask;
> > > > > value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw-
> > > > >mii.reg_mask;
> > > > > value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)
> > > > > & priv->hw->mii.clk_csr_mask;
> > > > > - if (priv->plat->has_gmac4)
> > > > > + if (priv->plat->has_gmac4) {
> > > > > value |= MII_GMAC4_READ;
> > > > > + if (phyreg & MII_ADDR_C45)
> > > > > + stmmac_mdio_c45_setup(priv, phyreg, &value, &data);
> > > > > + }
> > > > >
> > > > > if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v &
> > > > MII_BUSY),
> > > > > 100, 10000))
> > > > > return -EBUSY;
> > > > >
> > > > > + writel(data, priv->ioaddr + mii_data);
> > > >
> > > > That looks odd. Could you explain why it is needed.
> > > >
> > > > Thanks
> > > > Andrew
> > >
> > > Hi Andrew,
> > > This mdio c45 support needed to access DWC xPCS which is a Clause-45
> >
> > I mean it looks odd doing a write to the data register in the middle of
> > stmmac_mdio_read().
>
> MAC is using an indirect access to access mdio devices. In order to read,
> the driver needs to write into both mii_data and mii_address to select
> c45, read/write command, phy address, address to read, and etc.
Yes, that is all clear. The stmmac_mdio_c45_setup() does part of this
setup. There is also a write to mii_address which i snipped out when
replying. But why do you need to write to the data registers during a
read? C22 does not need this write. Are there some bits in the top of
the data register which are relevant to C45?
Thanks
Andrew
^ permalink raw reply
* Re: [net-next 1/3] ice: Initialize and register platform device to provide RDMA
From: Jason Gunthorpe @ 2019-07-04 13:53 UTC (permalink / raw)
To: Greg KH
Cc: Jeff Kirsher, davem@davemloft.net, dledford@redhat.com,
Tony Nguyen, netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
nhorman@redhat.com, sassmann@redhat.com, poswald@suse.com,
mustafa.ismail@intel.com, shiraz.saleem@intel.com, Dave Ertman,
Andrew Bowers
In-Reply-To: <20190704134612.GB10963@kroah.com>
On Thu, Jul 04, 2019 at 03:46:12PM +0200, Greg KH wrote:
> On Thu, Jul 04, 2019 at 12:48:29PM +0000, Jason Gunthorpe wrote:
> > On Thu, Jul 04, 2019 at 02:42:47PM +0200, Greg KH wrote:
> > > On Thu, Jul 04, 2019 at 12:37:33PM +0000, Jason Gunthorpe wrote:
> > > > On Thu, Jul 04, 2019 at 02:29:50PM +0200, Greg KH wrote:
> > > > > On Thu, Jul 04, 2019 at 12:16:41PM +0000, Jason Gunthorpe wrote:
> > > > > > On Wed, Jul 03, 2019 at 07:12:50PM -0700, Jeff Kirsher wrote:
> > > > > > > From: Tony Nguyen <anthony.l.nguyen@intel.com>
> > > > > > >
> > > > > > > The RDMA block does not advertise on the PCI bus or any other bus.
> > > > > > > Thus the ice driver needs to provide access to the RDMA hardware block
> > > > > > > via a virtual bus; utilize the platform bus to provide this access.
> > > > > > >
> > > > > > > This patch initializes the driver to support RDMA as well as creates
> > > > > > > and registers a platform device for the RDMA driver to register to. At
> > > > > > > this point the driver is fully initialized to register a platform
> > > > > > > driver, however, can not yet register as the ops have not been
> > > > > > > implemented.
> > > > > >
> > > > > > I think you need Greg's ack on all this driver stuff - particularly
> > > > > > that a platform_device is OK.
> > > > >
> > > > > A platform_device is almost NEVER ok.
> > > > >
> > > > > Don't abuse it, make a real device on a real bus. If you don't have a
> > > > > real bus and just need to create a device to hang other things off of,
> > > > > then use the virtual one, that's what it is there for.
> > > >
> > > > Ideally I'd like to see all the RDMA drivers that connect to ethernet
> > > > drivers use some similar scheme.
> > >
> > > Why? They should be attached to a "real" device, why make any up?
> >
> > ? A "real" device, like struct pci_device, can only bind to one
> > driver. How can we bind it concurrently to net, rdma, scsi, etc?
>
> MFD was designed for this very problem.
>
> > > > This is for a PCI device that plugs into multiple subsystems in the
> > > > kernel, ie it has net driver functionality, rdma functionality, some
> > > > even have SCSI functionality
> > >
> > > Sounds like a MFD device, why aren't you using that functionality
> > > instead?
> >
> > This was also my advice, but in another email Jeff says:
> >
> > MFD architecture was also considered, and we selected the simpler
> > platform model. Supporting a MFD architecture would require an
> > additional MFD core driver, individual platform netdev, RDMA function
> > drivers, and stripping a large portion of the netdev drivers into
> > MFD core. The sub-devices registered by MFD core for function
> > drivers are indeed platform devices.
>
> So, "mfd is too hard, let's abuse a platform device" is ok?
>
> People have been wanting to do MFD drivers for PCI devices for a long
> time, it's about time someone actually did the work for it, I bet it
> will not be all that complex if tiny embedded drivers can do it :)
Okay, sounds like a NAK to me. I'll drop these patches from the RDMA
patchworks and Jeff can work through the MFD stuff first.
Jason
^ permalink raw reply
* Re: [net-next 1/3] ice: Initialize and register platform device to provide RDMA
From: Greg KH @ 2019-07-04 13:46 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Jeff Kirsher, davem@davemloft.net, dledford@redhat.com,
Tony Nguyen, netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
nhorman@redhat.com, sassmann@redhat.com, poswald@suse.com,
mustafa.ismail@intel.com, shiraz.saleem@intel.com, Dave Ertman,
Andrew Bowers
In-Reply-To: <20190704124824.GK3401@mellanox.com>
On Thu, Jul 04, 2019 at 12:48:29PM +0000, Jason Gunthorpe wrote:
> On Thu, Jul 04, 2019 at 02:42:47PM +0200, Greg KH wrote:
> > On Thu, Jul 04, 2019 at 12:37:33PM +0000, Jason Gunthorpe wrote:
> > > On Thu, Jul 04, 2019 at 02:29:50PM +0200, Greg KH wrote:
> > > > On Thu, Jul 04, 2019 at 12:16:41PM +0000, Jason Gunthorpe wrote:
> > > > > On Wed, Jul 03, 2019 at 07:12:50PM -0700, Jeff Kirsher wrote:
> > > > > > From: Tony Nguyen <anthony.l.nguyen@intel.com>
> > > > > >
> > > > > > The RDMA block does not advertise on the PCI bus or any other bus.
> > > > > > Thus the ice driver needs to provide access to the RDMA hardware block
> > > > > > via a virtual bus; utilize the platform bus to provide this access.
> > > > > >
> > > > > > This patch initializes the driver to support RDMA as well as creates
> > > > > > and registers a platform device for the RDMA driver to register to. At
> > > > > > this point the driver is fully initialized to register a platform
> > > > > > driver, however, can not yet register as the ops have not been
> > > > > > implemented.
> > > > >
> > > > > I think you need Greg's ack on all this driver stuff - particularly
> > > > > that a platform_device is OK.
> > > >
> > > > A platform_device is almost NEVER ok.
> > > >
> > > > Don't abuse it, make a real device on a real bus. If you don't have a
> > > > real bus and just need to create a device to hang other things off of,
> > > > then use the virtual one, that's what it is there for.
> > >
> > > Ideally I'd like to see all the RDMA drivers that connect to ethernet
> > > drivers use some similar scheme.
> >
> > Why? They should be attached to a "real" device, why make any up?
>
> ? A "real" device, like struct pci_device, can only bind to one
> driver. How can we bind it concurrently to net, rdma, scsi, etc?
MFD was designed for this very problem.
> > > This is for a PCI device that plugs into multiple subsystems in the
> > > kernel, ie it has net driver functionality, rdma functionality, some
> > > even have SCSI functionality
> >
> > Sounds like a MFD device, why aren't you using that functionality
> > instead?
>
> This was also my advice, but in another email Jeff says:
>
> MFD architecture was also considered, and we selected the simpler
> platform model. Supporting a MFD architecture would require an
> additional MFD core driver, individual platform netdev, RDMA function
> drivers, and stripping a large portion of the netdev drivers into
> MFD core. The sub-devices registered by MFD core for function
> drivers are indeed platform devices.
So, "mfd is too hard, let's abuse a platform device" is ok?
People have been wanting to do MFD drivers for PCI devices for a long
time, it's about time someone actually did the work for it, I bet it
will not be all that complex if tiny embedded drivers can do it :)
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH net-next v5 5/5] selftests: tc-tests: actions: add MPLS tests
From: John Hurley @ 2019-07-04 13:40 UTC (permalink / raw)
To: Davide Caratti
Cc: Linux Netdev List, David Miller, Jiri Pirko, Cong Wang,
David Ahern, Willem de Bruijn, Simon Horman, Jakub Kicinski,
oss-drivers
In-Reply-To: <0130c56ef79f8bf360ddb0b01db5e7684f0bf62a.camel@redhat.com>
On Thu, Jul 4, 2019 at 9:40 AM Davide Caratti <dcaratti@redhat.com> wrote:
>
> On Wed, 2019-07-03 at 01:25 +0100, John Hurley wrote:
> > Add a new series of selftests to verify the functionality of act_mpls in
> > TC.
> >
> > Signed-off-by: John Hurley <john.hurley@netronome.com>
> > Reviewed-by: Simon Horman <simon.horman@netronome.com>
> > Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
> > ---
> > .../tc-testing/tc-tests/actions/mpls.json | 812 +++++++++++++++++++++
> > 1 file changed, 812 insertions(+)
> > create mode 100644 tools/testing/selftests/tc-testing/tc-tests/actions/mpls.json
> >
>
> hello John,
>
> (sorry for noticing this late). some scripts use
>
> tools/testing/selftests/tc-testing/config
>
> to rebuild vmlinux before running TDC. I think you should add a line
> there that sets CONFIG_NET_ACT_MPLS=y.
>
> WDYT?
Hi Davide,
Thanks for pointing this out.
Yes, I'll add it.
Thanks
>
> thanks!
> --
> davide
>
^ permalink raw reply
* Re: i.mx6ul with DSA in multi chip addressing mode - no MDIO access
From: Andrew Lunn @ 2019-07-04 13:27 UTC (permalink / raw)
To: Benjamin Beckmeyer; +Cc: netdev
In-Reply-To: <d1181129-ec9d-01c1-3102-e1dc5dec0378@eks-engel.de>
On Thu, Jul 04, 2019 at 10:54:47AM +0200, Benjamin Beckmeyer wrote:
>
> On 03.07.19 17:55, Andrew Lunn wrote:
> > On Wed, Jul 03, 2019 at 03:10:34PM +0200, Benjamin Beckmeyer wrote:
> >> Hey folks,
> >>
> >> I'm having a problem with a custom i.mx6ul board. When DSA is loaded I can't
> >> get access to the switch via MDIO, but the DSA is working properly. I set up
> >> a bridge for testing and the switch is in forwarding mode and i can ping the
> >> board. But the MDIO access isn't working at address 2 for the switch. When I
> >> delete the DSA from the devicetree and start the board up, I can access the
> >> switch via MDIO.
> >>
> >> With DSA up and running:
> >>
> >> mii -i 2 0 0x9800
> >> mii -i 2 1
> >> phyid:2, reg:0x01 -> 0x4000
> >> mii -i 2 0 0x9803
> >> mii -i 2 1
> >> phyid:2, reg:0x01 -> 0x4000
> >> mii -i 2 1 0x1883
> >> mii -i 2 1
> >> phyid:2, reg:0x01 -> 0x4000
> > Hi Benjamin
> >
> > I'm guessing that the driver is also using register 0 and 1 at the
> > same time you are, e.g. to poll the PHYs for link status etc.
> >
> > There are trace points for MDIO, so you can get the kernel to log all
> > registers access. That should confirm if i'm right.
> >
> > Andrew
>
> Hi Andrew,
> you were absolutly right. The bus is really busy the whole time, I've
> checked that with the tracepoints in mdio_access.
>
> But I'm still wondering why isn't that with a single chip addressing
> mode configured switch? I mean, okay, the switch has more ports, but
> I've checked the accesses for both. The 6321(single chip addressing
> mode) has around 4-5 accesses to the MDIO bus and the 6390(multi chip
> addressing mode) has around 600 accesses per second.
Hi Benjamin
In single chip mode, reading a register is atomic. With multi-chip,
you need to access two registers, so it clearly is not atomic. And so
any other action on the bus will cause you problems when doing things
from user space without being able to take the register mutex.
But 4-5 vs 600 suggests you don't have the interrupt line in your
device tree. If you have the interrupt line connected to a GPIO, and
the driver knows about it, it has no need to poll the PHYs. I also
added support for 'polled interrupts', as a fall back when then
interrupt is not listed in device tree. 10 times a second the driver
polls the interrupt status register, and if any interrupts have
happened within the switch, it triggers the needed handlers. Reading
one status register every 100ms is much less effort than reading all
the PHY status registers once per second.
Still, 600 per second sounds too high. Do you have an SNMP agent
getting statistics?
Andrew
^ permalink raw reply
* [PATCH net-next v2 4/4] qed*: Add devlink support for configuration attributes.
From: Sudarsana Reddy Kalluru @ 2019-07-04 13:20 UTC (permalink / raw)
To: davem; +Cc: netdev, mkalderon, aelior
In-Reply-To: <20190704132011.13600-1-skalluru@marvell.com>
This patch adds implementation for devlink callbacks for reading and
configuring the device attributes.
Signed-off-by: Sudarsana Reddy Kalluru <skalluru@marvell.com>
Signed-off-by: Ariel Elior <aelior@marvell.com>
---
Documentation/networking/devlink-params-qede.txt | 72 ++++++++
drivers/net/ethernet/qlogic/qed/qed_main.c | 38 +++++
drivers/net/ethernet/qlogic/qede/qede.h | 3 +
drivers/net/ethernet/qlogic/qede/qede_devlink.c | 202 ++++++++++++++++++++++-
drivers/net/ethernet/qlogic/qede/qede_devlink.h | 23 +++
include/linux/qed/qed_if.h | 16 ++
6 files changed, 353 insertions(+), 1 deletion(-)
create mode 100644 Documentation/networking/devlink-params-qede.txt
diff --git a/Documentation/networking/devlink-params-qede.txt b/Documentation/networking/devlink-params-qede.txt
new file mode 100644
index 0000000..f78a993
--- /dev/null
+++ b/Documentation/networking/devlink-params-qede.txt
@@ -0,0 +1,72 @@
+enable_sriov [DEVICE, GENERIC]
+ Configuration mode: Permanent
+
+iwarp_cmt [DEVICE, DRIVER-SPECIFIC]
+ Enable iWARP support over 100G device (CMT mode).
+ Type: Boolean
+ Configuration mode: runtime
+
+entity_id [DEVICE, DRIVER-SPECIFIC]
+ Set the entity ID value to be used for this device
+ while reading/configuring the devlink attributes.
+ Type: u8
+ Configuration mode: runtime
+
+device_capabilities [DEVICE, DRIVER-SPECIFIC]
+ Set the entity ID value to be used for this device
+ while reading/configuring the devlink attributes.
+ Type: u8
+ Configuration mode: runtime
+
+mf_mode [DEVICE, DRIVER-SPECIFIC]
+ Configure Multi Function mode for the device.
+ Supported MF modes and the assoicated values are,
+ MF allowed(0), Default(1), SPIO4(2), NPAR1.0(3),
+ NPAR1.5(4), NPAR2.0(5), BD(6) and UFP(7)
+ Type: u8
+ Configuration mode: Permanent
+
+dcbx_mode [PORT, DRIVER-SPECIFIC]
+ Configure DCBX mode for the device.
+ Supported dcbx modes are,
+ Disabled(0), IEEE(1), CEE(2) and Dynamic(3)
+ Type: u8
+ Configuration mode: Permanent
+
+preboot_oprom [PORT, DRIVER-SPECIFIC]
+ Enable Preboot Option ROM.
+ Type: Boolean
+ Configuration mode: Permanent
+
+preboot_boot_protocol [PORT, DRIVER-SPECIFIC]
+ Configure preboot Boot protocol.
+ Possible values are,
+ PXE(0), iSCSI Boot(3), FCoE Boot(4) and NONE(7)
+ Type: u8
+ Configuration mode: Permanent
+
+preboot_vlan [PORT, DRIVER-SPECIFIC]
+ Preboot VLAN.
+ Type: u16
+ Configuration mode: Permanent
+
+preboot_vlan_value [PORT, DRIVER-SPECIFIC]
+ Configure Preboot VLAN value.
+ Type: u16
+ Configuration mode: Permanent
+
+mba_delay_time [PORT, DRIVER-SPECIFIC]
+ Configure MBA Delay Time. Supported range is [0-15].
+ Type: u8
+ Configuration mode: Permanent
+
+mba_setup_hot_key [PORT, DRIVER-SPECIFIC]
+ Configure MBA setup Hot Key. Possible values are,
+ Ctrl S(0) and Ctrl B(1).
+ Type: u8
+ Configuration mode: Permanent
+
+mba_hide_setup_prompt [PORT, DRIVER-SPECIFIC]
+ Configure MBA hide setup prompt.
+ Type: Boolean
+ Configuration mode: Permanent
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index f0183e2..3d43140 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -2388,6 +2388,42 @@ static void qed_set_iwarp_cmt(struct qed_dev *cdev, bool iwarp_cmt)
cdev->iwarp_cmt = iwarp_cmt;
}
+static int qed_get_cfg_attr(struct qed_dev *cdev, u16 cmd, u8 entity, u32 flags,
+ u8 *buf, int *len)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *ptt;
+ int status = 0;
+
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt)
+ return -EAGAIN;
+
+ status = qed_mcp_nvm_get_cfg(hwfn, ptt, cmd, entity, flags, buf, len);
+
+ qed_ptt_release(hwfn, ptt);
+
+ return status;
+}
+
+static int qed_set_cfg_attr(struct qed_dev *cdev, u16 cmd, u8 entity, u32 flags,
+ u8 *buf, int len)
+{
+ struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *ptt;
+ int status = 0;
+
+ ptt = qed_ptt_acquire(hwfn);
+ if (!ptt)
+ return -EAGAIN;
+
+ status = qed_mcp_nvm_set_cfg(hwfn, ptt, cmd, entity, flags, buf, len);
+
+ qed_ptt_release(hwfn, ptt);
+
+ return status;
+}
+
static struct qed_selftest_ops qed_selftest_ops_pass = {
.selftest_memory = &qed_selftest_memory,
.selftest_interrupt = &qed_selftest_interrupt,
@@ -2438,6 +2474,8 @@ static void qed_set_iwarp_cmt(struct qed_dev *cdev, bool iwarp_cmt)
.get_affin_hwfn_idx = &qed_get_affin_hwfn_idx,
.get_iwarp_cmt = &qed_get_iwarp_cmt,
.set_iwarp_cmt = &qed_set_iwarp_cmt,
+ .get_cfg_attr = &qed_get_cfg_attr,
+ .set_cfg_attr = &qed_set_cfg_attr,
};
void qed_get_protocol_stats(struct qed_dev *cdev,
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index 35ad5cd..e175d30 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -54,6 +54,7 @@
#include <net/pkt_cls.h>
#include <net/tc_act/tc_gact.h>
+#include <net/devlink.h>
#define QEDE_MAJOR_VERSION 8
#define QEDE_MINOR_VERSION 37
@@ -264,6 +265,8 @@ struct qede_dev {
struct bpf_prog *xdp_prog;
struct devlink *dl;
+ struct devlink_port dl_port;
+ u8 cfg_entity_id;
};
enum QEDE_STATE {
diff --git a/drivers/net/ethernet/qlogic/qede/qede_devlink.c b/drivers/net/ethernet/qlogic/qede/qede_devlink.c
index 3f362ac..076a66a 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_devlink.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_devlink.c
@@ -2,6 +2,31 @@
#include "qede.h"
#include "qede_devlink.h"
+static const struct qede_devlink_cfg_param cfg_params[] = {
+ {DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, QED_NVM_CFG_ID_ENABLE_SRIOV,
+ DEVLINK_PARAM_TYPE_BOOL},
+ {QEDE_DEVLINK_ENTITY_ID, 0, DEVLINK_PARAM_TYPE_U8},
+ {QEDE_DEVLINK_DEVICE_CAPABILITIES,
+ QED_NVM_CFG_ID_DEVICE_CAPABILITIES, DEVLINK_PARAM_TYPE_U8},
+ {QEDE_DEVLINK_MF_MODE, QED_NVM_CFG_ID_MF_MODE, DEVLINK_PARAM_TYPE_U8},
+ {QEDE_DEVLINK_DCBX_MODE, QED_NVM_CFG_ID_DCBX_MODE,
+ DEVLINK_PARAM_TYPE_U8},
+ {QEDE_DEVLINK_PREBOOT_OPROM, QED_NVM_CFG_ID_PREBOOT_OPROM,
+ DEVLINK_PARAM_TYPE_BOOL},
+ {QEDE_DEVLINK_PREBOOT_BOOT_PROTOCOL,
+ QED_NVM_CFG_ID_PREBOOT_BOOT_PROTOCOL, DEVLINK_PARAM_TYPE_U8},
+ {QEDE_DEVLINK_PREBOOT_VLAN, QED_NVM_CFG_ID_PREBOOT_VLAN,
+ DEVLINK_PARAM_TYPE_U16},
+ {QEDE_DEVLINK_PREBOOT_VLAN_VALUE, QED_NVM_CFG_ID_PREBOOT_VLAN_VALUE,
+ DEVLINK_PARAM_TYPE_U16},
+ {QEDE_DEVLINK_MBA_DELAY_TIME, QED_NVM_CFG_ID_MBA_DELAY_TIME,
+ DEVLINK_PARAM_TYPE_U8},
+ {QEDE_DEVLINK_MBA_SETUP_HOT_KEY, QED_NVM_CFG_ID_MBA_SETUP_HOT_KEY,
+ DEVLINK_PARAM_TYPE_U8},
+ {QEDE_DEVLINK_MBA_HIDE_SETUP_PROMPT,
+ QED_NVM_CFG_ID_MBA_HIDE_SETUP_PROMPT, DEVLINK_PARAM_TYPE_BOOL},
+};
+
static int qede_dl_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
{
@@ -28,11 +53,159 @@ static int qede_dl_param_set(struct devlink *dl, u32 id,
return 0;
}
+static int qede_dl_get_perm_cfg(struct devlink *dl, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ u8 buf[QEDE_DL_PARAM_BUF_LEN];
+ struct qede_devlink *qede_dl;
+ int rc, idx, len = 0;
+ struct qede_dev *edev;
+ u32 flags;
+
+ qede_dl = devlink_priv(dl);
+ edev = qede_dl->edev;
+
+ if (id == QEDE_DEVLINK_ENTITY_ID) {
+ ctx->val.vu8 = edev->cfg_entity_id;
+ return 0;
+ }
+
+ for (idx = 0; idx < ARRAY_SIZE(cfg_params); idx++)
+ if (cfg_params[idx].id == id)
+ break;
+
+ if (idx == ARRAY_SIZE(cfg_params)) {
+ DP_ERR(edev, "Invalid command id %d\n", id);
+ return -EINVAL;
+ }
+
+ memset(buf, 0, QEDE_DL_PARAM_BUF_LEN);
+ flags = edev->cfg_entity_id ? QEDE_DL_PARAM_PF_GET_FLAGS :
+ QEDE_DL_PARAM_GET_FLAGS;
+
+ rc = edev->ops->common->get_cfg_attr(edev->cdev, cfg_params[idx].cmd,
+ edev->cfg_entity_id, flags, buf,
+ &len);
+ if (rc)
+ DP_ERR(edev, "Error = %d\n", rc);
+ else
+ memcpy(&ctx->val, buf, len);
+
+ return rc;
+}
+
+static int qede_dl_set_perm_cfg(struct devlink *dl, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ u8 buf[QEDE_DL_PARAM_BUF_LEN];
+ struct qede_devlink *qede_dl;
+ int rc, idx, len = 0;
+ struct qede_dev *edev;
+ u32 flags;
+
+ qede_dl = devlink_priv(dl);
+ edev = qede_dl->edev;
+
+ if (id == QEDE_DEVLINK_ENTITY_ID) {
+ edev->cfg_entity_id = ctx->val.vu8;
+ return 0;
+ }
+
+ for (idx = 0; idx < ARRAY_SIZE(cfg_params); idx++)
+ if (cfg_params[idx].id == id)
+ break;
+
+ if (idx == ARRAY_SIZE(cfg_params)) {
+ DP_ERR(edev, "Invalid command id %d\n", id);
+ return -EINVAL;
+ }
+
+ memset(buf, 0, QEDE_DL_PARAM_BUF_LEN);
+ switch (cfg_params[idx].type) {
+ case DEVLINK_PARAM_TYPE_BOOL:
+ len = 1;
+ break;
+ case DEVLINK_PARAM_TYPE_U8:
+ len = 1;
+ break;
+ case DEVLINK_PARAM_TYPE_U16:
+ len = 2;
+ break;
+ case DEVLINK_PARAM_TYPE_U32:
+ len = 4;
+ break;
+ case DEVLINK_PARAM_TYPE_STRING:
+ len = strlen(ctx->val.vstr);
+ break;
+ }
+
+ memcpy(buf, &ctx->val, len);
+ flags = edev->cfg_entity_id ? QEDE_DL_PARAM_PF_SET_FLAGS :
+ QEDE_DL_PARAM_SET_FLAGS;
+
+ rc = edev->ops->common->set_cfg_attr(edev->cdev, cfg_params[idx].cmd,
+ edev->cfg_entity_id, flags, buf,
+ len);
+ if (rc)
+ DP_ERR(edev, "Error = %d\n", rc);
+
+ return rc;
+}
+
static const struct devlink_param qede_devlink_params[] = {
DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_PARAM_ID_IWARP_CMT,
"iwarp_cmt", DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
qede_dl_param_get, qede_dl_param_set, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_ENTITY_ID,
+ "entity_id", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_GENERIC(ENABLE_SRIOV, BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_MF_MODE,
+ "mf_mode", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_DEVICE_CAPABILITIES,
+ "device_capabilities", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+};
+
+static const struct devlink_param qede_devlink_port_params[] = {
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_DCBX_MODE,
+ "dcbx_mode", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_PREBOOT_OPROM,
+ "preboot_oprom", DEVLINK_PARAM_TYPE_BOOL,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_PREBOOT_BOOT_PROTOCOL,
+ "preboot_boot_protocol", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_PREBOOT_VLAN,
+ "preboot_vlan", DEVLINK_PARAM_TYPE_U16,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_PREBOOT_VLAN_VALUE,
+ "preboot_vlan_value", DEVLINK_PARAM_TYPE_U16,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_MBA_DELAY_TIME,
+ "mba_delay_time", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_MBA_SETUP_HOT_KEY,
+ "mba_setup_hot_key", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_MBA_HIDE_SETUP_PROMPT,
+ "mba_hide_setup_prompt", DEVLINK_PARAM_TYPE_BOOL,
+ BIT(DEVLINK_PARAM_CMODE_PERMANENT),
+ qede_dl_get_perm_cfg, qede_dl_set_perm_cfg, NULL),
};
static const struct devlink_ops qede_dl_ops;
@@ -66,11 +239,34 @@ int qede_devlink_register(struct qede_dev *edev)
devlink_param_driverinit_value_set(dl, QEDE_DEVLINK_PARAM_ID_IWARP_CMT,
value);
+ devlink_port_attrs_set(&edev->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
+ 0, false, 0, NULL, 0);
+ rc = devlink_port_register(dl, &edev->dl_port, 0);
+ if (rc) {
+ DP_ERR(edev, "devlink_port_register failed");
+ goto err_param_unregister;
+ }
+ devlink_port_type_eth_set(&edev->dl_port, edev->ndev);
+
+ rc = devlink_port_params_register(&edev->dl_port,
+ qede_devlink_port_params,
+ ARRAY_SIZE(qede_devlink_port_params));
+ if (rc) {
+ DP_ERR(edev, "devlink_port_params_register failed");
+ goto err_port_unregister;
+ }
+
devlink_params_publish(dl);
+ devlink_port_params_publish(&edev->dl_port);
edev->ops->common->set_iwarp_cmt(edev->cdev, false);
return 0;
+err_port_unregister:
+ devlink_port_unregister(&edev->dl_port);
+err_param_unregister:
+ devlink_params_unregister(edev->dl, qede_devlink_params,
+ ARRAY_SIZE(qede_devlink_params));
err_unregister:
devlink_unregister(dl);
@@ -86,9 +282,13 @@ void qede_devlink_unregister(struct qede_dev *edev)
if (!edev->dl)
return;
+ devlink_port_params_unpublish(&edev->dl_port);
+ devlink_params_unpublish(edev->dl);
+ devlink_port_params_unregister(&edev->dl_port, qede_devlink_port_params,
+ ARRAY_SIZE(qede_devlink_port_params));
devlink_params_unregister(edev->dl, qede_devlink_params,
ARRAY_SIZE(qede_devlink_params));
-
+ devlink_port_unregister(&edev->dl_port);
devlink_unregister(edev->dl);
devlink_free(edev->dl);
}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_devlink.h b/drivers/net/ethernet/qlogic/qede/qede_devlink.h
index 5aa79dd..57b5fcc 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_devlink.h
+++ b/drivers/net/ethernet/qlogic/qede/qede_devlink.h
@@ -3,6 +3,12 @@
#define _QEDE_DEVLINK_H
#include <net/devlink.h>
+#define QEDE_DL_PARAM_GET_FLAGS 0xA
+#define QEDE_DL_PARAM_SET_FLAGS 0xE
+#define QEDE_DL_PARAM_PF_GET_FLAGS 0x1A
+#define QEDE_DL_PARAM_PF_SET_FLAGS 0x1E
+#define QEDE_DL_PARAM_BUF_LEN 32
+
struct qede_devlink {
struct qede_dev *edev;
};
@@ -10,6 +16,23 @@ struct qede_devlink {
enum qede_devlink_param_id {
QEDE_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
QEDE_DEVLINK_PARAM_ID_IWARP_CMT,
+ QEDE_DEVLINK_ENTITY_ID,
+ QEDE_DEVLINK_DEVICE_CAPABILITIES,
+ QEDE_DEVLINK_MF_MODE,
+ QEDE_DEVLINK_DCBX_MODE,
+ QEDE_DEVLINK_PREBOOT_OPROM,
+ QEDE_DEVLINK_PREBOOT_BOOT_PROTOCOL,
+ QEDE_DEVLINK_PREBOOT_VLAN,
+ QEDE_DEVLINK_PREBOOT_VLAN_VALUE,
+ QEDE_DEVLINK_MBA_DELAY_TIME,
+ QEDE_DEVLINK_MBA_SETUP_HOT_KEY,
+ QEDE_DEVLINK_MBA_HIDE_SETUP_PROMPT,
+};
+
+struct qede_devlink_cfg_param {
+ u16 id;
+ u16 cmd;
+ enum devlink_param_type type;
};
int qede_devlink_register(struct qede_dev *edev);
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index 7c41304..6430762 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -48,6 +48,18 @@
#include <linux/qed/qed_chain.h>
#include <linux/io-64-nonatomic-lo-hi.h>
+#define QED_NVM_CFG_ID_MF_MODE 9
+#define QED_NVM_CFG_ID_DCBX_MODE 26
+#define QED_NVM_CFG_ID_PREBOOT_OPROM 59
+#define QED_NVM_CFG_ID_MBA_DELAY_TIME 61
+#define QED_NVM_CFG_ID_MBA_SETUP_HOT_KEY 62
+#define QED_NVM_CFG_ID_MBA_HIDE_SETUP_PROMPT 63
+#define QED_NVM_CFG_ID_PREBOOT_BOOT_PROTOCOL 69
+#define QED_NVM_CFG_ID_ENABLE_SRIOV 70
+#define QED_NVM_CFG_ID_DEVICE_CAPABILITIES 117
+#define QED_NVM_CFG_ID_PREBOOT_VLAN_VALUE 132
+#define QED_NVM_CFG_ID_PREBOOT_VLAN 133
+
enum dcbx_protocol_type {
DCBX_PROTOCOL_ISCSI,
DCBX_PROTOCOL_FCOE,
@@ -1134,6 +1146,10 @@ struct qed_common_ops {
bool (*get_iwarp_cmt)(struct qed_dev *cdev);
void (*set_iwarp_cmt)(struct qed_dev *cdev, bool iwarp_cmt);
+ int (*get_cfg_attr)(struct qed_dev *cdev, u16 cmd, u8 entity, u32 flags,
+ u8 *buf, int *len);
+ int (*set_cfg_attr)(struct qed_dev *cdev, u16 cmd, u8 entity, u32 flags,
+ u8 *buf, int len);
};
#define MASK_FIELD(_name, _value) \
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v2 3/4] qed*: Add new file for devlink implementation.
From: Sudarsana Reddy Kalluru @ 2019-07-04 13:20 UTC (permalink / raw)
To: davem; +Cc: netdev, mkalderon, aelior
In-Reply-To: <20190704132011.13600-1-skalluru@marvell.com>
Moving devlink implementation from qed to qede driver. The change is
required as qede is the actual PCI driver and qed is only the control
driver.
Signed-off-by: Sudarsana Reddy Kalluru <skalluru@marvell.com>
Signed-off-by: Ariel Elior <aelior@marvell.com>
---
drivers/net/ethernet/qlogic/qed/qed.h | 1 -
drivers/net/ethernet/qlogic/qed/qed_main.c | 122 +++---------------------
drivers/net/ethernet/qlogic/qede/Makefile | 2 +-
drivers/net/ethernet/qlogic/qede/qede.h | 2 +
drivers/net/ethernet/qlogic/qede/qede_devlink.c | 94 ++++++++++++++++++
drivers/net/ethernet/qlogic/qede/qede_devlink.h | 18 ++++
drivers/net/ethernet/qlogic/qede/qede_main.c | 13 +++
include/linux/qed/qed_if.h | 3 +
8 files changed, 143 insertions(+), 112 deletions(-)
create mode 100644 drivers/net/ethernet/qlogic/qede/qede_devlink.c
create mode 100644 drivers/net/ethernet/qlogic/qede/qede_devlink.h
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index 89fe091..cebd822 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -864,7 +864,6 @@ struct qed_dev {
u32 rdma_max_srq_sge;
u16 tunn_feature_mask;
- struct devlink *dl;
bool iwarp_cmt;
};
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 829dd60..f0183e2 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -48,7 +48,6 @@
#include <linux/crc32.h>
#include <linux/qed/qed_if.h>
#include <linux/qed/qed_ll2_if.h>
-#include <net/devlink.h>
#include "qed.h"
#include "qed_sriov.h"
@@ -343,107 +342,6 @@ static int qed_set_power_state(struct qed_dev *cdev, pci_power_t state)
return 0;
}
-struct qed_devlink {
- struct qed_dev *cdev;
-};
-
-enum qed_devlink_param_id {
- QED_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
- QED_DEVLINK_PARAM_ID_IWARP_CMT,
-};
-
-static int qed_dl_param_get(struct devlink *dl, u32 id,
- struct devlink_param_gset_ctx *ctx)
-{
- struct qed_devlink *qed_dl;
- struct qed_dev *cdev;
-
- qed_dl = devlink_priv(dl);
- cdev = qed_dl->cdev;
- ctx->val.vbool = cdev->iwarp_cmt;
-
- return 0;
-}
-
-static int qed_dl_param_set(struct devlink *dl, u32 id,
- struct devlink_param_gset_ctx *ctx)
-{
- struct qed_devlink *qed_dl;
- struct qed_dev *cdev;
-
- qed_dl = devlink_priv(dl);
- cdev = qed_dl->cdev;
- cdev->iwarp_cmt = ctx->val.vbool;
-
- return 0;
-}
-
-static const struct devlink_param qed_devlink_params[] = {
- DEVLINK_PARAM_DRIVER(QED_DEVLINK_PARAM_ID_IWARP_CMT,
- "iwarp_cmt", DEVLINK_PARAM_TYPE_BOOL,
- BIT(DEVLINK_PARAM_CMODE_RUNTIME),
- qed_dl_param_get, qed_dl_param_set, NULL),
-};
-
-static const struct devlink_ops qed_dl_ops;
-
-static int qed_devlink_register(struct qed_dev *cdev)
-{
- union devlink_param_value value;
- struct qed_devlink *qed_dl;
- struct devlink *dl;
- int rc;
-
- dl = devlink_alloc(&qed_dl_ops, sizeof(*qed_dl));
- if (!dl)
- return -ENOMEM;
-
- qed_dl = devlink_priv(dl);
-
- cdev->dl = dl;
- qed_dl->cdev = cdev;
-
- rc = devlink_register(dl, &cdev->pdev->dev);
- if (rc)
- goto err_free;
-
- rc = devlink_params_register(dl, qed_devlink_params,
- ARRAY_SIZE(qed_devlink_params));
- if (rc)
- goto err_unregister;
-
- value.vbool = false;
- devlink_param_driverinit_value_set(dl,
- QED_DEVLINK_PARAM_ID_IWARP_CMT,
- value);
-
- devlink_params_publish(dl);
- cdev->iwarp_cmt = false;
-
- return 0;
-
-err_unregister:
- devlink_unregister(dl);
-
-err_free:
- cdev->dl = NULL;
- devlink_free(dl);
-
- return rc;
-}
-
-static void qed_devlink_unregister(struct qed_dev *cdev)
-{
- if (!cdev->dl)
- return;
-
- devlink_params_unregister(cdev->dl, qed_devlink_params,
- ARRAY_SIZE(qed_devlink_params));
-
- devlink_unregister(cdev->dl);
- devlink_free(cdev->dl);
-}
-
/* probing */
static struct qed_dev *qed_probe(struct pci_dev *pdev,
struct qed_probe_params *params)
@@ -472,12 +370,6 @@ static struct qed_dev *qed_probe(struct pci_dev *pdev,
}
DP_INFO(cdev, "PCI init completed successfully\n");
- rc = qed_devlink_register(cdev);
- if (rc) {
- DP_INFO(cdev, "Failed to register devlink.\n");
- goto err2;
- }
-
rc = qed_hw_prepare(cdev, QED_PCI_DEFAULT);
if (rc) {
DP_ERR(cdev, "hw prepare failed\n");
@@ -507,8 +399,6 @@ static void qed_remove(struct qed_dev *cdev)
qed_set_power_state(cdev, PCI_D3hot);
- qed_devlink_unregister(cdev);
-
qed_free_cdev(cdev);
}
@@ -2488,6 +2378,16 @@ static u8 qed_get_affin_hwfn_idx(struct qed_dev *cdev)
return QED_AFFIN_HWFN_IDX(cdev);
}
+static bool qed_get_iwarp_cmt(struct qed_dev *cdev)
+{
+ return cdev->iwarp_cmt;
+}
+
+static void qed_set_iwarp_cmt(struct qed_dev *cdev, bool iwarp_cmt)
+{
+ cdev->iwarp_cmt = iwarp_cmt;
+}
+
static struct qed_selftest_ops qed_selftest_ops_pass = {
.selftest_memory = &qed_selftest_memory,
.selftest_interrupt = &qed_selftest_interrupt,
@@ -2536,6 +2436,8 @@ static u8 qed_get_affin_hwfn_idx(struct qed_dev *cdev)
.db_recovery_del = &qed_db_recovery_del,
.read_module_eeprom = &qed_read_module_eeprom,
.get_affin_hwfn_idx = &qed_get_affin_hwfn_idx,
+ .get_iwarp_cmt = &qed_get_iwarp_cmt,
+ .set_iwarp_cmt = &qed_set_iwarp_cmt,
};
void qed_get_protocol_stats(struct qed_dev *cdev,
diff --git a/drivers/net/ethernet/qlogic/qede/Makefile b/drivers/net/ethernet/qlogic/qede/Makefile
index 3fc91d1..4585864 100644
--- a/drivers/net/ethernet/qlogic/qede/Makefile
+++ b/drivers/net/ethernet/qlogic/qede/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_QEDE) := qede.o
-qede-y := qede_main.o qede_fp.o qede_filter.o qede_ethtool.o qede_ptp.o
+qede-y := qede_main.o qede_fp.o qede_filter.o qede_ethtool.o qede_ptp.o qede_devlink.o
qede-$(CONFIG_DCB) += qede_dcbnl.o
qede-$(CONFIG_QED_RDMA) += qede_rdma.o
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index b972ab0..35ad5cd 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -262,6 +262,8 @@ struct qede_dev {
struct qede_rdma_dev rdma_info;
struct bpf_prog *xdp_prog;
+
+ struct devlink *dl;
};
enum QEDE_STATE {
diff --git a/drivers/net/ethernet/qlogic/qede/qede_devlink.c b/drivers/net/ethernet/qlogic/qede/qede_devlink.c
new file mode 100644
index 0000000..3f362ac
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qede/qede_devlink.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "qede.h"
+#include "qede_devlink.h"
+
+static int qede_dl_param_get(struct devlink *dl, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct qede_devlink *qede_dl;
+ struct qede_dev *edev;
+
+ qede_dl = devlink_priv(dl);
+ edev = qede_dl->edev;
+ ctx->val.vbool = edev->ops->common->get_iwarp_cmt(edev->cdev);
+
+ return 0;
+}
+
+static int qede_dl_param_set(struct devlink *dl, u32 id,
+ struct devlink_param_gset_ctx *ctx)
+{
+ struct qede_devlink *qede_dl;
+ struct qede_dev *edev;
+
+ qede_dl = devlink_priv(dl);
+ edev = qede_dl->edev;
+ edev->ops->common->set_iwarp_cmt(edev->cdev, ctx->val.vbool);
+
+ return 0;
+}
+
+static const struct devlink_param qede_devlink_params[] = {
+ DEVLINK_PARAM_DRIVER(QEDE_DEVLINK_PARAM_ID_IWARP_CMT,
+ "iwarp_cmt", DEVLINK_PARAM_TYPE_BOOL,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ qede_dl_param_get, qede_dl_param_set, NULL),
+};
+
+static const struct devlink_ops qede_dl_ops;
+
+int qede_devlink_register(struct qede_dev *edev)
+{
+ union devlink_param_value value;
+ struct qede_devlink *qede_dl;
+ struct devlink *dl;
+ int rc;
+
+ dl = devlink_alloc(&qede_dl_ops, sizeof(*qede_dl));
+ if (!dl)
+ return -ENOMEM;
+
+ qede_dl = devlink_priv(dl);
+
+ edev->dl = dl;
+ qede_dl->edev = edev;
+
+ rc = devlink_register(dl, &edev->pdev->dev);
+ if (rc)
+ goto err_free;
+
+ rc = devlink_params_register(dl, qede_devlink_params,
+ ARRAY_SIZE(qede_devlink_params));
+ if (rc)
+ goto err_unregister;
+
+ value.vbool = false;
+ devlink_param_driverinit_value_set(dl, QEDE_DEVLINK_PARAM_ID_IWARP_CMT,
+ value);
+
+ devlink_params_publish(dl);
+ edev->ops->common->set_iwarp_cmt(edev->cdev, false);
+
+ return 0;
+
+err_unregister:
+ devlink_unregister(dl);
+
+err_free:
+ edev->dl = NULL;
+ devlink_free(dl);
+
+ return rc;
+}
+
+void qede_devlink_unregister(struct qede_dev *edev)
+{
+ if (!edev->dl)
+ return;
+
+ devlink_params_unregister(edev->dl, qede_devlink_params,
+ ARRAY_SIZE(qede_devlink_params));
+
+ devlink_unregister(edev->dl);
+ devlink_free(edev->dl);
+}
diff --git a/drivers/net/ethernet/qlogic/qede/qede_devlink.h b/drivers/net/ethernet/qlogic/qede/qede_devlink.h
new file mode 100644
index 0000000..5aa79dd
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qede/qede_devlink.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _QEDE_DEVLINK_H
+#define _QEDE_DEVLINK_H
+#include <net/devlink.h>
+
+struct qede_devlink {
+ struct qede_dev *edev;
+};
+
+enum qede_devlink_param_id {
+ QEDE_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
+ QEDE_DEVLINK_PARAM_ID_IWARP_CMT,
+};
+
+int qede_devlink_register(struct qede_dev *edev);
+void qede_devlink_unregister(struct qede_dev *edev);
+
+#endif
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index d4a2966..cef946f 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -62,6 +62,7 @@
#include <linux/vmalloc.h>
#include "qede.h"
#include "qede_ptp.h"
+#include "qede_devlink.h"
static char version[] =
"QLogic FastLinQ 4xxxx Ethernet Driver qede " DRV_MODULE_VERSION "\n";
@@ -1177,8 +1178,18 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
edev->rx_copybreak = QEDE_RX_HDR_SIZE;
qede_log_probe(edev);
+
+ rc = qede_devlink_register(edev);
+ if (rc) {
+ DP_INFO(edev, "Failed to register devlink.\n");
+ goto err5;
+ }
+
return 0;
+err5:
+ if (!is_vf)
+ qede_ptp_disable(edev);
err4:
qede_rdma_dev_remove(edev, (mode == QEDE_PROBE_RECOVERY));
err3:
@@ -1227,6 +1238,8 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode)
DP_INFO(edev, "Starting qede_remove\n");
+ qede_devlink_unregister(edev);
+
qede_rdma_dev_remove(edev, (mode == QEDE_REMOVE_RECOVERY));
if (mode != QEDE_REMOVE_RECOVERY) {
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index eef02e6..7c41304 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -1131,6 +1131,9 @@ struct qed_common_ops {
* @param cdev
*/
u8 (*get_affin_hwfn_idx)(struct qed_dev *cdev);
+
+ bool (*get_iwarp_cmt)(struct qed_dev *cdev);
+ void (*set_iwarp_cmt)(struct qed_dev *cdev, bool iwarp_cmt);
};
#define MASK_FIELD(_name, _value) \
--
1.8.3.1
^ permalink raw reply related
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