[svn-commits] sruffell: linux/trunk r8118 - /linux/trunk/drivers/dahdi/voicebus/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Feb 26 10:40:52 CST 2010


Author: sruffell
Date: Fri Feb 26 10:40:41 2010
New Revision: 8118

URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=8118
Log:
voicebus: Add optional network debugging interface.

This interface is only used to facilitate debugging.

Added:
    linux/trunk/drivers/dahdi/voicebus/voicebus_net.c   (with props)
    linux/trunk/drivers/dahdi/voicebus/voicebus_net.h   (with props)
Modified:
    linux/trunk/drivers/dahdi/voicebus/Kbuild
    linux/trunk/drivers/dahdi/voicebus/voicebus.c
    linux/trunk/drivers/dahdi/voicebus/voicebus.h

Modified: linux/trunk/drivers/dahdi/voicebus/Kbuild
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/voicebus/Kbuild?view=diff&rev=8118&r1=8117&r2=8118
==============================================================================
--- linux/trunk/drivers/dahdi/voicebus/Kbuild (original)
+++ linux/trunk/drivers/dahdi/voicebus/Kbuild Fri Feb 26 10:40:41 2010
@@ -1,5 +1,5 @@
 obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += dahdi_voicebus.o
 
-dahdi_voicebus-objs := voicebus.o GpakCust.o GpakApi.o
+dahdi_voicebus-objs := voicebus.o GpakCust.o GpakApi.o voicebus_net.o
 
 EXTRA_CFLAGS := -I$(src)/.. -Wno-undef

Modified: linux/trunk/drivers/dahdi/voicebus/voicebus.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/voicebus/voicebus.c?view=diff&rev=8118&r1=8117&r2=8118
==============================================================================
--- linux/trunk/drivers/dahdi/voicebus/voicebus.c (original)
+++ linux/trunk/drivers/dahdi/voicebus/voicebus.c Fri Feb 26 10:40:41 2010
@@ -39,6 +39,7 @@
 
 #include <dahdi/kernel.h>
 #include "voicebus.h"
+#include "voicebus_net.h"
 #include "vpmadtreg.h"
 #include "GpakCust.h"
 
@@ -828,6 +829,7 @@
 	d->buffer1 = vb->idle_vbb_dma_addr;
 	SET_OWNED(d);
 	atomic_dec(&dl->count);
+	vb_net_capture_vbb(vb, vbb, 1, d->des0, d->container);
 	return vbb;
 }
 
@@ -850,6 +852,9 @@
 	dl->head = (++head) & DRING_MASK;
 	d->buffer1 = 0;
 	atomic_dec(&dl->count);
+#	ifdef VOICEBUS_NET_DEBUG
+	vb_net_capture_vbb(vb, vbb, 0, d->des0, d->container);
+#	endif
 	return vbb;
 }
 
@@ -1041,6 +1046,10 @@
 void
 voicebus_release(struct voicebus *vb)
 {
+#ifdef VOICEBUS_NET_DEBUG
+	vb_net_unregister(vb);
+#endif
+
 	/* quiesce the hardware */
 	voicebus_stop(vb);
 
@@ -1521,6 +1530,9 @@
 	}
 #endif
 
+#ifdef VOICEBUS_NET_DEBUG
+	vb_net_register(vb, board_name);
+#endif
 	return retval;
 cleanup:
 

Modified: linux/trunk/drivers/dahdi/voicebus/voicebus.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/voicebus/voicebus.h?view=diff&rev=8118&r1=8117&r2=8118
==============================================================================
--- linux/trunk/drivers/dahdi/voicebus/voicebus.h (original)
+++ linux/trunk/drivers/dahdi/voicebus/voicebus.h Fri Feb 26 10:40:41 2010
@@ -31,6 +31,12 @@
 
 #include <linux/interrupt.h>
 
+
+#ifdef VOICEBUS_NET_DEBUG
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#endif
+
 #define VOICEBUS_DEFAULT_LATENCY	3
 #define VOICEBUS_DEFAULT_MAXLATENCY	25
 #define VOICEBUS_MAXLATENCY_BUMP	6
@@ -48,6 +54,9 @@
 
 /* Do not generate interrupts on this interface, but instead just poll it */
 #undef CONFIG_VOICEBUS_TIMER
+
+/* Define this in order to create a debugging network interface. */
+#undef VOICEBUS_NET_DEBUG
 
 struct voicebus;
 
@@ -103,6 +112,17 @@
 	unsigned int		min_tx_buffer_count;
 	unsigned int		max_latency;
 	struct list_head	tx_complete;
+
+#ifdef VOICEBUS_NET_DEBUG
+	struct sk_buff_head captured_packets;
+	struct net_device *netdev;
+	struct net_device_stats net_stats;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
+	struct napi_struct napi;
+#endif
+	atomic_t tx_seqnum;
+	atomic_t rx_seqnum;
+#endif
 };
 
 int voicebus_init(struct voicebus *vb, const char *board_name);
@@ -116,5 +136,5 @@
 void voicebus_lock_latency(struct voicebus *vb);
 void voicebus_unlock_latency(struct voicebus *vb);
 int voicebus_is_latency_locked(const struct voicebus *vb);
- 
+
 #endif /* __VOICEBUS_H__ */

Added: linux/trunk/drivers/dahdi/voicebus/voicebus_net.c
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/voicebus/voicebus_net.c?view=auto&rev=8118
==============================================================================
--- linux/trunk/drivers/dahdi/voicebus/voicebus_net.c (added)
+++ linux/trunk/drivers/dahdi/voicebus/voicebus_net.c Fri Feb 26 10:40:41 2010
@@ -1,0 +1,377 @@
+/*
+ * Voicebus network debug interface
+ *
+ * Written by Shaun Ruffell <sruffell at digium.com>
+ *
+ * Copyright (C) 2010 Digium, Inc.
+ *
+ * All rights reserved.
+
+ * VoiceBus is a registered trademark of Digium.
+ *
+ */
+
+/*
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2 as published by the
+ * Free Software Foundation. See the LICENSE file included with
+ * this program for more details.
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include "voicebus.h"
+#include "voicebus_net.h"
+
+#ifdef VOICEBUS_NET_DEBUG
+
+#ifdef HAVE_NETDEV_PRIV
+struct voicebus_netdev_priv {
+	struct voicebus *vb;
+};
+#endif
+
+static inline struct voicebus *
+voicebus_from_netdev(struct net_device *netdev)
+{
+#ifdef HAVE_NETDEV_PRIV
+	struct voicebus_netdev_priv *priv;
+	priv = netdev_priv(netdev);
+	return priv->vb;
+#else
+	return netdev->priv;
+#endif
+}
+
+static void *
+skb_to_vbb(struct voicebus *vb, struct sk_buff *skb)
+{
+	int res;
+	void *vbb;
+	const int COMMON_HEADER = 30;
+
+	if (skb->len != (VOICEBUS_SFRAME_SIZE + COMMON_HEADER)) {
+		dev_warn(&vb->pdev->dev, "Packet of length %d is not the "
+			 "required %d.\n", skb->len,
+			 VOICEBUS_SFRAME_SIZE + COMMON_HEADER);
+		return NULL;
+	}
+
+	vbb = voicebus_alloc(vb);
+	if (!vbb)
+		return NULL;
+	res = skb_copy_bits(skb, COMMON_HEADER, vbb, VOICEBUS_SFRAME_SIZE);
+	if (res) {
+		dev_warn(&vb->pdev->dev, "Failed call to skb_copy_bits.\n");
+		voicebus_free(vb, vbb);
+		return NULL;
+	}
+	return vbb;
+}
+
+static int
+vb_net_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct voicebus *vb = voicebus_from_netdev(netdev);
+	void *vbb;
+
+	vbb = skb_to_vbb(vb, skb);
+	if (vbb)
+		voicebus_transmit(vb, vbb);
+
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static int vb_net_receive(struct voicebus *vb, int max)
+{
+	int count = 0;
+	struct sk_buff *skb;
+	WARN_ON(0 == max);
+	while ((skb = skb_dequeue(&vb->captured_packets))) {
+		netif_receive_skb(skb);
+		if (++count >= max)
+			break;
+	}
+	return count;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+static int vb_net_poll(struct net_device *netdev, int *budget)
+{
+	struct voicebus *vb = voicebus_from_netdev(netdev);
+	int count = 0;
+	int quota = min(netdev->quota, *budget);
+
+	count = vb_net_receive(vb, quota);
+
+	*budget -=       count;
+	netdev->quota -= count;
+
+	if (!skb_queue_len(&vb->captured_packets)) {
+		netif_rx_complete(netdev);
+		return 0;
+	} else {
+		return -1;
+	}
+}
+#else
+static int vb_net_poll(struct napi_struct *napi, int budget)
+{
+	struct voicebus *vb = container_of(napi, struct voicebus, napi);
+	int count;
+
+	count = vb_net_receive(vb, budget);
+
+	if (!skb_queue_len(&vb->captured_packets)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
+		netif_rx_complete(vb->netdev, &vb->napi);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+		netif_rx_complete(&vb->napi);
+#else
+		napi_complete(&vb->napi);
+#endif
+	}
+	return count;
+}
+#endif
+
+static void vb_net_set_multi(struct net_device *netdev)
+{
+	struct voicebus *vb = voicebus_from_netdev(netdev);
+	dev_dbg(&vb->pdev->dev, "%s promiscuity:%d\n",
+		__func__, netdev->promiscuity);
+}
+
+static int vb_net_up(struct net_device *netdev)
+{
+	struct voicebus *vb = voicebus_from_netdev(netdev);
+	dev_dbg(&vb->pdev->dev, "%s\n", __func__);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	netif_poll_enable(netdev);
+#else
+	napi_enable(&vb->napi);
+#endif
+	return 0;
+}
+
+static int vb_net_down(struct net_device *netdev)
+{
+	struct voicebus *vb = voicebus_from_netdev(netdev);
+	dev_dbg(&vb->pdev->dev, "%s\n", __func__);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	netif_poll_disable(netdev);
+#else
+	napi_disable(&vb->napi);
+#endif
+	return 0;
+}
+
+static struct net_device_stats *
+vb_net_get_stats(struct net_device *netdev)
+{
+	struct voicebus *vb = voicebus_from_netdev(netdev);
+	return &vb->net_stats;
+}
+
+#ifdef HAVE_NET_DEVICE_OPS
+static const struct net_device_ops vb_netdev_ops = {
+	.ndo_set_multicast_list = &vb_net_set_multi,
+	.ndo_open = &vb_net_up,
+	.ndo_stop = &vb_net_down,
+	.ndo_start_xmit = &vb_net_hard_start_xmit,
+	.ndo_get_stats = &vb_net_get_stats,
+};
+#endif
+
+/**
+ * vb_net_register - Register a new network interface.
+ * @vb: voicebus card to register the interface for.
+ *
+ * The network interface is primarily used for debugging in order to watch the
+ * traffic between the transcoder and the host.
+ *
+ */
+int vb_net_register(struct voicebus *vb, const char *board_name)
+{
+	int res;
+	struct net_device *netdev;
+#	ifdef HAVE_NETDEV_PRIV
+	struct voicebus_netdev_priv *priv;
+#	endif
+	const char our_mac[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
+
+#	ifdef HAVE_NETDEV_PRIV
+	netdev = alloc_netdev(sizeof(*priv), board_name, ether_setup);
+	if (!netdev)
+		return -ENOMEM;
+	priv = netdev_priv(netdev);
+	priv->vb = vb;
+#	else
+	netdev = alloc_netdev(0, vb->board_name, ether_setup);
+	if (!netdev)
+		return -ENOMEM;
+	netdev->priv = vb;
+#	endif
+	memcpy(netdev->dev_addr, our_mac, sizeof(our_mac));
+#	ifdef HAVE_NET_DEVICE_OPS
+	netdev->netdev_ops = &vb_netdev_ops;
+#	else
+	netdev->set_multicast_list = vb_net_set_multi;
+	netdev->open = vb_net_up;
+	netdev->stop = vb_net_down;
+	netdev->hard_start_xmit = vb_net_hard_start_xmit;
+	netdev->get_stats = vb_net_get_stats;
+#	endif
+
+	netdev->promiscuity = 0;
+	netdev->flags |= IFF_NOARP;
+#	if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	netdev->poll = vb_net_poll;
+	netdev->weight = 64;
+#	else
+	netif_napi_add(netdev, &vb->napi, vb_net_poll, 64);
+#	endif
+
+	skb_queue_head_init(&vb->captured_packets);
+	res = register_netdev(netdev);
+	if (res) {
+		dev_warn(&vb->pdev->dev,
+			 "Failed to register network device %s.\n", board_name);
+		goto error_sw;
+	}
+
+	vb->netdev = netdev;
+
+	dev_dbg(&vb->pdev->dev,
+		"Created network device %s for debug.\n", board_name);
+	return 0;
+
+error_sw:
+	if (netdev)
+		free_netdev(netdev);
+	return res;
+}
+
+void vb_net_unregister(struct voicebus *wc)
+{
+	struct sk_buff *skb;
+	if (!wc->netdev)
+		return;
+
+	unregister_netdev(wc->netdev);
+
+	while ((skb = skb_dequeue(&wc->captured_packets)))
+		kfree_skb(skb);
+
+	free_netdev(wc->netdev);
+	wc->netdev = NULL;
+}
+
+/* Header format for the voicebus network interface. */
+struct voicebus_net_hdr {
+	struct ethhdr ethhdr;
+	__be16 seq_num;
+	__be32 des0;
+	__be16 tag;
+	__be16 filler[4];
+} __attribute__((packed));
+
+static struct sk_buff *
+vbb_to_skb(struct net_device *netdev, const void *vbb, const int tx,
+	   const u32 des0, const u16 tag)
+{
+	struct voicebus *vb = voicebus_from_netdev(netdev);
+	struct sk_buff *skb;
+	struct voicebus_net_hdr *hdr;
+	/* 0x88B5 is the local experimental ethertype */
+	const u16 VOICEBUS_ETHTYPE = 0x88b5;
+	const u8 BOARD_MAC[6] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
+	const u8 HOST_MAC[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	skb = netdev_alloc_skb(vb->netdev,
+		VOICEBUS_SFRAME_SIZE + sizeof(*hdr) + NET_IP_ALIGN);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, NET_IP_ALIGN);
+	skb->dev = netdev;
+	hdr = (struct voicebus_net_hdr *)skb_put(skb, VOICEBUS_SFRAME_SIZE +
+						 sizeof(*hdr));
+	/* Fill in the source and destination mac addresses appropriately
+	 * depending on whether this is a packet we are transmitting or a packet
+	 * that we have received. */
+	if (tx) {
+		memcpy(hdr->ethhdr.h_dest, BOARD_MAC, sizeof(BOARD_MAC));
+		memcpy(hdr->ethhdr.h_source, HOST_MAC, sizeof(HOST_MAC));
+		hdr->seq_num = cpu_to_be16(atomic_inc_return(
+			&vb->tx_seqnum));
+	} else {
+		memcpy(hdr->ethhdr.h_dest, HOST_MAC, sizeof(HOST_MAC));
+		memcpy(hdr->ethhdr.h_source, BOARD_MAC, sizeof(BOARD_MAC));
+		hdr->seq_num = cpu_to_be16(atomic_inc_return(
+			&vb->rx_seqnum));
+	}
+	memset(hdr->filler, 0, sizeof(hdr->filler));
+	hdr->des0 = cpu_to_be32(des0);
+	hdr->tag = cpu_to_be16(tag);
+	hdr->ethhdr.h_proto = htons(VOICEBUS_ETHTYPE);
+	/* copy the rest of the packet. */
+	memcpy(skb->data + sizeof(*hdr), vbb, VOICEBUS_SFRAME_SIZE);
+	skb->protocol = eth_type_trans(skb, netdev);
+
+	return skb;
+}
+
+/**
+ * vb_net_capture_cmd - Send a vbb to the network stack.
+ * @vb: Interface card received the command.
+ * @vbb: Voicebus buffer to pass up..
+ * @tx: 1 if this is a vbb that the driver is sending to the card.
+ *
+ */
+void vb_net_capture_vbb(struct voicebus *vb, const void *vbb, const int tx,
+			const u32 des0, const u16 tag)
+{
+	struct sk_buff *skb;
+	struct net_device *netdev = vb->netdev;
+	const int MAX_CAPTURED_PACKETS = 5000;
+
+	if (!netdev)
+		return;
+
+	/* If the interface isn't up, we don't need to capture the packet. */
+	if (!(netdev->flags & IFF_UP))
+		return;
+
+	if (skb_queue_len(&vb->captured_packets) > MAX_CAPTURED_PACKETS) {
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	skb = vbb_to_skb(netdev, vbb, tx, des0, tag);
+	if (!skb)
+		return;
+
+	skb_queue_tail(&vb->captured_packets, skb);
+#	if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
+	netif_rx_schedule(netdev);
+#	elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
+	netif_rx_schedule(netdev, &vb->napi);
+#	elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+	netif_rx_schedule(&vb->napi);
+#	else
+	napi_schedule(&vb->napi);
+#	endif
+	return;
+}
+
+#endif

Propchange: linux/trunk/drivers/dahdi/voicebus/voicebus_net.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: linux/trunk/drivers/dahdi/voicebus/voicebus_net.c
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: linux/trunk/drivers/dahdi/voicebus/voicebus_net.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: linux/trunk/drivers/dahdi/voicebus/voicebus_net.h
URL: http://svnview.digium.com/svn/dahdi/linux/trunk/drivers/dahdi/voicebus/voicebus_net.h?view=auto&rev=8118
==============================================================================
--- linux/trunk/drivers/dahdi/voicebus/voicebus_net.h (added)
+++ linux/trunk/drivers/dahdi/voicebus/voicebus_net.h Fri Feb 26 10:40:41 2010
@@ -1,0 +1,10 @@
+#ifdef VOICEBUS_NET_DEBUG
+int vb_net_register(struct voicebus *, const char *);
+void vb_net_unregister(struct voicebus *);
+void vb_net_capture_vbb(struct voicebus *, const void *,
+			const int, const u32, const u16);
+#else
+#define vb_net_register(a, b) do { ; } while (0)
+#define vb_net_unregister(a) do { ; } while (0)
+#define vb_net_capture_vbb(a, b, c, d, e) do { ; } while (0)
+#endif

Propchange: linux/trunk/drivers/dahdi/voicebus/voicebus_net.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: linux/trunk/drivers/dahdi/voicebus/voicebus_net.h
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: linux/trunk/drivers/dahdi/voicebus/voicebus_net.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the svn-commits mailing list