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.

Change-Id: Iaa716e14c1a178a99b51b1104e7c68eb2f8e592e
Signed-off-by: Mark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Git-commit: f428011b90ec0de7429886f753b7c3293392761c
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Signed-off-by: Karthik Rudrapatna <quic_krudrapa@quicinc.com>
This commit is contained in:
Mark Starovoytov 2020-03-25 15:52:36 +03:00 • committed by Gerrit - the friendly Code Review server
commit 811cdefef1

View file

@ -992,22 +992,53 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
{
/* Deliver to the uncontrolled port by default */
enum rx_handler_result ret = RX_HANDLER_PASS;
struct ethhdr *hdr = eth_hdr(skb);
struct macsec_rxh_data *rxd;
struct macsec_dev *macsec;
rcu_read_lock();
rxd = macsec_data_rcu(skb->dev);
/* 10.6 If the management control validateFrames is not
* Strict, frames without a SecTAG are received, counted, and
* delivered to the Controlled Port
*/
list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
struct sk_buff *nskb;
struct pcpu_secy_stats *secy_stats = this_cpu_ptr(macsec->stats);
struct net_device *ndev = macsec->secy.netdev;
if (!macsec_is_offloaded(macsec) &&
macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
/* If h/w offloading is enabled, HW decodes frames and strips
* the SecTAG, so we have to deduce which port to deliver to.
*/
if (macsec_is_offloaded(macsec) && netif_running(ndev)) {
if (ether_addr_equal_64bits(hdr->h_dest,
ndev->dev_addr)) {
/* exact match, divert skb to this port */
skb->dev = ndev;
skb->pkt_type = PACKET_HOST;
ret = RX_HANDLER_ANOTHER;
goto out;
} else if (is_multicast_ether_addr_64bits(
hdr->h_dest)) {
/* multicast frame, deliver on this port too */
nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb)
break;
nskb->dev = ndev;
if (ether_addr_equal_64bits(hdr->h_dest,
ndev->broadcast))
nskb->pkt_type = PACKET_BROADCAST;
else
nskb->pkt_type = PACKET_MULTICAST;
netif_rx(nskb);
}
continue;
}
/* 10.6 If the management control validateFrames is not
* Strict, frames without a SecTAG are received, counted, and
* delivered to the Controlled Port
*/
if (macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) {
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsNoTag++;
u64_stats_update_end(&secy_stats->syncp);
@ -1019,19 +1050,13 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
if (!nskb)
break;
nskb->dev = macsec->secy.netdev;
nskb->dev = ndev;
if (netif_rx(nskb) == NET_RX_SUCCESS) {
u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsUntagged++;
u64_stats_update_end(&secy_stats->syncp);
}
if (netif_running(macsec->secy.netdev) &&
macsec_is_offloaded(macsec)) {
ret = RX_HANDLER_EXACT;
goto out;
}
}
out: