aboutsummaryrefslogtreecommitdiff
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c101
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: