Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Apr 2005 10:50:31 +0300
From:      "Donatas" <donatas@lrtc.net>
To:        <freebsd-net@freebsd.org>
Subject:   unable to load atm_aal.ko (Corrected)
Message-ID:  <010e01c53f34$4d006d10$9f90a8c0@DONATAS>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
sorry for an error(wrote atm_llc.ko)
so once again,

atm_aal.c and atm_aal.h files cannot be compiled under FreeBSD5.3
and on 5.2 machine compiled atm_aal.ko cannot be loaded:
kldload atm_aal.ko 
link_elf: symbol m_gethdr undefined

can someone help to solve this problem?

thank you

Donatas Gendvilas
SC Lithuanian Radio And Television Center
Data Transfers Department - N.O.C. 
Phone: +370 5 2040444, +370 652 37580
Sausio 13-osios st. 10, 04347 Vilnius, Lithuania

[-- Attachment #2 --]
# -nostdinc -D_KERNEL -DKLD_MODULE -I- -I. -I@ -I@/dev -I@/../include -I/usr/include atm_aal.c atm_aal5.c
atm_aal.o: atm_aal.c @/sys/param.h @/sys/types.h @/sys/cdefs.h \
  machine/endian.h @/sys/_types.h machine/_types.h @/sys/select.h \
  @/sys/_sigset.h @/sys/_timeval.h @/sys/timespec.h @/sys/syslimits.h \
  @/sys/errno.h @/sys/time.h @/sys/priority.h machine/param.h \
  @/sys/systm.h machine/atomic.h machine/cpufunc.h machine/psl.h \
  @/sys/callout.h @/sys/queue.h @/sys/stdint.h machine/_stdint.h \
  @/sys/libkern.h @/sys/mbuf.h @/sys/malloc.h @/sys/_lock.h \
  @/sys/_mutex.h @/sys/kernel.h @/sys/linker_set.h @/sys/module.h \
  @/sys/lock.h @/sys/mutex.h @/sys/pcpu.h @/sys/vmmeter.h machine/pcpu.h \
  machine/segments.h machine/tss.h machine/mutex.h @/sys/socket.h \
  @/sys/_iovec.h @/net/if.h @/net/if_var.h @/sys/_label.h @/sys/event.h \
  @/net/if_media.h @/net/if_atm.h atm_aal.h
atm_aal5.o: atm_aal5.c @/sys/param.h @/sys/types.h @/sys/cdefs.h \
  machine/endian.h @/sys/_types.h machine/_types.h @/sys/select.h \
  @/sys/_sigset.h @/sys/_timeval.h @/sys/timespec.h @/sys/syslimits.h \
  @/sys/errno.h @/sys/time.h @/sys/priority.h machine/param.h \
  @/sys/systm.h machine/atomic.h machine/cpufunc.h machine/psl.h \
  @/sys/callout.h @/sys/queue.h @/sys/stdint.h machine/_stdint.h \
  @/sys/libkern.h @/sys/mbuf.h @/sys/malloc.h @/sys/_lock.h \
  @/sys/_mutex.h @/sys/kernel.h @/sys/linker_set.h @/sys/module.h \
  @/sys/lock.h @/sys/mutex.h @/sys/pcpu.h @/sys/vmmeter.h machine/pcpu.h \
  machine/segments.h machine/tss.h machine/mutex.h @/sys/socket.h \
  @/sys/_iovec.h @/net/if.h @/net/if_var.h @/sys/_label.h @/sys/event.h \
  @/net/if_media.h @/net/if_atm.h atm_aal.h

[-- Attachment #3 --]
/*
 * Copyright (c) 2003, Benno Rice <benno@eloquent.com.au>
 * All Rights Reserved.
 *
 * Development sponsored by Traverse Technologies, http://www.traverse.com.au/
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR  BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Eloquent: projects/atm_aal/atm_aal5.c,v 1.9 2003/12/01 23:56:18 benno Exp $
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/socket.h>

#include <net/if.h>
#include <net/if_media.h>
#include <net/if_atm.h>

#include "atm_aal.h"

#define ATM_AAL5_EOM(cell)	(cell[3] & 0x2)

struct atm_aal5_trailer {
	uint8_t		cpcs_uu;
	uint8_t		cpi;
	uint16_t	length;
	uint32_t	crc;
};

static uint32_t crc32table[] = {
	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
	0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 
	0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 
	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
	0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 
	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
	0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, 
	0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 
	0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
	0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 
	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
	0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, 
	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
	0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 
	0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
	0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 
	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 
	0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
	0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 
	0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
	0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 
	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
	0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, 
	0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
	0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 
	0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 
	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
	0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, 
	0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
	0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 
	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
	0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 
	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
	0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, 
	0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 
	0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
	0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 
	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
	0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, 
	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
	0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 
	0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
	0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 
	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 
	0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
	0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 
	0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
	0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 
	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
	0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 
	0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
	0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 
	0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 
	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
	0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, 
	0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
	0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4, 
};

static uint32_t	atm_aal5_crc(struct mbuf *, int);

struct mbuf *
atm_aal5_decode(struct atm_aal *aal, struct atm_aal_vcc *vcc, uint8_t *cell)
{
	uint8_t	*data;
	u_int	pdu_length;
	struct	atm_aal5_trailer trailer;
	struct	mbuf *m;

	if (vcc->vcc_m == NULL) {
		MGETHDR(vcc->vcc_m, M_DONTWAIT, MT_DATA);
		if (vcc->vcc_m == NULL) {
			printf("atm_aal5_decode: MGETHDR failed\n");
			return (NULL);
		}
		vcc->vcc_m->m_len = 0;
		vcc->vcc_m->m_pkthdr.len = 0;
	}

	data = cell + (aal->aal_flags & ATM_AAL_HEADER_4BYTE ? 4 : 5);

	m_copyback(vcc->vcc_m, vcc->vcc_length, 48, data);
	vcc->vcc_length += 48;

	if (ATM_AAL5_EOM(cell)) {
		trailer.cpcs_uu = data[40];
		trailer.cpi = data[41];
		trailer.length = ((data[42] & 0xff) << 8) + (data[43] & 0xff);
		trailer.crc = (data[44] << 24) + (data[45] << 16) +
		    (data[46] << 8) + data[47];

		if (vcc->vcc_length < trailer.length) {
			/* We've lost some data. */
			printf("atm_aal5_decode: PDU too small\n");
			m_freem(vcc->vcc_m);
			m = NULL;
			goto reset;
		}

		pdu_length = ((trailer.length + 8 + 47) / 48) * 48;

		if (vcc->vcc_length > pdu_length) {
			/*
			 * We've got too much data.
			 * Try trimming out the start on the assumption that
			 * there's been a lost EOM cell.
			 */
			printf("atm_aal5_decode: PDU too large\n");
			m_adj(vcc->vcc_m, vcc->vcc_length - pdu_length);
			vcc->vcc_length = pdu_length;
		}

		/* Calculate and check CRC. */
		if (atm_aal5_crc(vcc->vcc_m, pdu_length - 4) != trailer.crc) {
			printf("atm_aal5_decode: CRC mismatch\n");
			m_freem(vcc->vcc_m);
			m = NULL;
			goto reset;
		}

		/* Discard the trailer and the padding. */
		m_adj(vcc->vcc_m, trailer.length - vcc->vcc_length);

		m = vcc->vcc_m;
		m->m_pkthdr.len = trailer.length;

reset:
		MGETHDR(vcc->vcc_m, M_DONTWAIT, MT_DATA);
		if (vcc->vcc_m == NULL) {
			printf("atm_aal5_decode: MGETHDR failed\n");
		} else {
			vcc->vcc_m->m_len = 0;
			vcc->vcc_m->m_pkthdr.len = 0;
		}

		vcc->vcc_length = 0;

		return (m);
	}

	return (NULL);
}

struct mbuf *
atm_aal5_encode(struct atm_aal *aal, struct atm_aal_vcc *vcc, struct mbuf *m0)
{
	uint16_t	payload_length;
	int		pdu_length, pad_length;
	uint32_t	crc;
	uint8_t		buffer[53], *trailer;

	if (m0->m_pkthdr.len > 65535) {
		return (NULL);
	}

	payload_length = m0->m_pkthdr.len & 0xffff;
	pdu_length = ((payload_length + 8 + 47) / 48) * 48;
	pad_length = pdu_length - payload_length - 8;
	bzero(buffer, pad_length + 8);

	/* We leave the CPCS-UU and CPI bits as zero for now. */
	trailer = &buffer[pad_length];
	trailer[2] = (payload_length >> 8) & 0xff;
	trailer[3] = payload_length & 0xff;
	m_copyback(m0, payload_length, pad_length + 4, buffer);

	crc = atm_aal5_crc(m0, pdu_length - 4);

	buffer[0] = (crc >> 24) & 0xff;
	buffer[1] = (crc >> 16) & 0xff;
	buffer[2] = (crc >> 8) & 0xff;
	buffer[3] = crc & 0xff;
	m_copyback(m0, pdu_length - 4, 4, buffer);

	return (atm_aal_segment(vcc, m0));
}

static uint32_t
atm_aal5_crc(struct mbuf *m0, int length)
{
	uint32_t	crc;
	struct		mbuf *m;
	uint8_t		*data;
	int		len, total;

	crc = 0xffffffff;
	total = 0;

	for (m = m0; m != NULL; m = m->m_next) {
		for (len = m->m_len, data = m->m_data; len > 0; len--, data++) {
			crc = crc32table[((crc >> 24) ^ *data) & 0xff] ^
			    (crc << 8);
			total++;
			if (total >= length)
				break;
		}

		if (total >= length)
			break;
	}

	return (~crc);
}

[-- Attachment #4 --]
/*
 * Copyright (c) 2003, Benno Rice <benno@eloquent.com.au>
 * All Rights Reserved.
 *
 * Development sponsored by Traverse Technologies, http://www.traverse.com.au/
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR  BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Eloquent: projects/atm_aal/atm_aal.c,v 1.20 2003/12/01 23:56:18 benno Exp $
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/socket.h>
#include <sys/queue.h>

#include <net/if.h>
#include <net/if_media.h>
#include <net/if_atm.h>

#include "atm_aal.h"

MALLOC_DEFINE(M_ATM_AAL, "atm_aal", "Data for ATM AAL operations");

#define	ATM_AAL_GET_VPI(cell)	\
    (((cell[0] & 0xf) << 4) + (cell[1] >> 4))
#define	ATM_AAL_GET_VCI(cell)	\
    (((cell[1] & 0xf) << 12) + (cell[2] << 4) + (cell[3] >> 4))

static void	atm_aal_vcc_free(struct atm_aal_vcc *);
static int	atm_aal_modevent(module_t, int, void *);

struct atm_aal *
atm_aal_create(struct ifnet *ifnet, u_int flags, atm_aal_callback_t callback,
    void *arg)
{
	struct	atm_aal *aal;

	MALLOC(aal, struct atm_aal *, sizeof(struct atm_aal),
	    M_ATM_AAL, M_WAITOK | M_ZERO);
	if (aal == NULL) {
		printf("atm_aal_create: malloc failed\n");
		return (NULL);
	}

	SLIST_INIT(&aal->aal_vccs);
	aal->aal_nvccs = 0;
	mtx_init(&aal->aal_mtx, "ATM AAL", NULL, MTX_DEF);
	aal->aal_flags = flags;
	aal->aal_callback = callback;
	aal->aal_arg = arg;

	return (aal);
}

void
atm_aal_destroy(struct atm_aal *aal)
{

	atm_aal_vcc_closeall(aal);

	mtx_lock(&aal->aal_mtx);
	mtx_destroy(&aal->aal_mtx);
	FREE(aal, M_ATM_AAL);
}

int
atm_aal_vcc_open(struct atm_aal *aal, u_int vpi, u_int vci, u_int aaltype,
    u_int flags, void *arg)
{
	struct	atm_aal_vcc *vcc, *vcc1;

	if ((flags & ATMIO_FLAG_NOTX) &&
	    (flags & ATMIO_FLAG_NORX)) {
		return (EINVAL);
	}

	switch (aaltype) {
	case ATMIO_AAL_RAW:
	case ATMIO_AAL_5:
		break;
	default:
		return (EINVAL);
	}

	MALLOC(vcc, struct atm_aal_vcc *, sizeof(struct atm_aal_vcc),
	    M_ATM_AAL, M_WAITOK | M_ZERO);
	if (vcc == NULL) {
		printf("atm_aal_vcc_open: malloc failed\n");
		return (ENOMEM);
	}

	MGETHDR(vcc->vcc_m, M_TRYWAIT, MT_DATA);
	if (vcc->vcc_m == NULL) {
		printf("atm_aal_vcc_open: MGETHDR failed\n");
		FREE(vcc, M_ATM_AAL);
		return (ENOMEM);
	}
	vcc->vcc_m->m_len = 0;
	vcc->vcc_m->m_pkthdr.len = 0;

	vcc->vcc_vpi = vpi;
	vcc->vcc_vci = vci;
	vcc->vcc_aal = aaltype;
	vcc->vcc_flags = flags;
	vcc->vcc_length = 0;
	vcc->vcc_arg = arg;

	mtx_lock(&aal->aal_mtx);

	SLIST_FOREACH(vcc1, &aal->aal_vccs, vcc_next) {
		if (vcc1->vcc_vpi == vpi && vcc1->vcc_vci == vci) {
			m_freem(vcc->vcc_m);
			free(vcc, M_ATM_AAL);
			return (EBUSY);
		}
	}


	SLIST_INSERT_HEAD(&aal->aal_vccs, vcc, vcc_next);
	aal->aal_nvccs++;

	mtx_unlock(&aal->aal_mtx);

	return (0);
}

void
atm_aal_vcc_close(struct atm_aal *aal, u_int vpi, u_int vci)
{
	struct	atm_aal_vcc *vcc;

	mtx_lock(&aal->aal_mtx);

	SLIST_FOREACH(vcc, &aal->aal_vccs, vcc_next) {
		if (vcc->vcc_vpi == vpi && vcc->vcc_vci == vci) {
			SLIST_REMOVE(&aal->aal_vccs, vcc, atm_aal_vcc,
			    vcc_next);
			atm_aal_vcc_free(vcc);
			aal->aal_nvccs--;
			mtx_unlock(&aal->aal_mtx);
			return;
		}
	}

	mtx_unlock(&aal->aal_mtx);
}

void
atm_aal_vcc_closeall(struct atm_aal *aal)
{
	struct	atm_aal_vcc *vcc;

	mtx_lock(&aal->aal_mtx);

	while (!SLIST_EMPTY(&aal->aal_vccs)) {
		vcc = SLIST_FIRST(&aal->aal_vccs);
		SLIST_REMOVE_HEAD(&aal->aal_vccs, vcc_next);
		atm_aal_vcc_free(vcc);
	}

	aal->aal_nvccs = 0;

	mtx_unlock(&aal->aal_mtx);
}

void
atm_aal_process_in(struct atm_aal *aal, uint8_t *cells, u_int ncells)
{
	struct	atm_aal_vcc *vcc;
	u_int	vpi, vci;
	uint8_t	*cell;
	int	i;
	struct	mbuf *m;

	vcc = NULL;

	mtx_lock(&aal->aal_mtx);
	for (i = 0; i < ncells; i++) {
		if (aal->aal_flags & ATM_AAL_HEADER_4BYTE) {
			cell = &cells[i * 52];
		} else {
			cell = &cells[i * 53];
		}

		vpi = ATM_AAL_GET_VPI(cell);
		vci = ATM_AAL_GET_VCI(cell);

		if (vcc == NULL || vcc->vcc_vpi != vpi || vcc->vcc_vci != vci) {
			SLIST_FOREACH(vcc, &aal->aal_vccs, vcc_next) {
				if (vcc->vcc_vpi == vpi &&
				    vcc->vcc_vci == vci) {
					break;
				}
			}

			if (vcc == NULL)
				continue;
		}

		if (vcc->vcc_flags & ATMIO_FLAG_NORX) {
			continue;
		}

		m = NULL;

		switch (vcc->vcc_aal) {
		case ATMIO_AAL_0:
		case ATMIO_AAL_34:
			break;	/* UNSUPPORTED */

		case ATMIO_AAL_5:
			m = atm_aal5_decode(aal, vcc, cell);
			break;

		case ATMIO_AAL_RAW:
			m = atm_aalraw_decode(aal, vcc, cell);
			break;
		}

		if (m != NULL) {
			mtx_unlock(&aal->aal_mtx);
			aal->aal_callback(aal, vcc, m);
			vcc = NULL;
			mtx_lock(&aal->aal_mtx);
		}
	}
	mtx_unlock(&aal->aal_mtx);
}

struct mbuf *
atm_aal_process_out(struct atm_aal *aal, struct mbuf *m)
{
	struct	atm_pseudohdr *aph;
	u_int	vpi, vci;
	struct	atm_aal_vcc *vcc;

	if (m->m_pkthdr.len < sizeof(struct atm_pseudohdr)) {
		printf("atm_aal_process_out: chain too small (%d)\n",
		    m->m_pkthdr.len);
		m_freem(m);
		return (NULL);
	}

	if (m->m_len < sizeof(struct atm_pseudohdr) &&
	    (m = m_pullup(m, sizeof(struct atm_pseudohdr))) == NULL) {
		printf("atm_aal_process_out: m_pullup failed\n");
		return (NULL);
	}

	aph = mtod(m, struct atm_pseudohdr *);

	vpi = ATM_PH_VPI(aph);
	vci = ATM_PH_VCI(aph);

	m_adj(m, sizeof(struct atm_pseudohdr));

	if (m->m_pkthdr.len == 0) {
		printf("atm_aal_process_out: no data\n");
		m_freem(m);
		return (NULL);
	}

	mtx_lock(&aal->aal_mtx);

	SLIST_FOREACH(vcc, &aal->aal_vccs, vcc_next) {
		if (vcc->vcc_vpi == vpi && vcc->vcc_vci == vci) {
			break;
		}
	}

	if (vcc == NULL) {
		printf("atm_aal_process_out: no vcc for %d/%d\n", vpi, vci);
		mtx_unlock(&aal->aal_mtx);
		m_freem(m);
		return (NULL);
	}

	switch (vcc->vcc_aal) {
	case ATMIO_AAL_0:
		m = atm_aal_segment(vcc, m);
		break;

	case ATMIO_AAL_34:
		break;	/* UNSUPPORTED */

	case ATMIO_AAL_5:
		m = atm_aal5_encode(aal, vcc, m);
		break;
	}

	mtx_unlock(&aal->aal_mtx);

	return (m);
}

/*
 * Allocate an mbuf chain that holds the given amount of data filled
 * with what junk we got from the allocation routines.
 */
static struct mbuf *
atm_aal_mgetm(struct mbuf *m0, u_int len)
{
	struct mbuf *m, *tmp;

	if (len <= MHLEN) {
		MGETHDR(m, M_DONTWAIT, MT_DATA);
		if (m == NULL)  {
			printf("atm_aal_segment: MGETHDR failed\n");
			return (NULL);
		}
		if (m_dup_pkthdr(m, m0, M_DONTWAIT) == 0) {
			printf("atm_aal_segment: m_dup_pkthdr failed?\n");
			m_freem(m);
			return (NULL);
		}
		m->m_len = m->m_pkthdr.len = len;
		return (m);
	}
	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
	if (m == NULL) {
		printf("atm_aal_segment: MGETHDR failed\n");
		return (NULL);
	}
	if (m_dup_pkthdr(m, m0, M_DONTWAIT) == 0) {
		printf("atm_aal_segment: m_dup_pkthdr failed?\n");
		m_freem(m);
		return (NULL);
	}
	if (len <= MCLBYTES) {
		m->m_len = m->m_pkthdr.len = len;
		return (m);
	}
	m->m_len = MCLBYTES;
	m->m_pkthdr.len = len;
	len -= MCLBYTES;
	tmp = m_getm(m, len, M_DONTWAIT, MT_DATA);
	if (tmp == NULL) {
		printf("atm_aal_segment: allocating chain failed\n");
		m_freem(m);
		return (NULL);
	}
	/* fixup lengths */
	while (len > 0) {
		if (tmp->m_flags & M_EXT)
			tmp->m_len = min(len, MCLBYTES);
		else
			tmp->m_len = min(len, MLEN);
		len -= tmp->m_len;
		tmp = tmp->m_next;
	}
	return (m);
}

struct mbuf *
atm_aal_segment(struct atm_aal_vcc *vcc, struct mbuf *m0)
{
	int		pdu_cells, pdu_length, i;
	uint8_t		buffer[53];
	struct		mbuf *m;

	pdu_length = m0->m_pkthdr.len;
	pdu_cells = pdu_length / 48;

	m = atm_aal_mgetm(m0, pdu_cells * 52);
	if (m == NULL)
		return (NULL);

	buffer[0] = (vcc->vcc_vpi >> 4) & 0xf;
	buffer[1] = ((vcc->vcc_vpi << 4) & 0xf0) +
	    ((vcc->vcc_vci >> 12) & 0xf);
	buffer[2] = (vcc->vcc_vci >> 4) & 0xff;
	buffer[3] = (vcc->vcc_vci << 4) & 0xf0;
	/* XXX: HEC */

	for (i = 0; i < pdu_cells; i++) {
#ifdef DEBUG
		printf("atm_aal_segment: before: m0 = %d m = %d\n", m_length(m0, NULL), m_length(m, NULL));
#endif
		m_copydata(m0, i * 48, 48, &buffer[4]);

		if (i == pdu_cells - 1) {
			/* XXX: All the world is AAL5? */
			buffer[3] |= 0x2;
			/* XXX: HEC */
		}

		/* XXX should optimize and not use m_copyback */
		m_copyback(m, i * 52, 52, buffer);
#ifdef DEBUG
		printf("atm_aal_segment: after: m0 = %d m = %d\n", m_length(m0, NULL), m_length(m, NULL));
#endif
	}

	m_freem(m0);
	return (m);
}

void
atm_aal_input(struct atm_aal *aal, struct atm_aal_vcc *vcc, struct mbuf *m)
{
	struct	ifnet *ifp;
	struct	atm_pseudohdr aph;

	ifp = (struct ifnet *)aal->aal_arg;

	m->m_pkthdr.rcvif = ifp;

	ATM_PH_FLAGS(&aph) = vcc->vcc_flags;
	ATM_PH_VPI(&aph) = vcc->vcc_vpi;
	ATM_PH_SETVCI(&aph, vcc->vcc_vci);

	ifp->if_ipackets++;

	atm_input(ifp, &aph, m, vcc->vcc_arg);
}

static void
atm_aal_vcc_free(struct atm_aal_vcc *vcc) {
	m_freem(vcc->vcc_m);
	FREE(vcc, M_ATM_AAL);
}

static int
atm_aal_modevent(module_t mod, int type, void *unused)
{

	switch (type) {
	case MOD_LOAD:
		if (bootverbose)
			printf("atm_aal: <Software ATM Adaptation Layer>\n");
		return (0);
		break;

	case MOD_UNLOAD:
		return (0);
		break;
	}

	return (EINVAL);
}

static moduledata_t atm_aal_mod = {
	"atm_aal",
	atm_aal_modevent,
	0
};

DECLARE_MODULE(atm_aal, atm_aal_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
MODULE_VERSION(atm_aal, 1);
MODULE_DEPEND(atm_aal, atm, 1, 1, 1);

/*
 * RAW AAL - just produce one mbuf per cell
 */
struct mbuf *
atm_aalraw_decode(struct atm_aal *aal, struct atm_aal_vcc *vcc, uint8_t *cell)
{
	struct mbuf *m;

	if (vcc->vcc_m == NULL) {
		MGETHDR(vcc->vcc_m, M_DONTWAIT, MT_DATA);
		if (vcc->vcc_m == NULL) {
			printf("atm_aal5_decode: MGETHDR failed\n");
			return (NULL);
		}
		vcc->vcc_m->m_len = 0;
		vcc->vcc_m->m_pkthdr.len = 0;
	}

	vcc->vcc_m->m_len = 52;
	vcc->vcc_m->m_pkthdr.len = 52;

	if (aal->aal_flags & ATM_AAL_HEADER_4BYTE)
		bcopy(cell, vcc->vcc_m->m_data, 52);
	else {
		bcopy(cell, vcc->vcc_m->m_data, 4);
		bcopy(cell + 5, vcc->vcc_m->m_data + 4, 48);
	}

	m = vcc->vcc_m;
	vcc->vcc_m = NULL;

	return (m);
}

/*
 * Return just a copy but be sure to truncate to a multiple of 52 byte
 */
struct mbuf *
atm_aalraw_encode(struct atm_aal *aal, struct atm_aal_vcc *vcc, struct mbuf *m0)
{
	struct mbuf *m;
	u_int pdu_cells;

	pdu_cells = m0->m_pkthdr.len / 52;

	if (m0->m_pkthdr.len % 52 == 0)
		m = m_copypacket(m0, M_DONTWAIT);
	else {
		m = m_dup(m0, M_DONTWAIT);
		if (m != NULL)
			m_adj(m, -(m0->m_pkthdr.len % 52));
	}
	return (m);
}

[-- Attachment #5 --]
/*
 * Copyright (c) 2003, Benno Rice <benno@eloquent.com.au>
 * All Rights Reserved.
 *
 * Development sponsored by Traverse Technologies, http://www.traverse.com.au/
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR  ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR  BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Eloquent: projects/atm_aal/atm_aal.h,v 1.11 2003/12/01 23:56:18 benno Exp $
 */

#ifndef _ATM_AAL_H_
#define _ATM_AAL_H_

#include <sys/queue.h>

MALLOC_DECLARE(M_ATM_AAL);

SLIST_HEAD(atm_aal_vcc_list, atm_aal_vcc);

struct atm_aal;
struct atm_aal_vcc;

typedef void atm_aal_callback_t(struct atm_aal *, struct atm_aal_vcc *,
    struct mbuf *);

struct atm_aal {
	int	aal_nvccs;		/* How many VCCs we have. */
	struct	atm_aal_vcc_list aal_vccs; /* List of VCCs. */
	struct	mtx aal_mtx;		/* Mutex. */
	u_int	aal_flags;		/* Flags. */
	atm_aal_callback_t *aal_callback; /* Callback for when we have data. */
	void	*aal_arg;		/* Callback argument. */
};

struct atm_aal_vcc {
	u_int	vcc_vpi;		/* Virtual Path Identifier */
	u_int	vcc_vci;		/* Virtual Channel Identifier */
	u_int	vcc_aal;		/* ATM Adaptation Layer */
	u_int	vcc_flags;		/* Flags */
	struct	mbuf *vcc_m;		/* Our current mbuf. */
	u_int	vcc_length;		/* How much data we're holding. */
	void	*vcc_arg;		/* Callback argument. */
	SLIST_ENTRY(atm_aal_vcc) vcc_next;
};

/* Flag definitions. */
#define	ATM_AAL_HEADER_4BYTE	0x00000001	/* HEC is done elsewhere. */

/* AAL context management. */
struct atm_aal *	atm_aal_create(struct ifnet *, u_int,
			    atm_aal_callback_t, void *);
void			atm_aal_destroy(struct atm_aal *);

/* AAL VCC management. */
int			atm_aal_vcc_open(struct atm_aal *, u_int, u_int, u_int,
			    u_int, void *);
void			atm_aal_vcc_close(struct atm_aal *, u_int, u_int);
void			atm_aal_vcc_closeall(struct atm_aal *);

/* Entry points for in- and outbound processing. */
void			atm_aal_process_in(struct atm_aal *, uint8_t *, u_int);
struct mbuf *		atm_aal_process_out(struct atm_aal *, struct mbuf *);

/* Convenience function for AALs.  Handles segmentation and header addition. */
struct mbuf *		atm_aal_segment(struct atm_aal_vcc *, struct mbuf *);

/* Convenience function to act as a callback to hand mbufs to the ATM layer. */
void			atm_aal_input(struct atm_aal *, struct atm_aal_vcc *,
			    struct mbuf *);

/* Function for returning the vcc table. */
struct atmio_vcctable *	atm_aal_getvccs(struct atm_aal *, int);

/* AAL5 routines. */
struct mbuf *		atm_aal5_decode(struct atm_aal *, struct atm_aal_vcc *,
			    uint8_t *);
struct mbuf *		atm_aal5_encode(struct atm_aal *, struct atm_aal_vcc *,
			    struct mbuf *);

/* RAW AAL routines. */
struct mbuf *		atm_aalraw_decode(struct atm_aal *,
			    struct atm_aal_vcc *, uint8_t *);
struct mbuf *		atm_aalraw_encode(struct atm_aal *,
			    struct atm_aal_vcc *, struct mbuf *);

#endif

[-- Attachment #6 --]
# $Eloquent: projects/atm_aal/Makefile,v 1.1 2003/09/20 12:00:50 benno Exp $

KMOD=	atm_aal
SRCS=	atm_aal.c atm_aal5.c

.include <bsd.kmod.mk>

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?010e01c53f34$4d006d10$9f90a8c0>