blob: 2f17478262e5584a21483d95511c5e712518db71 [file] [log] [blame]
developer7e32f7e2022-05-18 21:10:08 +08001From f428011b90ec0de7429886f753b7c3293392761c Mon Sep 17 00:00:00 2001
2From: Mark Starovoytov <mstarovoitov@marvell.com>
3Date: Wed, 25 Mar 2020 15:52:36 +0300
4Subject: net: macsec: support multicast/broadcast when offloading
5
6The idea is simple. If the frame is an exact match for the controlled port
7(based on DA comparison), then we simply divert this skb to matching port.
8
9Multicast/broadcast messages are delivered to all ports.
10
11Signed-off-by: Mark Starovoytov <mstarovoitov@marvell.com>
12Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
13Signed-off-by: David S. Miller <davem@davemloft.net>
14---
15 drivers/net/macsec.c | 51 ++++++++++++++++++++++++++++++++++++++-------------
16 1 file changed, 38 insertions(+), 13 deletions(-)
17
18diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
19index 146a7881a20ac..c7ad7c6f1d1ec 100644
20--- a/drivers/net/macsec.c
21+++ b/drivers/net/macsec.c
22@@ -1006,22 +1006,53 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
23 {
24 /* Deliver to the uncontrolled port by default */
25 enum rx_handler_result ret = RX_HANDLER_PASS;
26+ struct ethhdr *hdr = eth_hdr(skb);
27 struct macsec_rxh_data *rxd;
28 struct macsec_dev *macsec;
29
30 rcu_read_lock();
31 rxd = macsec_data_rcu(skb->dev);
32
33- /* 10.6 If the management control validateFrames is not
34- * Strict, frames without a SecTAG are received, counted, and
35- * delivered to the Controlled Port
36- */
37 list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
38 struct sk_buff *nskb;
39 struct pcpu_secy_stats *secy_stats = this_cpu_ptr(macsec->stats);
40+ struct net_device *ndev = macsec->secy.netdev;
41
42- if (!macsec_is_offloaded(macsec) &&
43- macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
44+ /* If h/w offloading is enabled, HW decodes frames and strips
45+ * the SecTAG, so we have to deduce which port to deliver to.
46+ */
47+ if (macsec_is_offloaded(macsec) && netif_running(ndev)) {
48+ if (ether_addr_equal_64bits(hdr->h_dest,
49+ ndev->dev_addr)) {
50+ /* exact match, divert skb to this port */
51+ skb->dev = ndev;
52+ skb->pkt_type = PACKET_HOST;
53+ ret = RX_HANDLER_ANOTHER;
54+ goto out;
55+ } else if (is_multicast_ether_addr_64bits(
56+ hdr->h_dest)) {
57+ /* multicast frame, deliver on this port too */
58+ nskb = skb_clone(skb, GFP_ATOMIC);
59+ if (!nskb)
60+ break;
61+
62+ nskb->dev = ndev;
63+ if (ether_addr_equal_64bits(hdr->h_dest,
64+ ndev->broadcast))
65+ nskb->pkt_type = PACKET_BROADCAST;
66+ else
67+ nskb->pkt_type = PACKET_MULTICAST;
68+
69+ netif_rx(nskb);
70+ }
71+ continue;
72+ }
73+
74+ /* 10.6 If the management control validateFrames is not
75+ * Strict, frames without a SecTAG are received, counted, and
76+ * delivered to the Controlled Port
77+ */
78+ if (macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
79 u64_stats_update_begin(&secy_stats->syncp);
80 secy_stats->stats.InPktsNoTag++;
81 u64_stats_update_end(&secy_stats->syncp);
82@@ -1033,19 +1064,13 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
83 if (!nskb)
84 break;
85
86- nskb->dev = macsec->secy.netdev;
87+ nskb->dev = ndev;
88
89 if (netif_rx(nskb) == NET_RX_SUCCESS) {
90 u64_stats_update_begin(&secy_stats->syncp);
91 secy_stats->stats.InPktsUntagged++;
92 u64_stats_update_end(&secy_stats->syncp);
93 }
94-
95- if (netif_running(macsec->secy.netdev) &&
96- macsec_is_offloaded(macsec)) {
97- ret = RX_HANDLER_EXACT;
98- goto out;
99- }
100 }
101
102 out:
103--
104cgit 1.2.3-1.el7
105