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 <mstarovoitov@marvell.com> Signed-off-by: Igor Russkikh <irusskikh@marvell.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a249f80506
commit
f428011b90
@ -1006,22 +1006,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);
|
||||
@ -1033,19 +1064,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:
|
||||
|
Loading…
Reference in New Issue
Block a user