summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-02-13 20:24:17 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-02-13 20:24:17 +0000
commit872af797f8f0588df93271ee4af5bd387e44cd48 (patch)
treeb9ee61298c9321a1ea5dac4adfc215b14d41c669
parent6d4f5dcdbf90fd8dc38802d4d05d01eecddbf61b (diff)
Version 0.1.6 from FTP
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@59 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rwxr-xr-xzaptel.conf.sample14
-rwxr-xr-xztcfg.c60
-rwxr-xr-xztd-eth.c348
3 files changed, 420 insertions, 2 deletions
diff --git a/zaptel.conf.sample b/zaptel.conf.sample
index 2de39d2..e1b720f 100755
--- a/zaptel.conf.sample
+++ b/zaptel.conf.sample
@@ -1,7 +1,7 @@
#
# Zaptel Configuration File
#
-# This file is parsed by the Zaptel Configurator, torcfg
+# This file is parsed by the Zaptel Configurator, ztcfg
#
#
# First come the span definitions, in the format
@@ -32,6 +32,18 @@
#span=1,0,0,esf,b8zs
#span=2,1,0,esf,b8zs
#
+# Next come the dynamic span definitions, in the form:
+# dynamic=<driver>,<address>,<numchans>,<timing>
+#
+# Where <driver> is the name of the driver (e.g. eth), <address> is the
+# driver specific address (like a MAC for eth), <numchans> is the number
+# of channels, and <timing> is a timing priority, like for a normal span.
+# use "0" to not use this as a timing source, or prioritize them as
+# primary, secondard, etc. Note that you MUST have a REAL zaptel device
+# if you are not using external timing.
+#
+# dynamic=eth,eth0/00:02:b3:35:43:9c,24,0
+#
# Next come the definitions for using the channels. The format is:
# <device>=<channel list>
#
diff --git a/ztcfg.c b/ztcfg.c
index 5b37dfb..360654e 100755
--- a/ztcfg.c
+++ b/ztcfg.c
@@ -43,6 +43,9 @@
#define NUM_SPANS ZT_MAX_SPANS
+/* Assume no more than 1024 dynamics */
+#define NUM_DYNAMIC 1024
+
static int lineno=0;
static FILE *cf;
@@ -62,6 +65,8 @@ static struct zt_lineconfig lc[ZT_MAX_SPANS];
static struct zt_chanconfig cc[ZT_MAX_CHANNELS];
+static struct zt_dynamic_span zds[NUM_DYNAMIC];
+
static char *sig[ZT_MAX_CHANNELS]; /* Signalling */
static int slineno[ZT_MAX_CHANNELS]; /* Line number where signalling specified */
@@ -74,6 +79,8 @@ static int verbose = 0;
static int stopmode = 0;
+static int numdynamic = 0;
+
static char zonestoload[ZT_TONE_ZONE_MAX][10];
static int numzones = 0;
@@ -146,9 +153,44 @@ static int parseargs(char *input, char *output[], int maxargs, char sep)
return pos;
}
+int dspanconfig(char *keyword, char *args)
+{
+ static char *realargs[10];
+ int argc;
+ int res;
+ int chans;
+ int timing;
+ argc = res = parseargs(args, realargs, 4, ',');
+ if (res != 4) {
+ error("Incorrect number of arguments to 'dynamic' (should be <driver>,<address>,<num channels>, <timing>)\n");
+ }
+ res = sscanf(realargs[2], "%d", &chans);
+ if ((res == 1) && (chans < 1))
+ res = -1;
+ if (res != 1) {
+ error("Invalid number of channels '%s', should be a number > 0.\n", realargs[2]);
+ }
+
+ res = sscanf(realargs[3], "%d", &timing);
+ if ((res == 1) && (timing < 0))
+ res = -1;
+ if (res != 1) {
+ error("Invalid timing '%s', should be a number > 0.\n", realargs[3]);
+ }
+
+
+ strncpy(zds[numdynamic].driver, realargs[0], sizeof(zds[numdynamic].driver));
+ strncpy(zds[numdynamic].addr, realargs[1], sizeof(zds[numdynamic].addr));
+ zds[numdynamic].numchans = chans;
+ zds[numdynamic].timing = timing;
+
+ numdynamic++;
+ return 0;
+}
+
int spanconfig(char *keyword, char *args)
{
- static char *realargs[5];
+ static char *realargs[10];
int res;
int argc;
int span;
@@ -448,6 +490,10 @@ static void printconfig()
x+1, ( lc[x].lineconfig & ZT_CONFIG_ESF ? "ESF" : "D4"),
(lc[x].lineconfig & ZT_CONFIG_B8ZS ? "B8ZS" : "AMI"),
lbostr[lc[x].lbo]);
+ for (x=0;x<numdynamic;x++) {
+ printf("Dynamic span %d: driver %s, addr %s, channels %d, timing %d\n",
+ x +1, zds[x].driver, zds[x].addr, zds[x].numchans, zds[x].timing);
+ }
if (verbose > 1) {
printf("\nChannel map:\n\n");
for (x=1;x<ZT_MAX_CHANNELS;x++) {
@@ -475,6 +521,7 @@ static struct handler {
int (*func)(char *keyword, char *args);
} handlers[] = {
{ "span", spanconfig },
+ { "dynamic", dspanconfig },
{ "loadzone", registerzone },
{ "defaultzone", defaultzone },
{ "e&m", chanconfig },
@@ -613,6 +660,10 @@ int main(int argc, char *argv[])
if (fd < 0)
error("Unable to open master device '%s'\n", MASTER_DEVICE);
else {
+ for (x=0;x<numdynamic;x++) {
+ /* destroy them all */
+ ioctl(fd, ZT_DYNAMIC_DESTROY, &zds[x]);
+ }
if (stopmode) {
for (x=0;x<spans;x++) {
if (ioctl(fd, ZT_SHUTDOWN, &lc[x].span)) {
@@ -629,6 +680,13 @@ int main(int argc, char *argv[])
exit(1);
}
}
+ for (x=0;x<numdynamic;x++) {
+ if (ioctl(fd, ZT_DYNAMIC_CREATE, &zds[x])) {
+ fprintf(stderr, "Zaptel dynamic span creation failed: %s\n", strerror(errno));
+ close(fd);
+ exit(1);
+ }
+ }
for (x=1;x<ZT_MAX_CHANNELS;x++) {
if (debug & DEBUG_APPLY) {
printf("Configuring device %d\n", x);
diff --git a/ztd-eth.c b/ztd-eth.c
new file mode 100755
index 0000000..a9959b5
--- /dev/null
+++ b/ztd-eth.c
@@ -0,0 +1,348 @@
+/*
+ * Dynamic Span Interface for Zaptel (Ethernet Interface)
+ *
+ * Written by Mark Spencer <markster@linux-support.net>
+ *
+ * Copyright (C) 2001, Linux Support Services, Inc.
+ *
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
+#include <linux/netdevice.h>
+#include <linux/notifier.h>
+
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+#endif
+#ifdef STANDALONE_ZAPATA
+#include "zaptel.h"
+#else
+#include <linux/zaptel.h>
+#endif
+
+#define ETH_P_ZTDETH 0xd00d
+
+struct ztdeth_header {
+ unsigned short subaddr;
+};
+
+/* We take the raw message, put it in an ethernet frame, and add a
+ two byte addressing header at the top for future use */
+
+static spinlock_t zlock = SPIN_LOCK_UNLOCKED;
+
+static struct ztdeth {
+ unsigned char addr[ETH_ALEN];
+ unsigned short subaddr; /* Network byte order */
+ struct zt_span *span;
+ char ethdev[IFNAMSIZ];
+ struct net_device *dev;
+ struct ztdeth *next;
+} *zdevs = NULL;
+
+struct zt_span *ztdeth_getspan(unsigned char *addr, unsigned short subaddr)
+{
+ long flags;
+ struct ztdeth *z;
+ struct zt_span *span = NULL;
+ spin_lock_irqsave(&zlock, flags);
+ z = zdevs;
+ while(z) {
+ if (!memcmp(addr, z->addr, ETH_ALEN) &&
+ z->subaddr == subaddr)
+ break;
+ z = z->next;
+ }
+ if (z)
+ span = z->span;
+ spin_unlock_irqrestore(&zlock, flags);
+ return span;
+}
+
+static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+{
+ struct zt_span *span;
+ struct ztdeth_header *zh;
+ zh = (struct ztdeth_header *)skb->nh.raw;
+ span = ztdeth_getspan(skb->mac.ethernet->h_source, zh->subaddr);
+ if (span) {
+ skb_pull(skb, sizeof(struct ztdeth_header));
+ zt_dynamic_receive(span, (unsigned char *)skb->data, skb->len);
+ }
+ kfree_skb(skb);
+ return 0;
+}
+
+static int ztdeth_notifier(struct notifier_block *block, unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct ztdeth *z;
+ long flags;
+ switch(event) {
+ case NETDEV_GOING_DOWN:
+ case NETDEV_DOWN:
+ spin_lock_irqsave(&zlock, flags);
+ z = zdevs;
+ while(z) {
+ /* Note that the device no longer exists */
+ if (z->dev == dev)
+ z->dev = NULL;
+ z = z->next;
+ }
+ spin_unlock_irqrestore(&zlock, flags);
+ break;
+ case NETDEV_UP:
+ spin_lock_irqsave(&zlock, flags);
+ z = zdevs;
+ while(z) {
+ /* Now that the device exists again, use it */
+ if (!strcmp(z->ethdev, dev->name))
+ z->dev = dev;
+ z = z->next;
+ }
+ spin_unlock_irqrestore(&zlock, flags);
+ break;
+ default:
+ }
+ return 0;
+}
+
+static int ztdeth_transmit(void *pvt, unsigned char *msg, int msglen)
+{
+ struct ztdeth *z;
+ struct sk_buff *skb;
+ struct ztdeth_header *zh;
+ long flags;
+
+ spin_lock_irqsave(&zlock, flags);
+ z = pvt;
+ if (z->dev) {
+ skb = dev_alloc_skb(msglen + z->dev->hard_header_len + sizeof(struct ztdeth_header) + 32);
+ if (skb) {
+ /* Reserve header space */
+ skb_reserve(skb, z->dev->hard_header_len + sizeof(struct ztdeth_header));
+
+ /* Copy message body */
+ memcpy(skb_put(skb, msglen), msg, msglen);
+
+ /* Throw on header */
+ zh = (struct ztdeth_header *)skb_push(skb, sizeof(struct ztdeth_header));
+ zh->subaddr = z->subaddr;
+
+ /* Setup protocol and such */
+ skb->protocol = __constant_htons(ETH_P_ZTDETH);
+ skb->nh.raw = skb->data;
+ skb->dev = z->dev;
+ z->dev->hard_header(skb, z->dev, ETH_P_ZTDETH, z->addr, z->dev->dev_addr, skb->len);
+ dev_queue_xmit(skb);
+ }
+ }
+ spin_unlock_irqrestore(&zlock, flags);
+ return 0;
+}
+
+static struct packet_type ztdeth_ptype = {
+ __constant_htons(ETH_P_ZTDETH), /* Protocol */
+ NULL, /* Device (NULL = wildcard) */
+ ztdeth_rcv, /* Receiver */
+ NULL, /* Data */
+ NULL /* Next */
+};
+
+static int digit2int(char d)
+{
+ switch(d) {
+ case 'F':
+ case 'E':
+ case 'D':
+ case 'C':
+ case 'B':
+ case 'A':
+ return d - 'A' + 10;
+ case 'f':
+ case 'e':
+ case 'd':
+ case 'c':
+ case 'b':
+ case 'a':
+ return d - 'a' + 10;
+ case '9':
+ case '8':
+ case '7':
+ case '6':
+ case '5':
+ case '4':
+ case '3':
+ case '2':
+ case '1':
+ case '0':
+ return d - '0';
+ }
+ return -1;
+}
+
+static int hex2int(char *s)
+{
+ int res;
+ int tmp;
+ /* Gotta be at least one digit */
+ if (strlen(s) < 1)
+ return -1;
+ /* Can't be more than two */
+ if (strlen(s) > 2)
+ return -1;
+ /* Grab the first digit */
+ res = digit2int(s[0]);
+ if (res < 0)
+ return -1;
+ tmp = res;
+ /* Grab the next */
+ if (strlen(s) > 1) {
+ res = digit2int(s[1]);
+ if (res < 0)
+ return -1;
+ tmp = tmp * 16 + res;
+ }
+ return tmp;
+}
+
+static void ztdeth_destroy(void *pvt)
+{
+ struct ztdeth *z = pvt;
+ long flags;
+ struct ztdeth *prev=NULL, *cur;
+ spin_lock_irqsave(&zlock, flags);
+ cur = zdevs;
+ while(cur) {
+ if (cur == z) {
+ if (prev)
+ prev->next = cur->next;
+ else
+ zdevs = cur->next;
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+ spin_unlock_irqrestore(&zlock, flags);
+}
+
+static void *ztdeth_create(struct zt_span *span, char *addr)
+{
+ struct ztdeth *z;
+ char src[256];
+ char tmp[256], *tmp2, *tmp3;
+ int res,x;
+ long flags;
+
+ z = kmalloc(sizeof(struct ztdeth), GFP_KERNEL);
+ if (z) {
+ /* Zero it out */
+ memset(z, 0, sizeof(struct ztdeth));
+
+ /* Address should be <dev>/<macaddr>[/subaddr] */
+ strncpy(tmp, addr, sizeof(tmp) - 1);
+ tmp2 = strtok(tmp, "/");
+ if (tmp2) {
+ strncpy(z->ethdev, tmp2, sizeof(z->ethdev) - 1);
+ } else {
+ printk("Invalid TDMoE address (no device) '%s'\n", addr);
+ kfree(z);
+ return NULL;
+ }
+ tmp2 = strtok(NULL, "/");
+ if (tmp2) {
+ /* We don't have SSCANF :( Gotta do this the hard way */
+ tmp3 = strtok(tmp2, ":");
+ for (x=0;x<6;x++) {
+ if (tmp3) {
+ res = hex2int(tmp3);
+ if (res < 0)
+ break;
+ z->addr[x] = res & 0xff;
+ } else
+ break;
+ tmp3 = strtok(NULL, ":");
+ }
+ if (x != 6) {
+ printk("TDMoE: Invalid MAC address in: %s\n", addr);
+ kfree(z);
+ return NULL;
+ }
+ } else {
+ printk("TDMoE: Missing MAC address\n");
+ kfree(z);
+ return NULL;
+ }
+ z->dev = dev_get_by_name(z->ethdev);
+ if (!z->dev) {
+ printk("TDMoE: Invalid device '%s'\n", z->ethdev);
+ kfree(z);
+ return NULL;
+ }
+ z->span = span;
+ src[0] ='\0';
+ for (x=0;x<5;x++)
+ sprintf(src + strlen(src), "%02x:", z->dev->dev_addr[x]);
+ sprintf(src + strlen(src), "%02x", z->dev->dev_addr[5]);
+ printk("TDMoE: Added new interface for %s at %s (addr=%s, src=%s)\n", span->name, z->dev->name, addr, src);
+
+ spin_lock_irqsave(&zlock, flags);
+ z->next = zdevs;
+ zdevs = z;
+ spin_unlock_irqrestore(&zlock, flags);
+ }
+ return z;
+}
+
+static struct zt_dynamic_driver ztd_eth = {
+ "eth",
+ "Ethernet",
+ ztdeth_create,
+ ztdeth_destroy,
+ ztdeth_transmit
+};
+
+static struct notifier_block ztdeth_nblock = {
+ notifier_call: ztdeth_notifier,
+};
+
+static int __init ztdeth_init(void)
+{
+ dev_add_pack(&ztdeth_ptype);
+ register_netdevice_notifier(&ztdeth_nblock);
+ zt_dynamic_register(&ztd_eth);
+ return 0;
+}
+
+static void __exit ztdeth_exit(void)
+{
+ dev_remove_pack(&ztdeth_ptype);
+ unregister_netdevice_notifier(&ztdeth_nblock);
+ zt_dynamic_unregister(&ztd_eth);
+}
+
+module_init(ztdeth_init);
+module_exit(ztdeth_exit);