voicebus_net.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. * Voicebus network debug interface
  3. *
  4. * Written by Shaun Ruffell <sruffell@digium.com>
  5. *
  6. * Copyright (C) 2010-2011 Digium, Inc.
  7. *
  8. * All rights reserved.
  9. * VoiceBus is a registered trademark of Digium.
  10. *
  11. */
  12. /*
  13. * See http://www.asterisk.org for more information about
  14. * the Asterisk project. Please do not directly contact
  15. * any of the maintainers of this project for assistance;
  16. * the project provides a web site, mailing lists and IRC
  17. * channels for your use.
  18. *
  19. * This program is free software, distributed under the terms of
  20. * the GNU General Public License Version 2 as published by the
  21. * Free Software Foundation. See the LICENSE file included with
  22. * this program for more details.
  23. */
  24. #include <linux/version.h>
  25. #include <linux/kernel.h>
  26. #include <linux/pci.h>
  27. #include <linux/slab.h>
  28. #include <dahdi/kernel.h>
  29. #include "voicebus.h"
  30. #include "voicebus_net.h"
  31. #ifdef VOICEBUS_NET_DEBUG
  32. struct voicebus_netdev_priv {
  33. struct voicebus *vb;
  34. };
  35. static inline struct voicebus *
  36. voicebus_from_netdev(struct net_device *netdev)
  37. {
  38. struct voicebus_netdev_priv *priv;
  39. priv = netdev_priv(netdev);
  40. return priv->vb;
  41. }
  42. static void *
  43. skb_to_vbb(struct voicebus *vb, struct sk_buff *skb)
  44. {
  45. int res;
  46. struct vbb *vbb;
  47. const int COMMON_HEADER = 30;
  48. dma_addr_t dma_addr;
  49. if (skb->len != (VOICEBUS_SFRAME_SIZE + COMMON_HEADER)) {
  50. dev_warn(&vb->pdev->dev, "Packet of length %d is not the "
  51. "required %d.\n", skb->len,
  52. VOICEBUS_SFRAME_SIZE + COMMON_HEADER);
  53. return NULL;
  54. }
  55. vbb = dma_pool_alloc(vb->pool, GFP_KERNEL, &dma_addr);
  56. if (!vbb)
  57. return NULL;
  58. vbb->dma_addr = dma_addr;
  59. res = skb_copy_bits(skb, COMMON_HEADER, vbb, VOICEBUS_SFRAME_SIZE);
  60. if (res) {
  61. dev_warn(&vb->pdev->dev, "Failed call to skb_copy_bits.\n");
  62. dma_pool_free(vb->pool, vbb, vbb->dma_addr);
  63. return NULL;
  64. }
  65. return vbb;
  66. }
  67. static int
  68. vb_net_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
  69. {
  70. struct voicebus *vb = voicebus_from_netdev(netdev);
  71. void *vbb;
  72. vbb = skb_to_vbb(vb, skb);
  73. if (vbb)
  74. voicebus_transmit(vb, vbb);
  75. dev_kfree_skb_any(skb);
  76. return NETDEV_TX_OK;
  77. }
  78. static int vb_net_receive(struct voicebus *vb, int max)
  79. {
  80. int count = 0;
  81. struct sk_buff *skb;
  82. WARN_ON(0 == max);
  83. while ((skb = skb_dequeue(&vb->captured_packets))) {
  84. netif_receive_skb(skb);
  85. if (++count >= max)
  86. break;
  87. }
  88. return count;
  89. }
  90. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  91. static int vb_net_poll(struct net_device *netdev, int *budget)
  92. {
  93. struct voicebus *vb = voicebus_from_netdev(netdev);
  94. int count = 0;
  95. int quota = min(netdev->quota, *budget);
  96. count = vb_net_receive(vb, quota);
  97. *budget -= count;
  98. netdev->quota -= count;
  99. if (!skb_queue_len(&vb->captured_packets)) {
  100. netif_rx_complete(netdev);
  101. return 0;
  102. } else {
  103. return -1;
  104. }
  105. }
  106. #else
  107. static int vb_net_poll(struct napi_struct *napi, int budget)
  108. {
  109. struct voicebus *vb = container_of(napi, struct voicebus, napi);
  110. int count;
  111. count = vb_net_receive(vb, budget);
  112. if (!skb_queue_len(&vb->captured_packets)) {
  113. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
  114. netif_rx_complete(vb->netdev, &vb->napi);
  115. #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
  116. netif_rx_complete(&vb->napi);
  117. #else
  118. napi_complete(&vb->napi);
  119. #endif
  120. }
  121. return count;
  122. }
  123. #endif
  124. static void vb_net_set_multi(struct net_device *netdev)
  125. {
  126. struct voicebus *vb = voicebus_from_netdev(netdev);
  127. dev_dbg(&vb->pdev->dev, "%s promiscuity:%d\n",
  128. __func__, netdev->promiscuity);
  129. }
  130. static int vb_net_up(struct net_device *netdev)
  131. {
  132. struct voicebus *vb = voicebus_from_netdev(netdev);
  133. dev_dbg(&vb->pdev->dev, "%s\n", __func__);
  134. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  135. netif_poll_enable(netdev);
  136. #else
  137. napi_enable(&vb->napi);
  138. #endif
  139. return 0;
  140. }
  141. static int vb_net_down(struct net_device *netdev)
  142. {
  143. struct voicebus *vb = voicebus_from_netdev(netdev);
  144. dev_dbg(&vb->pdev->dev, "%s\n", __func__);
  145. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  146. netif_poll_disable(netdev);
  147. #else
  148. napi_disable(&vb->napi);
  149. #endif
  150. return 0;
  151. }
  152. static struct net_device_stats *
  153. vb_net_get_stats(struct net_device *netdev)
  154. {
  155. struct voicebus *vb = voicebus_from_netdev(netdev);
  156. return &vb->net_stats;
  157. }
  158. #ifdef HAVE_NET_DEVICE_OPS
  159. static const struct net_device_ops vb_netdev_ops = {
  160. .ndo_set_multicast_list = &vb_net_set_multi,
  161. .ndo_open = &vb_net_up,
  162. .ndo_stop = &vb_net_down,
  163. .ndo_start_xmit = &vb_net_hard_start_xmit,
  164. .ndo_get_stats = &vb_net_get_stats,
  165. };
  166. #endif
  167. /**
  168. * vb_net_register - Register a new network interface.
  169. * @vb: voicebus card to register the interface for.
  170. *
  171. * The network interface is primarily used for debugging in order to watch the
  172. * traffic between the transcoder and the host.
  173. *
  174. */
  175. int vb_net_register(struct voicebus *vb, const char *board_name)
  176. {
  177. int res;
  178. struct net_device *netdev;
  179. struct voicebus_netdev_priv *priv;
  180. const char our_mac[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
  181. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
  182. netdev = alloc_netdev(sizeof(*priv), board_name,
  183. NET_NAME_UNKNOWN, ether_setup);
  184. #else
  185. netdev = alloc_netdev(sizeof(*priv), board_name, ether_setup);
  186. #endif
  187. if (!netdev)
  188. return -ENOMEM;
  189. priv = netdev_priv(netdev);
  190. priv->vb = vb;
  191. memcpy(netdev->dev_addr, our_mac, sizeof(our_mac));
  192. # ifdef HAVE_NET_DEVICE_OPS
  193. netdev->netdev_ops = &vb_netdev_ops;
  194. # else
  195. netdev->set_multicast_list = vb_net_set_multi;
  196. netdev->open = vb_net_up;
  197. netdev->stop = vb_net_down;
  198. netdev->hard_start_xmit = vb_net_hard_start_xmit;
  199. netdev->get_stats = vb_net_get_stats;
  200. # endif
  201. netdev->promiscuity = 0;
  202. netdev->flags |= IFF_NOARP;
  203. # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  204. netdev->poll = vb_net_poll;
  205. netdev->weight = 64;
  206. # else
  207. netif_napi_add(netdev, &vb->napi, vb_net_poll, 64);
  208. # endif
  209. skb_queue_head_init(&vb->captured_packets);
  210. res = register_netdev(netdev);
  211. if (res) {
  212. dev_warn(&vb->pdev->dev,
  213. "Failed to register network device %s.\n", board_name);
  214. goto error_sw;
  215. }
  216. vb->netdev = netdev;
  217. dev_dbg(&vb->pdev->dev,
  218. "Created network device %s for debug.\n", board_name);
  219. return 0;
  220. error_sw:
  221. if (netdev)
  222. free_netdev(netdev);
  223. return res;
  224. }
  225. void vb_net_unregister(struct voicebus *wc)
  226. {
  227. struct sk_buff *skb;
  228. if (!wc->netdev)
  229. return;
  230. unregister_netdev(wc->netdev);
  231. while ((skb = skb_dequeue(&wc->captured_packets)))
  232. kfree_skb(skb);
  233. free_netdev(wc->netdev);
  234. wc->netdev = NULL;
  235. }
  236. /* Header format for the voicebus network interface. */
  237. struct voicebus_net_hdr {
  238. struct ethhdr ethhdr;
  239. __be16 seq_num;
  240. __be32 des0;
  241. __be16 tag;
  242. __be16 filler[4];
  243. } __attribute__((packed));
  244. static struct sk_buff *
  245. vbb_to_skb(struct net_device *netdev, const void *vbb, const int tx,
  246. const u32 des0, const u16 tag)
  247. {
  248. struct voicebus *vb = voicebus_from_netdev(netdev);
  249. struct sk_buff *skb;
  250. struct voicebus_net_hdr *hdr;
  251. /* 0x88B5 is the local experimental ethertype */
  252. const u16 VOICEBUS_ETHTYPE = 0x88b5;
  253. const u8 BOARD_MAC[6] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
  254. const u8 HOST_MAC[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  255. skb = netdev_alloc_skb(vb->netdev,
  256. VOICEBUS_SFRAME_SIZE + sizeof(*hdr) + NET_IP_ALIGN);
  257. if (!skb)
  258. return NULL;
  259. skb_reserve(skb, NET_IP_ALIGN);
  260. skb->dev = netdev;
  261. hdr = (struct voicebus_net_hdr *)skb_put(skb, VOICEBUS_SFRAME_SIZE +
  262. sizeof(*hdr));
  263. /* Fill in the source and destination mac addresses appropriately
  264. * depending on whether this is a packet we are transmitting or a packet
  265. * that we have received. */
  266. if (tx) {
  267. memcpy(hdr->ethhdr.h_dest, BOARD_MAC, sizeof(BOARD_MAC));
  268. memcpy(hdr->ethhdr.h_source, HOST_MAC, sizeof(HOST_MAC));
  269. hdr->seq_num = cpu_to_be16(atomic_inc_return(
  270. &vb->tx_seqnum));
  271. } else {
  272. memcpy(hdr->ethhdr.h_dest, HOST_MAC, sizeof(HOST_MAC));
  273. memcpy(hdr->ethhdr.h_source, BOARD_MAC, sizeof(BOARD_MAC));
  274. hdr->seq_num = cpu_to_be16(atomic_inc_return(
  275. &vb->rx_seqnum));
  276. }
  277. memset(hdr->filler, 0, sizeof(hdr->filler));
  278. hdr->des0 = cpu_to_be32(des0);
  279. hdr->tag = cpu_to_be16(tag);
  280. hdr->ethhdr.h_proto = htons(VOICEBUS_ETHTYPE);
  281. /* copy the rest of the packet. */
  282. memcpy(skb->data + sizeof(*hdr), vbb, VOICEBUS_SFRAME_SIZE);
  283. skb->protocol = eth_type_trans(skb, netdev);
  284. return skb;
  285. }
  286. /**
  287. * vb_net_capture_cmd - Send a vbb to the network stack.
  288. * @vb: Interface card received the command.
  289. * @vbb: Voicebus buffer to pass up..
  290. * @tx: 1 if this is a vbb that the driver is sending to the card.
  291. *
  292. */
  293. void vb_net_capture_vbb(struct voicebus *vb, const void *vbb, const int tx,
  294. const u32 des0, const u16 tag)
  295. {
  296. struct sk_buff *skb;
  297. struct net_device *netdev = vb->netdev;
  298. const int MAX_CAPTURED_PACKETS = 5000;
  299. if (!netdev)
  300. return;
  301. /* If the interface isn't up, we don't need to capture the packet. */
  302. if (!(netdev->flags & IFF_UP))
  303. return;
  304. if (skb_queue_len(&vb->captured_packets) > MAX_CAPTURED_PACKETS) {
  305. WARN_ON_ONCE(1);
  306. return;
  307. }
  308. skb = vbb_to_skb(netdev, vbb, tx, des0, tag);
  309. if (!skb)
  310. return;
  311. skb_queue_tail(&vb->captured_packets, skb);
  312. # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  313. netif_rx_schedule(netdev);
  314. # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
  315. netif_rx_schedule(netdev, &vb->napi);
  316. # elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
  317. netif_rx_schedule(&vb->napi);
  318. # else
  319. napi_schedule(&vb->napi);
  320. # endif
  321. return;
  322. }
  323. #endif