Commit f428011b authored by Mark Starovoytov's avatar Mark Starovoytov Committed by David S. Miller

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: default avatarMark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a249f805
...@@ -1006,22 +1006,53 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb) ...@@ -1006,22 +1006,53 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
{ {
/* Deliver to the uncontrolled port by default */ /* Deliver to the uncontrolled port by default */
enum rx_handler_result ret = RX_HANDLER_PASS; enum rx_handler_result ret = RX_HANDLER_PASS;
struct ethhdr *hdr = eth_hdr(skb);
struct macsec_rxh_data *rxd; struct macsec_rxh_data *rxd;
struct macsec_dev *macsec; struct macsec_dev *macsec;
rcu_read_lock(); rcu_read_lock();
rxd = macsec_data_rcu(skb->dev); 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) { list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
struct sk_buff *nskb; struct sk_buff *nskb;
struct pcpu_secy_stats *secy_stats = this_cpu_ptr(macsec->stats); struct pcpu_secy_stats *secy_stats = this_cpu_ptr(macsec->stats);
struct net_device *ndev = macsec->secy.netdev;
if (!macsec_is_offloaded(macsec) && /* If h/w offloading is enabled, HW decodes frames and strips
macsec->secy.validate_frames == MACSEC_VALIDATE_STRICT) { * 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); u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsNoTag++; secy_stats->stats.InPktsNoTag++;
u64_stats_update_end(&secy_stats->syncp); u64_stats_update_end(&secy_stats->syncp);
...@@ -1033,19 +1064,13 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb) ...@@ -1033,19 +1064,13 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
if (!nskb) if (!nskb)
break; break;
nskb->dev = macsec->secy.netdev; nskb->dev = ndev;
if (netif_rx(nskb) == NET_RX_SUCCESS) { if (netif_rx(nskb) == NET_RX_SUCCESS) {
u64_stats_update_begin(&secy_stats->syncp); u64_stats_update_begin(&secy_stats->syncp);
secy_stats->stats.InPktsUntagged++; secy_stats->stats.InPktsUntagged++;
u64_stats_update_end(&secy_stats->syncp); u64_stats_update_end(&secy_stats->syncp);
} }
if (netif_running(macsec->secy.netdev) &&
macsec_is_offloaded(macsec)) {
ret = RX_HANDLER_EXACT;
goto out;
}
} }
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment