[Linux-ATM-General] OAM not support [SOLVED]
Dario Lesca
d.lesca at solinos.it
Wed Aug 2 09:36:23 UTC 2006
Il giorno mer, 02/08/2006 alle 10.51 +0200, Dario Lesca ha scritto:
> produced this structure (see attach):
Makefile:
>
> obj-m += usbatm.o
> obj-m += cxacru.o
>
> PWD := $(shell pwd)
> MDIR := /lib/modules/$(shell uname -r)
> KDIR := $(MDIR)/build
> SUDO := sudo -p 'Sudo Password: '
>
> default:
> @echo "make {patch|build|install|uninstall|clean|cleanall}"
>
> #Patch
> patch: usbatm.c.orig usbatm.h.orig
> patch < usbatm-oam-support.patch
> usbatm.c.orig:
> test -f usbatm.c.orig && exit 1
> cp -a usbatm.c usbatm.c.orig
> usbatm.h.orig:
> test -f usbatm.h.orig && exit 1
> cp -a usbatm.h usbatm.h.orig
>
> #Build
> build: usbatm.ko cxacru.ko
>
> usbatm.ko: usbatm.c
> $(MAKE) -C $(KDIR) M=$(PWD) modules
> cxacru.ko: cxacru.c
> $(MAKE) -C $(KDIR) M=$(PWD) modules
>
> #Install
> install: usbatm.ko cxacru.ko uninstall
> $(SUDO) sh -x -c '/sbin/modprobe -rv cxacru;\
> /sbin/modprobe -rv usbatm;\
> cp -a usbatm.ko $(MDIR)/updates/.;\
> cp -a cxacru.ko $(MDIR)/updates/.;\
> /sbin/depmod -a;\
> /sbin/modprobe -v cxacru;\
> /sbin/modprobe -v usbatm'
>
> uninstall:
> $(SUDO) sh -x -c '/sbin/modprobe -rv cxacru;\
> /sbin/modprobe -rv usbatm;\
> /sbin/modprobe -rv cxacru;\
> rm -f $(MDIR)/updates/usbatm.ko;\
> rm -f $(MDIR)/updates/cxacru.ko;\
> /sbin/depmod -a;\
> /sbin/modprobe -v cxacru;\
> /sbin/modprobe -v usbatm'
> #Clear files
> clear: clean
> clean:
> rm -fr \
> usbatm.ko usbatm.mod.c usbatm.mod.o usbatm.o \
> .usbatm.ko.cmd .usbatm.mod.o.cmd .usbatm.o.cmd \
> cxacru.ko cxacru.mod.c cxacru.mod.o cxacru.o \
> .cxacru.ko.cmd .cxacru.mod.o.cmd .cxacru.o.cmd \
> Modules.symvers .tmp_versions
>
> cleanall: clean uninstall
>
usbatm-oam-support.patch:
> diff -u atm.orig/usbatm.c atm/usbatm.c
> --- atm.orig/usbatm.c 2006-06-18 03:49:35.000000000 +0200
> +++ atm/usbatm.c 2006-07-25 12:07:28.000000000 +0200
> @@ -92,18 +92,18 @@
> #endif
>
> #define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands at free.fr>"
> -#define DRIVER_VERSION "1.10"
> +#define DRIVER_VERSION "1.10-OAM"
> #define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION
>
> static const char usbatm_driver_name[] = "usbatm";
>
> #define UDSL_MAX_RCV_URBS 16
> #define UDSL_MAX_SND_URBS 16
> -#define UDSL_MAX_BUF_SIZE 65536
> +#define UDSL_MAX_BUF_SIZE 64 * 1024 /* bytes */
> #define UDSL_DEFAULT_RCV_URBS 4
> #define UDSL_DEFAULT_SND_URBS 4
> -#define UDSL_DEFAULT_RCV_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */
> -#define UDSL_DEFAULT_SND_BUF_SIZE 3392 /* 64 * ATM_CELL_SIZE */
> +#define UDSL_DEFAULT_RCV_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
> +#define UDSL_DEFAULT_SND_BUF_SIZE 64 * ATM_CELL_SIZE /* bytes */
>
> #define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
>
> @@ -135,7 +135,7 @@
> module_param(snd_buf_bytes, uint, S_IRUGO);
> MODULE_PARM_DESC(snd_buf_bytes,
> "Size of the buffers used for transmission, in bytes (range: 1-"
> - __MODULE_STRING(UDSL_MAX_BUF_SIZE) ", default: "
> + __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
> __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
>
>
> @@ -183,7 +183,6 @@
> .owner = THIS_MODULE,
> };
>
> -
> /***********
> ** misc **
> ***********/
> @@ -202,12 +201,37 @@
> dev_kfree_skb_any(skb);
> }
>
> +static u16 crc10_table[256] = {
> + 0x000, 0x233, 0x255, 0x066, 0x299, 0x0aa, 0x0cc, 0x2ff, 0x301, 0x132, 0x154, 0x367, 0x198, 0x3ab, 0x3cd, 0x1fe,
> + 0x031, 0x202, 0x264, 0x057, 0x2a8, 0x09b, 0x0fd, 0x2ce, 0x330, 0x103, 0x165, 0x356, 0x1a9, 0x39a, 0x3fc, 0x1cf,
> + 0x062, 0x251, 0x237, 0x004, 0x2fb, 0x0c8, 0x0ae, 0x29d, 0x363, 0x150, 0x136, 0x305, 0x1fa, 0x3c9, 0x3af, 0x19c,
> + 0x053, 0x260, 0x206, 0x035, 0x2ca, 0x0f9, 0x09f, 0x2ac, 0x352, 0x161, 0x107, 0x334, 0x1cb, 0x3f8, 0x39e, 0x1ad,
> + 0x0c4, 0x2f7, 0x291, 0x0a2, 0x25d, 0x06e, 0x008, 0x23b, 0x3c5, 0x1f6, 0x190, 0x3a3, 0x15c, 0x36f, 0x309, 0x13a,
> + 0x0f5, 0x2c6, 0x2a0, 0x093, 0x26c, 0x05f, 0x039, 0x20a, 0x3f4, 0x1c7, 0x1a1, 0x392, 0x16d, 0x35e, 0x338, 0x10b,
> + 0x0a6, 0x295, 0x2f3, 0x0c0, 0x23f, 0x00c, 0x06a, 0x259, 0x3a7, 0x194, 0x1f2, 0x3c1, 0x13e, 0x30d, 0x36b, 0x158,
> + 0x097, 0x2a4, 0x2c2, 0x0f1, 0x20e, 0x03d, 0x05b, 0x268, 0x396, 0x1a5, 0x1c3, 0x3f0, 0x10f, 0x33c, 0x35a, 0x169,
> + 0x188, 0x3bb, 0x3dd, 0x1ee, 0x311, 0x122, 0x144, 0x377, 0x289, 0x0ba, 0x0dc, 0x2ef, 0x010, 0x223, 0x245, 0x076,
> + 0x1b9, 0x38a, 0x3ec, 0x1df, 0x320, 0x113, 0x175, 0x346, 0x2b8, 0x08b, 0x0ed, 0x2de, 0x021, 0x212, 0x274, 0x047,
> + 0x1ea, 0x3d9, 0x3bf, 0x18c, 0x373, 0x140, 0x126, 0x315, 0x2eb, 0x0d8, 0x0be, 0x28d, 0x072, 0x241, 0x227, 0x014,
> + 0x1db, 0x3e8, 0x38e, 0x1bd, 0x342, 0x171, 0x117, 0x324, 0x2da, 0x0e9, 0x08f, 0x2bc, 0x043, 0x270, 0x216, 0x025,
> + 0x14c, 0x37f, 0x319, 0x12a, 0x3d5, 0x1e6, 0x180, 0x3b3, 0x24d, 0x07e, 0x018, 0x22b, 0x0d4, 0x2e7, 0x281, 0x0b2,
> + 0x17d, 0x34e, 0x328, 0x11b, 0x3e4, 0x1d7, 0x1b1, 0x382, 0x27c, 0x04f, 0x029, 0x21a, 0x0e5, 0x2d6, 0x2b0, 0x083,
> + 0x12e, 0x31d, 0x37b, 0x148, 0x3b7, 0x184, 0x1e2, 0x3d1, 0x22f, 0x01c, 0x07a, 0x249, 0x0b6, 0x285, 0x2e3, 0x0d0,
> + 0x11f, 0x32c, 0x34a, 0x179, 0x386, 0x1b5, 0x1d3, 0x3e0, 0x21e, 0x02d, 0x04b, 0x278, 0x087, 0x2b4, 0x2d2, 0x0e1,
> +};
> +
> +static u16 inline crc10(u16 init, u8 *data, int len)
> +{
> + while (len--)
> + init = ((init << 8) & 0x3ff) ^ crc10_table[(init >> 2) & 0xff] ^ *data++;
> + return init;
> +}
>
> /***********
> ** urbs **
> ************/
>
> -static struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
> +static inline struct urb *usbatm_pop_urb(struct usbatm_channel *channel)
> {
> struct urb *urb;
>
> @@ -224,7 +248,7 @@
> return urb;
> }
>
> -static int usbatm_submit_urb(struct urb *urb)
> +static inline int usbatm_submit_urb(struct urb *urb)
> {
> struct usbatm_channel *channel = urb->context;
> int ret;
> @@ -283,6 +307,42 @@
> tasklet_schedule(&channel->tasklet);
> }
>
> +/* OAM loopback reply (fire-and-forget) */
> +static int usbatm_oam_reply(struct usbatm_data *instance, u8 *source)
> +{
> + struct urb *urb;
> + u16 crc;
> + u8 *buffer;
> +
> + if (source[ATM_CELL_HEADER] != 0x18 || source[ATM_CELL_HEADER + 1] != 0x01) {
> + atm_dbg(instance, "%s: unexpected OAM type/function %x direction %x!\n",
> + __func__, source[ATM_CELL_HEADER], source[ATM_CELL_HEADER + 1]);
> + return -EPROTO;
> + }
> +
> + if (crc10(0, source + ATM_CELL_HEADER, ATM_CELL_PAYLOAD)) {
> + atm_dbg(instance, "%s: OAM CRC10 error!\n", __func__);
> + return -EIO;
> + }
> +
> + urb = usbatm_pop_urb(&instance->tx_channel);
> + if (!urb)
> + return -ENOMEM;
> +
> + buffer = urb->transfer_buffer;
> + memcpy(buffer, source, ATM_CELL_SIZE);
> +
> + buffer[ATM_CELL_HEADER + 1] = 0; /* update the direction field */
> +
> + memset(buffer + ATM_CELL_SIZE - 2, 0, 2);
> +
> + crc = crc10(0, buffer + ATM_CELL_HEADER, ATM_CELL_PAYLOAD);
> + buffer[ATM_CELL_SIZE - 2] = (crc >> 8) & 0x3;
> + buffer[ATM_CELL_SIZE - 1] = crc & 0xff;
> +
> + urb->transfer_buffer_length = instance->tx_channel.stride;
> + return usbatm_submit_urb(urb);
> +}
>
> /*************
> ** decode **
> @@ -324,12 +384,24 @@
>
> vcc = instance->cached_vcc->vcc;
>
> +// /* OAM F5 end-to-end */
> +// if (pti == ATM_PTI_E2EF5) {
> +// if (printk_ratelimit())
> +// atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
> +// __func__, vpi, vci);
> +// atomic_inc(&vcc->stats->rx_err);
> +// return;
> +// }
> +
> /* OAM F5 end-to-end */
> if (pti == ATM_PTI_E2EF5) {
> if (printk_ratelimit())
> - atm_warn(instance, "%s: OAM not supported (vpi %d, vci %d)!\n",
> + atm_warn(instance, "%s: Trying to support OAM (vpi %d, vci %d)!\n",
> __func__, vpi, vci);
> - atomic_inc(&vcc->stats->rx_err);
> + if (usbatm_oam_reply(instance, source)) {
> + atm_dbg(instance, "%s: OAM reply failed (vpi %d, vci %d)!\n", __func__, vpi, vci);
> + atomic_inc(&vcc->stats->rx_err);
> + }
> return;
> }
>
> @@ -823,7 +895,7 @@
> return -EINVAL;
> }
>
> - mutex_lock(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */+ down(&instance->serialize); /* vs self, usbatm_atm_close, usbatm_usb_disconnect */
>
> if (instance->disconnected) {
> atm_dbg(instance, "%s: disconnected!\n", __func__);
> @@ -837,7 +909,7 @@
> goto fail;
> }
>
> - if (!(new = kzalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
> + if (!(new = kmalloc(sizeof(struct usbatm_vcc_data), GFP_KERNEL))) {
> atm_err(instance, "%s: no memory for vcc_data!\n", __func__);
> ret = -ENOMEM;
> goto fail;
> @@ -867,7 +939,7 @@
> set_bit(ATM_VF_PARTIAL, &vcc->flags);
> set_bit(ATM_VF_READY, &vcc->flags);
>
> - mutex_unlock(&instance->serialize);
> + up(&instance->serialize);
>
> atm_dbg(instance, "%s: allocated vcc data 0x%p\n", __func__, new);
>
> @@ -875,7 +947,7 @@
>
> fail:
> kfree(new);
> - mutex_unlock(&instance->serialize);
> + up(&instance->serialize);
> return ret;
> }
>
> @@ -896,7 +968,7 @@
>
> usbatm_cancel_send(instance, vcc);
>
> - mutex_lock(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
> + down(&instance->serialize); /* vs self, usbatm_atm_open, usbatm_usb_disconnect */
>
> tasklet_disable(&instance->rx_channel.tasklet);
> if (instance->cached_vcc == vcc_data) {
> @@ -919,7 +991,7 @@
> clear_bit(ATM_VF_PARTIAL, &vcc->flags);
> clear_bit(ATM_VF_ADDR, &vcc->flags);
>
> - mutex_unlock(&instance->serialize);
> + up(&instance->serialize);
>
> atm_dbg(instance, "%s successful\n", __func__);
> }
> @@ -1009,9 +1081,9 @@
> if (!ret)
> ret = usbatm_atm_init(instance);
>
> - mutex_lock(&instance->serialize);
> + down(&instance->serialize);
> instance->thread_pid = -1;
> - mutex_unlock(&instance->serialize);
> + up(&instance->serialize);
>
> complete_and_exit(&instance->thread_exited, ret);
> }
> @@ -1025,9 +1097,9 @@
> return ret;
> }
>
> - mutex_lock(&instance->serialize);
> + down(&instance->serialize);
> instance->thread_pid = ret;
> - mutex_unlock(&instance->serialize);
> + up(&instance->serialize);
>
> wait_for_completion(&instance->thread_started);
>
> @@ -1066,7 +1138,7 @@
> intf->altsetting->desc.bInterfaceNumber);
>
> /* instance init */
> - instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
> + instance = kmalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);
> if (!instance) {
> dev_err(dev, "%s: no memory for instance data!\n", __func__);
> return -ENOMEM;
> @@ -1110,7 +1182,7 @@
> /* private fields */
>
> kref_init(&instance->refcount); /* dropped in usbatm_usb_disconnect */
> - mutex_init(&instance->serialize);
> + init_MUTEX(&instance->serialize);
>
> instance->thread_pid = -1;
> init_completion(&instance->thread_started);
> @@ -1186,7 +1258,7 @@
> instance->urbs[i] = urb;
>
> /* zero the tx padding to avoid leaking information */
> - buffer = kzalloc(channel->buf_size, GFP_KERNEL);
> + buffer = kmalloc(channel->buf_size, GFP_KERNEL);
> if (!buffer) {
> dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i);
> error = -ENOMEM;
> @@ -1273,18 +1345,18 @@
>
> usb_set_intfdata(intf, NULL);
>
> - mutex_lock(&instance->serialize);
> + down(&instance->serialize);
> instance->disconnected = 1;
> if (instance->thread_pid >= 0)
> kill_proc(instance->thread_pid, SIGTERM, 1);
> - mutex_unlock(&instance->serialize);
> + up(&instance->serialize);
>
> wait_for_completion(&instance->thread_exited);
>
> - mutex_lock(&instance->serialize);
> + down(&instance->serialize);
> list_for_each_entry(vcc_data, &instance->vcc_list, list)
> vcc_release_async(vcc_data->vcc, -EPIPE);
> - mutex_unlock(&instance->serialize);
> + up(&instance->serialize);
>
> tasklet_disable(&instance->rx_channel.tasklet);
> tasklet_disable(&instance->tx_channel.tasklet);
> diff -u atm.orig/usbatm.h atm/usbatm.h
> --- atm.orig/usbatm.h 2006-06-18 03:49:35.000000000 +0200
> +++ atm/usbatm.h 2006-07-25 12:11:53.000000000 +0200
> @@ -34,7 +34,6 @@
> #include <linux/list.h>
> #include <linux/stringify.h>
> #include <linux/usb.h>
> -#include <linux/mutex.h>
>
> /*
> #define VERBOSE_DEBUG
> @@ -172,7 +171,7 @@
> ********************************/
>
> struct kref refcount;
> - struct mutex serialize;
> + struct semaphore serialize;
> int disconnected;
>
> /* heavy init */
--
Dario Lesca <d.lesca at solinos.it>
More information about the fedora-devel-list
mailing list