diff options
Diffstat (limited to 'net/core/dev.c')
-rw-r--r-- | net/core/dev.c | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 74d0ccef22d..9b2e671c7b7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -104,6 +104,7 @@ #include <net/dst.h> #include <net/pkt_sched.h> #include <net/checksum.h> +#include <net/macsec.h> #include <linux/highmem.h> #include <linux/init.h> #include <linux/kmod.h> @@ -1721,6 +1722,13 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, if (dev->priv_flags & IFF_XMIT_DST_RELEASE) skb_dst_drop(skb); +#ifdef CONFIG_NET_MACSEC + if (netdev_macsec_priv(dev)) { + rc = dev->macsec_output_hw(skb, dev); + if (rc == -EINPROGRESS) + return 0; + } +#endif rc = ops->ndo_start_xmit(skb, dev); if (rc == NETDEV_TX_OK) txq_trans_update(txq); @@ -2350,7 +2358,21 @@ ncls: skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev); if (!skb) goto out; - + +#ifdef CONFIG_NET_MACSEC + if (macsec_type_trans(skb) == ETH_P_MACSEC) { + if (skb->dev->macsec_priv) { + ret = skb->dev->macsec_input_hw(skb); + if (ret == -EINPROGRESS) { + ret = 0; + goto out; + } + } + kfree_skb(skb); + ret = NET_RX_DROP; + goto out; + } +#endif type = skb->protocol; list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { @@ -2379,6 +2401,55 @@ out: } EXPORT_SYMBOL(netif_receive_skb); +int macsec_netif_receive_skb(struct sk_buff *skb, __be16 type) +{ + struct packet_type *ptype, *pt_prev; + struct net_device *orig_dev; + struct net_device *null_or_orig; + int ret = NET_RX_DROP; + + pt_prev = NULL; +#if 0 + orig_dev = skb_bond(skb); + if (!orig_dev) + return NET_RX_DROP; +#endif + //printk("calling macsec_netif_receive_skb\n"); + null_or_orig = NULL; + orig_dev = skb->dev; + if (orig_dev->master) { + printk("Master is Different\n"); + if (skb_bond_should_drop(skb)) + null_or_orig = orig_dev; /* deliver only exact match */ + else + skb->dev = orig_dev->master; + } + + list_for_each_entry_rcu(ptype, + &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { + if (ptype->type == type && + (ptype->dev == null_or_orig || ptype->dev == skb->dev || + ptype->dev == orig_dev)) { + if (pt_prev) { + ret = deliver_skb(skb, pt_prev, orig_dev); + } + pt_prev = ptype; + } + } + if (pt_prev) { + ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev); + } else { + if (skb_shinfo(skb)->nr_frags) { + printk(KERN_ERR "skb has frags which is not possible !!!\n"); + } + kfree_skb(skb); + ret = NET_RX_DROP; + } + + return ret; + +} + /* Network device is going away, flush any packets still pending */ static void flush_backlog(void *arg) { @@ -4328,6 +4399,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) int err; struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); const struct net_device_ops *ops; + void *mac_priv; if (!dev) return -ENODEV; @@ -4392,6 +4464,31 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) ifr->ifr_newname[IFNAMSIZ-1] = '\0'; return dev_change_name(dev, ifr->ifr_newname); + case SIOCSETMACSEC: +#ifdef CONFIG_NET_MACSEC + mac_priv = netdev_macsec_priv(dev); + err = 0; + if (!mac_priv){ + err = macsec_init_state(dev); + } else { + printk("Macsec session already set\n"); + return -EEXIST; + } + dev->hard_header_len = ETH_HLEN + 8; + return err; +#else + return -EINVAL; +#endif + + case SIOCUNSETMACSEC: +#ifdef CONFIG_NET_MACSEC + macsec_destroy(dev); + dev->hard_header_len = ETH_HLEN; + return 0; +#else + return -EINVAL; +#endif + /* * Unknown or private ioctl */ @@ -4550,6 +4647,8 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) case SIOCSIFFLAGS: case SIOCSIFMETRIC: case SIOCSIFMTU: + case SIOCSETMACSEC: + case SIOCUNSETMACSEC: case SIOCSIFMAP: case SIOCSIFHWADDR: case SIOCSIFSLAVE: |