From fcf4a4369976cb355092c049e30916d9706fbae0 Mon Sep 17 00:00:00 2001 From: Catalin Boie Date: Wed, 17 Nov 2004 00:08:01 -0800 Subject: [PKT_SCHED]: Allow using nfmark as key in U32 classifier. Signed-off-by: Catalin(ux aka Dino) BOIE Signed-off-by: David S. Miller --- include/linux/pkt_cls.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h index 45ac289f1bbf..45ed903d247c 100644 --- a/include/linux/pkt_cls.h +++ b/include/linux/pkt_cls.h @@ -192,6 +192,7 @@ enum TCA_U32_ACT, TCA_U32_INDEV, TCA_U32_PCNT, + TCA_U32_MARK, __TCA_U32_MAX }; -- cgit v1.2.3 From 8f78d753284f7bee7cf7bcd27e230eb0a68aa751 Mon Sep 17 00:00:00 2001 From: Ian Pratt Date: Wed, 17 Nov 2004 22:03:59 -0800 Subject: [NET]: Add alloc_skb_from_cache. This serves two purposes: firstly, we like to allocate page-sized skbs as this means we zero-copy transfer of network buffers between guest operating systems. Secondly, it enables us to have a cache of pages that have been used for network buffers that we can be more lax about scrubbing when they change VM ownership (since they could be sniffed on the wire). Signed-off-by: David S. Miller --- include/linux/skbuff.h | 6 ++++++ net/core/skbuff.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 71fc2bdc0cd6..57a2843faa21 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -292,6 +292,8 @@ struct sk_buff { extern void __kfree_skb(struct sk_buff *skb); extern struct sk_buff *alloc_skb(unsigned int size, int priority); +extern struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, + unsigned int size, int priority); extern void kfree_skbmem(struct sk_buff *skb); extern struct sk_buff *skb_clone(struct sk_buff *skb, int priority); extern struct sk_buff *skb_copy(const struct sk_buff *skb, int priority); @@ -935,6 +937,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list) * * %NULL is returned in there is no free memory. */ +#ifndef CONFIG_HAVE_ARCH_DEV_ALLOC_SKB static inline struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask) { @@ -943,6 +946,9 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length, skb_reserve(skb, 16); return skb; } +#else +extern struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask); +#endif /** * dev_alloc_skb - allocate an skbuff for sending diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0bc35a015555..a6d1d698230e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -163,6 +163,59 @@ nodata: goto out; } +/** + * alloc_skb_from_cache - allocate a network buffer + * @cp: kmem_cache from which to allocate the data area + * (object size must be big enough for @size bytes + skb overheads) + * @size: size to allocate + * @gfp_mask: allocation mask + * + * Allocate a new &sk_buff. The returned buffer has no headroom and + * tail room of size bytes. The object has a reference count of one. + * The return is the buffer. On a failure the return is %NULL. + * + * Buffers may only be allocated from interrupts using a @gfp_mask of + * %GFP_ATOMIC. + */ +struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, + unsigned int size, int gfp_mask) +{ + struct sk_buff *skb; + u8 *data; + + /* Get the HEAD */ + skb = kmem_cache_alloc(skbuff_head_cache, + gfp_mask & ~__GFP_DMA); + if (!skb) + goto out; + + /* Get the DATA. */ + size = SKB_DATA_ALIGN(size); + data = kmem_cache_alloc(cp, gfp_mask); + if (!data) + goto nodata; + + memset(skb, 0, offsetof(struct sk_buff, truesize)); + skb->truesize = size + sizeof(struct sk_buff); + atomic_set(&skb->users, 1); + skb->head = data; + skb->data = data; + skb->tail = data; + skb->end = data + size; + + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->nr_frags = 0; + skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->tso_segs = 0; + skb_shinfo(skb)->frag_list = NULL; +out: + return skb; +nodata: + kmem_cache_free(skbuff_head_cache, skb); + skb = NULL; + goto out; +} + static void skb_drop_fraglist(struct sk_buff *skb) { -- cgit v1.2.3 From 8fb8f6c69cca3e4dad3da202c120b328b803f19b Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Tue, 23 Nov 2004 07:47:34 -0800 Subject: [EBTABLES]: Add userspace logging via netlink socket. The patch below adds the ebtables ulog watcher, that sends packets to userspace. It is based on ipt_ULOG.c. The complete packet, including Ethernet header, is sent to userspace. The in and out bridge ports are also sent to userspace. Logging is of course not restricted to IP packets. An example of a userspace program that receives and parses packets sent by the ulog watcher is in the ebtables CVS tree under examples/ulog/ Signed-off-by: Bart De Schuymer Signed-off-by: David S. Miller --- include/linux/netfilter_bridge/ebt_ulog.h | 36 ++++ include/linux/netfilter_bridge/ebtables.h | 6 +- net/bridge/netfilter/Kconfig | 18 +- net/bridge/netfilter/Makefile | 1 + net/bridge/netfilter/ebt_log.c | 5 +- net/bridge/netfilter/ebt_ulog.c | 295 ++++++++++++++++++++++++++++++ net/bridge/netfilter/ebtables.c | 6 +- 7 files changed, 357 insertions(+), 10 deletions(-) create mode 100644 include/linux/netfilter_bridge/ebt_ulog.h create mode 100644 net/bridge/netfilter/ebt_ulog.c (limited to 'include/linux') diff --git a/include/linux/netfilter_bridge/ebt_ulog.h b/include/linux/netfilter_bridge/ebt_ulog.h new file mode 100644 index 000000000000..b677e2671541 --- /dev/null +++ b/include/linux/netfilter_bridge/ebt_ulog.h @@ -0,0 +1,36 @@ +#ifndef _EBT_ULOG_H +#define _EBT_ULOG_H + +#define EBT_ULOG_DEFAULT_NLGROUP 0 +#define EBT_ULOG_DEFAULT_QTHRESHOLD 1 +#define EBT_ULOG_MAXNLGROUPS 32 /* hardcoded netlink max */ +#define EBT_ULOG_PREFIX_LEN 32 +#define EBT_ULOG_MAX_QLEN 50 +#define EBT_ULOG_WATCHER "ulog" +#define EBT_ULOG_VERSION 1 + +struct ebt_ulog_info { + uint32_t nlgroup; + unsigned int cprange; + unsigned int qthreshold; + char prefix[EBT_ULOG_PREFIX_LEN]; +}; + +typedef struct ebt_ulog_packet_msg { + int version; + char indev[IFNAMSIZ]; + char outdev[IFNAMSIZ]; + char physindev[IFNAMSIZ]; + char physoutdev[IFNAMSIZ]; + char prefix[EBT_ULOG_PREFIX_LEN]; + struct timeval stamp; + unsigned long mark; + unsigned int hook; + size_t data_len; + /* The complete packet, including Ethernet header and perhaps + * the VLAN header is appended */ + unsigned char data[0] __attribute__ + ((aligned (__alignof__(struct ebt_ulog_info)))); +} ebt_ulog_packet_msg_t; + +#endif /* _EBT_ULOG_H */ diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index b9fcbf85f047..b1a7cc90877b 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -201,9 +201,9 @@ struct ebt_watcher { struct list_head list; const char name[EBT_FUNCTION_MAXNAMELEN]; - void (*watcher)(const struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, const void *watcherdata, - unsigned int datalen); + void (*watcher)(const struct sk_buff *skb, unsigned int hooknr, + const struct net_device *in, const struct net_device *out, + const void *watcherdata, unsigned int datalen); /* 0 == let it in */ int (*check)(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *watcherdata, unsigned int datalen); diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig index b0e9f66269ee..68ccef507b49 100644 --- a/net/bridge/netfilter/Kconfig +++ b/net/bridge/netfilter/Kconfig @@ -189,8 +189,22 @@ config BRIDGE_EBT_LOG tristate "ebt: log support" depends on BRIDGE_NF_EBTABLES help - This option adds the log target, that you can use in any rule in - any ebtables table. It records the frame header to the syslog. + This option adds the log watcher, that you can use in any rule + in any ebtables table. It records info about the frame header + to the syslog. + + To compile it as a module, choose M here. If unsure, say N. + +config BRIDGE_EBT_ULOG + tristate "ebt: ulog support" + depends on BRIDGE_NF_EBTABLES + help + This option adds the ulog watcher, that you can use in any rule + in any ebtables table. The packet is passed to a userspace + logging daemon using netlink multicast sockets. This differs + from the log watcher in the sense that the complete packet is + sent to userspace instead of a descriptive text and that + netlink multicast sockets are used instead of the syslog. To compile it as a module, choose M here. If unsure, say N. diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile index 6b7d017fcd18..8bf6d9f6e9d3 100644 --- a/net/bridge/netfilter/Makefile +++ b/net/bridge/netfilter/Makefile @@ -29,3 +29,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o # watchers obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o +obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_ulog.o diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 6c022efaab80..5071e5327241 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -55,8 +55,9 @@ static void print_MAC(unsigned char *p) } #define myNIPQUAD(a) a[0], a[1], a[2], a[3] -static void ebt_log(const struct sk_buff *skb, const struct net_device *in, - const struct net_device *out, const void *data, unsigned int datalen) +static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, + const struct net_device *in, const struct net_device *out, + const void *data, unsigned int datalen) { struct ebt_log_info *info = (struct ebt_log_info *)data; char level_string[4] = "< >"; diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c new file mode 100644 index 000000000000..ea6c24f6ff26 --- /dev/null +++ b/net/bridge/netfilter/ebt_ulog.c @@ -0,0 +1,295 @@ +/* + * netfilter module for userspace bridged Ethernet frames logging daemons + * + * Authors: + * Bart De Schuymer + * + * November, 2004 + * + * Based on ipt_ULOG.c, which is + * (C) 2000-2002 by Harald Welte + * + * This module accepts two parameters: + * + * nlbufsiz: + * The parameter specifies how big the buffer for each netlink multicast + * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will + * get accumulated in the kernel until they are sent to userspace. It is + * NOT possible to allocate more than 128kB, and it is strongly discouraged, + * because atomically allocating 128kB inside the network rx softirq is not + * reliable. Please also keep in mind that this buffer size is allocated for + * each nlgroup you are using, so the total kernel memory usage increases + * by that factor. + * + * flushtimeout: + * Specify, after how many hundredths of a second the queue should be + * flushed even if it is not full yet. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../br_private.h" + +#define PRINTR(format, args...) do { if (net_ratelimit()) \ + printk(format , ## args); } while (0) + +static unsigned int nlbufsiz = 4096; +module_param(nlbufsiz, uint, 0600); +MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " + "(defaults to 4096)"); + +static unsigned int flushtimeout = 10; +module_param(flushtimeout, uint, 0600); +MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) " + "(defaults to 10)"); + +typedef struct { + unsigned int qlen; /* number of nlmsgs' in the skb */ + struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ + struct sk_buff *skb; /* the pre-allocated skb */ + struct timer_list timer; /* the timer function */ + spinlock_t lock; /* the per-queue lock */ +} ebt_ulog_buff_t; + +static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; +static struct sock *ebtulognl; + +/* send one ulog_buff_t to userspace */ +static void ulog_send(unsigned int nlgroup) +{ + ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup]; + + if (timer_pending(&ub->timer)) + del_timer(&ub->timer); + + /* last nlmsg needs NLMSG_DONE */ + if (ub->qlen > 1) + ub->lastnlh->nlmsg_type = NLMSG_DONE; + + NETLINK_CB(ub->skb).dst_groups = 1 << nlgroup; + netlink_broadcast(ebtulognl, ub->skb, 0, 1 << nlgroup, GFP_ATOMIC); + + ub->qlen = 0; + ub->skb = NULL; +} + +/* timer function to flush queue in flushtimeout time */ +static void ulog_timer(unsigned long data) +{ + spin_lock_bh(&ulog_buffers[data].lock); + if (ulog_buffers[data].skb) + ulog_send(data); + spin_unlock_bh(&ulog_buffers[data].lock); +} + +static struct sk_buff *ulog_alloc_skb(unsigned int size) +{ + struct sk_buff *skb; + + skb = alloc_skb(nlbufsiz, GFP_ATOMIC); + if (!skb) { + PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer " + "of size %ub!\n", nlbufsiz); + if (size < nlbufsiz) { + /* try to allocate only as much as we need for + * current packet */ + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) + PRINTR(KERN_ERR "ebt_ulog: can't even allocate " + "buffer of size %ub\n", size); + } + } + + return skb; +} + +static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, + const struct net_device *in, const struct net_device *out, + const void *data, unsigned int datalen) +{ + ebt_ulog_packet_msg_t *pm; + size_t size, copy_len; + struct nlmsghdr *nlh; + struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data; + unsigned int group = uloginfo->nlgroup; + ebt_ulog_buff_t *ub = &ulog_buffers[group]; + spinlock_t *lock = &ub->lock; + + if ((uloginfo->cprange == 0) || + (uloginfo->cprange > skb->len + ETH_HLEN)) + copy_len = skb->len + ETH_HLEN; + else + copy_len = uloginfo->cprange; + + size = NLMSG_SPACE(sizeof(*pm) + copy_len); + if (size > nlbufsiz) { + PRINTR("ebt_ulog: Size %d needed, but nlbufsiz=%d\n", + size, nlbufsiz); + return; + } + + spin_lock_bh(lock); + + if (!ub->skb) { + if (!(ub->skb = ulog_alloc_skb(size))) + goto alloc_failure; + } else if (size > skb_tailroom(ub->skb)) { + ulog_send(group); + + if (!(ub->skb = ulog_alloc_skb(size))) + goto alloc_failure; + } + + nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0, + size - NLMSG_ALIGN(sizeof(*nlh))); + ub->qlen++; + + pm = NLMSG_DATA(nlh); + + /* Fill in the ulog data */ + pm->version = EBT_ULOG_VERSION; + do_gettimeofday(&pm->stamp); + if (ub->qlen == 1) + ub->skb->stamp = pm->stamp; + pm->data_len = copy_len; + pm->mark = skb->nfmark; + pm->hook = hooknr; + if (uloginfo->prefix != NULL) + strcpy(pm->prefix, uloginfo->prefix); + else + *(pm->prefix) = '\0'; + + if (in) { + strcpy(pm->physindev, in->name); + /* If in isn't a bridge, then physindev==indev */ + if (in->br_port) + strcpy(pm->indev, in->br_port->br->dev->name); + else + strcpy(pm->indev, in->name); + } else + pm->indev[0] = pm->physindev[0] = '\0'; + + if (out) { + /* If out exists, then out is a bridge port */ + strcpy(pm->physoutdev, out->name); + strcpy(pm->outdev, out->br_port->br->dev->name); + } else + pm->outdev[0] = pm->physoutdev[0] = '\0'; + + if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) + BUG(); + + if (ub->qlen > 1) + ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; + + ub->lastnlh = nlh; + + if (ub->qlen >= uloginfo->qthreshold) + ulog_send(group); + else if (!timer_pending(&ub->timer)) { + ub->timer.expires = jiffies + flushtimeout * HZ / 100; + add_timer(&ub->timer); + } + +unlock: + spin_unlock_bh(lock); + + return; + +nlmsg_failure: + printk(KERN_CRIT "ebt_ulog: error during NLMSG_PUT. This should " + "not happen, please report to author.\n"); + goto unlock; +alloc_failure: + goto unlock; +} + +static int ebt_ulog_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen) +{ + struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data; + + if (datalen != EBT_ALIGN(sizeof(struct ebt_ulog_info)) || + uloginfo->nlgroup > 31) + return -EINVAL; + + uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; + + if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN) + uloginfo->qthreshold = EBT_ULOG_MAX_QLEN; + + return 0; +} + +static struct ebt_watcher ulog = { + .name = EBT_ULOG_WATCHER, + .watcher = ebt_ulog, + .check = ebt_ulog_check, + .me = THIS_MODULE, +}; + +static int __init init(void) +{ + int i, ret = 0; + + if (nlbufsiz >= 128*1024) { + printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB," + " please try a smaller nlbufsiz parameter.\n"); + return -EINVAL; + } + + /* initialize ulog_buffers */ + for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { + init_timer(&ulog_buffers[i].timer); + ulog_buffers[i].timer.function = ulog_timer; + ulog_buffers[i].timer.data = i; + ulog_buffers[i].lock = SPIN_LOCK_UNLOCKED; + } + + ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL); + if (!ebtulognl) + ret = -ENOMEM; + else if ((ret = ebt_register_watcher(&ulog))) + sock_release(ebtulognl->sk_socket); + + return ret; +} + +static void __exit fini(void) +{ + ebt_ulog_buff_t *ub; + int i; + + ebt_unregister_watcher(&ulog); + for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { + ub = &ulog_buffers[i]; + if (timer_pending(&ub->timer)) + del_timer(&ub->timer); + spin_lock_bh(&ub->lock); + if (ub->skb) { + kfree_skb(ub->skb); + ub->skb = NULL; + } + spin_unlock_bh(&ub->lock); + } + sock_release(ebtulognl->sk_socket); +} + +module_init(init); +module_exit(fini); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Bart De Schuymer "); +MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet" + " frames"); diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 00926f0bb3a9..33dde2be31ba 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -90,10 +90,10 @@ static struct ebt_target ebt_standard_target = { {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL}; static inline int ebt_do_watcher (struct ebt_entry_watcher *w, - const struct sk_buff *skb, const struct net_device *in, + const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out) { - w->u.watcher->watcher(skb, in, out, w->data, + w->u.watcher->watcher(skb, hooknr, in, out, w->data, w->watcher_size); /* watchers don't give a verdict */ return 0; @@ -208,7 +208,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb, /* these should only watch: not modify, nor tell us what to do with the packet */ - EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, in, + EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, hook, in, out); t = (struct ebt_entry_target *) -- cgit v1.2.3 From 4db3af5c739b99ec1edf38f074a4b6e6717b02b1 Mon Sep 17 00:00:00 2001 From: Esben Nielsen Date: Tue, 23 Nov 2004 07:54:43 -0800 Subject: [ARCNET]: Fixes. As previously reported the ArcNet driver didn't work with Preempt and SMB on. They do now. I have changed the locking system from being a global arcnet lock to being a lock per device. I used the lock in dev->hard_start_xmit = arcnet_send_packet. Furthermore I added the 'CAP mode' encapsulation. As far as I see it it is the only encapsulation which actually makes ArcNet usefull over ethernet. Previously, the driver just ignored the hardware transmit status, now you can get hardware acknowledge and excessive nacks back to userspace via a raw socket. The capmode.c is nearly just a copy of arc-rawmode.c. The difference is that it inserts a ack_tx() handle into the general driver framework. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/arcnet/Kconfig | 19 +++ drivers/net/arcnet/Makefile | 1 + drivers/net/arcnet/arc-rawmode.c | 9 +- drivers/net/arcnet/arcnet.c | 253 ++++++++++++++++++++++---------- drivers/net/arcnet/capmode.c | 296 ++++++++++++++++++++++++++++++++++++++ drivers/net/arcnet/com20020-isa.c | 1 - drivers/net/arcnet/com20020.c | 28 ++-- drivers/net/arcnet/rfc1051.c | 3 + drivers/net/arcnet/rfc1201.c | 2 + include/linux/arcdevice.h | 21 ++- include/linux/com20020.h | 30 ++-- include/linux/if_arcnet.h | 14 ++ include/linux/if_ether.h | 1 + 13 files changed, 574 insertions(+), 104 deletions(-) create mode 100644 drivers/net/arcnet/capmode.c (limited to 'include/linux') diff --git a/drivers/net/arcnet/Kconfig b/drivers/net/arcnet/Kconfig index 528691c8df8b..b258fe614e82 100644 --- a/drivers/net/arcnet/Kconfig +++ b/drivers/net/arcnet/Kconfig @@ -59,6 +59,25 @@ config ARCNET_RAW to work unless talking to a copy of the same Linux arcnet driver, but perhaps marginally faster in that case. +config ARCNET_CAP + tristate "Enable CAP mode packet interface" + depends on ARCNET + help + ARCnet "cap mode" packet encapsulation. Used to get the hardware + acknowledge back to userspace. After the initial protocol byte every + packet is stuffed with an extra 4 byte "cookie" which doesn't + actually appear on the network. After transmit the driver will send + back a packet with protocol byte 0 containing the status of the + transmition: + 0=no hardware acknowledge + 1=excessive nak + 2=transmition accepted by the reciever hardware + + Received packets are also stuffed with the extra 4 bytes but it will + be random data. + + Cap only listens to protocol 1-8. + config ARCNET_COM90xx tristate "ARCnet COM90xx (normal) chipset driver" depends on ARCNET diff --git a/drivers/net/arcnet/Makefile b/drivers/net/arcnet/Makefile index e4dae223a344..5861af543d42 100644 --- a/drivers/net/arcnet/Makefile +++ b/drivers/net/arcnet/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_ARCNET) += arcnet.o obj-$(CONFIG_ARCNET_1201) += rfc1201.o obj-$(CONFIG_ARCNET_1051) += rfc1051.o obj-$(CONFIG_ARCNET_RAW) += arc-rawmode.o +obj-$(CONFIG_ARCNET_CAP) += capmode.o obj-$(CONFIG_ARCNET_COM90xx) += com90xx.o obj-$(CONFIG_ARCNET_COM90xxIO) += com90io.o obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c index 222caa4a243d..925574cc6b32 100644 --- a/drivers/net/arcnet/arc-rawmode.c +++ b/drivers/net/arcnet/arc-rawmode.c @@ -42,7 +42,6 @@ static int build_header(struct sk_buff *skb, struct net_device *dev, static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, int bufnum); - struct ArcProto rawmode_proto = { .suffix = 'r', @@ -50,6 +49,8 @@ struct ArcProto rawmode_proto = .rx = rx, .build_header = build_header, .prepare_tx = prepare_tx, + .continue_tx = NULL, + .ack_tx = NULL }; @@ -121,7 +122,8 @@ static void rx(struct net_device *dev, int bufnum, BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); - skb->protocol = 0; + skb->protocol = __constant_htons(ETH_P_ARCNET); +; netif_rx(skb); dev->last_rx = jiffies; } @@ -190,6 +192,9 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, } else hard->offset[0] = ofs = 256 - length; + BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", + length,ofs); + lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft, length); diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 5d304676f3df..6b4051df2d6f 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -53,7 +53,6 @@ #include #include - /* "do nothing" functions for protocol drivers */ static void null_rx(struct net_device *dev, int bufnum, struct archdr *pkthdr, int length); @@ -69,25 +68,28 @@ static int null_prepare_tx(struct net_device *dev, struct archdr *pkt, * arc_proto_default instead. It also must not be NULL; if you would like * to set it to NULL, set it to &arc_proto_null instead. */ -struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto; + struct ArcProto *arc_proto_map[256], *arc_proto_default, + *arc_bcast_proto, *arc_raw_proto; struct ArcProto arc_proto_null = { .suffix = '?', .mtu = XMTU, + .is_ip = 0, .rx = null_rx, .build_header = null_build_header, .prepare_tx = null_prepare_tx, + .continue_tx = NULL, + .ack_tx = NULL }; -static spinlock_t arcnet_lock = SPIN_LOCK_UNLOCKED; - /* Exported function prototypes */ int arcnet_debug = ARCNET_DEBUG; EXPORT_SYMBOL(arc_proto_map); EXPORT_SYMBOL(arc_proto_default); EXPORT_SYMBOL(arc_bcast_proto); +EXPORT_SYMBOL(arc_raw_proto); EXPORT_SYMBOL(arc_proto_null); EXPORT_SYMBOL(arcnet_unregister_proto); EXPORT_SYMBOL(arcnet_debug); @@ -131,7 +133,7 @@ static int __init arcnet_init(void) #endif /* initialize the protocol map */ - arc_proto_default = arc_bcast_proto = &arc_proto_null; + arc_raw_proto = arc_proto_default = arc_bcast_proto = &arc_proto_null; for (count = 0; count < 256; count++) arc_proto_map[count] = arc_proto_default; @@ -155,7 +157,8 @@ module_exit(arcnet_exit); * Dump the contents of an sk_buff */ #if ARCNET_DEBUG_MAX & D_SKB -void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) +void arcnet_dump_skb(struct net_device *dev, + struct sk_buff *skb, char *desc) { int i; @@ -176,18 +179,22 @@ EXPORT_SYMBOL(arcnet_dump_skb); * Dump the contents of an ARCnet buffer */ #if (ARCNET_DEBUG_MAX & (D_RX | D_TX)) -void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc) +void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, + int take_arcnet_lock) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int i, length; - unsigned long flags; + unsigned long flags = 0; static uint8_t buf[512]; /* hw.copy_from_card expects IRQ context so take the IRQ lock to keep it single threaded */ - spin_lock_irqsave(&arcnet_lock, flags); + if(take_arcnet_lock) + spin_lock_irqsave(&lp->lock, flags); + lp->hw.copy_from_card(dev, bufnum, 0, buf, 512); - spin_unlock_irqrestore(&arcnet_lock, flags); + if(take_arcnet_lock) + spin_unlock_irqrestore(&lp->lock, flags); /* if the offset[0] byte is nonzero, this is a 256-byte packet */ length = (buf[2] ? 256 : 512); @@ -219,6 +226,8 @@ void arcnet_unregister_proto(struct ArcProto *proto) arc_proto_default = &arc_proto_null; if (arc_bcast_proto == proto) arc_bcast_proto = arc_proto_default; + if (arc_raw_proto == proto) + arc_raw_proto = arc_proto_default; for (count = 0; count < 256; count++) { if (arc_proto_map[count] == proto) @@ -261,8 +270,11 @@ static int get_arcbuf(struct net_device *dev) struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int buf = -1, i; - if (!atomic_dec_and_test(&lp->buf_lock)) /* already in this function */ - BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n", lp->buf_lock.counter); + if (!atomic_dec_and_test(&lp->buf_lock)) { + /* already in this function */ + BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n", + lp->buf_lock.counter); + } else { /* we can continue */ if (lp->next_buf >= 5) lp->next_buf -= 5; @@ -312,7 +324,7 @@ void arcdev_setup(struct net_device *dev) dev->mtu = choose_mtu(); dev->addr_len = ARCNET_ALEN; - dev->tx_queue_len = 30; + dev->tx_queue_len = 100; dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */ dev->watchdog_timeo = TX_TIMEOUT; @@ -334,8 +346,16 @@ void arcdev_setup(struct net_device *dev) struct net_device *alloc_arcdev(char *name) { - return alloc_netdev(sizeof(struct arcnet_local), - name && *name ? name : "arc%d", arcdev_setup); + struct net_device *dev; + + dev = alloc_netdev(sizeof(struct arcnet_local), + name && *name ? name : "arc%d", arcdev_setup); + if(dev) { + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + lp->lock = SPIN_LOCK_UNLOCKED; + } + + return dev; } /* @@ -351,6 +371,8 @@ static int arcnet_open(struct net_device *dev) struct arcnet_local *lp = (struct arcnet_local *) dev->priv; int count, newmtu, error; + BUGMSG(D_INIT,"opened."); + if (!try_module_get(lp->hw.owner)) return -ENODEV; @@ -377,6 +399,8 @@ static int arcnet_open(struct net_device *dev) if (newmtu < dev->mtu) dev->mtu = newmtu; + BUGMSG(D_INIT, "arcnet_open: mtu: %d.\n", dev->mtu); + /* autodetect the encapsulation for each host. */ memset(lp->default_proto, 0, sizeof(lp->default_proto)); @@ -390,6 +414,7 @@ static int arcnet_open(struct net_device *dev) /* initialize buffers */ atomic_set(&lp->buf_lock, 1); + lp->next_buf = lp->first_free_buf = 0; release_arcbuf(dev, 0); release_arcbuf(dev, 1); @@ -411,17 +436,24 @@ static int arcnet_open(struct net_device *dev) BUGMSG(D_NORMAL, "WARNING! Station address FF may confuse " "DOS networking programs!\n"); - if (ASTATUS() & RESETflag) + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + if (ASTATUS() & RESETflag) { + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); ACOMMAND(CFLAGScmd | RESETclear); + } + + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); /* make sure we're ready to receive IRQ's. */ AINTMASK(0); udelay(1); /* give it time to set the mask before * we reset it again. (may not even be * necessary) */ + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); lp->intmask = NORXflag | RECONflag; AINTMASK(lp->intmask); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); netif_start_queue(dev); @@ -467,32 +499,41 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev, daddr ? *(uint8_t *) daddr : -1, type, type, len); - if (len != skb->len) + if (skb->len!=0 && len != skb->len) BUGMSG(D_NORMAL, "arcnet_header: Yikes! skb->len(%d) != len(%d)!\n", skb->len, len); - /* - * if the dest addr isn't provided, we can't choose an encapsulation! - * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a - * real header when we do rebuild_header. - */ - if (!daddr) { + + /* Type is host order - ? */ + if(type == ETH_P_ARCNET) { + proto = arc_raw_proto; + BUGMSG(D_DEBUG, "arc_raw_proto used. proto='%c'\n",proto->suffix); + _daddr = daddr ? *(uint8_t *) daddr : 0; + } + else if (!daddr) { + /* + * if the dest addr isn't provided, we can't choose an encapsulation! + * Store the packet type (eg. ETH_P_IP) for now, and we'll push on a + * real header when we do rebuild_header. + */ *(uint16_t *) skb_push(skb, 2) = type; if (skb->nh.raw - skb->mac.raw != 2) BUGMSG(D_NORMAL, "arcnet_header: Yikes! diff (%d) is not 2!\n", (int)(skb->nh.raw - skb->mac.raw)); return -2; /* return error -- can't transmit yet! */ } - /* otherwise, we can just add the header as usual. */ - _daddr = *(uint8_t *) daddr; - proto_num = lp->default_proto[_daddr]; - proto = arc_proto_map[proto_num]; - BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n", - proto_num, proto->suffix); - if (proto == &arc_proto_null && arc_bcast_proto != proto) { - BUGMSG(D_DURING, "actually, let's use '%c' instead.\n", - arc_bcast_proto->suffix); - proto = arc_bcast_proto; + else { + /* otherwise, we can just add the header as usual. */ + _daddr = *(uint8_t *) daddr; + proto_num = lp->default_proto[_daddr]; + proto = arc_proto_map[proto_num]; + BUGMSG(D_DURING, "building header for %02Xh using protocol '%c'\n", + proto_num, proto->suffix); + if (proto == &arc_proto_null && arc_bcast_proto != proto) { + BUGMSG(D_DURING, "actually, let's use '%c' instead.\n", + arc_bcast_proto->suffix); + proto = arc_bcast_proto; + } } return proto->build_header(skb, dev, type, _daddr); } @@ -519,6 +560,7 @@ static int arcnet_rebuild_header(struct sk_buff *skb) return 0; } type = *(uint16_t *) skb_pull(skb, 2); + BUGMSG(D_DURING, "rebuild header for protocol %Xh\n", type); if (type == ETH_P_IP) { #ifdef CONFIG_INET @@ -555,10 +597,12 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) struct arc_rfc1201 *soft; struct ArcProto *proto; int txbuf; + unsigned long flags; + int freeskb = 0; BUGMSG(D_DURING, - "transmit requested (status=%Xh, txbufs=%d/%d, len=%d)\n", - ASTATUS(), lp->cur_tx, lp->next_tx, skb->len); + "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n", + ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol); pkt = (struct archdr *) skb->data; soft = &pkt->soft.rfc1201; @@ -578,38 +622,49 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev) /* We're busy transmitting a packet... */ netif_stop_queue(dev); + spin_lock_irqsave(&lp->lock, flags); AINTMASK(0); txbuf = get_arcbuf(dev); if (txbuf != -1) { - if (proto->prepare_tx(dev, pkt, skb->len, txbuf)) { - /* done right away */ + if (proto->prepare_tx(dev, pkt, skb->len, txbuf) && + !proto->ack_tx) { + /* done right away and we don't want to acknowledge + the package later - forget about it now */ lp->stats.tx_bytes += skb->len; - dev_kfree_skb(skb); + freeskb = 1; } else { /* do it the 'split' way */ lp->outgoing.proto = proto; lp->outgoing.skb = skb; lp->outgoing.pkt = pkt; - if (!proto->continue_tx) - BUGMSG(D_NORMAL, "bug! prep_tx==0, but no continue_tx!\n"); - else if (proto->continue_tx(dev, txbuf)) { - BUGMSG(D_NORMAL, - "bug! continue_tx finished the first time! " - "(proto='%c')\n", proto->suffix); + if (proto->continue_tx && + proto->continue_tx(dev, txbuf)) { + BUGMSG(D_NORMAL, + "bug! continue_tx finished the first time! " + "(proto='%c')\n", proto->suffix); } } lp->next_tx = txbuf; - } else - dev_kfree_skb(skb); + } else { + freeskb = 1; + } + BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS()); /* make sure we didn't ignore a TX IRQ while we were in here */ AINTMASK(0); - lp->intmask |= TXFREEflag; + + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); + lp->intmask |= TXFREEflag|EXCNAKflag; AINTMASK(lp->intmask); + BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS()); + spin_unlock_irqrestore(&lp->lock, flags); + if (freeskb) { + dev_kfree_skb(skb); + } return 0; /* no need to try again */ } @@ -628,7 +683,7 @@ static int go_tx(struct net_device *dev) if (lp->cur_tx != -1 || lp->next_tx == -1) return 0; - BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx"); + BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0); lp->cur_tx = lp->next_tx; lp->next_tx = -1; @@ -640,7 +695,8 @@ static int go_tx(struct net_device *dev) lp->stats.tx_packets++; lp->lasttrans_dest = lp->lastload_dest; lp->lastload_dest = 0; - lp->intmask |= TXFREEflag; + lp->excnak_pending = 0; + lp->intmask |= TXFREEflag|EXCNAKflag; return 1; } @@ -654,7 +710,7 @@ static void arcnet_timeout(struct net_device *dev) int status = ASTATUS(); char *msg; - spin_lock_irqsave(&arcnet_lock, flags); + spin_lock_irqsave(&lp->lock, flags); if (status & TXFREEflag) { /* transmit _DID_ finish */ msg = " - missed IRQ?"; } else { @@ -665,12 +721,12 @@ static void arcnet_timeout(struct net_device *dev) } lp->stats.tx_errors++; - /* make sure we didn't miss a TX IRQ */ + /* make sure we didn't miss a TX or a EXC NAK IRQ */ AINTMASK(0); - lp->intmask |= TXFREEflag; + lp->intmask |= TXFREEflag|EXCNAKflag; AINTMASK(lp->intmask); - spin_unlock_irqrestore(&arcnet_lock, flags); + spin_unlock_irqrestore(&lp->lock, flags); if (jiffies - lp->last_timeout > 10*HZ) { BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n", @@ -692,18 +748,19 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct arcnet_local *lp; - int recbuf, status, didsomething, boguscount; + int recbuf, status, diagstatus, didsomething, boguscount; + int retval = IRQ_NONE; BUGMSG(D_DURING, "\n"); BUGMSG(D_DURING, "in arcnet_interrupt\n"); - - spin_lock(&arcnet_lock); lp = (struct arcnet_local *) dev->priv; if (!lp) BUG(); + spin_lock(&lp->lock); + /* * RESET flag was enabled - if device is not running, we must clear it right * away (but nothing else). @@ -712,7 +769,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (ASTATUS() & RESETflag) ACOMMAND(CFLAGScmd | RESETclear); AINTMASK(0); - spin_unlock(&arcnet_lock); + spin_unlock(&lp->lock); return IRQ_HANDLED; } @@ -722,6 +779,10 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) boguscount = 5; do { status = ASTATUS(); + diagstatus = (status >> 8) & 0xFF; + + BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n", + __FILE__,__LINE__,__FUNCTION__,status); didsomething = 0; /* @@ -761,24 +822,55 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) } didsomething++; } + + if((diagstatus & EXCNAKflag)) { + BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n", + diagstatus); + + ACOMMAND(NOTXcmd); /* disable transmit */ + lp->excnak_pending = 1; + + ACOMMAND(EXCNAKclear); + lp->intmask &= ~(EXCNAKflag); + didsomething++; + } + + /* a transmit finished, and we're interested in it. */ if ((status & lp->intmask & TXFREEflag) || lp->timed_out) { - lp->intmask &= ~TXFREEflag; + lp->intmask &= ~(TXFREEflag|EXCNAKflag); BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status); - if (lp->cur_tx != -1 && !(status & TXACKflag) && !lp->timed_out) { - if (lp->lasttrans_dest != 0) { - BUGMSG(D_EXTRA, "transmit was not acknowledged! " - "(status=%Xh, dest=%02Xh)\n", - status, lp->lasttrans_dest); - lp->stats.tx_errors++; - lp->stats.tx_carrier_errors++; - } else { - BUGMSG(D_DURING, - "broadcast was not acknowledged; that's normal " - "(status=%Xh, dest=%02Xh)\n", - status, lp->lasttrans_dest); + if (lp->cur_tx != -1 && !lp->timed_out) { + if(!(status & TXACKflag)) { + if (lp->lasttrans_dest != 0) { + BUGMSG(D_EXTRA, + "transmit was not acknowledged! " + "(status=%Xh, dest=%02Xh)\n", + status, lp->lasttrans_dest); + lp->stats.tx_errors++; + lp->stats.tx_carrier_errors++; + } else { + BUGMSG(D_DURING, + "broadcast was not acknowledged; that's normal " + "(status=%Xh, dest=%02Xh)\n", + status, lp->lasttrans_dest); + } + } + + if (lp->outgoing.proto && + lp->outgoing.proto->ack_tx) { + int ackstatus; + if(status & TXACKflag) + ackstatus=2; + else if(lp->excnak_pending) + ackstatus=1; + else + ackstatus=0; + + lp->outgoing.proto + ->ack_tx(dev, ackstatus); } } if (lp->cur_tx != -1) @@ -798,8 +890,11 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (lp->outgoing.proto->continue_tx(dev, txbuf)) { /* that was the last segment */ lp->stats.tx_bytes += lp->outgoing.skb->len; - dev_kfree_skb_irq(lp->outgoing.skb); - lp->outgoing.proto = NULL; + if(!lp->outgoing.proto->ack_tx) + { + dev_kfree_skb_irq(lp->outgoing.skb); + lp->outgoing.proto = NULL; + } } lp->next_tx = txbuf; } @@ -810,7 +905,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) } /* now process the received packet, if any */ if (recbuf != -1) { - BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq"); + BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq", 0); arcnet_rx(dev, recbuf); release_arcbuf(dev, recbuf); @@ -868,6 +963,10 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) BUGMSG(D_DURING, "not recon: clearing counters anyway.\n"); } + + if(didsomething) { + retval |= IRQ_HANDLED; + } } while (--boguscount && didsomething); @@ -880,8 +979,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) udelay(1); AINTMASK(lp->intmask); - spin_unlock(&arcnet_lock); - return IRQ_RETVAL(didsomething); + spin_unlock(&lp->lock); + return retval; } @@ -908,7 +1007,7 @@ void arcnet_rx(struct net_device *dev, int bufnum) } /* get the full header, if possible */ - if (sizeof(pkt.soft) < length) + if (sizeof(pkt.soft) <= length) lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft)); else { memset(&pkt.soft, 0, sizeof(pkt.soft)); @@ -923,7 +1022,7 @@ void arcnet_rx(struct net_device *dev, int bufnum) lp->stats.rx_bytes += length + ARC_HDR_SIZE; /* call the right receiver for the protocol */ - if (arc_proto_map[soft->proto] != &arc_proto_null) { + if (arc_proto_map[soft->proto]->is_ip) { BUGLVL(D_PROTO) { struct ArcProto *oldp = arc_proto_map[lp->default_proto[pkt.hard.source]], diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c new file mode 100644 index 000000000000..16e155b04129 --- /dev/null +++ b/drivers/net/arcnet/capmode.c @@ -0,0 +1,296 @@ +/* + * Linux ARCnet driver - "cap mode" packet encapsulation. + * It adds sequence numbers to packets for communicating between a user space + * application and the driver. After a transmit it sends a packet with protocol + * byte 0 back up to the userspace containing the sequence number of the packet + * plus the transmit-status on the ArcNet. + * + * Written 2002-4 by Esben Nielsen, Vestas Wind Systems A/S + * Derived from arc-rawmode.c by Avery Pennarun. + * arc-rawmode was in turned based on skeleton.c, see below. + * + * ********************** + * + * The original copyright of skeleton.c was as follows: + * + * skeleton.c Written 1993 by Donald Becker. + * Copyright 1993 United States Government as represented by the + * Director, National Security Agency. This software may only be used + * and distributed according to the terms of the GNU General Public License as + * modified by SRC, incorporated herein by reference. + * + * ********************** + * + * For more details, see drivers/net/arcnet.c + * + * ********************** + */ + +#include +#include +#include +#include +#include +#include +#include + +#define VERSION "arcnet: cap mode (`c') encapsulation support loaded.\n" + + +static void rx(struct net_device *dev, int bufnum, + struct archdr *pkthdr, int length); +static int build_header(struct sk_buff *skb, + struct net_device *dev, + unsigned short type, + uint8_t daddr); +static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, + int bufnum); +static int ack_tx(struct net_device *dev, int acked); + + +struct ArcProto capmode_proto = +{ + 'r', + XMTU, + 0, + rx, + build_header, + prepare_tx, + NULL, + ack_tx +}; + + +void arcnet_cap_init(void) +{ + int count; + + for (count = 1; count <= 8; count++) + if (arc_proto_map[count] == arc_proto_default) + arc_proto_map[count] = &capmode_proto; + + /* for cap mode, we only set the bcast proto if there's no better one */ + if (arc_bcast_proto == arc_proto_default) + arc_bcast_proto = &capmode_proto; + + arc_proto_default = &capmode_proto; + arc_raw_proto = &capmode_proto; +} + + +#ifdef MODULE + +int __init init_module(void) +{ + printk(VERSION); + arcnet_cap_init(); + return 0; +} + +void cleanup_module(void) +{ + arcnet_unregister_proto(&capmode_proto); +} + +MODULE_LICENSE("GPL"); +#endif /* MODULE */ + + + +/* packet receiver */ +static void rx(struct net_device *dev, int bufnum, + struct archdr *pkthdr, int length) +{ + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + struct sk_buff *skb; + struct archdr *pkt = pkthdr; + char *pktbuf, *pkthdrbuf; + int ofs; + + BUGMSG(D_DURING, "it's a raw(cap) packet (length=%d)\n", length); + + if (length >= MinTU) + ofs = 512 - length; + else + ofs = 256 - length; + + skb = alloc_skb(length + ARC_HDR_SIZE + sizeof(int), GFP_ATOMIC); + if (skb == NULL) { + BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n"); + lp->stats.rx_dropped++; + return; + } + skb_put(skb, length + ARC_HDR_SIZE + sizeof(int)); + skb->dev = dev; + + pkt = (struct archdr *) skb->data; + + skb->mac.raw = skb->data; + skb_pull(skb, ARC_HDR_SIZE); + + /* up to sizeof(pkt->soft) has already been copied from the card */ + /* squeeze in an int for the cap encapsulation */ + + /* use these variables to be sure we count in bytes, not in + sizeof(struct archdr) */ + pktbuf=(char*)pkt; + pkthdrbuf=(char*)pkthdr; + memcpy(pktbuf, pkthdrbuf, ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)); + memcpy(pktbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto)+sizeof(int), + pkthdrbuf+ARC_HDR_SIZE+sizeof(pkt->soft.cap.proto), + sizeof(struct archdr)-ARC_HDR_SIZE-sizeof(pkt->soft.cap.proto)); + + if (length > sizeof(pkt->soft)) + lp->hw.copy_from_card(dev, bufnum, ofs + sizeof(pkt->soft), + pkt->soft.raw + sizeof(pkt->soft) + + sizeof(int), + length - sizeof(pkt->soft)); + + BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx"); + + skb->protocol = __constant_htons(ETH_P_ARCNET); +; + netif_rx(skb); + dev->last_rx = jiffies; +} + + +/* + * Create the ARCnet hard/soft headers for cap mode. + * There aren't any soft headers in cap mode - not even the protocol id. + */ +static int build_header(struct sk_buff *skb, + struct net_device *dev, + unsigned short type, + uint8_t daddr) +{ + int hdr_size = ARC_HDR_SIZE; + struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size); + + BUGMSG(D_PROTO, "Preparing header for cap packet %x.\n", + *((int*)&pkt->soft.cap.cookie[0])); + /* + * Set the source hardware address. + * + * This is pretty pointless for most purposes, but it can help in + * debugging. ARCnet does not allow us to change the source address in + * the actual packet sent) + */ + pkt->hard.source = *dev->dev_addr; + + /* see linux/net/ethernet/eth.c to see where I got the following */ + + if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { + /* + * FIXME: fill in the last byte of the dest ipaddr here to better + * comply with RFC1051 in "noarp" mode. + */ + pkt->hard.dest = 0; + return hdr_size; + } + /* otherwise, just fill it in and go! */ + pkt->hard.dest = daddr; + + return hdr_size; /* success */ +} + + +static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, + int bufnum) +{ + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + struct arc_hardware *hard = &pkt->hard; + int ofs; + + + /* hard header is not included in packet length */ + length -= ARC_HDR_SIZE; + /* And neither is the cookie field */ + length -= sizeof(int); + + BUGMSG(D_DURING, "prepare_tx: txbufs=%d/%d/%d\n", + lp->next_tx, lp->cur_tx, bufnum); + + BUGMSG(D_PROTO, "Sending for cap packet %x.\n", + *((int*)&pkt->soft.cap.cookie[0])); + + if (length > XMTU) { + /* should never happen! other people already check for this. */ + BUGMSG(D_NORMAL, "Bug! prepare_tx with size %d (> %d)\n", + length, XMTU); + length = XMTU; + } + if (length > MinTU) { + hard->offset[0] = 0; + hard->offset[1] = ofs = 512 - length; + } else if (length > MTU) { + hard->offset[0] = 0; + hard->offset[1] = ofs = 512 - length - 3; + } else + hard->offset[0] = ofs = 256 - length; + + BUGMSG(D_DURING, "prepare_tx: length=%d ofs=%d\n", + length,ofs); + + // Copy the arcnet-header + the protocol byte down: + lp->hw.copy_to_card(dev, bufnum, 0, hard, ARC_HDR_SIZE); + lp->hw.copy_to_card(dev, bufnum, ofs, &pkt->soft.cap.proto, + sizeof(pkt->soft.cap.proto)); + + // Skip the extra integer we have written into it as a cookie + // but write the rest of the message: + lp->hw.copy_to_card(dev, bufnum, ofs+1, + ((unsigned char*)&pkt->soft.cap.mes),length-1); + + lp->lastload_dest = hard->dest; + + return 1; /* done */ +} + + +static int ack_tx(struct net_device *dev, int acked) +{ + struct arcnet_local *lp = (struct arcnet_local *) dev->priv; + struct sk_buff *ackskb; + struct archdr *ackpkt; + int length=sizeof(struct arc_cap); + + BUGMSG(D_DURING, "capmode: ack_tx: protocol: %x: result: %d\n", + lp->outgoing.skb->protocol, acked); + + BUGLVL(D_SKB) arcnet_dump_skb(dev, lp->outgoing.skb, "ack_tx"); + + /* Now alloc a skb to send back up through the layers: */ + ackskb = alloc_skb(length + ARC_HDR_SIZE , GFP_ATOMIC); + if (ackskb == NULL) { + BUGMSG(D_NORMAL, "Memory squeeze, can't acknowledge.\n"); + goto free_outskb; + } + + skb_put(ackskb, length + ARC_HDR_SIZE ); + ackskb->dev = dev; + + ackpkt = (struct archdr *) ackskb->data; + + ackskb->mac.raw = ackskb->data; + /* skb_pull(ackskb, ARC_HDR_SIZE); */ + + + memcpy(ackpkt, lp->outgoing.skb->data, ARC_HDR_SIZE+sizeof(struct arc_cap)); + ackpkt->soft.cap.proto=0; /* using protocol 0 for acknowledge */ + ackpkt->soft.cap.mes.ack=acked; + + BUGMSG(D_PROTO, "Ackknowledge for cap packet %x.\n", + *((int*)&ackpkt->soft.cap.cookie[0])); + + ackskb->protocol = __constant_htons(ETH_P_ARCNET); + + BUGLVL(D_SKB) arcnet_dump_skb(dev, ackskb, "ack_tx_recv"); + netif_rx(ackskb); + + free_outskb: + dev_kfree_skb_irq(lp->outgoing.skb); + lp->outgoing.proto = NULL; /* We are always finished when in this protocol */ + + return 0; +} diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index 09af99a724b2..9289e6103de5 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -41,7 +41,6 @@ #include - #define VERSION "arcnet: COM20020 ISA support (by David Woodhouse et al.)\n" diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 7fa829eef427..b40ee3ff7fb4 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -117,7 +117,7 @@ int com20020_check(struct net_device *dev) lp->config = 0x21 | (lp->timeout << 3) | (lp->backplane << 2); /* set node ID to 0x42 (but transmitter is disabled, so it's okay) */ SETCONF; - outb(0x42, ioaddr + 7); + outb(0x42, ioaddr + BUS_ALIGN*7); status = ASTATUS(); @@ -129,7 +129,7 @@ int com20020_check(struct net_device *dev) /* Enable TX */ outb(0x39, _CONFIG); - outb(inb(ioaddr + 8), ioaddr + 7); + outb(inb(ioaddr + BUS_ALIGN*8), ioaddr + BUS_ALIGN*7); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); @@ -173,7 +173,7 @@ int com20020_found(struct net_device *dev, int shared) dev->set_multicast_list = com20020_set_mc_list; if (!dev->dev_addr[0]) - dev->dev_addr[0] = inb(ioaddr + 8); /* FIXME: do this some other way! */ + dev->dev_addr[0] = inb(ioaddr + BUS_ALIGN*8); /* FIXME: do this some other way! */ SET_SUBADR(SUB_SETUP1); outb(lp->setup, _XREG); @@ -188,7 +188,6 @@ int com20020_found(struct net_device *dev, int shared) outb(0x18, _COMMAND); } - lp->config = 0x20 | (lp->timeout << 3) | (lp->backplane << 2) | 1; /* Default 0x38 + register: Node ID */ SETCONF; @@ -235,15 +234,19 @@ int com20020_found(struct net_device *dev, int shared) static int com20020_reset(struct net_device *dev, int really_reset) { struct arcnet_local *lp = (struct arcnet_local *) dev->priv; - short ioaddr = dev->base_addr; + u_int ioaddr = dev->base_addr; u_char inbyte; + BUGMSG(D_DEBUG, "%s: %d: %s: dev: %p, lp: %p, dev->name: %s\n", + __FILE__,__LINE__,__FUNCTION__,dev,lp,dev->name); BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS()); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); lp->config = TXENcfg | (lp->timeout << 3) | (lp->backplane << 2); /* power-up defaults */ SETCONF; + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); if (really_reset) { /* reset the card */ @@ -251,17 +254,22 @@ static int com20020_reset(struct net_device *dev, int really_reset) mdelay(RESETtime * 2); /* COM20020 seems to be slower sometimes */ } /* clear flags & end reset */ + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear); /* verify that the ARCnet signature byte is present */ + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); com20020_copy_from_card(dev, 0, 0, &inbyte, 1); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); if (inbyte != TESTvalue) { + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n"); return 1; } /* enable extended (512-byte) packets */ ACOMMAND(CONFIGcmd | EXTconf); + BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__); /* done! return success. */ return 0; @@ -270,22 +278,24 @@ static int com20020_reset(struct net_device *dev, int really_reset) static void com20020_setmask(struct net_device *dev, int mask) { - short ioaddr = dev->base_addr; + u_int ioaddr = dev->base_addr; + BUGMSG(D_DURING, "Setting mask to %x at %x\n",mask,ioaddr); AINTMASK(mask); } static void com20020_command(struct net_device *dev, int cmd) { - short ioaddr = dev->base_addr; + u_int ioaddr = dev->base_addr; ACOMMAND(cmd); } static int com20020_status(struct net_device *dev) { - short ioaddr = dev->base_addr; - return ASTATUS(); + u_int ioaddr = dev->base_addr; + + return ASTATUS() + (ADIAGSTATUS()<<8); } static void com20020_close(struct net_device *dev) diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c index 3fd23f97bd46..fd959cb3ef7d 100644 --- a/drivers/net/arcnet/rfc1051.c +++ b/drivers/net/arcnet/rfc1051.c @@ -47,9 +47,12 @@ struct ArcProto rfc1051_proto = { .suffix = 's', .mtu = XMTU - RFC1051_HDR_SIZE, + .is_ip = 1, .rx = rx, .build_header = build_header, .prepare_tx = prepare_tx, + .continue_tx = NULL, + .ack_tx = NULL }; diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c index ff1d434c7c51..ed793b15f0ee 100644 --- a/drivers/net/arcnet/rfc1201.c +++ b/drivers/net/arcnet/rfc1201.c @@ -47,10 +47,12 @@ struct ArcProto rfc1201_proto = { .suffix = 'a', .mtu = 1500, /* could be more, but some receivers can't handle it... */ + .is_ip = 1, /* This is for sending IP and ARP packages */ .rx = rx, .build_header = build_header, .prepare_tx = prepare_tx, .continue_tx = continue_tx, + .ack_tx = NULL }; diff --git a/include/linux/arcdevice.h b/include/linux/arcdevice.h index 9d2429f07a64..bd4364daf948 100644 --- a/include/linux/arcdevice.h +++ b/include/linux/arcdevice.h @@ -25,7 +25,6 @@ #define bool int #endif - /* * RECON_THRESHOLD is the maximum number of RECON messages to receive * within one minute before printing a "cabling problem" warning. The @@ -74,6 +73,7 @@ #define D_SKB 1024 /* show skb's */ #define D_SKB_SIZE 2048 /* show skb sizes */ #define D_TIMING 4096 /* show time needed to copy buffers to card */ +#define D_DEBUG 8192 /* Very detailed debug line for line */ #ifndef ARCNET_DEBUG_MAX #define ARCNET_DEBUG_MAX (127) /* change to ~0 if you want detailed debugging */ @@ -135,6 +135,7 @@ extern int arcnet_debug; #define TXACKflag 0x02 /* transmitted msg. ackd */ #define RECONflag 0x04 /* network reconfigured */ #define TESTflag 0x08 /* test flag */ +#define EXCNAKflag 0x08 /* excesive nak flag */ #define RESETflag 0x10 /* power-on-reset */ #define RES1flag 0x20 /* reserved - usually set by jumper */ #define RES2flag 0x40 /* reserved - usually set by jumper */ @@ -162,6 +163,8 @@ extern int arcnet_debug; #define RESETclear 0x08 /* power-on-reset */ #define CONFIGclear 0x10 /* system reconfigured */ +#define EXCNAKclear 0x0E /* Clear and acknowledge the excive nak bit */ + /* flags for "load test flags" command */ #define TESTload 0x08 /* test flag (diagnostic) */ @@ -187,6 +190,7 @@ extern int arcnet_debug; struct ArcProto { char suffix; /* a for RFC1201, e for ether-encap, etc. */ int mtu; /* largest possible packet */ + int is_ip; /* This is a ip plugin - not a raw thing */ void (*rx) (struct net_device * dev, int bufnum, struct archdr * pkthdr, int length); @@ -197,9 +201,11 @@ struct ArcProto { int (*prepare_tx) (struct net_device * dev, struct archdr * pkt, int length, int bufnum); int (*continue_tx) (struct net_device * dev, int bufnum); + int (*ack_tx) (struct net_device * dev, int acked); }; -extern struct ArcProto *arc_proto_map[256], *arc_proto_default, *arc_bcast_proto; +extern struct ArcProto *arc_proto_map[256], *arc_proto_default, + *arc_bcast_proto, *arc_raw_proto; extern struct ArcProto arc_proto_null; @@ -251,6 +257,10 @@ struct arcnet_local { char *card_name; /* card ident string */ int card_flags; /* special card features */ + + /* On preemtive and SMB a lock is needed */ + spinlock_t lock; + /* * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of * which can be used for either sending or receiving. The new dynamic @@ -279,6 +289,8 @@ struct arcnet_local { int num_recons; /* number of RECONs between first and last. */ bool network_down; /* do we think the network is down? */ + bool excnak_pending; /* We just got an excesive nak interrupt */ + struct { uint16_t sequence; /* sequence number (incs with each packet) */ uint16_t aborted_seq; @@ -323,9 +335,10 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc); #endif #if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX) -void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc); +void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc, + int take_arcnet_lock); #else -#define arcnet_dump_packet(dev, bufnum, desc) ; +#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) ; #endif void arcnet_unregister_proto(struct ArcProto *proto); diff --git a/include/linux/com20020.h b/include/linux/com20020.h index c88d530bf637..ac6d9a43e085 100644 --- a/include/linux/com20020.h +++ b/include/linux/com20020.h @@ -34,17 +34,24 @@ int com20020_found(struct net_device *dev, int shared); #define ARCNET_TOTAL_SIZE 8 /* various register addresses */ -#define _INTMASK (ioaddr+0) /* writable */ -#define _STATUS (ioaddr+0) /* readable */ -#define _COMMAND (ioaddr+1) /* standard arcnet commands */ -#define _DIAGSTAT (ioaddr+1) /* diagnostic status register */ -#define _ADDR_HI (ioaddr+2) /* control registers for IO-mapped memory */ -#define _ADDR_LO (ioaddr+3) -#define _MEMDATA (ioaddr+4) /* data port for IO-mapped memory */ -#define _SUBADR (ioaddr+5) /* the extended port _XREG refers to */ -#define _CONFIG (ioaddr+6) /* configuration register */ -#define _XREG (ioaddr+7) /* extra registers (indexed by _CONFIG - or _SUBADR) */ +#ifdef CONFIG_SA1100_CT6001 +#define BUS_ALIGN 2 /* 8 bit device on a 16 bit bus - needs padding */ +#else +#define BUS_ALIGN 1 +#endif + + +#define _INTMASK (ioaddr+BUS_ALIGN*0) /* writable */ +#define _STATUS (ioaddr+BUS_ALIGN*0) /* readable */ +#define _COMMAND (ioaddr+BUS_ALIGN*1) /* standard arcnet commands */ +#define _DIAGSTAT (ioaddr+BUS_ALIGN*1) /* diagnostic status register */ +#define _ADDR_HI (ioaddr+BUS_ALIGN*2) /* control registers for IO-mapped memory */ +#define _ADDR_LO (ioaddr+BUS_ALIGN*3) +#define _MEMDATA (ioaddr+BUS_ALIGN*4) /* data port for IO-mapped memory */ +#define _SUBADR (ioaddr+BUS_ALIGN*5) /* the extended port _XREG refers to */ +#define _CONFIG (ioaddr+BUS_ALIGN*6) /* configuration register */ +#define _XREG (ioaddr+BUS_ALIGN*7) /* extra registers (indexed by _CONFIG + or _SUBADR) */ /* in the ADDR_HI register */ #define RDDATAflag 0x80 /* next access is a read (not a write) */ @@ -99,6 +106,7 @@ int com20020_found(struct net_device *dev, int shared); } #define ASTATUS() inb(_STATUS) +#define ADIAGSTATUS() inb(_DIAGSTAT) #define ACOMMAND(cmd) outb((cmd),_COMMAND) #define AINTMASK(msk) outb((msk),_INTMASK) diff --git a/include/linux/if_arcnet.h b/include/linux/if_arcnet.h index 08f413b0fceb..af380cb876a0 100644 --- a/include/linux/if_arcnet.h +++ b/include/linux/if_arcnet.h @@ -23,6 +23,9 @@ * These are the defined ARCnet Protocol ID's. */ +/* CAP mode */ +/* No macro but uses 1-8 */ + /* RFC1201 Protocol ID's */ #define ARC_P_IP 212 /* 0xD4 */ #define ARC_P_IPV6 196 /* 0xC4: RFC2497 */ @@ -86,6 +89,16 @@ struct arc_eth_encap #define ETH_ENCAP_HDR_SIZE 14 +struct arc_cap +{ + uint8_t proto; + uint8_t cookie[sizeof(int)]; /* Actually NOT sent over the network */ + union { + uint8_t ack; + uint8_t raw[0]; /* 507 bytes */ + } mes; +}; + /* * The data needed by the actual arcnet hardware. * @@ -116,6 +129,7 @@ struct archdr struct arc_rfc1201 rfc1201; struct arc_rfc1051 rfc1051; struct arc_eth_encap eth_encap; + struct arc_cap cap; uint8_t raw[0]; /* 508 bytes */ } soft; }; diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 4037aaab7aa9..75c1a290c8c2 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -91,6 +91,7 @@ #define ETH_P_IRDA 0x0017 /* Linux-IrDA */ #define ETH_P_ECONET 0x0018 /* Acorn Econet */ #define ETH_P_HDLC 0x0019 /* HDLC frames */ +#define ETH_P_ARCNET 0x001A /* 1A for ArcNet :-) */ /* * This is an Ethernet frame header. -- cgit v1.2.3 From 9a8ce58ac0161da625aeae2ef3ca91c681ca526e Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 27 Nov 2004 14:20:20 +0100 Subject: [NETFILTER]: Remove CONFIG_IP_NF_NAT_LOCAL config option Signed-off-by: Patrick McHardy --- arch/alpha/defconfig | 1 - arch/arm/configs/ebsa110_defconfig | 1 - arch/arm/configs/ixp4xx_defconfig | 1 - arch/i386/defconfig | 1 - arch/m68k/configs/amiga_defconfig | 1 - arch/m68k/configs/apollo_defconfig | 1 - arch/m68k/configs/atari_defconfig | 1 - arch/m68k/configs/bvme6000_defconfig | 1 - arch/m68k/configs/hp300_defconfig | 1 - arch/m68k/configs/mac_defconfig | 1 - arch/m68k/configs/mvme147_defconfig | 1 - arch/m68k/configs/mvme16x_defconfig | 1 - arch/m68k/configs/q40_defconfig | 1 - arch/m68k/configs/sun3_defconfig | 1 - arch/m68k/configs/sun3x_defconfig | 1 - arch/mips/configs/ip22_defconfig | 1 - arch/mips/configs/rm200_defconfig | 1 - arch/mips/defconfig | 1 - arch/parisc/configs/a500_defconfig | 1 - arch/parisc/configs/c3000_defconfig | 1 - arch/parisc/configs/n4000_defconfig | 1 - arch/ppc/configs/adir_defconfig | 1 - arch/ppc/configs/apus_defconfig | 1 - arch/ppc/configs/common_defconfig | 1 - arch/ppc/configs/ibmchrp_defconfig | 1 - arch/ppc/configs/k2_defconfig | 1 - arch/ppc/configs/menf1_defconfig | 1 - arch/ppc/configs/pcore_defconfig | 1 - arch/ppc/configs/pmac_defconfig | 1 - arch/ppc/configs/pplus_defconfig | 1 - arch/ppc/defconfig | 1 - arch/ppc64/configs/g5_defconfig | 1 - arch/ppc64/configs/iSeries_defconfig | 1 - arch/ppc64/configs/pSeries_defconfig | 1 - arch/ppc64/defconfig | 1 - arch/sparc64/defconfig | 1 - include/linux/netfilter_ipv4/ip_nat.h | 5 ----- net/ipv4/netfilter/Kconfig | 14 -------------- net/ipv4/netfilter/ip_nat_core.c | 8 -------- net/ipv4/netfilter/ip_nat_rule.c | 11 ----------- net/ipv4/netfilter/ip_nat_standalone.c | 26 ++++---------------------- 41 files changed, 4 insertions(+), 96 deletions(-) (limited to 'include/linux') diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index 6ac8d4a7d634..5e39b7a7c8f4 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -411,7 +411,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m # CONFIG_IP_NF_TARGET_REDIRECT is not set # CONFIG_IP_NF_TARGET_NETMAP is not set # CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/arm/configs/ebsa110_defconfig b/arch/arm/configs/ebsa110_defconfig index 68f4047fc309..5296812f87d8 100644 --- a/arch/arm/configs/ebsa110_defconfig +++ b/arch/arm/configs/ebsa110_defconfig @@ -239,7 +239,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_IP_NF_TARGET_REDIRECT=y CONFIG_IP_NF_TARGET_NETMAP=y CONFIG_IP_NF_TARGET_SAME=y -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_NAT_IRC=y CONFIG_IP_NF_NAT_FTP=y diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig index 7b821f811a86..3a068df0e6d7 100644 --- a/arch/arm/configs/ixp4xx_defconfig +++ b/arch/arm/configs/ixp4xx_defconfig @@ -399,7 +399,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m # CONFIG_IP_NF_TARGET_NETMAP is not set # CONFIG_IP_NF_TARGET_SAME is not set -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 1a0ba2c4d88b..8b91f12fdbc5 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -534,7 +534,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_IP_NF_TARGET_REDIRECT=y CONFIG_IP_NF_TARGET_NETMAP=y CONFIG_IP_NF_TARGET_SAME=y -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_MANGLE=y CONFIG_IP_NF_TARGET_TOS=y diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig index d9c4a1a1e2ee..736015226cda 100644 --- a/arch/m68k/configs/amiga_defconfig +++ b/arch/m68k/configs/amiga_defconfig @@ -356,7 +356,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig index e6a0881c65e6..8b26f5562158 100644 --- a/arch/m68k/configs/apollo_defconfig +++ b/arch/m68k/configs/apollo_defconfig @@ -281,7 +281,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig index 9c39729f8f06..64b235758c10 100644 --- a/arch/m68k/configs/atari_defconfig +++ b/arch/m68k/configs/atari_defconfig @@ -311,7 +311,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig index 971d96965675..3300ee17c8b6 100644 --- a/arch/m68k/configs/bvme6000_defconfig +++ b/arch/m68k/configs/bvme6000_defconfig @@ -281,7 +281,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig index 06db209c14c3..e3dd814a8334 100644 --- a/arch/m68k/configs/hp300_defconfig +++ b/arch/m68k/configs/hp300_defconfig @@ -282,7 +282,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig index 45065e68ceda..00584b78ccc0 100644 --- a/arch/m68k/configs/mac_defconfig +++ b/arch/m68k/configs/mac_defconfig @@ -318,7 +318,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig index 7232b0cfbbda..07c0b063582f 100644 --- a/arch/m68k/configs/mvme147_defconfig +++ b/arch/m68k/configs/mvme147_defconfig @@ -282,7 +282,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig index 8f87aebaa8f8..792d016e548c 100644 --- a/arch/m68k/configs/mvme16x_defconfig +++ b/arch/m68k/configs/mvme16x_defconfig @@ -281,7 +281,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig index eb4dba248aab..44ec065ff0fa 100644 --- a/arch/m68k/configs/q40_defconfig +++ b/arch/m68k/configs/q40_defconfig @@ -336,7 +336,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig index 640ab0ad12a7..e905b02b7356 100644 --- a/arch/m68k/configs/sun3_defconfig +++ b/arch/m68k/configs/sun3_defconfig @@ -270,7 +270,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig index 315dd4d7eccf..5df8adaa3a43 100644 --- a/arch/m68k/configs/sun3x_defconfig +++ b/arch/m68k/configs/sun3x_defconfig @@ -281,7 +281,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 8bc7792d6cf6..26b2ef143873 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -342,7 +342,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index 2ec3932802cd..790f94c542dd 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -437,7 +437,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 8bc7792d6cf6..26b2ef143873 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -342,7 +342,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig index e5c57399e67c..6cbb2118673f 100644 --- a/arch/parisc/configs/a500_defconfig +++ b/arch/parisc/configs/a500_defconfig @@ -338,7 +338,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig index 087dfcd1d4c9..902775106de4 100644 --- a/arch/parisc/configs/c3000_defconfig +++ b/arch/parisc/configs/c3000_defconfig @@ -396,7 +396,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/parisc/configs/n4000_defconfig b/arch/parisc/configs/n4000_defconfig index 8df4bb1cc7b1..605718cfe99f 100644 --- a/arch/parisc/configs/n4000_defconfig +++ b/arch/parisc/configs/n4000_defconfig @@ -331,7 +331,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc/configs/adir_defconfig b/arch/ppc/configs/adir_defconfig index 3c40aaaecb98..f20e6533dc79 100644 --- a/arch/ppc/configs/adir_defconfig +++ b/arch/ppc/configs/adir_defconfig @@ -302,7 +302,6 @@ CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc/configs/apus_defconfig b/arch/ppc/configs/apus_defconfig index 53fb29358a67..e2245252d31f 100644 --- a/arch/ppc/configs/apus_defconfig +++ b/arch/ppc/configs/apus_defconfig @@ -354,7 +354,6 @@ CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig index 1e331f73523d..ac453e160070 100644 --- a/arch/ppc/configs/common_defconfig +++ b/arch/ppc/configs/common_defconfig @@ -457,7 +457,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc/configs/ibmchrp_defconfig b/arch/ppc/configs/ibmchrp_defconfig index a3b6ec0d5592..27f3e69c1f96 100644 --- a/arch/ppc/configs/ibmchrp_defconfig +++ b/arch/ppc/configs/ibmchrp_defconfig @@ -367,7 +367,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc/configs/k2_defconfig b/arch/ppc/configs/k2_defconfig index edf52030f95b..f10f5a6d2dae 100644 --- a/arch/ppc/configs/k2_defconfig +++ b/arch/ppc/configs/k2_defconfig @@ -319,7 +319,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m # CONFIG_IP_NF_TARGET_NETMAP is not set # CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_NAT_FTP=m # CONFIG_IP_NF_MANGLE is not set diff --git a/arch/ppc/configs/menf1_defconfig b/arch/ppc/configs/menf1_defconfig index e84d06af2b29..321659b5505f 100644 --- a/arch/ppc/configs/menf1_defconfig +++ b/arch/ppc/configs/menf1_defconfig @@ -249,7 +249,6 @@ CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc/configs/pcore_defconfig b/arch/ppc/configs/pcore_defconfig index ba09d840d03f..ed34405a7574 100644 --- a/arch/ppc/configs/pcore_defconfig +++ b/arch/ppc/configs/pcore_defconfig @@ -332,7 +332,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m # CONFIG_IP_NF_TARGET_NETMAP is not set # CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig index ce480563bd7b..c8e1d5d0c70d 100644 --- a/arch/ppc/configs/pmac_defconfig +++ b/arch/ppc/configs/pmac_defconfig @@ -479,7 +479,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc/configs/pplus_defconfig b/arch/ppc/configs/pplus_defconfig index f1153f58a3e3..5e459bcbf591 100644 --- a/arch/ppc/configs/pplus_defconfig +++ b/arch/ppc/configs/pplus_defconfig @@ -343,7 +343,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m # CONFIG_IP_NF_TARGET_NETMAP is not set # CONFIG_IP_NF_TARGET_SAME is not set -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_NAT_FTP=m # CONFIG_IP_NF_MANGLE is not set diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig index 86b2164302e0..729c32efe62d 100644 --- a/arch/ppc/defconfig +++ b/arch/ppc/defconfig @@ -464,7 +464,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig index 9cc01b5ba633..39c0eb00ddd3 100644 --- a/arch/ppc64/configs/g5_defconfig +++ b/arch/ppc64/configs/g5_defconfig @@ -440,7 +440,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_IP_NF_TARGET_REDIRECT=y CONFIG_IP_NF_TARGET_NETMAP=y CONFIG_IP_NF_TARGET_SAME=y -# CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_MANGLE=y CONFIG_IP_NF_TARGET_TOS=y diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig index 84ae55bcc4c5..0ee69246bab8 100644 --- a/arch/ppc64/configs/iSeries_defconfig +++ b/arch/ppc64/configs/iSeries_defconfig @@ -316,7 +316,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig index 73981148d88f..5d242e1530a4 100644 --- a/arch/ppc64/configs/pSeries_defconfig +++ b/arch/ppc64/configs/pSeries_defconfig @@ -408,7 +408,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig index f5503873a953..cdee0276b87e 100644 --- a/arch/ppc64/defconfig +++ b/arch/ppc64/defconfig @@ -374,7 +374,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -# CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index d6cce39f27b3..9152a1c011bb 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -601,7 +601,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_SAME=m -CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h index c4a3622604b7..16fc49298174 100644 --- a/include/linux/netfilter_ipv4/ip_nat.h +++ b/include/linux/netfilter_ipv4/ip_nat.h @@ -11,13 +11,8 @@ enum ip_nat_manip_type IP_NAT_MANIP_DST }; -#ifndef CONFIG_IP_NF_NAT_LOCAL -/* SRC manip occurs only on POST_ROUTING */ -#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING) -#else /* SRC manip occurs POST_ROUTING or LOCAL_IN */ #define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) != NF_IP_LOCAL_IN) -#endif #define IP_NAT_RANGE_MAP_IPS 1 #define IP_NAT_RANGE_PROTO_SPECIFIED 2 diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index eb8cf140ef51..2d59090cbf6f 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -504,20 +504,6 @@ config IP_NF_TARGET_SAME To compile it as a module, choose M here. If unsure, say N. -config IP_NF_NAT_LOCAL - bool "NAT of local connections (READ HELP)" - depends on IP_NF_NAT - help - This option enables support for NAT of locally originated connections. - Enable this if you need to use destination NAT on connections - originating from local processes on the nat box itself. - - Please note that you will need a recent version (>= 1.2.6a) - of the iptables userspace program in order to use this feature. - See for download instructions. - - If unsure, say 'N'. - config IP_NF_NAT_SNMP_BASIC tristate "Basic SNMP-ALG support (EXPERIMENTAL)" depends on EXPERIMENTAL && IP_NF_NAT diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 4ff337eb1e81..4b00d4886e6f 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -182,7 +182,6 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple, return 0; } -#ifdef CONFIG_IP_NF_NAT_LOCAL /* If it's really a local destination manip, it may need to do a source manip too. */ static int @@ -202,7 +201,6 @@ do_extra_mangle(u_int32_t var_ip, u_int32_t *other_ipp) ip_rt_put(rt); return 1; } -#endif /* Simple way to iterate through all. */ static inline int fake_cmp(const struct ip_conntrack *ct, @@ -301,7 +299,6 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple, * do_extra_mangle last time. */ *other_ipp = saved_ip; -#ifdef CONFIG_IP_NF_NAT_LOCAL if (hooknum == NF_IP_LOCAL_OUT && *var_ipp != orig_dstip && !do_extra_mangle(*var_ipp, other_ipp)) { @@ -312,7 +309,6 @@ find_best_ips_proto(struct ip_conntrack_tuple *tuple, * anyway. */ continue; } -#endif /* Count how many others map onto this. */ score = count_maps(tuple->src.ip, tuple->dst.ip, @@ -356,13 +352,11 @@ find_best_ips_proto_fast(struct ip_conntrack_tuple *tuple, else { /* Only do extra mangle when required (breaks socket binding) */ -#ifdef CONFIG_IP_NF_NAT_LOCAL if (tuple->dst.ip != mr->range[0].min_ip && hooknum == NF_IP_LOCAL_OUT && !do_extra_mangle(mr->range[0].min_ip, &tuple->src.ip)) return NULL; -#endif tuple->dst.ip = mr->range[0].min_ip; } } @@ -473,10 +467,8 @@ get_unique_tuple(struct ip_conntrack_tuple *tuple, static unsigned int opposite_hook[NF_IP_NUMHOOKS] = { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING, [NF_IP_POST_ROUTING] = NF_IP_PRE_ROUTING, -#ifdef CONFIG_IP_NF_NAT_LOCAL [NF_IP_LOCAL_OUT] = NF_IP_LOCAL_IN, [NF_IP_LOCAL_IN] = NF_IP_LOCAL_OUT, -#endif }; unsigned int diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index 9f727b630923..db0bf47bacff 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c @@ -149,12 +149,8 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; -#ifdef CONFIG_IP_NF_NAT_LOCAL IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING || hooknum == NF_IP_LOCAL_OUT); -#else - IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING); -#endif ct = ip_conntrack_get(*pskb, &ctinfo); @@ -232,13 +228,6 @@ static int ipt_dnat_checkentry(const char *tablename, return 0; } -#ifndef CONFIG_IP_NF_NAT_LOCAL - if (hook_mask & (1 << NF_IP_LOCAL_OUT)) { - DEBUGP("DNAT: CONFIG_IP_NF_NAT_LOCAL not enabled\n"); - return 0; - } -#endif - return 1; } diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index c37d35879168..0ef8efffb91b 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -128,16 +128,7 @@ ip_nat_fn(unsigned int hooknum, WRITE_LOCK(&ip_nat_lock); /* Seen it before? This can happen for loopback, retrans, or local packets.. */ - if (!(info->initialized & (1 << maniptype)) -#ifndef CONFIG_IP_NF_NAT_LOCAL - /* If this session has already been confirmed we must not - * touch it again even if there is no mapping set up. - * Can only happen on local->local traffic with - * CONFIG_IP_NF_NAT_LOCAL disabled. - */ - && !(ct->status & IPS_CONFIRMED) -#endif - ) { + if (!(info->initialized & (1 << maniptype))) { unsigned int ret; if (ct->master @@ -146,15 +137,14 @@ ip_nat_fn(unsigned int hooknum, ret = call_expect(master_ct(ct), pskb, hooknum, ct, info); } else { -#ifdef CONFIG_IP_NF_NAT_LOCAL /* LOCAL_IN hook doesn't have a chain! */ if (hooknum == NF_IP_LOCAL_IN) ret = alloc_null_binding(ct, info, hooknum); else -#endif - ret = ip_nat_rule_find(pskb, hooknum, in, out, - ct, info); + ret = ip_nat_rule_find(pskb, hooknum, + in, out, ct, + info); } if (ret != NF_ACCEPT) { @@ -234,7 +224,6 @@ ip_nat_out(unsigned int hooknum, return ip_nat_fn(hooknum, pskb, in, out, okfn); } -#ifdef CONFIG_IP_NF_NAT_LOCAL static unsigned int ip_nat_local_fn(unsigned int hooknum, struct sk_buff **pskb, @@ -260,7 +249,6 @@ ip_nat_local_fn(unsigned int hooknum, return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP; return ret; } -#endif /* We must be after connection tracking and before packet filtering. */ @@ -282,7 +270,6 @@ static struct nf_hook_ops ip_nat_out_ops = { .priority = NF_IP_PRI_NAT_SRC, }; -#ifdef CONFIG_IP_NF_NAT_LOCAL /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_local_out_ops = { .hook = ip_nat_local_fn, @@ -300,7 +287,6 @@ static struct nf_hook_ops ip_nat_local_in_ops = { .hooknum = NF_IP_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC, }; -#endif /* Protocol registration. */ int ip_nat_protocol_register(struct ip_nat_protocol *proto) @@ -357,7 +343,6 @@ static int init_or_cleanup(int init) printk("ip_nat_init: can't register out hook.\n"); goto cleanup_inops; } -#ifdef CONFIG_IP_NF_NAT_LOCAL ret = nf_register_hook(&ip_nat_local_out_ops); if (ret < 0) { printk("ip_nat_init: can't register local out hook.\n"); @@ -368,16 +353,13 @@ static int init_or_cleanup(int init) printk("ip_nat_init: can't register local in hook.\n"); goto cleanup_localoutops; } -#endif return ret; cleanup: -#ifdef CONFIG_IP_NF_NAT_LOCAL nf_unregister_hook(&ip_nat_local_in_ops); cleanup_localoutops: nf_unregister_hook(&ip_nat_local_out_ops); cleanup_outops: -#endif nf_unregister_hook(&ip_nat_out_ops); cleanup_inops: nf_unregister_hook(&ip_nat_in_ops); -- cgit v1.2.3 From ce9b008ad480cc3f01c39d292c9532d148a0018f Mon Sep 17 00:00:00 2001 From: Michal Ludvig Date: Tue, 30 Nov 2004 06:01:06 -0800 Subject: [CRYPTO]: Standalone VIA PadLock driver. Signed-off-by: David S. Miller --- crypto/Kconfig | 1 + drivers/Makefile | 1 + drivers/crypto/Kconfig | 23 ++ drivers/crypto/Makefile | 7 + drivers/crypto/padlock-aes.c | 470 +++++++++++++++++++++++++++++++++++++++ drivers/crypto/padlock-generic.c | 63 ++++++ drivers/crypto/padlock.h | 36 +++ include/linux/crypto.h | 3 + 8 files changed, 604 insertions(+) create mode 100644 drivers/crypto/Kconfig create mode 100644 drivers/crypto/Makefile create mode 100644 drivers/crypto/padlock-aes.c create mode 100644 drivers/crypto/padlock-generic.c create mode 100644 drivers/crypto/padlock.h (limited to 'include/linux') diff --git a/crypto/Kconfig b/crypto/Kconfig index 3f0f54a2190c..06d45679dbb8 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -274,5 +274,6 @@ config CRYPTO_TEST help Quick & dirty crypto test module. +source "drivers/crypto/Kconfig" endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 46b313027b8d..fe3956d17e17 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_MMC) += mmc/ obj-y += firmware/ +obj-$(CONFIG_CRYPTO) += crypto/ diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig new file mode 100644 index 000000000000..094835cce321 --- /dev/null +++ b/drivers/crypto/Kconfig @@ -0,0 +1,23 @@ +menu "Hardware crypto devices" + +config CRYPTO_DEV_PADLOCK + tristate "Support for VIA PadLock ACE" + depends on CRYPTO && X86 && !X86_64 + help + Some VIA processors come with an integrated crypto engine + (so called VIA PadLock ACE, Advanced Cryptography Engine) + that provides instructions for very fast {en,de}cryption + with some algorithms. + + The instructions are used only when the CPU supports them. + Otherwise software encryption is used. If you are unsure, + say Y. + +config CRYPTO_DEV_PADLOCK_AES + bool "Support for AES in VIA PadLock" + depends on CRYPTO_DEV_PADLOCK + default y + help + Use VIA PadLock for AES algorithm. + +endmenu diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile new file mode 100644 index 000000000000..45426ca19a23 --- /dev/null +++ b/drivers/crypto/Makefile @@ -0,0 +1,7 @@ + +obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o + +padlock-objs-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o + +padlock-objs := padlock-generic.o $(padlock-objs-y) + diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c new file mode 100644 index 000000000000..dd148de5eef8 --- /dev/null +++ b/drivers/crypto/padlock-aes.c @@ -0,0 +1,470 @@ +/* + * Cryptographic API. + * + * Support for VIA PadLock hardware crypto engine. + * + * Copyright (c) 2004 Michal Ludvig + * + * Key expansion routine taken from crypto/aes.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * --------------------------------------------------------------------------- + * Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and/or fitness for purpose. + * --------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include +#include +#include "padlock.h" + +#define AES_MIN_KEY_SIZE 16 /* in uint8_t units */ +#define AES_MAX_KEY_SIZE 32 /* ditto */ +#define AES_BLOCK_SIZE 16 /* ditto */ +#define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */ +#define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t)) + +static inline int aes_hw_extkey_available (uint8_t key_len); + +struct aes_ctx { + uint32_t e_data[AES_EXTENDED_KEY_SIZE+4]; + uint32_t d_data[AES_EXTENDED_KEY_SIZE+4]; + uint32_t *E; + uint32_t *D; + int key_length; +}; + +/* ====== Key management routines ====== */ + +static inline uint32_t +generic_rotr32 (const uint32_t x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x >> n) | (x << (32 - n)); +} + +static inline uint32_t +generic_rotl32 (const uint32_t x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x << n) | (x >> (32 - n)); +} + +#define rotl generic_rotl32 +#define rotr generic_rotr32 + +/* + * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) + */ +static inline uint8_t +byte(const uint32_t x, const unsigned n) +{ + return x >> (n << 3); +} + +#define uint32_t_in(x) le32_to_cpu(*(const uint32_t *)(x)) +#define uint32_t_out(to, from) (*(uint32_t *)(to) = cpu_to_le32(from)) + +#define E_KEY ctx->E +#define D_KEY ctx->D + +static uint8_t pow_tab[256]; +static uint8_t log_tab[256]; +static uint8_t sbx_tab[256]; +static uint8_t isb_tab[256]; +static uint32_t rco_tab[10]; +static uint32_t ft_tab[4][256]; +static uint32_t it_tab[4][256]; + +static uint32_t fl_tab[4][256]; +static uint32_t il_tab[4][256]; + +static inline uint8_t +f_mult (uint8_t a, uint8_t b) +{ + uint8_t aa = log_tab[a], cc = aa + log_tab[b]; + + return pow_tab[cc + (cc < aa ? 1 : 0)]; +} + +#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0) + +#define f_rn(bo, bi, n, k) \ + bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ + ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rn(bo, bi, n, k) \ + bo[n] = it_tab[0][byte(bi[n],0)] ^ \ + it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#define ls_box(x) \ + ( fl_tab[0][byte(x, 0)] ^ \ + fl_tab[1][byte(x, 1)] ^ \ + fl_tab[2][byte(x, 2)] ^ \ + fl_tab[3][byte(x, 3)] ) + +#define f_rl(bo, bi, n, k) \ + bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ + fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = il_tab[0][byte(bi[n],0)] ^ \ + il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +static void +gen_tabs (void) +{ + uint32_t i, t; + uint8_t p, q; + + /* log and power tables for GF(2**8) finite field with + 0x011b as modular polynomial - the simplest prmitive + root is 0x03, used here to generate the tables */ + + for (i = 0, p = 1; i < 256; ++i) { + pow_tab[i] = (uint8_t) p; + log_tab[p] = (uint8_t) i; + + p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + log_tab[1] = 0; + + for (i = 0, p = 1; i < 10; ++i) { + rco_tab[i] = p; + + p = (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + for (i = 0; i < 256; ++i) { + p = (i ? pow_tab[255 - log_tab[i]] : 0); + q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2)); + p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2)); + sbx_tab[i] = p; + isb_tab[p] = (uint8_t) i; + } + + for (i = 0; i < 256; ++i) { + p = sbx_tab[i]; + + t = p; + fl_tab[0][i] = t; + fl_tab[1][i] = rotl (t, 8); + fl_tab[2][i] = rotl (t, 16); + fl_tab[3][i] = rotl (t, 24); + + t = ((uint32_t) ff_mult (2, p)) | + ((uint32_t) p << 8) | + ((uint32_t) p << 16) | ((uint32_t) ff_mult (3, p) << 24); + + ft_tab[0][i] = t; + ft_tab[1][i] = rotl (t, 8); + ft_tab[2][i] = rotl (t, 16); + ft_tab[3][i] = rotl (t, 24); + + p = isb_tab[i]; + + t = p; + il_tab[0][i] = t; + il_tab[1][i] = rotl (t, 8); + il_tab[2][i] = rotl (t, 16); + il_tab[3][i] = rotl (t, 24); + + t = ((uint32_t) ff_mult (14, p)) | + ((uint32_t) ff_mult (9, p) << 8) | + ((uint32_t) ff_mult (13, p) << 16) | + ((uint32_t) ff_mult (11, p) << 24); + + it_tab[0][i] = t; + it_tab[1][i] = rotl (t, 8); + it_tab[2][i] = rotl (t, 16); + it_tab[3][i] = rotl (t, 24); + } +} + +#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y,x) \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= rotr(u ^ t, 8) ^ \ + rotr(v ^ t, 16) ^ \ + rotr(t,24) + +/* initialise the key schedule from the user supplied key */ + +#define loop4(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \ + t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \ + t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \ + t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \ +} + +#define loop6(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \ + t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \ + t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \ + t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \ + t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \ + t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \ +} + +#define loop8(i) \ +{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \ + t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \ + t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \ + t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \ + t = E_KEY[8 * i + 4] ^ ls_box(t); \ + E_KEY[8 * i + 12] = t; \ + t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \ + t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \ + t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \ +} + +static int +aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags) +{ + struct aes_ctx *ctx = ctx_arg; + uint32_t i, t, u, v, w; + uint32_t P[AES_EXTENDED_KEY_SIZE]; + uint32_t rounds; + + if (key_len != 16 && key_len != 24 && key_len != 32) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + ctx->key_length = key_len; + + ctx->E = ctx->e_data; + ctx->D = ctx->d_data; + + /* Ensure 16-Bytes alignmentation of keys for VIA PadLock. */ + if ((int)(ctx->e_data) & 0x0F) + ctx->E += 4 - (((int)(ctx->e_data) & 0x0F) / sizeof (ctx->e_data[0])); + + if ((int)(ctx->d_data) & 0x0F) + ctx->D += 4 - (((int)(ctx->d_data) & 0x0F) / sizeof (ctx->d_data[0])); + + E_KEY[0] = uint32_t_in (in_key); + E_KEY[1] = uint32_t_in (in_key + 4); + E_KEY[2] = uint32_t_in (in_key + 8); + E_KEY[3] = uint32_t_in (in_key + 12); + + /* Don't generate extended keys if the hardware can do it. */ + if (aes_hw_extkey_available(key_len)) + return 0; + + switch (key_len) { + case 16: + t = E_KEY[3]; + for (i = 0; i < 10; ++i) + loop4 (i); + break; + + case 24: + E_KEY[4] = uint32_t_in (in_key + 16); + t = E_KEY[5] = uint32_t_in (in_key + 20); + for (i = 0; i < 8; ++i) + loop6 (i); + break; + + case 32: + E_KEY[4] = uint32_t_in (in_key + 16); + E_KEY[5] = uint32_t_in (in_key + 20); + E_KEY[6] = uint32_t_in (in_key + 24); + t = E_KEY[7] = uint32_t_in (in_key + 28); + for (i = 0; i < 7; ++i) + loop8 (i); + break; + } + + D_KEY[0] = E_KEY[0]; + D_KEY[1] = E_KEY[1]; + D_KEY[2] = E_KEY[2]; + D_KEY[3] = E_KEY[3]; + + for (i = 4; i < key_len + 24; ++i) { + imix_col (D_KEY[i], E_KEY[i]); + } + + /* PadLock needs a different format of the decryption key. */ + rounds = 10 + (key_len - 16) / 4; + + for (i = 0; i < rounds; i++) { + P[((i + 1) * 4) + 0] = D_KEY[((rounds - i - 1) * 4) + 0]; + P[((i + 1) * 4) + 1] = D_KEY[((rounds - i - 1) * 4) + 1]; + P[((i + 1) * 4) + 2] = D_KEY[((rounds - i - 1) * 4) + 2]; + P[((i + 1) * 4) + 3] = D_KEY[((rounds - i - 1) * 4) + 3]; + } + + P[0] = E_KEY[(rounds * 4) + 0]; + P[1] = E_KEY[(rounds * 4) + 1]; + P[2] = E_KEY[(rounds * 4) + 2]; + P[3] = E_KEY[(rounds * 4) + 3]; + + memcpy(D_KEY, P, AES_EXTENDED_KEY_SIZE_B); + + return 0; +} + +/* Tells whether the ACE is capable to generate + the extended key for a given key_len. */ +static inline int +aes_hw_extkey_available(uint8_t key_len) +{ + /* TODO: We should check the actual CPU model/stepping + as it's possible that the capability will be + added in the next CPU revisions. */ + if (key_len == 16) + return 1; + return 0; +} + +/* ====== Encryption/decryption routines ====== */ + +/* This is the real call to PadLock. */ +static inline void +padlock_xcrypt_ecb(uint8_t *input, uint8_t *output, uint8_t *key, + void *control_word, uint32_t count) +{ + asm volatile ("pushfl; popfl"); /* enforce key reload. */ + asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ + : "=m"(*output), "+S"(input), "+D"(output) + : "d"(control_word), "b"(key), "c"(count)); +} + +static void +aes_padlock(void *ctx_arg, uint8_t *out_arg, const uint8_t *in_arg, int encdec) +{ + /* Don't blindly modify this structure - the items must + fit on 16-Bytes boundaries! */ + struct padlock_xcrypt_data { + uint8_t buf[AES_BLOCK_SIZE]; + union cword cword; + }; + + struct aes_ctx *ctx = ctx_arg; + char bigbuf[sizeof(struct padlock_xcrypt_data) + 16]; + struct padlock_xcrypt_data *data; + void *key; + + /* Place 'data' at the first 16-Bytes aligned address in 'bigbuf'. */ + if (((long)bigbuf) & 0x0F) + data = (void*)(bigbuf + 16 - ((long)bigbuf & 0x0F)); + else + data = (void*)bigbuf; + + /* Prepare Control word. */ + memset (data, 0, sizeof(struct padlock_xcrypt_data)); + data->cword.b.encdec = !encdec; /* in the rest of cryptoapi ENC=1/DEC=0 */ + data->cword.b.rounds = 10 + (ctx->key_length - 16) / 4; + data->cword.b.ksize = (ctx->key_length - 16) / 8; + + /* Is the hardware capable to generate the extended key? */ + if (!aes_hw_extkey_available(ctx->key_length)) + data->cword.b.keygen = 1; + + /* ctx->E starts with a plain key - if the hardware is capable + to generate the extended key itself we must supply + the plain key for both Encryption and Decryption. */ + if (encdec == CRYPTO_DIR_ENCRYPT || data->cword.b.keygen == 0) + key = ctx->E; + else + key = ctx->D; + + memcpy(data->buf, in_arg, AES_BLOCK_SIZE); + padlock_xcrypt_ecb(data->buf, data->buf, key, &data->cword, 1); + memcpy(out_arg, data->buf, AES_BLOCK_SIZE); +} + +static void +aes_encrypt(void *ctx_arg, uint8_t *out, const uint8_t *in) +{ + aes_padlock(ctx_arg, out, in, CRYPTO_DIR_ENCRYPT); +} + +static void +aes_decrypt(void *ctx_arg, uint8_t *out, const uint8_t *in) +{ + aes_padlock(ctx_arg, out, in, CRYPTO_DIR_DECRYPT); +} + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aes_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt + } + } +}; + +int __init padlock_init_aes(void) +{ + printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n"); + + gen_tabs(); + return crypto_register_alg(&aes_alg); +} + +void __exit padlock_fini_aes(void) +{ + crypto_unregister_alg(&aes_alg); +} diff --git a/drivers/crypto/padlock-generic.c b/drivers/crypto/padlock-generic.c new file mode 100644 index 000000000000..18cf0e8274a7 --- /dev/null +++ b/drivers/crypto/padlock-generic.c @@ -0,0 +1,63 @@ +/* + * Cryptographic API. + * + * Support for VIA PadLock hardware crypto engine. + * + * Copyright (c) 2004 Michal Ludvig + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include "padlock.h" + +static int __init +padlock_init(void) +{ + int ret = -ENOSYS; + + if (!cpu_has_xcrypt) { + printk(KERN_ERR PFX "VIA PadLock not detected.\n"); + return -ENODEV; + } + + if (!cpu_has_xcrypt_enabled) { + printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); + return -ENODEV; + } + +#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES + if ((ret = padlock_init_aes())) { + printk(KERN_ERR PFX "VIA PadLock AES initialization failed.\n"); + return ret; + } +#endif + + if (ret == -ENOSYS) + printk(KERN_ERR PFX "Hmm, VIA PadLock was compiled without any algorithm.\n"); + + return ret; +} + +static void __exit +padlock_fini(void) +{ +#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES + padlock_fini_aes(); +#endif +} + +module_init(padlock_init); +module_exit(padlock_fini); + +MODULE_DESCRIPTION("VIA PadLock crypto engine support."); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Michal Ludvig"); diff --git a/drivers/crypto/padlock.h b/drivers/crypto/padlock.h new file mode 100644 index 000000000000..7a500605e449 --- /dev/null +++ b/drivers/crypto/padlock.h @@ -0,0 +1,36 @@ +/* + * Driver for VIA PadLock + * + * Copyright (c) 2004 Michal Ludvig + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#ifndef _CRYPTO_PADLOCK_H +#define _CRYPTO_PADLOCK_H + +/* Control word. */ +union cword { + uint32_t cword[4]; + struct { + int rounds:4; + int algo:3; + int keygen:1; + int interm:1; + int encdec:1; + int ksize:2; + } b; +}; + +#define PFX "padlock: " + +#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES +int padlock_init_aes(void); +void padlock_fini_aes(void); +#endif + +#endif /* _CRYPTO_PADLOCK_H */ diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 0f0d8a9f5b53..4626d40e8c6e 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -56,6 +56,9 @@ #define CRYPTO_UNSPEC 0 #define CRYPTO_MAX_ALG_NAME 64 +#define CRYPTO_DIR_ENCRYPT 1 +#define CRYPTO_DIR_DECRYPT 0 + struct scatterlist; /* -- cgit v1.2.3