Skip to content

Commit f428011

Browse files
mstarovodavem330
authored andcommitted
net: macsec: support multicast/broadcast when offloading
The idea is simple. If the frame is an exact match for the controlled port (based on DA comparison), then we simply divert this skb to matching port. Multicast/broadcast messages are delivered to all ports. Signed-off-by: Mark Starovoytov <[email protected]> Signed-off-by: Igor Russkikh <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a249f80 commit f428011

File tree

1 file changed

+38
-13
lines changed

1 file changed

+38
-13
lines changed

drivers/net/macsec.c

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,22 +1006,53 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
10061006
{
10071007
/* Deliver to the uncontrolled port by default */
10081008
enum rx_handler_result ret = RX_HANDLER_PASS;
1009+
struct ethhdr *hdr = eth_hdr(skb);
10091010
struct macsec_rxh_data *rxd;
10101011
struct macsec_dev *macsec;
10111012

10121013
rcu_read_lock();
10131014
rxd = macsec_data_rcu(skb->dev);
10141015

1015-
/* 10.6 If the management control validateFrames is not
1016-
* Strict, frames without a SecTAG are received, counted, and
1017-
* delivered to the Controlled Port
1018-
*/
10191016
list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
10201017
struct sk_buff *nskb;
10211018
struct pcpu_secy_stats *secy_stats = this_cpu_ptr(macsec->stats);
1019+
struct net_device *ndev = macsec->secy.netdev;
10221020

1023-
if (!macsec_is_offloaded(macsec) &&
1024-
macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
1021+
/* If h/w offloading is enabled, HW decodes frames and strips
1022+
* the SecTAG, so we have to deduce which port to deliver to.
1023+
*/
1024+
if (macsec_is_offloaded(macsec) && netif_running(ndev)) {
1025+
if (ether_addr_equal_64bits(hdr->h_dest,
1026+
ndev->dev_addr)) {
1027+
/* exact match, divert skb to this port */
1028+
skb->dev = ndev;
1029+
skb->pkt_type = PACKET_HOST;
1030+
ret = RX_HANDLER_ANOTHER;
1031+
goto out;
1032+
} else if (is_multicast_ether_addr_64bits(
1033+
hdr->h_dest)) {
1034+
/* multicast frame, deliver on this port too */
1035+
nskb = skb_clone(skb, GFP_ATOMIC);
1036+
if (!nskb)
1037+
break;
1038+
1039+
nskb->dev = ndev;
1040+
if (ether_addr_equal_64bits(hdr->h_dest,
1041+
ndev->broadcast))
1042+
nskb->pkt_type = PACKET_BROADCAST;
1043+
else
1044+
nskb->pkt_type = PACKET_MULTICAST;
1045+
1046+
netif_rx(nskb);
1047+
}
1048+
continue;
1049+
}
1050+
1051+
/* 10.6 If the management control validateFrames is not
1052+
* Strict, frames without a SecTAG are received, counted, and
1053+
* delivered to the Controlled Port
1054+
*/
1055+
if (macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
10251056
u64_stats_update_begin(&secy_stats->syncp);
10261057
secy_stats->stats.InPktsNoTag++;
10271058
u64_stats_update_end(&secy_stats->syncp);
@@ -1033,19 +1064,13 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
10331064
if (!nskb)
10341065
break;
10351066

1036-
nskb->dev = macsec->secy.netdev;
1067+
nskb->dev = ndev;
10371068

10381069
if (netif_rx(nskb) == NET_RX_SUCCESS) {
10391070
u64_stats_update_begin(&secy_stats->syncp);
10401071
secy_stats->stats.InPktsUntagged++;
10411072
u64_stats_update_end(&secy_stats->syncp);
10421073
}
1043-
1044-
if (netif_running(macsec->secy.netdev) &&
1045-
macsec_is_offloaded(macsec)) {
1046-
ret = RX_HANDLER_EXACT;
1047-
goto out;
1048-
}
10491074
}
10501075

10511076
out:

0 commit comments

Comments
 (0)