PageRenderTime 55ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/examples/live_stream/talker.c

https://github.com/masche842/Open-AVB
C | 889 lines | 719 code | 114 blank | 56 comment | 126 complexity | ba4acb07bb99de6f647c7ac919362494 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0
  1. /*
  2. * Copyright (c) <2013>, Intel Corporation.
  3. *
  4. * This program is free software; you can redistribute it and/or modify it
  5. * under the terms and conditions of the GNU Lesser General Public License,
  6. * version 2.1, as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope it will be useful, but WITHOUT
  9. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
  11. * more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License along with
  14. * this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  16. *
  17. */
  18. #include <errno.h>
  19. #include <fcntl.h>
  20. #include <math.h>
  21. #include <poll.h>
  22. #include <pthread.h>
  23. #include <signal.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <syslog.h>
  28. #include <unistd.h>
  29. #include <sched.h>
  30. #include <arpa/inet.h>
  31. #include <linux/if.h>
  32. #include <netinet/in.h>
  33. #include <net/ethernet.h>
  34. #include <netpacket/packet.h>
  35. #include <pci/pci.h>
  36. #include <sys/ioctl.h>
  37. #include <sys/mman.h>
  38. #include <sys/resource.h>
  39. #include <sys/socket.h>
  40. #include <sys/stat.h>
  41. #include <sys/time.h>
  42. #include <sys/queue.h>
  43. #include <sys/un.h>
  44. #include <sys/user.h>
  45. #include "avb.h"
  46. #include "mrpd.h"
  47. #include "mrp.h"
  48. #include "msrp.h"
  49. /* global variables */
  50. int control_socket = -1;
  51. volatile int halt_tx = 0;
  52. volatile int listeners = 0;
  53. volatile int mrp_okay;
  54. volatile int mrp_error = 0;;
  55. volatile int domain_a_valid = 0;
  56. volatile int domain_b_valid = 0;
  57. int domain_class_b_id;
  58. int domain_class_b_priority;
  59. int domain_class_b_vid;
  60. int g_start_feed_socket = 0;
  61. device_t igb_dev;
  62. pthread_t monitor_thread;
  63. pthread_attr_t monitor_attr;
  64. uint32_t payload_length;
  65. unsigned char monitor_stream_id[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  66. unsigned char STATION_ADDR[] = { 0, 0, 0, 0, 0, 0 };
  67. unsigned char STREAM_ID[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  68. /* IEEE 1722 reserved address */
  69. unsigned char DEST_ADDR[] = { 0x91, 0xE0, 0xF0, 0x00, 0x0E, 0x80 };
  70. #define STREAMID 0xABCDEF
  71. /* (1) packet every 125 usec */
  72. #define PACKET_IPG 125000
  73. #define USE_MRPD 1
  74. #ifdef USE_MRPD
  75. int domain_class_a_id;
  76. int domain_class_a_priority;
  77. int domain_class_a_vid;
  78. int send_mrp_msg(char *notify_data, int notify_len)
  79. {
  80. struct sockaddr_in addr;
  81. socklen_t addr_len;
  82. memset(&addr, 0, sizeof(addr));
  83. addr.sin_family = AF_INET;
  84. addr.sin_port = htons(MRPD_PORT_DEFAULT);
  85. inet_aton("127.0.0.1", &addr.sin_addr);
  86. addr_len = sizeof(addr);
  87. if (control_socket != -1)
  88. return (sendto
  89. (control_socket, notify_data, notify_len, 0,
  90. (struct sockaddr *)&addr, addr_len));
  91. return 0;
  92. }
  93. int mrp_connect()
  94. {
  95. struct sockaddr_in addr;
  96. int sock_fd = -1;
  97. sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  98. if (sock_fd < 0)
  99. goto out;
  100. memset(&addr, 0, sizeof(addr));
  101. addr.sin_family = AF_INET;
  102. addr.sin_port = htons(MRPD_PORT_DEFAULT);
  103. inet_aton("127.0.0.1", &addr.sin_addr);
  104. memset(&addr, 0, sizeof(addr));
  105. control_socket = sock_fd;
  106. return 0;
  107. out: if (sock_fd != -1)
  108. close(sock_fd);
  109. sock_fd = -1;
  110. return -1;
  111. }
  112. int mrp_disconnect()
  113. {
  114. char *msgbuf;
  115. int rc;
  116. msgbuf = malloc(64);
  117. if (NULL == msgbuf)
  118. return -1;
  119. memset(msgbuf, 0, 64);
  120. sprintf(msgbuf, "BYE");
  121. mrp_okay = 0;
  122. rc = send_mrp_msg(msgbuf, 1500);
  123. free(msgbuf);
  124. return rc;
  125. }
  126. int recv_mrp_okay()
  127. {
  128. while ((mrp_okay == 0) && (mrp_error == 0))
  129. usleep(20000);
  130. return 0;
  131. }
  132. int mrp_register_domain(int *class_id, int *priority, u_int16_t * vid)
  133. {
  134. char *msgbuf;
  135. int rc;
  136. msgbuf = malloc(64);
  137. if (NULL == msgbuf)
  138. return -1;
  139. memset(msgbuf, 0, 64);
  140. sprintf(msgbuf, "S+D:C=%d,P=%d,V=%04x", *class_id, *priority, *vid);
  141. mrp_okay = 0;
  142. rc = send_mrp_msg(msgbuf, 1500);
  143. free(msgbuf);
  144. return rc;
  145. }
  146. int mrp_get_domain(int *class_a_id, int *a_priority, u_int16_t * a_vid,
  147. int *class_b_id, int *b_priority, u_int16_t * b_vid)
  148. {
  149. char *msgbuf;
  150. /* we may not get a notification if we are joining late,
  151. * so query for what is already there ...
  152. */
  153. msgbuf = malloc(64);
  154. if (NULL == msgbuf)
  155. return -1;
  156. memset(msgbuf, 0, 64);
  157. sprintf(msgbuf, "S??");
  158. send_mrp_msg(msgbuf, 64);
  159. free(msgbuf);
  160. while (!halt_tx && (domain_a_valid == 0) && (domain_b_valid == 0))
  161. usleep(20000);
  162. *class_a_id = 0;
  163. *a_priority = 0;
  164. *a_vid = 0;
  165. *class_b_id = 0;
  166. *b_priority = 0;
  167. *b_vid = 0;
  168. if (domain_a_valid) {
  169. *class_a_id = domain_class_a_id;
  170. *a_priority = domain_class_a_priority;
  171. *a_vid = domain_class_a_vid;
  172. }
  173. if (domain_b_valid) {
  174. *class_b_id = domain_class_b_id;
  175. *b_priority = domain_class_b_priority;
  176. *b_vid = domain_class_b_vid;
  177. }
  178. return 0;
  179. }
  180. int mrp_await_listener(unsigned char *streamid)
  181. {
  182. char *msgbuf;
  183. memcpy(monitor_stream_id, streamid, sizeof(monitor_stream_id));
  184. msgbuf = malloc(64);
  185. if (NULL == msgbuf)
  186. return -1;
  187. memset(msgbuf, 0, 64);
  188. sprintf(msgbuf, "S??");
  189. send_mrp_msg(msgbuf, 64);
  190. free(msgbuf);
  191. /* either already there ... or need to wait ... */
  192. while (!halt_tx && (listeners == 0))
  193. usleep(20000);
  194. return 0;
  195. }
  196. int process_mrp_msg(char *buf, int buflen)
  197. {
  198. /*
  199. * 1st character indicates application
  200. * [MVS] - MAC, VLAN or STREAM
  201. */
  202. unsigned int id;
  203. unsigned int priority;
  204. unsigned int vid;
  205. int i, j, k;
  206. unsigned int substate;
  207. unsigned char recovered_streamid[8];
  208. k = 0;
  209. next_line:if (k >= buflen)
  210. return 0;
  211. switch (buf[k]) {
  212. case 'E':
  213. fprintf(stderr, "%s from mrpd\n", buf);
  214. fflush(stdout);
  215. mrp_error = 1;
  216. break;
  217. case 'O':
  218. mrp_okay = 1;
  219. break;
  220. case 'M':
  221. case 'V':
  222. fprintf(stderr, "%s unhandled from mrpd\n", buf);
  223. fflush(stdout);
  224. /* unhandled for now */
  225. break;
  226. case 'L':
  227. /* parse a listener attribute - see if it matches our monitor_stream_id */
  228. i = k;
  229. while (buf[i] != 'D')
  230. i++;
  231. i += 2; /* skip the ':' */
  232. sscanf(&(buf[i]), "%d", &substate);
  233. while (buf[i] != 'S')
  234. i++;
  235. i += 2; /* skip the ':' */
  236. for (j = 0; j < 8; j++) {
  237. sscanf(&(buf[i + 2 * j]), "%02x", &id);
  238. recovered_streamid[j] = (unsigned char)id;
  239. } printf
  240. ("FOUND STREAM ID=%02x%02x%02x%02x%02x%02x%02x%02x ",
  241. recovered_streamid[0], recovered_streamid[1],
  242. recovered_streamid[2], recovered_streamid[3],
  243. recovered_streamid[4], recovered_streamid[5],
  244. recovered_streamid[6], recovered_streamid[7]);
  245. switch (substate) {
  246. case 0:
  247. fprintf(stderr, "with state ignore\n");
  248. break;
  249. case 1:
  250. fprintf(stderr, "with state askfailed\n");
  251. break;
  252. case 2:
  253. fprintf(stderr, "with state ready\n");
  254. break;
  255. case 3:
  256. fprintf(stderr, "with state readyfail\n");
  257. break;
  258. default:
  259. fprintf(stderr, "with state UNKNOWN (%d)\n", substate);
  260. break;
  261. }
  262. if (substate > MSRP_LISTENER_ASKFAILED) {
  263. if (memcmp
  264. (recovered_streamid, monitor_stream_id,
  265. sizeof(recovered_streamid)) == 0) {
  266. listeners = 1;
  267. fprintf(stderr, "added listener\n");
  268. }
  269. }
  270. fflush(stdout);
  271. /* try to find a newline ... */
  272. while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
  273. i++;
  274. if (i == buflen)
  275. return 0;
  276. if (buf[i] == '\0')
  277. return 0;
  278. i++;
  279. k = i;
  280. goto next_line;
  281. break;
  282. case 'D':
  283. i = k + 4;
  284. /* save the domain attribute */
  285. sscanf(&(buf[i]), "%d", &id);
  286. while (buf[i] != 'P')
  287. i++;
  288. i += 2; /* skip the ':' */
  289. sscanf(&(buf[i]), "%d", &priority);
  290. while (buf[i] != 'V')
  291. i++;
  292. i += 2; /* skip the ':' */
  293. sscanf(&(buf[i]), "%x", &vid);
  294. if (id == 6) {
  295. domain_class_a_id = id;
  296. domain_class_a_priority = priority;
  297. domain_class_a_vid = vid;
  298. domain_a_valid = 1;
  299. } else {
  300. domain_class_b_id = id;
  301. domain_class_b_priority = priority;
  302. domain_class_b_vid = vid;
  303. domain_b_valid = 1;
  304. }
  305. while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
  306. i++;
  307. if ((i == buflen) || (buf[i] == '\0'))
  308. return 0;
  309. i++;
  310. k = i;
  311. goto next_line;
  312. break;
  313. case 'T':
  314. /* as simple_talker we don't care about other talkers */
  315. i = k;
  316. while ((i < buflen) && (buf[i] != '\n') && (buf[i] != '\0'))
  317. i++;
  318. if (i == buflen)
  319. return 0;
  320. if (buf[i] == '\0')
  321. return 0;
  322. i++;
  323. k = i;
  324. goto next_line;
  325. break;
  326. case 'S':
  327. /* handle the leave/join events */
  328. switch (buf[k + 4]) {
  329. case 'L':
  330. i = k + 5;
  331. while (buf[i] != 'D')
  332. i++;
  333. i += 2; /* skip the ':' */
  334. sscanf(&(buf[i]), "%d", &substate);
  335. while (buf[i] != 'S')
  336. i++;
  337. i += 2; /* skip the ':' */
  338. for (j = 0; j < 8; j++) {
  339. sscanf(&(buf[i + 2 * j]), "%02x", &id);
  340. recovered_streamid[j] = (unsigned char)id;
  341. } printf
  342. ("EVENT on STREAM ID=%02x%02x%02x%02x%02x%02x%02x%02x ",
  343. recovered_streamid[0], recovered_streamid[1],
  344. recovered_streamid[2], recovered_streamid[3],
  345. recovered_streamid[4], recovered_streamid[5],
  346. recovered_streamid[6], recovered_streamid[7]);
  347. switch (substate) {
  348. case 0:
  349. fprintf(stderr, "with state ignore\n");
  350. break;
  351. case 1:
  352. fprintf(stderr, "with state askfailed\n");
  353. break;
  354. case 2:
  355. fprintf(stderr, "with state ready\n");
  356. break;
  357. case 3:
  358. fprintf(stderr, "with state readyfail\n");
  359. break;
  360. default:
  361. fprintf(stderr, "with state UNKNOWN (%d)\n", substate);
  362. break;
  363. }
  364. switch (buf[k + 1]) {
  365. case 'L':
  366. fprintf(stderr, "got a leave indication\n");
  367. if (memcmp
  368. (recovered_streamid, monitor_stream_id,
  369. sizeof(recovered_streamid)) == 0) {
  370. listeners = 0;
  371. fprintf(stderr, "listener left\n");
  372. }
  373. break;
  374. case 'J':
  375. case 'N':
  376. fprintf(stderr, "got a new/join indication\n");
  377. if (substate > MSRP_LISTENER_ASKFAILED) {
  378. if (memcmp
  379. (recovered_streamid,
  380. monitor_stream_id,
  381. sizeof(recovered_streamid)) == 0)
  382. listeners = 1;
  383. }
  384. break;
  385. }
  386. /* only care about listeners ... */
  387. default:
  388. return 0;
  389. break;
  390. }
  391. break;
  392. case '\0':
  393. break;
  394. }
  395. return 0;
  396. }
  397. void *mrp_monitor_thread(void *arg)
  398. {
  399. char *msgbuf;
  400. struct sockaddr_in client_addr;
  401. struct msghdr msg;
  402. struct iovec iov;
  403. int bytes = 0;
  404. struct pollfd fds;
  405. int rc;
  406. if (NULL == arg)
  407. rc = 0;
  408. else
  409. rc = 1;
  410. msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
  411. if (NULL == msgbuf)
  412. return NULL;
  413. while (!halt_tx) {
  414. fds.fd = control_socket;
  415. fds.events = POLLIN;
  416. fds.revents = 0;
  417. rc = poll(&fds, 1, 100);
  418. if (rc < 0) {
  419. free(msgbuf);
  420. pthread_exit(NULL);
  421. }
  422. if (rc == 0)
  423. continue;
  424. if ((fds.revents & POLLIN) == 0) {
  425. free(msgbuf);
  426. pthread_exit(NULL);
  427. }
  428. memset(&msg, 0, sizeof(msg));
  429. memset(&client_addr, 0, sizeof(client_addr));
  430. memset(msgbuf, 0, MAX_MRPD_CMDSZ);
  431. iov.iov_len = MAX_MRPD_CMDSZ;
  432. iov.iov_base = msgbuf;
  433. msg.msg_name = &client_addr;
  434. msg.msg_namelen = sizeof(client_addr);
  435. msg.msg_iov = &iov;
  436. msg.msg_iovlen = 1;
  437. bytes = recvmsg(control_socket, &msg, 0);
  438. if (bytes < 0)
  439. continue;
  440. process_mrp_msg(msgbuf, bytes);
  441. }
  442. free(msgbuf);
  443. pthread_exit(NULL);
  444. }
  445. int mrp_monitor()
  446. {
  447. pthread_attr_init(&monitor_attr);
  448. pthread_create(&monitor_thread, NULL, mrp_monitor_thread, NULL);
  449. return 0;
  450. }
  451. int mrp_join_listener(uint8_t * streamid)
  452. {
  453. char *msgbuf;
  454. int rc;
  455. msgbuf = malloc(1500);
  456. if (NULL == msgbuf)
  457. return -1;
  458. memset(msgbuf, 0, 1500);
  459. sprintf(msgbuf, "S+L:S=%02X%02X%02X%02X%02X%02X%02X%02X"
  460. ",D=2", streamid[0], streamid[1], streamid[2], streamid[3],
  461. streamid[4], streamid[5], streamid[6], streamid[7]);
  462. mrp_okay = 0;
  463. rc = send_mrp_msg(msgbuf, 1500);
  464. free(msgbuf);
  465. return rc;
  466. }
  467. int
  468. mrp_advertise_stream(uint8_t * streamid,
  469. uint8_t * destaddr,
  470. u_int16_t vlan,
  471. int pktsz, int interval, int priority, int latency)
  472. {
  473. char *msgbuf;
  474. int rc;
  475. msgbuf = malloc(1500);
  476. if (NULL == msgbuf)
  477. return -1;
  478. memset(msgbuf, 0, 1500);
  479. sprintf(msgbuf, "S++:S=%02X%02X%02X%02X%02X%02X%02X%02X"
  480. ",A=%02X%02X%02X%02X%02X%02X"
  481. ",V=%04X"
  482. ",Z=%d"
  483. ",I=%d"
  484. ",P=%d"
  485. ",L=%d", streamid[0], streamid[1], streamid[2],
  486. streamid[3], streamid[4], streamid[5], streamid[6],
  487. streamid[7], destaddr[0], destaddr[1], destaddr[2],
  488. destaddr[3], destaddr[4], destaddr[5], vlan, pktsz,
  489. interval, priority << 5, latency);
  490. mrp_okay = 0;
  491. rc = send_mrp_msg(msgbuf, 1500);
  492. /* rc = recv_mrp_okay(); */
  493. free(msgbuf);
  494. return rc;
  495. }
  496. int
  497. mrp_unadvertise_stream(uint8_t * streamid,
  498. uint8_t * destaddr,
  499. u_int16_t vlan,
  500. int pktsz, int interval, int priority, int latency)
  501. {
  502. char *msgbuf;
  503. int rc;
  504. msgbuf = malloc(1500);
  505. if (NULL == msgbuf)
  506. return -1;
  507. memset(msgbuf, 0, 1500);
  508. sprintf(msgbuf, "S--:S=%02X%02X%02X%02X%02X%02X%02X%02X"
  509. ",A=%02X%02X%02X%02X%02X%02X"
  510. ",V=%04X"
  511. ",Z=%d"
  512. ",I=%d"
  513. ",P=%d"
  514. ",L=%d", streamid[0], streamid[1], streamid[2],
  515. streamid[3], streamid[4], streamid[5], streamid[6],
  516. streamid[7], destaddr[0], destaddr[1], destaddr[2],
  517. destaddr[3], destaddr[4], destaddr[5], vlan, pktsz,
  518. interval, priority << 5, latency);
  519. mrp_okay = 0;
  520. rc = send_mrp_msg(msgbuf, 1500);
  521. /* rc = recv_mrp_okay(); */
  522. free(msgbuf);
  523. return rc;
  524. }
  525. #endif
  526. uint64_t reverse_64(uint64_t val)
  527. {
  528. uint32_t low, high;
  529. low = val & 0xffffffff;
  530. high = (val >> 32) & 0xffffffff;
  531. low = htonl(low);
  532. high = htonl(high);
  533. val = 0;
  534. val = val | low;
  535. val = (val << 32) | high;
  536. return val;
  537. }
  538. void sigint_handler(int signum)
  539. {
  540. fprintf(stderr, "got SIGINT\n");
  541. halt_tx = signum;
  542. }
  543. int get_mac_addr(int8_t *iface)
  544. {
  545. int lsock = socket(PF_PACKET, SOCK_RAW, htons(0x800));
  546. struct ifreq if_request;
  547. int rc;
  548. if (lsock < 0)
  549. return -1;
  550. memset(&if_request, 0, sizeof(if_request));
  551. strncpy(if_request.ifr_name, (const char *)iface, sizeof(if_request.ifr_name));
  552. rc = ioctl(lsock, SIOCGIFHWADDR, &if_request);
  553. if (rc < 0) {
  554. close(lsock);
  555. return -1;
  556. }
  557. memcpy(STATION_ADDR, if_request.ifr_hwaddr.sa_data,
  558. sizeof(STATION_ADDR));
  559. close(lsock);
  560. return 0;
  561. }
  562. int main(int argc, char *argv[])
  563. {
  564. struct igb_dma_alloc a_page;
  565. struct igb_packet a_packet;
  566. struct igb_packet *tmp_packet;
  567. struct igb_packet *cleaned_packets;
  568. struct igb_packet *free_packets;
  569. six1883_header *h61883;
  570. seventeen22_header *h1722;
  571. unsigned i;
  572. int err, seq_number, frame_size;
  573. int8_t *iface = NULL;
  574. #ifdef DOMAIN_QUERY
  575. int class_b_id = 0;
  576. int b_priority = 0;
  577. u_int16_t b_vid = 0;
  578. #endif
  579. #ifdef USE_MRPD
  580. int class_a_id = 0;
  581. int a_priority = 0;
  582. u_int16_t a_vid = 0;
  583. #endif
  584. unsigned samples_count = 0;
  585. uint32_t packet_size;
  586. int32_t read_bytes;
  587. uint8_t *data_ptr;
  588. void *stream_packet;
  589. long long int frame_sequence = 0;
  590. struct sched_param sched;
  591. if (argc < 2) {
  592. fprintf(stderr,"%s <if_name> <payload>\n", argv[0]);
  593. return -1;
  594. }
  595. iface = (int8_t *)strdup(argv[1]);
  596. packet_size = atoi(argv[2]);;
  597. payload_length = atoi(argv[2]);;
  598. packet_size += sizeof(six1883_header) + sizeof(seventeen22_header) + sizeof(eth_header);
  599. #ifdef USE_MRPD
  600. err = mrp_connect();
  601. if (err) {
  602. fprintf(stderr, "socket creation failed\n");
  603. return (errno);
  604. }
  605. #endif
  606. err = pci_connect(&igb_dev);
  607. if (err) {
  608. fprintf(stderr, "connect failed (%s) - are you running as root?\n", strerror(errno));
  609. return (errno);
  610. }
  611. err = igb_init(&igb_dev);
  612. if (err) {
  613. fprintf(stderr, "init failed (%s) - is the driver really loaded?\n", strerror(errno));
  614. return (errno);
  615. }
  616. err = igb_dma_malloc_page(&igb_dev, &a_page);
  617. if (err) {
  618. fprintf(stderr, "malloc failed (%s) - out of memory?\n", strerror(errno));
  619. return (errno);
  620. }
  621. signal(SIGINT, sigint_handler);
  622. err = get_mac_addr(iface);
  623. if (err) {
  624. fprintf(stderr, "failed to open iface(%s)\n",iface);
  625. return -1;
  626. }
  627. #ifdef USE_MRPD
  628. mrp_monitor();
  629. domain_a_valid = 1;
  630. class_a_id = MSRP_SR_CLASS_A;
  631. a_priority = MSRP_SR_CLASS_A_PRIO;
  632. a_vid = 2;
  633. fprintf(stderr, "detected domain Class A PRIO=%d VID=%04x...\n", a_priority,
  634. a_vid);
  635. mrp_register_domain(&class_a_id, &a_priority, &a_vid);
  636. domain_a_valid = 1;
  637. a_vid = 2;
  638. fprintf(stderr, "detected domain Class A PRIO=%d VID=%04x...\n", a_priority, a_vid);
  639. #endif
  640. igb_set_class_bandwidth(&igb_dev, PACKET_IPG / 125000, 0, packet_size - 22, 0);
  641. memset(STREAM_ID, 0, sizeof(STREAM_ID));
  642. memcpy(STREAM_ID, STATION_ADDR, sizeof(STATION_ADDR));
  643. a_packet.dmatime = a_packet.attime = a_packet.flags = 0;
  644. a_packet.map.paddr = a_page.dma_paddr;
  645. a_packet.map.mmap_size = a_page.mmap_size;
  646. a_packet.offset = 0;
  647. a_packet.vaddr = a_page.dma_vaddr + a_packet.offset;
  648. a_packet.len = packet_size;
  649. free_packets = NULL;
  650. seq_number = 0;
  651. frame_size = payload_length + sizeof(six1883_header) + sizeof(seventeen22_header) + sizeof(eth_header);
  652. stream_packet = avb_create_packet(payload_length);
  653. h1722 = (seventeen22_header *)((uint8_t*)stream_packet + sizeof(eth_header));
  654. h61883 = (six1883_header *)((uint8_t*)stream_packet + sizeof(eth_header) +
  655. sizeof(seventeen22_header));
  656. /*initalize h1722 header */
  657. avb_initialize_h1722_to_defaults(h1722);
  658. /* set the length */
  659. avb_set_1722_length(h1722, htons(payload_length + sizeof(six1883_header)));
  660. avb_set_1722_stream_id(h1722,reverse_64(STREAMID));
  661. avb_set_1722_sid_valid(h1722, 0x1);
  662. /*initalize h61883 header */
  663. avb_initialize_61883_to_defaults(h61883);
  664. avb_set_61883_format_tag(h61883, 0x1);
  665. avb_set_61883_packet_channel(h61883, 0x1f);
  666. avb_set_61883_packet_tcode(h61883, 0xa);
  667. avb_set_61883_source_id(h61883 , 0x3f);
  668. avb_set_61883_data_block_size(h61883, 0x1);
  669. avb_set_61883_eoh(h61883, 0x2);
  670. avb_set_61883_format_id(h61883, 0x10);
  671. avb_set_61883_format_dependent_field(h61883, 0x2);
  672. avb_set_61883_syt(h61883, 0xffff);
  673. /* initilaze the source & destination mac address */
  674. avb_eth_header_set_mac(stream_packet, DEST_ADDR, iface);
  675. /* set 1772 eth type */
  676. avb_1722_set_eth_type(stream_packet);
  677. /* divide the dma page into buffers for packets */
  678. for (i = 1; i < ((a_page.mmap_size) / packet_size); i++) {
  679. tmp_packet = malloc(sizeof(struct igb_packet));
  680. if (NULL == tmp_packet) {
  681. fprintf(stderr, "failed to allocate igb_packet memory!\n");
  682. return (errno);
  683. }
  684. *tmp_packet = a_packet;
  685. tmp_packet->offset = (i * packet_size);
  686. tmp_packet->vaddr += tmp_packet->offset;
  687. tmp_packet->next = free_packets;
  688. memset(tmp_packet->vaddr, 0, packet_size); /* MAC header at least */
  689. memcpy(((char *)tmp_packet->vaddr), stream_packet, frame_size);
  690. tmp_packet->len = frame_size;
  691. free_packets = tmp_packet;
  692. }
  693. #ifdef USE_MRPD
  694. /*
  695. * subtract 16 bytes for the MAC header/Q-tag - pktsz is limited to the
  696. * data payload of the ethernet frame .
  697. *
  698. * IPG is scaled to the Class (A) observation interval of packets per 125 usec
  699. */
  700. fprintf(stderr, "advertising stream ...\n");
  701. mrp_advertise_stream(STREAM_ID, DEST_ADDR, a_vid, packet_size - 16,
  702. PACKET_IPG / 125000, a_priority, 3900);
  703. fprintf(stderr, "awaiting a listener ...\n");
  704. mrp_await_listener(STREAM_ID);
  705. #endif
  706. memset(&sched, 0 , sizeof (sched));
  707. sched.sched_priority = 1;
  708. sched_setscheduler(0, SCHED_RR, &sched);
  709. while (listeners && !halt_tx)
  710. {
  711. tmp_packet = free_packets;
  712. if (NULL == tmp_packet)
  713. goto cleanup;
  714. stream_packet = ((char *)tmp_packet->vaddr);
  715. free_packets = tmp_packet->next;
  716. /* unfortuntely unless this thread is at rtprio
  717. * you get pre-empted between fetching the time
  718. * and programming the packet and get a late packet
  719. */
  720. h1722 = (seventeen22_header *)((uint8_t*)stream_packet + sizeof(eth_header));
  721. avb_set_1722_seq_number(h1722, seq_number++);
  722. if (seq_number % 4 == 0)
  723. avb_set_1722_timestamp_valid(h1722, 0);
  724. else
  725. avb_set_1722_timestamp_valid(h1722, 1);
  726. data_ptr = (uint8_t *)((uint8_t*)stream_packet + sizeof(eth_header) + sizeof(seventeen22_header)
  727. + sizeof(six1883_header));
  728. read_bytes = read(0, (void *)data_ptr, payload_length);
  729. /* Error case while reading the input file */
  730. if (read_bytes < 0) {
  731. fprintf(stderr,"Failed to read from STDIN %s\n", argv[2]);
  732. continue;
  733. }
  734. samples_count += read_bytes;
  735. h61883 = (six1883_header *)((uint8_t*)stream_packet + sizeof(eth_header) + sizeof(seventeen22_header));
  736. avb_set_61883_data_block_continuity(h61883 , samples_count);
  737. err = igb_xmit(&igb_dev, 0, tmp_packet);
  738. if (!err) {
  739. fprintf(stderr,"frame sequence = %lld\n", frame_sequence++);
  740. continue;
  741. } else {
  742. fprintf(stderr,"Failed frame sequence = %lld !!!!\n", frame_sequence++);
  743. }
  744. if (ENOSPC == err) {
  745. /* put back for now */
  746. tmp_packet->next = free_packets;
  747. free_packets = tmp_packet;
  748. }
  749. cleanup:
  750. igb_clean(&igb_dev, &cleaned_packets);
  751. while (cleaned_packets) {
  752. tmp_packet = cleaned_packets;
  753. cleaned_packets = cleaned_packets->next;
  754. tmp_packet->next = free_packets;
  755. free_packets = tmp_packet;
  756. }
  757. }
  758. if (halt_tx == 0)
  759. fprintf(stderr, "listener left ...\n");
  760. halt_tx = 1;
  761. sleep(1);
  762. #ifdef USE_MRPD
  763. mrp_unadvertise_stream(STREAM_ID, DEST_ADDR, a_vid, packet_size - 16,
  764. PACKET_IPG / 125000, a_priority, 3900);
  765. #endif
  766. /* disable Qav */
  767. igb_set_class_bandwidth(&igb_dev, 0, 0, 0, 0);
  768. #ifdef USE_MRPD
  769. err = mrp_disconnect();
  770. #endif
  771. igb_dma_free_page(&igb_dev, &a_page);
  772. err = igb_detach(&igb_dev);
  773. pthread_exit(NULL);
  774. return 0;
  775. }