From caae98786c20d3f3ef29a330f3153df57696410c Mon Sep 17 00:00:00 2001 From: manjunathhadli Date: Sat, 17 Jan 2015 13:14:09 +0530 Subject: changed the file licenses from GPL to BSD. Signed-off-by: manjunathhadli --- daemons/maap/common/maap_protocol.c | 49 +++++++++++++++++++++++-------------- daemons/maap/common/maap_protocol.h | 49 +++++++++++++++++++++++-------------- daemons/maap/linux/maap_linux.c | 49 +++++++++++++++++++++++-------------- 3 files changed, 93 insertions(+), 54 deletions(-) diff --git a/daemons/maap/common/maap_protocol.c b/daemons/maap/common/maap_protocol.c index 921052d9..eb09b72e 100644 --- a/daemons/maap/common/maap_protocol.c +++ b/daemons/maap/common/maap_protocol.c @@ -1,21 +1,34 @@ -/* - * Copyright (c) 2014 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU Lesser General Public License, - * version 2.1, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for - * more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ +/************************************************************************* + Copyright (c) 2015 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ + All rights reserved. + + 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. + + 3. Neither the name of the Vayavya labs nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. + +****************************************************************************/ /* MAC Address Acquisition Protocol- dynamically allocate multicast MAC address */ #include "maap_protocol.h" diff --git a/daemons/maap/common/maap_protocol.h b/daemons/maap/common/maap_protocol.h index f3bf9bd7..c75f6646 100644 --- a/daemons/maap/common/maap_protocol.h +++ b/daemons/maap/common/maap_protocol.h @@ -1,21 +1,34 @@ -/* - * Copyright (c) 2014 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU Lesser General Public License, - * version 2.1, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for - * more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ +/************************************************************************* + Copyright (c) 2015 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ + All rights reserved. + + 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. + + 3. Neither the name of the Vayavya labs nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. + +****************************************************************************/ #ifndef __MAAP__PROTOCOL__ diff --git a/daemons/maap/linux/maap_linux.c b/daemons/maap/linux/maap_linux.c index 6ea31980..a0e19969 100644 --- a/daemons/maap/linux/maap_linux.c +++ b/daemons/maap/linux/maap_linux.c @@ -1,21 +1,34 @@ -/* - * Copyright (c) 2014 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU Lesser General Public License, - * version 2.1, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for - * more details. - * - * You should have received a copy of the GNU Lesser General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ +/************************************************************************* + Copyright (c) 2015 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ + All rights reserved. + + 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. + + 3. Neither the name of the Vayavya labs nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. + +****************************************************************************/ #include #include -- cgit v1.2.1 From 1d8055227ca63c6061de229b33996ae485e0f76b Mon Sep 17 00:00:00 2001 From: Sumeet Jain Date: Tue, 20 Jan 2015 16:55:36 +0530 Subject: Update jackd_talker.c Without the above change, igb_xmit fails as no tx_queues are allocated/mapped. --- examples/jackd-talker/jackd_talker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/jackd-talker/jackd_talker.c b/examples/jackd-talker/jackd_talker.c index 9fb83660..67f25bdc 100755 --- a/examples/jackd-talker/jackd_talker.c +++ b/examples/jackd-talker/jackd_talker.c @@ -766,7 +766,7 @@ int pci_connect() } printf("attaching to %s\n", devpath); err = igb_attach(devpath, &igb_dev); - if (err) { + if (err || igb_attach_tx( &igb_dev )) { printf("attach failed! (%s)\n", strerror(errno)); continue; } -- cgit v1.2.1 From 280a689014de37cadecc86e02d44e23ceb602e14 Mon Sep 17 00:00:00 2001 From: Sumeet Jain Date: Wed, 21 Jan 2015 19:25:21 +0530 Subject: Update jackd_talker.c --- examples/jackd-talker/jackd_talker.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/jackd-talker/jackd_talker.c b/examples/jackd-talker/jackd_talker.c index 67f25bdc..9484fd22 100755 --- a/examples/jackd-talker/jackd_talker.c +++ b/examples/jackd-talker/jackd_talker.c @@ -766,10 +766,15 @@ int pci_connect() } printf("attaching to %s\n", devpath); err = igb_attach(devpath, &igb_dev); - if (err || igb_attach_tx( &igb_dev )) { + if (err) { printf("attach failed! (%s)\n", strerror(errno)); continue; } + err = igb_attach_tx(devpath, &igb_dev); + if (err) { + printf("igb_attach_tx failed! (%s)\n", strerror(errno)); + continue; + } goto out; } pci_cleanup(pacc); -- cgit v1.2.1 From 03e2c0dd6f18918a6adf1aab4209c9771a91bcc4 Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Sun, 21 Jun 2015 16:19:54 -0600 Subject: Fix a jackd_talker error from last open-avb-next merge. A pull request was made against master a while back for a fix that was never applied to open-avb-next. There was some refactoring done in open-avb-next, so when it was last merged with master, this fix didn't have the refactor changes applied. Now it does. --- examples/jackd-talker/jackd_talker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/jackd-talker/jackd_talker.c b/examples/jackd-talker/jackd_talker.c index 05ea23ef..63041b2c 100755 --- a/examples/jackd-talker/jackd_talker.c +++ b/examples/jackd-talker/jackd_talker.c @@ -241,7 +241,7 @@ int pci_connect() printf("attach failed! (%s)\n", strerror(errno)); continue; } - err = igb_attach_tx(devpath, &igb_dev); + err = igb_attach_tx(&glob_igb_dev); if (err) { printf("igb_attach_tx failed! (%s)\n", strerror(errno)); continue; -- cgit v1.2.1 From 843f3a75bfa13a042d48acc8934ff58cf96d8d54 Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Thu, 14 Jan 2016 15:40:35 -0800 Subject: igb_avb: add rx queues differentiation for avb Allow rx queues to be split off for avb. --- kmod/igb/igb.h | 7 ++- kmod/igb/igb_main.c | 124 +++++++++++++++++++++++++++++++++---------------- lib/igb/igb_internal.h | 4 ++ 3 files changed, 95 insertions(+), 40 deletions(-) diff --git a/kmod/igb/igb.h b/kmod/igb/igb.h index 3e6a96b2..f1c7d066 100644 --- a/kmod/igb/igb.h +++ b/kmod/igb/igb.h @@ -576,7 +576,8 @@ struct igb_adapter { struct pci_dev *pdev; /* user-dma specific variables */ struct igb_user_page *userpages; - u32 uring_init; + u32 uring_tx_init; + u32 uring_rx_init; #ifndef HAVE_NETDEV_STATS_IN_NETDEV struct net_device_stats net_stats; #endif @@ -859,10 +860,14 @@ void igb_procfs_topdir_exit(void); #define IGB_BIND _IOW('E', 200, int) #define IGB_UNBIND _IOW('E', 201, int) #define IGB_MAPRING _IOW('E', 202, int) +#define IGB_MAP_TX_RING IGB_MAPRING #define IGB_UNMAPRING _IOW('E', 203, int) +#define IGB_UNMAP_TX_RING IGB_UNMAPRING #define IGB_MAPBUF _IOW('E', 204, int) #define IGB_UNMAPBUF _IOW('E', 205, int) #define IGB_LINKSPEED _IOW('E', 206, int) +#define IGB_MAP_RX_RING _IOW('E', 207, int) +#define IGB_UNMAP_RX_RING _IOW('E', 208, int) #define IGB_BIND_NAMESZ 24 diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index 085cfc9e..f9f97f1e 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -25,12 +25,12 @@ /* * NOTE: This is an AVB-customed version of the standard Intel igb * driver. This driver requires (4) tx-rx queues are enabled, with MSI-X. - * Standard best-effort LAN traffic is directed to tx queue(3), leaving tx-queue(0) - * through tx-queue(2) on the Intel i210 available to be mapped into a + * Standard best-effort LAN traffic is directed to tx queue(3), leaving tx-queue(0) + * through tx-queue(2) on the Intel i210 available to be mapped into a * user-space application and managed by the application. * * The driver includes the minimal AVB specific initialization code - * to setup the queues. + * to setup the queues. * * The application must map the register space into a user-space application. * then setup tx descriptor rings and packet buffers which the other queues @@ -280,12 +280,12 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba); static struct file_operations igb_fops = { .owner = THIS_MODULE, .llseek = no_llseek, - .read = igb_read, - .write = igb_write, + .read = igb_read, + .write = igb_write, .poll = igb_pollfd, - .open = igb_open_file, - .release = igb_close_file, - .mmap = igb_mmap, + .open = igb_open_file, + .release = igb_close_file, + .mmap = igb_mmap, .unlocked_ioctl = igb_ioctl_file, }; @@ -1567,7 +1567,8 @@ static void igb_configure(struct igb_adapter *adapter) /* call igb_desc_unused which always leaves * at least 1 descriptor unused to make sure * next_to_use != next_to_clean */ - for (i = 0; i < adapter->num_rx_queues; i++) { + + for (i = 2; i < adapter->num_rx_queues; i++) { /* AVB specific */ struct igb_ring *ring = adapter->rx_ring[i]; igb_alloc_rx_buffers(ring, igb_desc_unused(ring)); } @@ -2659,7 +2660,8 @@ static int igb_probe(struct pci_dev *pdev, adapter->msg_enable = (1 << debug) - 1; adapter->userpages = NULL; - adapter->uring_init = 0; + adapter->uring_tx_init = 0; + adapter->uring_rx_init = 0; #ifdef HAVE_PCI_ERS err = pci_save_state(pdev); if (err) @@ -3769,6 +3771,9 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) } igb_vmm_control(adapter); + /* AVB specific use queue 3 for all non-filtered packets */ +#define E1000_MRQC_ENABLE_DEF_Q3 (3 << 3) + mrqc = E1000_MRQC_ENABLE_DEF_Q3; /* AVB specific */ E1000_WRITE_REG(hw, E1000_MRQC, mrqc); } @@ -4251,7 +4256,7 @@ static void igb_clean_all_rx_rings(struct igb_adapter *adapter) { int i; - for (i = 0; i < adapter->num_rx_queues; i++) + for (i = 2; i < adapter->num_rx_queues; i++) /* AVB specific */ igb_clean_rx_ring(adapter->rx_ring[i]); } @@ -7082,7 +7087,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) return true; /* don't service user (AVB) queues */ - if (tx_ring->queue_index < 2) + if (tx_ring->queue_index < 2) return true; tx_buffer = &tx_ring->tx_buffer_info[i]; @@ -8082,6 +8087,10 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) unsigned int total_bytes = 0, total_packets = 0; u16 cleaned_count = igb_desc_unused(rx_ring); + /* don't service user (AVB) queues */ + if (rx_ring->queue_index < 2) + return true; + do { struct igb_rx_buffer *rx_buffer; union e1000_adv_rx_desc *rx_desc; @@ -8394,6 +8403,10 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget) unsigned int total_bytes = 0, total_packets = 0; u16 cleaned_count = igb_desc_unused(rx_ring); + /* don't service user (AVB) queues */ + if (rx_ring->queue_index < 2) + return true; + do { union e1000_adv_rx_desc *rx_desc; @@ -9956,7 +9969,7 @@ static int igb_init_avb( struct e1000_hw *hw ) E1000_WRITE_REG(hw, E1000_ITPBS, txpbsize); - /* std sized frames in 64 byte units with VLAN tags applied */ + /* std sized frames in 64 byte units with VLAN tags applied */ E1000_WRITE_REG(hw, E1000_DTXMXPKTSZ, 1536 / 64); /* @@ -9981,7 +9994,7 @@ static int igb_init_avb( struct e1000_hw *hw ) E1000_TQAVCTRL_DATA_TRAN_TIM | \ E1000_TQAVCTRL_SP_WAIT_SR; - /* default to a 10 usec prefetch delta from launch time - time for + /* default to a 10 usec prefetch delta from launch time - time for * a 1500 byte rx frame to be received over the PCIe Gen1 x1 link. */ tqavctrl |= (10 << 5) << E1000_TQAVCTRL_FETCH_TM_SHIFT ; @@ -9994,7 +10007,7 @@ static int igb_init_avb( struct e1000_hw *hw ) /* user-mode API routines */ static unsigned int igb_pollfd(struct file *file, poll_table *wait) -{ +{ return -EINVAL; /* don't support reads for any status or data */ } @@ -10035,7 +10048,7 @@ static struct igb_adapter *igb_lookup(char *id) adapter_lookup.adapter = NULL; adapter_lookup.pci_info = id; - /* + /* * iterate over the loaded intefaces and match on their * pci device ID identifier - e.g. "0000:7:0.0" */ @@ -10092,7 +10105,7 @@ static int igb_unbind(struct file *file) file->private_data = NULL; return 0; } - + static long igb_getspeed(struct file *file, void __user *arg) { struct igb_adapter *adapter; @@ -10123,7 +10136,7 @@ static long igb_getspeed(struct file *file, void __user *arg) return(0); } -static long igb_mapbuf(struct file *file, void __user *arg, int ring) +static long igb_mapbuf(struct file *file, void __user *arg, int ring) { struct igb_adapter *adapter; struct igb_buf_cmd req; @@ -10138,25 +10151,40 @@ static long igb_mapbuf(struct file *file, void __user *arg, int ring) return -ENOENT; } - if (ring) { + if ((ring == IGB_MAPRING) || (ring == IGB_MAP_TX_RING)) { if (req.queue >= 3) { printk("mapring:invalid queue specified(%d)\n", req.queue); return -EINVAL; } - if (adapter->uring_init & (1 << req.queue)) { + if (adapter->uring_tx_init & (1 << req.queue)) { printk("mapring:queue in use (%d)\n", req.queue); return -EBUSY; } - adapter->uring_init |= (1 << req.queue); + adapter->uring_tx_init |= (1 << req.queue); req.physaddr = adapter->tx_ring[req.queue]->dma; req.mmap_size = adapter->tx_ring[req.queue]->size; + } else if (ring == IGB_MAP_RX_RING) { + if (req.queue >= 3) { + printk("mapring:invalid queue specified(%d)\n", req.queue); + return -EINVAL; + } + + if (adapter->uring_rx_init & (1 << req.queue)) { + printk("mapring:queue in use (%d)\n", req.queue); + return -EBUSY; + } + + adapter->uring_rx_init |= (1 << req.queue); + + req.physaddr = adapter->rx_ring[req.queue]->dma; + req.mmap_size = adapter->rx_ring[req.queue]->size; } else { struct page *page; dma_addr_t page_dma; - struct igb_user_page *userpage; + struct igb_user_page *userpage; userpage = vzalloc(sizeof(struct igb_user_page)); if (unlikely(!userpage)) { @@ -10180,17 +10208,17 @@ static long igb_mapbuf(struct file *file, void __user *arg, int ring) err = -ENOMEM; goto failed; } - + page_dma = dma_map_page( pci_dev_to_dev(adapter->pdev), page, 0, PAGE_SIZE, DMA_FROM_DEVICE); - + if (dma_mapping_error(pci_dev_to_dev(adapter->pdev), page_dma)) { put_page(page); err = -ENOMEM; goto failed;; } - + adapter->userpages->page = page; adapter->userpages->page_dma = page_dma; @@ -10210,7 +10238,7 @@ failed: return err; } -static long igb_unmapbuf(struct file *file, void __user *arg, int ring) +static long igb_unmapbuf(struct file *file, void __user *arg, int ring) { int err = 0; struct igb_adapter *adapter; @@ -10225,19 +10253,28 @@ static long igb_unmapbuf(struct file *file, void __user *arg, int ring) return -ENOENT; } - if (ring) { + if ((ring == IGB_MAPRING) || (ring == IGB_MAP_TX_RING)) { + /* its easy to figure out what to free on the rings ... */ + if (req.queue >= 3) + return -EINVAL; + + if (0 == (adapter->uring_tx_init & (1 << req.queue))) + return -EINVAL; + + adapter->uring_tx_init &= ~(1 << req.queue); + } else if (ring == IGB_MAP_RX_RING) { /* its easy to figure out what to free on the rings ... */ if (req.queue >= 3) { return -EINVAL; } - if (0 == (adapter->uring_init & (1 << req.queue))) + if (0 == (adapter->uring_rx_init & (1 << req.queue))) return -EINVAL; - adapter->uring_init &= ~(1 << req.queue); + adapter->uring_rx_init &= ~(1 << req.queue); } else { /* have to find the corresponding page to free */ - struct igb_user_page *userpage; + struct igb_user_page *userpage; userpage = adapter->userpages; while (userpage != NULL) { @@ -10249,7 +10286,7 @@ static long igb_unmapbuf(struct file *file, void __user *arg, int ring) if (userpage == NULL) return -EINVAL; - dma_unmap_page(pci_dev_to_dev(adapter->pdev), + dma_unmap_page(pci_dev_to_dev(adapter->pdev), userpage->page_dma, PAGE_SIZE, DMA_FROM_DEVICE); @@ -10283,13 +10320,15 @@ static long igb_ioctl_file(struct file *file, unsigned int cmd, unsigned long ar case IGB_UNBIND: err = igb_unbind(file); break; - case IGB_MAPRING: + case IGB_MAP_TX_RING: + case IGB_MAP_RX_RING: case IGB_MAPBUF: - err = igb_mapbuf(file, argp, (cmd==IGB_MAPRING ? 1:0)); + err = igb_mapbuf(file, argp, cmd); break; - case IGB_UNMAPRING: + case IGB_UNMAP_TX_RING: + case IGB_UNMAP_RX_RING: case IGB_UNMAPBUF: - err = igb_unmapbuf(file, argp, (cmd==IGB_UNMAPRING ? 1:0)); + err = igb_unmapbuf(file, argp, cmd); break; case IGB_LINKSPEED: err = igb_getspeed(file, argp); @@ -10313,23 +10352,30 @@ static int igb_close_file(struct inode *inode, struct file *file) struct igb_adapter *adapter = file->private_data; int err; int i; - struct igb_user_page *userpage; + struct igb_user_page *userpage; if (NULL == adapter) return 0; /* free up any rings and user-mapped pages */ for (i = 0; i < 3; i++) { - if (adapter->uring_init & (1 << i)) { + if (adapter->uring_tx_init & (1 << i)) { igb_free_tx_resources(adapter->tx_ring[i]); - adapter->uring_init &= ~(1 << i); + adapter->uring_tx_init &= ~(1 << i); + } + } + + for (i = 0; i < 3; i++) { + if (adapter->uring_rx_init & (1 << i)) { + igb_free_rx_resources(adapter->rx_ring[i]); + adapter->uring_rx_init &= ~(1 << i); } } userpage = adapter->userpages; while (userpage != NULL) { - dma_unmap_page(pci_dev_to_dev(adapter->pdev), + dma_unmap_page(pci_dev_to_dev(adapter->pdev), userpage->page_dma, PAGE_SIZE, DMA_FROM_DEVICE); diff --git a/lib/igb/igb_internal.h b/lib/igb/igb_internal.h index 72c3dfc4..e6198d8d 100644 --- a/lib/igb/igb_internal.h +++ b/lib/igb/igb_internal.h @@ -169,10 +169,14 @@ typedef struct _igb_vendor_info_t { #define IGB_BIND _IOW('E', 200, int) #define IGB_UNBIND _IOW('E', 201, int) #define IGB_MAPRING _IOW('E', 202, int) +#define IGB_MAP_TX_RING IGB_MAPRING #define IGB_UNMAPRING _IOW('E', 203, int) +#define IGB_UNMAP_TX_RING IGB_UNMAPRING #define IGB_MAPBUF _IOW('E', 204, int) #define IGB_UNMAPBUF _IOW('E', 205, int) #define IGB_LINKSPEED _IOW('E', 206, int) +#define IGB_MAP_RX_RING _IOW('E', 207, int) +#define IGB_UNMAP_RX_RING _IOW('E', 208, int) #define IGB_BIND_NAMESZ 24 -- cgit v1.2.1 From 83ea126ddfc9b001613b36a8d731d94f59775ea1 Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Fri, 15 Jan 2016 09:00:22 -0800 Subject: igb_avb: fix errors found by checkpatch Sync with upstream igb driver which was mainly errors found running checkpatch in file mode. Signed-off-by: Todd Fujinaka --- kmod/igb/igb_main.c | 329 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 197 insertions(+), 132 deletions(-) diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index f9f97f1e..80c1c5b8 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -25,9 +25,9 @@ /* * NOTE: This is an AVB-customed version of the standard Intel igb * driver. This driver requires (4) tx-rx queues are enabled, with MSI-X. - * Standard best-effort LAN traffic is directed to tx queue(3), leaving tx-queue(0) - * through tx-queue(2) on the Intel i210 available to be mapped into a - * user-space application and managed by the application. + * Standard best-effort LAN traffic is directed to tx queue(3), leaving + * tx-queue(0) through tx-queue(2) on the Intel i210 available to be mapped + * into a user-space application and managed by the application. * * The driver includes the minimal AVB specific initialization code * to setup the queues. @@ -126,12 +126,12 @@ static void igb_watchdog(unsigned long); static void igb_watchdog_task(struct work_struct *); static void igb_dma_err_task(struct work_struct *); static void igb_dma_err_timer(unsigned long data); - -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) ) -static u16 igb_select_queue(struct net_device *dev, struct sk_buff *skb); -#else +/* AVB specific */ +#ifdef HAVE_NDO_SELECT_QUEUE_ACCEL_FALLBACK static u16 igb_select_queue(struct net_device *dev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback); +#else +static u16 igb_select_queue(struct net_device *dev, struct sk_buff *skb); #endif static netdev_tx_t igb_xmit_frame(struct sk_buff *skb, struct net_device *); @@ -188,28 +188,32 @@ static int igb_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting); #endif #ifdef HAVE_NDO_SET_VF_MIN_MAX_TX_RATE -int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, +static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, int tx_rate); #else -int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); +static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate); #endif /* HAVE_NDO_SET_VF_MIN_MAX_TX_RATE */ static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi); static void igb_check_vf_rate_limit(struct igb_adapter *); #endif static int igb_vf_configure(struct igb_adapter *adapter, int vf); -static int igb_init_avb( struct e1000_hw *hw ); +/* AVB specific */ +static int igb_init_avb(struct e1000_hw *hw); -/* user-mode API forward definitions */ -static int igb_open_file(struct inode *inode, struct file * file); +/* AVB user-mode API forward definitions */ +static int igb_open_file(struct inode *inode, struct file *file); static int igb_close_file(struct inode *inode, struct file *file); -static long igb_ioctl_file(struct file *file, unsigned int cmd, unsigned long arg); +static long igb_ioctl_file(struct file *file, unsigned int cmd, + unsigned long arg); static void igb_vm_open(struct vm_area_struct *vma); static void igb_vm_close(struct vm_area_struct *vma); static int igb_vm_fault(struct vm_area_struct *area, struct vm_fault *fdata); static int igb_mmap(struct file *file, struct vm_area_struct *vma); -static ssize_t igb_read(struct file * file, char __user * buf, size_t count, loff_t *pos); -static ssize_t igb_write(struct file * file, const char __user * buf, size_t count, loff_t *pos) ; +static ssize_t igb_read(struct file *file, char __user *buf, size_t count, + loff_t *pos); +static ssize_t igb_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos); static unsigned int igb_pollfd(struct file *file, poll_table *wait); static struct vm_operations_struct igb_mmap_ops = { @@ -452,6 +456,7 @@ u32 e1000_read_reg(struct e1000_hw *hw, u32 reg) /* reads should not return all F's */ if (!(~value) && (!reg || !(~readl(hw_addr)))) { struct net_device *netdev = igb->netdev; + hw->hw_addr = NULL; netif_device_detach(netdev); netdev_err(netdev, "PCIe link lost, device now detached\n"); @@ -539,9 +544,10 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) switch (hw->mac.type) { case e1000_82575: /* The 82575 assigns vectors using a bitmask, which matches the - bitmask for the EICR/EIMS/EIMC registers. To assign one - or more queues to a vector, we write the appropriate bits - into the MSIXBM register for that vector. */ + * bitmask for the EICR/EIMS/EIMC registers. To assign one + * or more queues to a vector, we write the appropriate bits + * into the MSIXBM register for that vector. + */ if (rx_queue > IGB_N0_QUEUE) msixbm = E1000_EICR_RX_QUEUE0 << rx_queue; if (tx_queue > IGB_N0_QUEUE) @@ -643,7 +649,8 @@ static void igb_configure_msix(struct igb_adapter *adapter) case e1000_i210: case e1000_i211: /* Turn on MSI-X capability first, or our settings - * won't stick. And it will take days to debug. */ + * won't stick. And it will take days to debug. + */ E1000_WRITE_REG(hw, E1000_GPIE, E1000_GPIE_MSIX_MODE | E1000_GPIE_PBA | E1000_GPIE_EIAME | E1000_GPIE_NSICR); @@ -762,7 +769,8 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx) struct igb_q_vector *q_vector = adapter->q_vector[v_idx]; /* if we're coming from igb_set_interrupt_capability, the vectors are - * not yet allocated */ + * not yet allocated + */ if (!q_vector) return; @@ -1215,7 +1223,7 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter, /* update q_vector Rx values */ igb_add_ring(ring, &q_vector->rx); -#ifndef HAVE_NDO_SET_FEATURES +#if defined(HAVE_RHEL6_NET_DEVICE_OPS_EXT) || !defined(HAVE_NDO_SET_FEATURES) /* enable rx checksum */ set_bit(IGB_RING_FLAG_RX_CSUM, &ring->flags); @@ -1566,10 +1574,12 @@ static void igb_configure(struct igb_adapter *adapter) /* call igb_desc_unused which always leaves * at least 1 descriptor unused to make sure - * next_to_use != next_to_clean */ - - for (i = 2; i < adapter->num_rx_queues; i++) { /* AVB specific */ + * next_to_use != next_to_clean + */ + /* AVB specific */ + for (i = 0; i < adapter->num_rx_queues; i++) { struct igb_ring *ring = adapter->rx_ring[i]; + igb_alloc_rx_buffers(ring, igb_desc_unused(ring)); } } @@ -1842,7 +1852,8 @@ void igb_down(struct igb_adapter *adapter) int i; /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer */ + * reschedule our watchdog timer + */ set_bit(__IGB_DOWN, &adapter->state); /* disable receives in the hardware */ @@ -1850,6 +1861,7 @@ void igb_down(struct igb_adapter *adapter) E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); /* flush and sleep below */ + netif_carrier_off(netdev); netif_tx_stop_all_queues(netdev); /* disable transmits in the hardware */ @@ -1916,11 +1928,11 @@ void igb_enable_mas(struct igb_adapter *adapter) /* configure for SerDes media detect */ if ((hw->phy.media_type == e1000_media_type_copper) && - (!(connsw & E1000_CONNSW_SERDESD))) { - connsw |= E1000_CONNSW_ENRGSRC; - connsw |= E1000_CONNSW_AUTOSENSE_EN; - E1000_WRITE_REG(hw, E1000_CONNSW, connsw); - E1000_WRITE_FLUSH(hw); + (!(connsw & E1000_CONNSW_SERDESD))) { + connsw |= E1000_CONNSW_ENRGSRC; + connsw |= E1000_CONNSW_AUTOSENSE_EN; + E1000_WRITE_REG(hw, E1000_CONNSW, connsw); + E1000_WRITE_FLUSH(hw); } } @@ -1947,14 +1959,16 @@ void igb_reset(struct igb_adapter *adapter) * rounded up to the next 1KB and expressed in KB. Likewise, * the Rx FIFO should be large enough to accommodate at least * one full receive packet and is similarly rounded up and - * expressed in KB. */ + * expressed in KB. + */ pba = E1000_READ_REG(hw, E1000_PBA); /* upper 16 bits has Tx packet buffer allocation size in KB */ tx_space = pba >> 16; /* lower 16 bits has Rx packet buffer allocation size in KB */ pba &= 0xffff; /* the tx fifo also stores 16 bytes of information about the tx - * but don't include ethernet FCS because hardware appends it */ + * but don't include ethernet FCS because hardware appends it + */ min_tx_space = (adapter->max_frame_size + sizeof(union e1000_adv_tx_desc) - ETH_FCS_LEN) * 2; @@ -1967,13 +1981,15 @@ void igb_reset(struct igb_adapter *adapter) /* If current Tx allocation is less than the min Tx FIFO size, * and the min Tx FIFO size is less than the current Rx FIFO - * allocation, take space away from current Rx allocation */ + * allocation, take space away from current Rx allocation + */ if (tx_space < min_tx_space && ((min_tx_space - tx_space) < pba)) { pba = pba - (min_tx_space - tx_space); /* if short on rx space, rx wins and must trump tx - * adjustment */ + * adjustment + */ if (pba < min_rx_space) pba = min_rx_space; } @@ -1985,7 +2001,8 @@ void igb_reset(struct igb_adapter *adapter) * (or the size used for early receive) above it in the Rx FIFO. * Set it to the lower of: * - 90% of the Rx FIFO size, or - * - the full Rx FIFO size minus one full frame */ + * - the full Rx FIFO size minus one full frame + */ hwm = min(((pba << 10) * 9 / 10), ((pba << 10) - 2 * adapter->max_frame_size)); @@ -2338,7 +2355,7 @@ static const struct net_device_ops igb_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = igb_netpoll, #endif -#ifdef HAVE_NDO_SET_FEATURES +#if defined(HAVE_NDO_SET_FEATURES) && !defined(HAVE_RHEL6_NET_DEVICE_OPS_EXT) .ndo_fix_features = igb_fix_features, .ndo_set_features = igb_set_features, #endif @@ -2414,12 +2431,14 @@ int igb_init_vmdq_netdevs(struct igb_adapter *adapter) for (pool = 1; pool < adapter->vmdq_pools; pool++) { int qpp = (!adapter->rss_queues ? 1 : adapter->rss_queues); + base_queue = pool * qpp; vnetdev = alloc_etherdev(sizeof(struct igb_vmdq_adapter)); if (!vnetdev) { err = -ENOMEM; break; } + vmdq_adapter = netdev_priv(vnetdev); vmdq_adapter->vnetdev = vnetdev; vmdq_adapter->real_adapter = adapter; @@ -2659,6 +2678,7 @@ static int igb_probe(struct pci_dev *pdev, adapter->port_num = hw->bus.func; adapter->msg_enable = (1 << debug) - 1; + /* AVB specific */ adapter->userpages = NULL; adapter->uring_tx_init = 0; adapter->uring_rx_init = 0; @@ -2758,7 +2778,7 @@ static int igb_probe(struct pci_dev *pdev, if (hw->mac.type >= e1000_82576) netdev->features |= NETIF_F_SCTP_CSUM; -#ifdef HAVE_NDO_SET_FEATURES +#if defined(HAVE_NDO_SET_FEATURES) && !defined(HAVE_RHEL6_NET_DEVICE_OPS_EXT) /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features; #ifndef IGB_NO_LRO @@ -2800,7 +2820,8 @@ static int igb_probe(struct pci_dev *pdev, #endif /* before reading the NVM, reset the controller to put the device in a - * known good starting state */ + * known good starting state + */ e1000_reset_hw(hw); /* make sure the NVM is good */ @@ -2879,7 +2900,8 @@ static int igb_probe(struct pci_dev *pdev, /* now that we have the eeprom settings, apply the special cases where * the eeprom may be wrong or the board simply won't support wake on - * lan on a particular port */ + * lan on a particular port + */ switch (pdev->device) { case E1000_DEV_ID_82575GB_QUAD_COPPER: adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; @@ -2888,7 +2910,8 @@ static int igb_probe(struct pci_dev *pdev, case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: /* Wake events only supported on port A for dual fiber - * regardless of eeprom setting */ + * regardless of eeprom setting + */ if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FUNC_1) adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED; break; @@ -3124,7 +3147,8 @@ static void igb_remove(struct pci_dev *pdev) #endif /* HAVE_PTP_1588_CLOCK */ /* flush_scheduled work may reschedule our watchdog task, so - * explicitly disable watchdog tasks from being rescheduled */ + * explicitly disable watchdog tasks from being rescheduled + */ set_bit(__IGB_DOWN, &adapter->state); del_timer_sync(&adapter->watchdog_timer); if (adapter->flags & IGB_FLAG_DETECT_BAD_DMA) @@ -3142,17 +3166,20 @@ static void igb_remove(struct pci_dev *pdev) } #endif +#ifdef CONFIG_IGB_VMDQ_NETDEV + igb_remove_vmdq_netdevs(adapter); +#endif + + igb_reset_sriov_capability(adapter); + /* Release control of h/w to f/w. If f/w is AMT enabled, this - * would have already happened in close and is redundant. */ + * would have already happened in close and is redundant. + */ igb_release_hw_control(adapter); unregister_netdev(netdev); -#ifdef CONFIG_IGB_VMDQ_NETDEV - igb_remove_vmdq_netdevs(adapter); -#endif igb_clear_interrupt_scheme(adapter); - igb_reset_sriov_capability(adapter); iounmap(hw->hw_addr); if (hw->flash_address) @@ -3293,7 +3320,8 @@ static int __igb_open(struct net_device *netdev, bool resuming) /* before we allocate an interrupt, we must be ready to handle it. * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt * as soon as we call pci_request_irq, so we have to setup our - * clean_rx handler before we do so. */ + * clean_rx handler before we do so. + */ igb_configure(adapter); err = igb_request_irq(adapter); @@ -3506,6 +3534,7 @@ void igb_setup_tctl(struct igb_adapter *adapter) static u32 igb_tx_wthresh(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; + switch (hw->mac.type) { case e1000_i354: return 4; @@ -3749,7 +3778,8 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) /* If VMDq is enabled then we set the appropriate mode for that, else * we default to RSS so that an RSS hash is calculated per packet even - * if we are only using one queue */ + * if we are only using one queue + */ if (adapter->vfs_allocated_count || adapter->vmdq_pools) { if (hw->mac.type > e1000_82575) { /* Set the default pool for the PF's first queue */ @@ -3766,8 +3796,7 @@ static void igb_setup_mrqc(struct igb_adapter *adapter) else mrqc |= E1000_MRQC_ENABLE_VMDQ; } else { - if (hw->mac.type != e1000_i211) - mrqc |= E1000_MRQC_ENABLE_RSS_4Q; + mrqc |= E1000_MRQC_ENABLE_RSS_4Q; } igb_vmm_control(adapter); @@ -3829,7 +3858,8 @@ static inline int igb_set_vf_rlpml(struct igb_adapter *adapter, int size, u32 vmolr; /* if it isn't the PF check to see if VFs are enabled and - * increase the size to support vlan tags */ + * increase the size to support vlan tags + */ if (vfn < adapter->vfs_allocated_count && adapter->vf_data[vfn].vlans_enabled) size += VLAN_HLEN; @@ -3866,6 +3896,7 @@ static void igb_rlpml_set(struct igb_adapter *adapter) if (adapter->vmdq_pools && hw->mac.type != e1000_82575) { int i; + for (i = 0; i < adapter->vmdq_pools; i++) igb_set_vf_rlpml(adapter, max_frame_size, pf_id + i); /* @@ -4045,7 +4076,8 @@ static void igb_configure_rx(struct igb_adapter *adapter) adapter->vfs_allocated_count); /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring */ + * the Base and Length of the Rx Descriptor Ring + */ for (i = 0; i < adapter->num_rx_queues; i++) igb_configure_rx_ring(adapter, adapter->rx_ring[i]); } @@ -4256,7 +4288,8 @@ static void igb_clean_all_rx_rings(struct igb_adapter *adapter) { int i; - for (i = 2; i < adapter->num_rx_queues; i++) /* AVB specific */ + /* AVB specific */ + for (i = 2; i < adapter->num_rx_queues; i++) igb_clean_rx_ring(adapter->rx_ring[i]); } @@ -4363,14 +4396,16 @@ void igb_full_sync_mac_table(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int i; + for (i = 0; i < hw->mac.rar_entry_count; i++) - igb_rar_set(adapter, i); + igb_rar_set(adapter, i); } void igb_sync_mac_table(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; int i; + for (i = 0; i < hw->mac.rar_entry_count; i++) { if (adapter->mac_table[i].state & IGB_MAC_STATE_MODIFIED) igb_rar_set(adapter, i); @@ -4529,6 +4564,7 @@ static void igb_set_rx_mode(struct net_device *netdev) vmolr |= E1000_VMOLR_ROPE; } #endif /* HAVE_SET_RX_MODE */ + /* AVB specific */ /* rctl |= E1000_RCTL_VFE; Disable VLAN filtering*/ } E1000_WRITE_REG(hw, E1000_RCTL, rctl); @@ -4608,10 +4644,12 @@ static void igb_spoof_check(struct igb_adapter *adapter) } /* Need to wait a few seconds after link up to get diagnostic information from - * the phy */ + * the phy + */ static void igb_update_phy_info(unsigned long data) { struct igb_adapter *adapter = (struct igb_adapter *) data; + e1000_get_phy_info(&adapter->hw); } @@ -4818,11 +4856,13 @@ static void igb_watchdog_task(struct work_struct *work) for (i = 0; i < adapter->num_tx_queues; i++) { struct igb_ring *tx_ring = adapter->tx_ring[i]; + if (!netif_carrier_ok(netdev)) { /* We've lost link, so the controller stops DMA, * but we've got queued Tx work that's never going * to get done, so reset controller to flush Tx. - * (Do the reset outside of interrupt context). */ + * (Do the reset outside of interrupt context). + */ if (igb_desc_unused(tx_ring) + 1 < tx_ring->count) { adapter->tx_timeout_count++; schedule_work(&adapter->reset_task); @@ -5046,13 +5086,12 @@ static void igb_update_itr(struct igb_q_vector *q_vector, case low_latency: /* 50 usec aka 20000 ints/s */ if (bytes > 10000) { /* this if handles the TSO accounting */ - if (bytes/packets > 8000) { + if (bytes/packets > 8000) itrval = bulk_latency; - } else if ((packets < 10) || ((bytes/packets) > 1200)) { + else if ((packets < 10) || ((bytes/packets) > 1200)) itrval = bulk_latency; - } else if ((packets > 35)) { + else if ((packets > 35)) itrval = lowest_latency; - } } else if (bytes/packets > 2000) { itrval = bulk_latency; } else if (packets <= 2 && bytes < 512) { @@ -5124,7 +5163,8 @@ set_itr_now: if (new_itr != q_vector->itr_val) { /* this attempts to bias the interrupt rate towards Bulk * by adding intermediate steps when interrupt rate is - * increasing */ + * increasing + */ new_itr = new_itr > q_vector->itr_val ? max((new_itr * q_vector->itr_val) / (new_itr + (q_vector->itr_val >> 2)), @@ -5193,6 +5233,7 @@ static int igb_tso(struct igb_ring *tx_ring, if (first->protocol == htons(ETH_P_IP)) { struct iphdr *iph = ip_hdr(skb); + iph->tot_len = 0; iph->check = 0; tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, @@ -5462,7 +5503,8 @@ static void igb_tx_map(struct igb_ring *tx_ring, writel(i, tx_ring->tail); /* we need this if more than one processor can write to our tail - * at a time, it syncronizes IO on IA64/Altix systems */ + * at a time, it syncronizes IO on IA64/Altix systems + */ mmiowb(); return; @@ -5495,11 +5537,13 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) /* Herbert's original patch had: * smp_mb__after_netif_stop_queue(); - * but since that doesn't exist yet, just open code it. */ + * but since that doesn't exist yet, just open code it. + */ smp_mb(); /* We need to check again in a case another CPU has just - * made room available. */ + * made room available. + */ if (igb_desc_unused(tx_ring) < size) return -EBUSY; @@ -5627,18 +5671,18 @@ static inline struct igb_ring *igb_tx_queue_mapping(struct igb_adapter *adapter, return adapter->tx_ring[r_idx]; } #else -#error This driver must have multi-queue transmit support enabled (CONFIG_NETDEVICES_MULTIQUEUE)! +#error Must have multi-queue tx support enabled (CONFIG_NETDEVICES_MULTIQUEUE)! #endif -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) ) -static u16 igb_select_queue(struct net_device *dev, struct sk_buff *skb) -#else +#ifdef HAVE_NDO_SELECT_QUEUE_ACCEL_FALLBACK static u16 igb_select_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv, select_queue_fallback_t fallback) + void *accel_priv, select_queue_fallback_t fallback) +#else +static u16 igb_select_queue(struct net_device *dev, struct sk_buff *skb) #endif { /* remap normal LAN to best effort queue[3] */ - return (3); + return 3; } static netdev_tx_t igb_xmit_frame(struct sk_buff *skb, @@ -5692,6 +5736,7 @@ static void igb_tx_timeout(struct net_device *netdev) static void igb_reset_task(struct work_struct *work) { struct igb_adapter *adapter; + adapter = container_of(work, struct igb_adapter, reset_task); igb_reinit_locked(adapter); @@ -5951,7 +5996,8 @@ void igb_update_stats(struct igb_adapter *adapter) /* Rx Errors */ /* RLEC on some newer hardware can be incorrect so build - * our own version based on RUC and ROC */ + * our own version based on RUC and ROC + */ net_stats->rx_errors = adapter->stats.rxerrc + adapter->stats.crcerrs + adapter->stats.algnerrc + adapter->stats.ruc + adapter->stats.roc + @@ -6006,7 +6052,8 @@ static irqreturn_t igb_msix_other(int irq, void *data) adapter->stats.doosync++; /* The DMA Out of Sync is also indication of a spoof event * in IOV mode. Check the Wrong VM Behavior register to - * see if it is really a spoof event. */ + * see if it is really a spoof event. + */ igb_check_wvbr(adapter); } @@ -6178,7 +6225,8 @@ static int __igb_notify_dca(struct device *dev, void *data) case DCA_PROVIDER_REMOVE: if (adapter->flags & IGB_FLAG_DCA_ENABLED) { /* without this a class_device is left - * hanging around in the sysfs model */ + * hanging around in the sysfs model + */ dca_remove_requester(dev); dev_info(pci_dev_to_dev(pdev), "DCA disabled\n"); adapter->flags &= ~IGB_FLAG_DCA_ENABLED; @@ -6639,6 +6687,7 @@ static int igb_set_vf_vlan(struct igb_adapter *adapter, u32 *msgbuf, u32 vf) u32 vlvf, bits; int regndx = igb_find_vlvf_entry(adapter, vid); + if (regndx < 0) goto out; /* See if any other pools are set for this VLAN filter @@ -6966,11 +7015,13 @@ static irqreturn_t igb_intr(int irq, void *data) struct igb_q_vector *q_vector = adapter->q_vector[0]; struct e1000_hw *hw = &adapter->hw; /* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No - * need for the IMC write */ + * need for the IMC write + */ u32 icr = E1000_READ_REG(hw, E1000_ICR); /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is - * not set, then the adapter didn't send an interrupt */ + * not set, then the adapter didn't send an interrupt + */ if (!(icr & E1000_ICR_INT_ASSERTED)) return IRQ_NONE; @@ -7185,7 +7236,8 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector) struct e1000_hw *hw = &adapter->hw; /* Detect a transmit hang in hardware, this serializes the - * check with the clearing of time_stamp and movement of i */ + * check with the clearing of time_stamp and movement of i + */ clear_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags); if (tx_buffer->next_to_watch && time_after(jiffies, tx_buffer->time_stamp + @@ -8373,6 +8425,7 @@ static bool igb_cleanup_headers(struct igb_ring *rx_ring, if (unlikely((igb_test_staterr(rx_desc, E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) { struct net_device *netdev = rx_ring->netdev; + if (!(netdev->features & NETIF_F_RXALL)) { dev_kfree_skb_any(skb); return true; @@ -8815,10 +8868,13 @@ void igb_vlan_mode(struct net_device *netdev, u32 features) for (i = 1; i < adapter->vmdq_pools; i++) { #ifdef HAVE_VLAN_RX_REGISTER struct igb_vmdq_adapter *vadapter; + vadapter = netdev_priv(adapter->vmdq_netdev[i-1]); + enable = !!vadapter->vlgrp; #else struct net_device *vnetdev; + vnetdev = adapter->vmdq_netdev[i-1]; #ifdef NETIF_F_HW_VLAN_CTAG_RX enable = !!(vnetdev->features & NETIF_F_HW_VLAN_CTAG_RX); @@ -8864,6 +8920,7 @@ static void igb_vlan_rx_add_vid(struct net_device *netdev, u16 vid) if (adapter->vlgrp) { struct vlan_group *vlgrp = adapter->vlgrp; struct net_device *v_netdev = vlan_group_get_device(vlgrp, vid); + if (v_netdev) { v_netdev->features |= netdev->features; vlan_group_set_device(vlgrp, vid, v_netdev); @@ -8925,6 +8982,7 @@ static void igb_restore_vlan(struct igb_adapter *adapter) if (adapter->vlgrp) { u16 vid; + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; @@ -9104,7 +9162,8 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake, igb_power_up_link(adapter); /* Release control of h/w to f/w. If f/w is AMT enabled, this - * would have already happened in close and is redundant. */ + * would have already happened in close and is redundant. + */ igb_release_hw_control(adapter); pci_disable_device(pdev); @@ -9169,14 +9228,15 @@ static int igb_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3cold, 0); if (igb_init_interrupt_scheme(adapter, true)) { - dev_err(pci_dev_to_dev(pdev), "Unable to allocate memory for queues\n"); + dev_err(pci_dev_to_dev(pdev), + "Unable to allocate memory for queues\n"); return -ENOMEM; } igb_reset(adapter); - /* let the f/w know that the h/w is now under the control of the - * driver. */ + /* let the f/w know that the h/w is now under the control of the driver. + */ igb_get_hw_control(adapter); E1000_WRITE_REG(hw, E1000_WUS, ~0); @@ -9467,8 +9527,8 @@ static void igb_io_resume(struct pci_dev *pdev) netif_device_attach(netdev); - /* let the f/w know that the h/w is now under the control of the - * driver. */ + /* let the f/w know that the h/w is now under the control of the driver. + */ igb_get_hw_control(adapter); } @@ -9534,6 +9594,7 @@ static int igb_set_vf_mac(struct igb_adapter *adapter, static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) { struct igb_adapter *adapter = netdev_priv(netdev); + if (!is_valid_ether_addr(mac) || (vf >= adapter->vfs_allocated_count)) return -EINVAL; adapter->vf_data[vf].flags |= IGB_VF_FLAG_PF_SET_MAC; @@ -9620,10 +9681,10 @@ static void igb_check_vf_rate_limit(struct igb_adapter *adapter) } #ifdef HAVE_NDO_SET_VF_MIN_MAX_TX_RATE -int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, +static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate, int max_tx_rate) #else -int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) +static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) #endif /* HAVE_NDO_SET_VF_MIN_MAX_TX_RATE */ { struct igb_adapter *adapter = netdev_priv(netdev); @@ -9659,6 +9720,7 @@ static int igb_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi) { struct igb_adapter *adapter = netdev_priv(netdev); + if (vf >= adapter->vfs_allocated_count) return -EINVAL; ivi->vf = vf; @@ -9838,7 +9900,7 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) /* no lower threshold to disable coalescing * (smart fifb)-UTRESH=0 - * */ + */ E1000_WRITE_REG(hw, E1000_DMCRTRH, 0); /* This sets the time to wait before requesting @@ -9865,6 +9927,7 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) } else { reg |= 0x4; } + E1000_WRITE_REG(hw, E1000_DMCTLX, reg); /* free space in tx pkt buffer to wake from DMA coal */ @@ -9879,6 +9942,7 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) } /* endif adapter->dmac is not disabled */ } else if (hw->mac.type == e1000_82580) { u32 reg = E1000_READ_REG(hw, E1000_PCIEMISC); + E1000_WRITE_REG(hw, E1000_PCIEMISC, reg & ~E1000_PCIEMISC_LX_DECISION); E1000_WRITE_REG(hw, E1000_DMACR, 0); @@ -9954,7 +10018,7 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, return E1000_SUCCESS; } #endif /* HAVE_I2C_SUPPORT */ -static int igb_init_avb( struct e1000_hw *hw ) +static int igb_init_avb(struct e1000_hw *hw) { u32 tqavctrl; u32 tqavcc0, tqavcc1; @@ -9988,20 +10052,20 @@ static int igb_init_avb( struct e1000_hw *hw ) E1000_WRITE_REG(hw, E1000_I210_TQAVHC(0), tqavhc0); E1000_WRITE_REG(hw, E1000_I210_TQAVHC(1), tqavhc1); - tqavctrl = E1000_TQAVCTRL_TXMODE | \ - E1000_TQAVCTRL_DATA_FETCH_ARB | \ - E1000_TQAVCTRL_DATA_TRAN_ARB | \ - E1000_TQAVCTRL_DATA_TRAN_TIM | \ - E1000_TQAVCTRL_SP_WAIT_SR; + tqavctrl = E1000_TQAVCTRL_TXMODE | + E1000_TQAVCTRL_DATA_FETCH_ARB | + E1000_TQAVCTRL_DATA_TRAN_ARB | + E1000_TQAVCTRL_DATA_TRAN_TIM | + E1000_TQAVCTRL_SP_WAIT_SR; /* default to a 10 usec prefetch delta from launch time - time for * a 1500 byte rx frame to be received over the PCIe Gen1 x1 link. */ - tqavctrl |= (10 << 5) << E1000_TQAVCTRL_FETCH_TM_SHIFT ; + tqavctrl |= (10 << 5) << E1000_TQAVCTRL_FETCH_TM_SHIFT; E1000_WRITE_REG(hw, E1000_I210_TQAVCTRL, tqavctrl); - return(0); + return 0; } /* user-mode API routines */ @@ -10011,14 +10075,14 @@ static unsigned int igb_pollfd(struct file *file, poll_table *wait) return -EINVAL; /* don't support reads for any status or data */ } -static ssize_t igb_read(struct file * file, char __user * buf, - size_t count, loff_t *pos) +static ssize_t igb_read(struct file *file, char __user *buf, size_t count, + loff_t *pos) { return -EINVAL; /* don't support reads for any status or data */ } -static ssize_t igb_write(struct file * file, const char __user * buf, - size_t count, loff_t *pos) +static ssize_t igb_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) { return -EINVAL; /* don't support writes for any status or data */ } @@ -10032,10 +10096,9 @@ static int __igb_notify_lookup(struct device *dev, void *data) /* look at pci string - if its me, update the adapter pointer */ printk("checking against adapter name %s\n", pci_name(adapter->pdev)); - if ( 0 == (strncmp(pci_name(adapter->pdev), \ - adapter_lookup->pci_info, \ - IGB_BIND_NAMESZ) ) ) - adapter_lookup->adapter = adapter; + if !(strncmp(pci_name(adapter->pdev), adapter_lookup->pci_info, + IGB_BIND_NAMESZ)) + adapter_lookup->adapter = adapter; return E1000_SUCCESS; } @@ -10053,10 +10116,10 @@ static struct igb_adapter *igb_lookup(char *id) * pci device ID identifier - e.g. "0000:7:0.0" */ - ret_val = driver_for_each_device(&igb_driver.driver, NULL, &adapter_lookup, - __igb_notify_lookup); + ret_val = driver_for_each_device(&igb_driver.driver, NULL, + &adapter_lookup, __igb_notify_lookup); - return (adapter_lookup.adapter); + return adapter_lookup.adapter; } static int igb_bind(struct file *file, void __user *argp) @@ -10071,7 +10134,7 @@ static int igb_bind(struct file *file, void __user *argp) printk("bind to iface %s\n", req.iface); adapter = igb_lookup(req.iface); - if (NULL == adapter) { + if (adapter == NULL) { printk("lookup failed to iface %s\n", req.iface); return -ENOENT; } @@ -10097,9 +10160,10 @@ failed: static int igb_unbind(struct file *file) { struct igb_adapter *adapter; + adapter = file->private_data; - if (NULL == adapter) + if (adapter == NULL) return -EBADFD; file->private_data = NULL; @@ -10113,7 +10177,7 @@ static long igb_getspeed(struct file *file, void __user *arg) u32 link; adapter = file->private_data; - if (NULL == adapter) { + if (adapter == NULL) { printk("map to unbound device!\n"); return -ENOENT; } @@ -10133,7 +10197,7 @@ static long igb_getspeed(struct file *file, void __user *arg) printk("copyout to user failed\n"); return -EFAULT; } - return(0); + return 0; } static long igb_mapbuf(struct file *file, void __user *arg, int ring) @@ -10146,14 +10210,15 @@ static long igb_mapbuf(struct file *file, void __user *arg, int ring) return -EFAULT; adapter = file->private_data; - if (NULL == adapter) { + if (adapter == NULL) { printk("map to unbound device!\n"); return -ENOENT; } if ((ring == IGB_MAPRING) || (ring == IGB_MAP_TX_RING)) { if (req.queue >= 3) { - printk("mapring:invalid queue specified(%d)\n", req.queue); + printk("mapring:invalid queue specified(%d)\n", + req.queue); return -EINVAL; } @@ -10168,7 +10233,8 @@ static long igb_mapbuf(struct file *file, void __user *arg, int ring) req.mmap_size = adapter->tx_ring[req.queue]->size; } else if (ring == IGB_MAP_RX_RING) { if (req.queue >= 3) { - printk("mapring:invalid queue specified(%d)\n", req.queue); + printk("mapring:invalid queue specified(%d)\n", + req.queue); return -EINVAL; } @@ -10209,14 +10275,13 @@ static long igb_mapbuf(struct file *file, void __user *arg, int ring) goto failed; } - page_dma = dma_map_page( pci_dev_to_dev(adapter->pdev), page, - 0, PAGE_SIZE, - DMA_FROM_DEVICE); + page_dma = dma_map_page(pci_dev_to_dev(adapter->pdev), page, + 0, PAGE_SIZE, DMA_FROM_DEVICE); if (dma_mapping_error(pci_dev_to_dev(adapter->pdev), page_dma)) { - put_page(page); + put_page(page); err = -ENOMEM; - goto failed;; + goto failed; } adapter->userpages->page = page; @@ -10248,7 +10313,7 @@ static long igb_unmapbuf(struct file *file, void __user *arg, int ring) return -EFAULT; adapter = file->private_data; - if (NULL == adapter) { + if (adapter == NULL) { printk("map to unbound device!\n"); return -ENOENT; } @@ -10264,9 +10329,8 @@ static long igb_unmapbuf(struct file *file, void __user *arg, int ring) adapter->uring_tx_init &= ~(1 << req.queue); } else if (ring == IGB_MAP_RX_RING) { /* its easy to figure out what to free on the rings ... */ - if (req.queue >= 3) { + if (req.queue >= 3) return -EINVAL; - } if (0 == (adapter->uring_rx_init & (1 << req.queue))) return -EINVAL; @@ -10275,12 +10339,13 @@ static long igb_unmapbuf(struct file *file, void __user *arg, int ring) } else { /* have to find the corresponding page to free */ struct igb_user_page *userpage; + userpage = adapter->userpages; while (userpage != NULL) { - if (req.physaddr == userpage->page_dma) + if (req.physaddr == userpage->page_dma) break; - userpage = userpage->next; + userpage = userpage->next; } if (userpage == NULL) @@ -10308,9 +10373,10 @@ static long igb_unmapbuf(struct file *file, void __user *arg, int ring) return err; } -static long igb_ioctl_file(struct file *file, unsigned int cmd, unsigned long arg) +static long igb_ioctl_file(struct file *file, unsigned int cmd, + unsigned long arg) { - void __user * argp = (void __user *) arg; + void __user *argp = (void __user *) arg; int err; switch (cmd) { @@ -10341,7 +10407,7 @@ static long igb_ioctl_file(struct file *file, unsigned int cmd, unsigned long ar return err; } -static int igb_open_file(struct inode *inode, struct file * file) +static int igb_open_file(struct inode *inode, struct file *file) { file->private_data = NULL; return 0; @@ -10354,7 +10420,7 @@ static int igb_close_file(struct inode *inode, struct file *file) int i; struct igb_user_page *userpage; - if (NULL == adapter) + if (adapter == NULL) return 0; /* free up any rings and user-mapped pages */ @@ -10420,19 +10486,18 @@ static int igb_mmap(struct file *file, struct vm_area_struct *vma) dma_addr_t pgoff = vma->vm_pgoff; dma_addr_t physaddr; - if (NULL == adapter) + if (adapter == NULL) return -ENODEV; - if (pgoff == 0) { + if (pgoff == 0) physaddr = pci_resource_start(adapter->pdev, 0) >> PAGE_SHIFT; - } else { + else physaddr = pgoff; - } + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - if (remap_pfn_range(vma, vma->vm_start, \ - physaddr, - size, vma->vm_page_prot)) + if (remap_pfn_range(vma, vma->vm_start, physaddr, size, + vma->vm_page_prot)) return -EAGAIN; vma->vm_ops = &igb_mmap_ops; -- cgit v1.2.1 From 7865b4f54d42062b57fcf5c83e9c270dd86c67fb Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Tue, 19 Jan 2016 14:05:51 -0800 Subject: libavb: Linux-ify igb.c Standardize igb.c coding style. Bump copyright date on appropriate files. Signed-off-by: Todd Fujinaka --- kmod/igb/igb.h | 2 +- kmod/igb/igb_main.c | 2 +- kmod/igb/kcompat.h | 2 +- lib/igb/igb.c | 792 +++++++++++++++++++++++++++++----------------------- 4 files changed, 438 insertions(+), 360 deletions(-) diff --git a/kmod/igb/igb.h b/kmod/igb/igb.h index f1c7d066..fdb35537 100644 --- a/kmod/igb/igb.h +++ b/kmod/igb/igb.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2015 Intel Corporation. + Copyright(c) 2007-2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index 80c1c5b8..9253cdec 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2015 Intel Corporation. + Copyright(c) 2007-2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/kmod/igb/kcompat.h b/kmod/igb/kcompat.h index ab9d8600..22a3c1b9 100644 --- a/kmod/igb/kcompat.h +++ b/kmod/igb/kcompat.h @@ -1,7 +1,7 @@ /******************************************************************************* Intel(R) Gigabit Ethernet Linux driver - Copyright(c) 2007-2015 Intel Corporation. + Copyright(c) 2007-2016 Intel Corporation. This program is free software; you can redistribute it and/or modify it under the terms and conditions of the GNU General Public License, diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 106dc6f5..17ac0889 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2015, Intel Corporation + Copyright (c) 2001-2016, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -63,8 +63,7 @@ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, String Index } *********************************************************************/ -static igb_vendor_info_t igb_vendor_info_array[] = -{ +static igb_vendor_info_t igb_vendor_info_array[] = { { 0x8086, E1000_DEV_ID_I210_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_I210_COPPER_FLASHLESS, PCI_ANY_ID, PCI_ANY_ID, 0}, @@ -92,29 +91,31 @@ static void igb_setup_transmit_structures(struct adapter *adapter); static void igb_setup_transmit_ring(struct tx_ring *txr); static void igb_initialize_transmit_units(struct adapter *adapter); static void igb_free_transmit_structures(struct adapter *adapter); -static void igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet); +static void igb_tx_ctx_setup(struct tx_ring *txr, + struct igb_packet *packet); int -igb_probe( device_t *dev ) +igb_probe(device_t *dev) { igb_vendor_info_t *ent; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; if (dev->pci_vendor_id != IGB_VENDOR_ID) - return (ENXIO); + return -ENXIO; ent = igb_vendor_info_array; while (ent->vendor_id != 0) { if ((dev->pci_vendor_id == ent->vendor_id) && - (dev->pci_device_id == ent->device_id) ) { + (dev->pci_device_id == ent->device_id)) { - return (0); + return 0; } ent++; } - return (ENXIO); + return -ENXIO; } #define IGB_SEM "igb_sem" @@ -126,15 +127,18 @@ igb_attach(char *dev_path, device_t *pdev) struct igb_bind_cmd bind; int error = 0; - if (NULL == pdev) return EINVAL; + if (pdev == NULL) + return -EINVAL; adapter = (struct adapter *)pdev->private_data; - if (NULL != adapter) return EBUSY; + if (adapter != NULL) + return -EBUSY; /* allocate an adapter */ pdev->private_data = malloc(sizeof(struct adapter)); - if (NULL == pdev->private_data) return ENXIO; + if (pdev->private_data == NULL) + return -ENXIO; memset(pdev->private_data, 0, sizeof(struct adapter)); @@ -142,21 +146,21 @@ igb_attach(char *dev_path, device_t *pdev) adapter->ldev = open("/dev/igb_avb", O_RDWR); if (adapter->ldev < 0) { - error = ENXIO; + error = -ENXIO; goto err_prebind; } adapter->memlock = - sem_open( IGB_SEM, O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, 1 ); - if( adapter->memlock == ((sem_t *)SEM_FAILED)) { + sem_open(IGB_SEM, O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, 1); + if (adapter->memlock == ((sem_t *)SEM_FAILED)) { error = errno; close(adapter->ldev); goto err_prebind; } - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) { error = errno; close(adapter->ldev); - sem_close( adapter->memlock ); + sem_close(adapter->memlock); goto err_prebind; } @@ -167,7 +171,7 @@ igb_attach(char *dev_path, device_t *pdev) strncpy(bind.iface, dev_path, IGB_BIND_NAMESZ - 1); if (ioctl(adapter->ldev, IGB_BIND, &bind) < 0) { - error = ENXIO; + error = -ENXIO; goto err_bind; } @@ -184,9 +188,9 @@ igb_attach(char *dev_path, device_t *pdev) /* Set MAC type early for PCI setup */ adapter->hw.mac.type = e1000_i210; /* Setup PCI resources */ - if (error = igb_allocate_pci_resources(adapter)) { + error = igb_allocate_pci_resources(adapter); + if (error) goto err_pci; - } /* * Set the frame limits assuming @@ -199,53 +203,55 @@ igb_attach(char *dev_path, device_t *pdev) ** Copy the permanent MAC address out of the EEPROM */ if (igb_read_mac_addr(&adapter->hw) < 0) { - error = EIO; + error = -EIO; goto err_late; } - if( sem_post( adapter->memlock ) != 0 ) { - error = errno; + if (sem_post(adapter->memlock) != 0) { + error = -errno; goto err_gen; } - return (0); + return 0; err_late: err_pci: igb_free_pci_resources(adapter); err_bind: - sem_post( adapter->memlock ); - sem_close( adapter->memlock ); + sem_post(adapter->memlock); + sem_close(adapter->memlock); close(adapter->ldev); err_prebind: free(pdev->private_data); pdev->private_data = NULL; err_gen: - return (error); + return error; } int -igb_attach_tx( device_t *pdev ) +igb_attach_tx(device_t *pdev) { int error; struct adapter *adapter; - if (NULL == pdev) return EINVAL; + if (pdev == NULL) + return -EINVAL; adapter = (struct adapter *)pdev->private_data; - if (NULL == adapter) return EINVAL; + if (adapter == NULL) + return -EINVAL; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } /* ** Allocate and Setup Queues */ adapter->num_queues = 2; /* XXX parameterize this */ - if (error = igb_allocate_queues(adapter)) { + error = igb_allocate_queues(adapter); + if (error) { adapter->num_queues = 0; goto release; } @@ -258,11 +264,10 @@ igb_attach_tx( device_t *pdev ) igb_reset(adapter); release: - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) return errno; - } - return (error); + return error; } int @@ -270,29 +275,30 @@ igb_detach(device_t *dev) { struct adapter *adapter; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; - if( sem_wait( adapter->memlock ) != 0 ) { - goto err_nolock; - } + if (sem_wait(adapter->memlock) != 0) + goto -err_nolock; igb_reset(adapter); - sem_post( adapter->memlock ); + sem_post(adapter->memlock); igb_free_transmit_structures(adapter); igb_free_pci_resources(adapter); err_nolock: - sem_close( adapter->memlock ); + sem_close(adapter->memlock); - close (adapter->ldev); + close(adapter->ldev); free(dev->private_data); dev->private_data = NULL; - return (0); + return 0; } int @@ -304,18 +310,19 @@ igb_suspend(device_t *dev) u32 txdctl; int i; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; txr = adapter->tx_rings; hw = &adapter->hw; txdctl = 0; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } /* stop but don't reset the Tx Descriptor Rings */ for (i = 0; i < adapter->num_queues; i++, txr++) { @@ -326,11 +333,10 @@ igb_suspend(device_t *dev) txr->queue_status = IGB_QUEUE_IDLE; } - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) return errno; - } - return (0); + return 0; } int @@ -343,18 +349,19 @@ igb_resume(device_t *dev) int i; int error; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; txr = adapter->tx_rings; hw = &adapter->hw; txdctl = 0; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } /* resume but don't reset the Tx Descriptor Rings */ for (i = 0; i < adapter->num_queues; i++, txr++) { @@ -368,11 +375,10 @@ igb_resume(device_t *dev) txr->queue_status = IGB_QUEUE_WORKING; } - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) return errno; - } - return (0); + return 0; err_lockfail: return error; @@ -383,24 +389,25 @@ igb_init(device_t *dev) { struct adapter *adapter; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } + igb_reset(adapter); /* Prepare transmit descriptors and buffers */ igb_setup_transmit_structures(adapter); igb_initialize_transmit_units(adapter); - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) return errno; - } - return(0); + return 0; } static void @@ -408,8 +415,8 @@ igb_reset(struct adapter *adapter) { struct tx_ring *txr = adapter->tx_rings; struct e1000_hw *hw = &adapter->hw; - u32 tctl, txdctl; - int i; + u32 tctl, txdctl; + int i; tctl = txdctl = 0; @@ -459,7 +466,7 @@ igb_read_mac_addr(struct e1000_hw *hw) for (i = 0; i < ETH_ADDR_LEN; i++) hw->mac.addr[i] = hw->mac.perm_addr[i]; - return E1000_SUCCESS; + return 0; } @@ -468,25 +475,20 @@ igb_allocate_pci_resources(struct adapter *adapter) { int dev = adapter->ldev; - adapter->hw.hw_addr = (u8 *)mmap(NULL, \ - adapter->csr.mmap_size, \ - PROT_READ | PROT_WRITE, \ - MAP_SHARED, \ - dev, - 0); + adapter->hw.hw_addr = (u8 *)mmap(NULL, adapter->csr.mmap_size, + PROT_READ | PROT_WRITE, MAP_SHARED, + dev, 0); - if (MAP_FAILED == adapter->hw.hw_addr) - return (ENXIO); + if (adapter->hw.hw_addr == MAP_FAILED) + return -ENXIO; - return (0); + return 0; } static void igb_free_pci_resources(struct adapter *adapter) { - munmap( adapter->hw.hw_addr, adapter->csr.mmap_size); - - return ; + munmap(adapter->hw.hw_addr, adapter->csr.mmap_size); } /* @@ -499,36 +501,42 @@ igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *dma) int error = 0; struct igb_buf_cmd ubuf; - if (NULL == dev) return EINVAL; - if (NULL == dma) return EINVAL; + if (dev == NULL) + return -EINVAL; + if (dma == NULL) + return -EINVAL; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) { error = errno; goto err; } error = ioctl(adapter->ldev, IGB_MAPBUF, &ubuf); - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) { error = errno; goto err; } - if (error < 0) { error = ENOMEM; goto err; } + if (error < 0) { + error = -ENOMEM; + goto err; } dma->dma_paddr = ubuf.physaddr; dma->mmap_size = ubuf.mmap_size; - dma->dma_vaddr = (void *)mmap(NULL, \ - ubuf.mmap_size, \ - PROT_READ | PROT_WRITE, \ - MAP_SHARED, \ - adapter->ldev, \ - ubuf.physaddr); - - if (MAP_FAILED == dma->dma_vaddr) - error = ENOMEM; + dma->dma_vaddr = (void *)mmap(NULL, + ubuf.mmap_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + adapter->ldev, + ubuf.physaddr); + + if (dma->dma_vaddr == MAP_FAILED) + error = -ENOMEM; err: - return (error); + return error; } void @@ -537,23 +545,26 @@ igb_dma_free_page(device_t *dev, struct igb_dma_alloc *dma) struct adapter *adapter; struct igb_buf_cmd ubuf; - if (NULL == dev) return; - if (NULL == dma) return; + if (dev == NULL) + return; + if (dma == NULL) + return; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return; + if (adapter == NULL) + return; - munmap( dma->dma_vaddr, + munmap(dma->dma_vaddr, dma->mmap_size); ubuf.physaddr = dma->dma_paddr; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) goto err; - } + ioctl(adapter->ldev, IGB_UNMAPBUF, &ubuf); - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) goto err; - } dma->dma_paddr = 0; dma->dma_vaddr = NULL; @@ -573,19 +584,21 @@ igb_dma_free_page(device_t *dev, struct igb_dma_alloc *dma) static int igb_allocate_queues(struct adapter *adapter) { - int dev = adapter->ldev; - struct igb_buf_cmd ubuf; - int i, error = E1000_SUCCESS; + struct igb_buf_cmd ubuf; + int dev = adapter->ldev; + int i, error = 0; /* allocate the TX ring struct memory */ - adapter->tx_rings = (struct tx_ring *) malloc(sizeof(struct tx_ring) \ - * adapter->num_queues); - if (NULL == adapter->tx_rings) { - error = ENOMEM; + adapter->tx_rings = (struct tx_ring *) malloc(sizeof(struct tx_ring) * + adapter->num_queues); + + if (adapter == NULL->tx_rings) { + error = -ENOMEM; goto tx_fail; } - memset(adapter->tx_rings, 0, sizeof(struct tx_ring) * adapter->num_queues); + memset(adapter->tx_rings, 0, sizeof(struct tx_ring) * + adapter->num_queues); for (i = 0; i < adapter->num_queues; i++) { ubuf.queue = i; @@ -597,48 +610,52 @@ igb_allocate_queues(struct adapter *adapter) adapter->tx_rings[i].txdma.paddr = ubuf.physaddr; adapter->tx_rings[i].txdma.mmap_size = ubuf.mmap_size; adapter->tx_rings[i].tx_base = NULL; - adapter->tx_rings[i].tx_base = (struct e1000_tx_desc *)mmap(NULL, \ - ubuf.mmap_size, \ - PROT_READ | PROT_WRITE, \ - MAP_SHARED, \ - adapter->ldev, \ - ubuf.physaddr); - - if (MAP_FAILED == adapter->tx_rings[i].tx_base) { - error = ENOMEM; + adapter->tx_rings[i].tx_base = + (struct e1000_tx_desc *)mmap(NULL, ubuf.mmap_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, adapter->ldev, + ubuf.physaddr); + + if (adapter->tx_rings[i].tx_base == MAP_FAILED) { + error = -ENOMEM; goto tx_desc; } + adapter->tx_rings[i].adapter = adapter; adapter->tx_rings[i].me = i; /* XXX Initialize a TX lock ?? */ - adapter->num_tx_desc = ubuf.mmap_size / sizeof(union e1000_adv_tx_desc); + adapter->num_tx_desc = ubuf.mmap_size / + sizeof(union e1000_adv_tx_desc); memset((void *)adapter->tx_rings[i].tx_base, 0, ubuf.mmap_size); - adapter->tx_rings[i].tx_buffers = (struct igb_tx_buffer *) malloc(sizeof(struct igb_tx_buffer) * \ - adapter->num_tx_desc); + adapter->tx_rings[i].tx_buffers = + (struct igb_tx_buffer *) + malloc(sizeof(struct igb_tx_buffer) * + adapter->num_tx_desc); - if (NULL == adapter->tx_rings[i].tx_buffers) { - error = ENOMEM; + if (adapter == NULL->tx_rings[i].tx_buffers) { + error = -ENOMEM; goto tx_desc; } - memset(adapter->tx_rings[i].tx_buffers, 0, sizeof(struct igb_tx_buffer) * adapter->num_tx_desc); + memset(adapter->tx_rings[i].tx_buffers, 0, + sizeof(struct igb_tx_buffer) * adapter->num_tx_desc); } - return (0); + return 0; tx_desc: for (i = 0; i < adapter->num_queues; i++) { if (adapter->tx_rings[i].tx_base) - munmap(adapter->tx_rings[i].tx_base, \ - adapter->tx_rings[i].txdma.mmap_size); + munmap(adapter->tx_rings[i].tx_base, + adapter->tx_rings[i].txdma.mmap_size); ubuf.queue = i; ioctl(dev, IGB_UNMAPRING, &ubuf); }; tx_fail: free(adapter->tx_rings); adapter->tx_rings = NULL; - return (error); + return error; } /********************************************************************* @@ -652,11 +669,11 @@ igb_setup_transmit_ring(struct tx_ring *txr) struct adapter *adapter = txr->adapter; /* Clear the old descriptor contents */ - memset((void *)txr->tx_base, \ - 0, \ - (sizeof(union e1000_adv_tx_desc)) * adapter->num_tx_desc); + memset((void *)txr->tx_base, 0, + (sizeof(union e1000_adv_tx_desc)) * adapter->num_tx_desc); - memset(txr->tx_buffers, 0, sizeof(struct igb_tx_buffer) * txr->adapter->num_tx_desc); + memset(txr->tx_buffers, 0, sizeof(struct igb_tx_buffer) * + txr->adapter->num_tx_desc); /* Reset indices */ txr->next_avail_desc = 0; @@ -664,7 +681,6 @@ igb_setup_transmit_ring(struct tx_ring *txr) /* Set number of descriptors available */ txr->tx_avail = adapter->num_tx_desc; - } /********************************************************************* @@ -680,8 +696,6 @@ igb_setup_transmit_structures(struct adapter *adapter) for (i = 0; i < adapter->num_queues; i++, txr++) igb_setup_transmit_ring(txr); - - return; } /********************************************************************* @@ -694,9 +708,11 @@ igb_initialize_transmit_units(struct adapter *adapter) { struct tx_ring *txr = adapter->tx_rings; struct e1000_hw *hw = &adapter->hw; - u32 tctl, txdctl; - int i; - tctl = txdctl = 0; + u32 tctl, txdctl; + int i; + + tctl = 0; + txdctl = 0; /* Setup the Tx Descriptor Rings */ for (i = 0; i < adapter->num_queues; i++, txr++) { @@ -732,14 +748,13 @@ igb_free_transmit_structures(struct adapter *adapter) for (i = 0; i < adapter->num_queues; i++) { if (adapter->tx_rings[i].tx_base) - munmap(adapter->tx_rings[i].tx_base, \ - adapter->tx_rings[i].txdma.mmap_size); + munmap(adapter->tx_rings[i].tx_base, + adapter->tx_rings[i].txdma.mmap_size); ubuf.queue = i; ioctl(adapter->ldev, IGB_UNMAPRING, &ubuf); free(adapter->tx_rings[i].tx_buffers); } - free(adapter->tx_rings); adapter->tx_rings = NULL; } @@ -773,7 +788,8 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet) TXD->mss_l4len_idx = 0; /* remap the 64-bit nsec time to the value represented in the desc */ - remapped_time = packet->attime - ((packet->attime / 1000000000)*1000000000); + remapped_time = packet->attime - ((packet->attime / 1000000000) * + 1000000000); remapped_time /= 32; /* scale to 32 nsec increments */ @@ -788,8 +804,6 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet) ctxd = 0; txr->next_avail_desc = ctxd; --txr->tx_avail; - - return; } @@ -816,22 +830,25 @@ igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet) int i, first, last = 0; int error = 0; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; txr = &adapter->tx_rings[queue_index]; - if( !txr ) return EINVAL; + if (!txr) + return -EINVAL; if (queue_index > adapter->num_queues) - return EINVAL; + return -EINVAL; - if (NULL == packet) - return EINVAL; + if (packet == NULL) + return -EINVAL; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } packet->next = NULL; /* used for cleanup */ @@ -895,7 +912,7 @@ igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet) tx_buffer->next_eop = -1; txr->next_avail_desc = i; - txr->tx_avail-- ; + txr->tx_avail--; tx_buffer->packet = packet; @@ -923,11 +940,10 @@ igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet) ++txr->tx_packets; unlock: - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) return errno; - } - return(error); + return error; } void @@ -935,20 +951,19 @@ igb_trigger(device_t *dev, u_int32_t data) { struct adapter *adapter; - if (NULL == dev) return; + if (dev == NULL) + return; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return; + if (adapter == NULL) + return; - if( sem_wait( adapter->memlock ) != 0 ) { - goto err; - } - E1000_WRITE_REG(&(adapter->hw), E1000_WUS, data); - if( sem_post( adapter->memlock ) != 0 ) { - goto err; - } + if (sem_wait(adapter->memlock) != 0) + return; - err: - return; + E1000_WRITE_REG(&(adapter->hw), E1000_WUS, data); + if (sem_post(adapter->memlock) != 0) + return; } void @@ -956,9 +971,12 @@ igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data) { struct adapter *adapter; - if (NULL == dev) return; + if (dev == NULL) + return; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return; + if (adapter == NULL) + return; E1000_WRITE_REG(&(adapter->hw), reg, data); } @@ -968,33 +986,45 @@ igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data) { struct adapter *adapter; - if (NULL == dev) return; + if (dev == NULL) + return; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return; + if (adapter == NULL) + return; - if (NULL == data) return; + if (data == NULL) + return; *data = E1000_READ_REG(&(adapter->hw), reg); } -int igb_lock( device_t *dev ) { +int igb_lock(device_t *dev) +{ struct adapter *adapter; - if (NULL == dev) return ENODEV; + if (dev == NULL) + return -ENODEV; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; - return sem_wait( adapter->memlock ); + return sem_wait(adapter->memlock); } -int igb_unlock( device_t *dev ) { +int igb_unlock(device_t *dev) +{ struct adapter *adapter; - if (NULL == dev) return ENODEV; + if (dev == NULL) + return -ENODEV; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; - return sem_post( adapter->memlock ); + return sem_post(adapter->memlock); } @@ -1007,25 +1037,27 @@ int igb_unlock( device_t *dev ) { void igb_clean(device_t *dev, struct igb_packet **cleaned_packets) { - struct adapter *adapter; - struct tx_ring *txr; - int first, last, done, processed; - struct igb_tx_buffer *tx_buffer; - struct e1000_tx_desc *tx_desc, *eop_desc; + struct e1000_tx_desc *tx_desc, *eop_desc; struct igb_packet *last_reclaimed; - int i; + struct igb_tx_buffer *tx_buffer; + struct adapter *adapter; + struct tx_ring *txr; + int first, last, done, processed, i; + + if (dev == NULL) + return; - if (NULL == dev) return; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return; + if (adapter == NULL) + return; - if (NULL == cleaned_packets) return; + if (cleaned_packets == NULL) + return; *cleaned_packets = NULL; /* nothing reclaimed yet */ - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return; - } for (i = 0; i < adapter->num_queues; i++) { txr = &adapter->tx_rings[i]; @@ -1049,21 +1081,28 @@ igb_clean(device_t *dev, struct igb_packet **cleaned_packets) * simple comparison on the inner while loop. */ if (++last == adapter->num_tx_desc) - last = 0; + last = 0; done = last; while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) { /* We clean the range of the packet */ while (first != done) { if (tx_buffer->packet) { - tx_buffer->packet->dmatime = (0xffffffff) & tx_desc->buffer_addr; - /* tx_buffer->packet->dmatime += (tx_desc->buffer_addr >> 32) * 1000000000; */ - txr->bytes += - tx_buffer->packet->len; - if (*cleaned_packets == NULL) - *cleaned_packets = tx_buffer->packet; - else - last_reclaimed->next = tx_buffer->packet; + tx_buffer->packet->dmatime = + (0xffffffff) & + tx_desc->buffer_addr; + /* tx_buffer->packet->dmatime += + * (tx_desc->buffer_addr >> 32) * + * 1000000000; + */ + txr->bytes += tx_buffer->packet->len; + if (*cleaned_packets == NULL) { + *cleaned_packets = + tx_buffer->packet; + } else { + last_reclaimed->next = + tx_buffer->packet; + } last_reclaimed = tx_buffer->packet; tx_buffer->packet = NULL; @@ -1075,7 +1114,6 @@ igb_clean(device_t *dev, struct igb_packet **cleaned_packets) ++txr->tx_avail; ++processed; - if (++first == adapter->num_tx_desc) first = 0; @@ -1087,7 +1125,9 @@ igb_clean(device_t *dev, struct igb_packet **cleaned_packets) last = tx_buffer->next_eop; if (last != -1) { eop_desc = &txr->tx_base[last]; - /* Get new done point */ if (++last == adapter->num_tx_desc) last = 0; + /* Get new done point */ + if (++last == adapter->num_tx_desc) + last = 0; done = last; } else break; @@ -1100,97 +1140,100 @@ igb_clean(device_t *dev, struct igb_packet **cleaned_packets) } unlock: - if( sem_post( adapter->memlock ) != 0 ) { - return; - } - - return; + sem_post(adapter->memlock); } #define MAX_ITER 32 #define MIN_WALLCLOCK_TSC_WINDOW 80 /* cycles */ #define MIN_SYSCLOCK_WINDOW 72 /* ns */ -static inline void rdtscpll( uint64_t *val ) { +static inline void rdtscpll(uint64_t *val) +{ uint32_t high, low; - __asm__ __volatile__( "lfence;" + + __asm__ __volatile__("lfence;" "rdtsc;" : "=d"(high), "=a"(low) : - : "memory" ); + : "memory"); *val = high; *val = (*val << 32) | low; } -static inline void __sync() { - __asm__ __volatile__( "mfence;" +static inline void __sync(void) +{ + __asm__ __volatile__("mfence;" : : - : "memory" ); + : "memory"); } int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc) { - u_int64_t t0 = 0, t1 = -1; - u_int32_t duration = -1; - u_int32_t timh, timl, tsauxc; - struct adapter *adapter; + u_int64_t t0 = 0, t1 = -1; + u_int32_t duration = -1; + u_int32_t timh, timl, tsauxc; + struct adapter *adapter; struct e1000_hw *hw; - int iter = 0; int error = 0; + int iter = 0; + + if (dev == NULL) + return -EINVAL; - if (NULL == dev) return EINVAL; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; hw = &adapter->hw; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } /* sample the timestamp bracketed by the RDTSC */ - for - ( iter = 0; iter < MAX_ITER && t1 - t0 > MIN_WALLCLOCK_TSC_WINDOW; - ++iter ) - { - tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); - tsauxc |= E1000_TSAUXC_SAMP_AUTO; - // Invalidate AUXSTMPH/L0 - E1000_READ_REG(hw, E1000_AUXSTMPH0); - rdtscpll(&t0); - E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc ); - rdtscpll(&t1); - - if( t1 - t0 < duration ) { - duration = t1 - t0; - timl = E1000_READ_REG(hw, E1000_AUXSTMPL0); - timh = E1000_READ_REG(hw, E1000_AUXSTMPH0); - - if( curtime ) - *curtime = (u_int64_t)timh * 1000000000 + (u_int64_t)timl; - if( rdtsc ) - *rdtsc = (t1 - t0) / 2 + t0; /* average */ - } + for (iter = 0; iter < MAX_ITER && t1 - t0 > MIN_WALLCLOCK_TSC_WINDOW; + ++iter) { + tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); + tsauxc |= E1000_TSAUXC_SAMP_AUTO; + + /* Invalidate AUXSTMPH/L0 */ + E1000_READ_REG(hw, E1000_AUXSTMPH0); + rdtscpll(&t0); + E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc); + rdtscpll(&t1); + + if (t1 - t0 < duration) { + duration = t1 - t0; + timl = E1000_READ_REG(hw, E1000_AUXSTMPL0); + timh = E1000_READ_REG(hw, E1000_AUXSTMPH0); + + if (curtime) + *curtime = (u_int64_t)timh * 1000000000 + + (u_int64_t)timl; + if (rdtsc) + /* average */ + *rdtsc = (t1 - t0) / 2 + t0; } + } - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) { error = errno; goto err; } - return -duration; // Return the window size * -1 + /* Return the window size * -1 */ + return -duration; - err: +err: return error; } -struct timespec timespec_subtract( struct timespec *a, struct timespec *b ) +struct timespec timespec_subtract(struct timespec *a, struct timespec *b) { a->tv_nsec = a->tv_nsec - b->tv_nsec; if (a->tv_nsec < 0) { - // borrow. + /* borrow */ a->tv_nsec += 1000000000; --a->tv_sec; } @@ -1199,11 +1242,11 @@ struct timespec timespec_subtract( struct timespec *a, struct timespec *b ) return *a; } -struct timespec timespec_addns( struct timespec *a, unsigned long addns ) +struct timespec timespec_addns(struct timespec *a, unsigned long addns) { a->tv_nsec = a->tv_nsec + (addns % 1000000000); - if (a->tv_nsec > 1000000000 ) { - // carry + if (a->tv_nsec > 1000000000) { + /* carry */ a->tv_nsec -= 1000000000; ++a->tv_sec; } @@ -1216,63 +1259,66 @@ struct timespec timespec_addns( struct timespec *a, unsigned long addns ) int igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, - struct timespec *system_time ) + struct timespec *system_time) { struct timespec t0 = { 0, 0 }, t1 = { .tv_sec = 4, .tv_nsec = 0 }; - u_int32_t duration = -1; - u_int32_t timh, timl, tsauxc; - struct adapter *adapter; + u_int32_t timh, timl, tsauxc; + u_int32_t duration = -1; + struct adapter *adapter; struct e1000_hw *hw; - int iter = 0; int error = 0; + int iter = 0; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; hw = &adapter->hw; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } /* sample the timestamp bracketed by the clock_gettime() */ - for - ( iter = 0; iter < MAX_ITER && duration > MIN_SYSCLOCK_WINDOW; ++iter ) - { - u_int32_t duration_c; - tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); - tsauxc |= E1000_TSAUXC_SAMP_AUTO; - // Invalidate AUXSTMPH/L0 - E1000_READ_REG( hw, E1000_AUXSTMPH0 ); - clock_gettime( clk_id, &t0 ); - E1000_WRITE_REG( hw, E1000_TSAUXC, tsauxc ); - __sync(); - clock_gettime( clk_id, &t1 ); - - timespec_subtract(&t1,&t0); - duration_c = TS2NS(t1); - if( duration_c < duration ) { - duration = duration_c; - timl = E1000_READ_REG(hw, E1000_AUXSTMPL0); - timh = E1000_READ_REG(hw, E1000_AUXSTMPH0); - - if( curtime ) - *curtime = (u_int64_t)timh * 1000000000 + (u_int64_t)timl; - if( system_time ) - *system_time = timespec_addns - (&t0,duration/2); - } + for (iter = 0; iter < MAX_ITER && duration > MIN_SYSCLOCK_WINDOW; + ++iter) { + u_int32_t duration_c; + + tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); + tsauxc |= E1000_TSAUXC_SAMP_AUTO; + + /* Invalidate AUXSTMPH/L0 */ + E1000_READ_REG(hw, E1000_AUXSTMPH0); + clock_gettime(clk_id, &t0); + E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc); + __sync(); + clock_gettime(clk_id, &t1); + + timespec_subtract(&t1, &t0); + duration_c = TS2NS(t1); + if (duration_c < duration) { + duration = duration_c; + timl = E1000_READ_REG(hw, E1000_AUXSTMPL0); + timh = E1000_READ_REG(hw, E1000_AUXSTMPH0); + + if (curtime) + *curtime = (u_int64_t)timh * 1000000000 + + (u_int64_t)timl; + if (system_time) + *system_time = + timespec_addns(&t0, duration/2); } + } - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) { error = errno; goto err; } + /* Return the window size * -1 */ + return -duration; - return -duration; // Return the window size * -1 - - err: +err: return error; } @@ -1295,9 +1341,11 @@ igb_set_class_bandwidth(device_t *dev, float class_a_percent, class_b_percent; int error = 0; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; hw = &adapter->hw; @@ -1305,33 +1353,36 @@ igb_set_class_bandwidth(device_t *dev, err = ioctl(adapter->ldev, IGB_LINKSPEED, &link); - if (err) return ENXIO; + if (err) + return -ENXIO; - if (0 == link.up) return EINVAL; + if (link.up == 0) + return -EINVAL; - if (link.speed < 100) return EINVAL; + if (link.speed < 100) + return -EINVAL; - if (link.duplex != FULL_DUPLEX ) return EINVAL; + if (link.duplex != FULL_DUPLEX) + return -EINVAL; if (tpktsz_a < 64) tpktsz_a = 64; /* minimum ethernet frame size */ if (tpktsz_a > 1500) - return EINVAL; + return -EINVAL; if (tpktsz_b < 64) tpktsz_b = 64; /* minimum ethernet frame size */ if (tpktsz_b > 1500) - return EINVAL; + return -EINVAL; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } tqavctrl = E1000_READ_REG(hw, E1000_TQAVCTRL); - if ((class_a + class_b) == 0 ) { + if ((class_a + class_b) == 0) { /* disable the Qav shaper */ tqavctrl &= ~E1000_TQAVCTRL_TX_ARB; E1000_WRITE_REG(hw, E1000_TQAVCTRL, tqavctrl); @@ -1354,50 +1405,62 @@ igb_set_class_bandwidth(device_t *dev, * (tpktsz + (media overhead)) * rate -> percentage of media rate. */ - /* 12=Ethernet IPG, 8=Preamble+Start of Frame, 18=Mac Header with VLAN+Etype, 4=CRC */ - class_a_percent = (float)((tpktsz_a + (12 + 8 + 18 + 4)) * class_a) ; - class_b_percent = (float)((tpktsz_b + (12 + 8 + 18 + 4)) * class_b) ; + /* 12=Ethernet IPG, + * 8=Preamble+Start of Frame, + * 18=Mac Header with VLAN+Etype, + * 4=CRC + */ + class_a_percent = (float)((tpktsz_a + (12 + 8 + 18 + 4)) * class_a); + class_b_percent = (float)((tpktsz_b + (12 + 8 + 18 + 4)) * class_b); class_a_percent /= 0.000125; /* class A observation window */ class_b_percent /= 0.000250; /* class B observation window */ if (link.speed == 100) { - class_a_percent /= (100000000.0 / 8); /* bytes-per-sec @ 100Mbps */ + /* bytes-per-sec @ 100Mbps */ + class_a_percent /= (100000000.0 / 8); class_b_percent /= (100000000.0 / 8); - class_a_idle = (u_int32_t)(class_a_percent * 0.2 * (float)linkrate + 0.5); - class_b_idle = (u_int32_t)(class_b_percent * 0.2 * (float)linkrate + 0.5); + class_a_idle = (u_int32_t)(class_a_percent * 0.2 * + (float)linkrate + 0.5); + class_b_idle = (u_int32_t)(class_b_percent * 0.2 * + (float)linkrate + 0.5); } else { - class_a_percent /= (1000000000.0 / 8); /* bytes-per-sec @ 1Gbps */ + /* bytes-per-sec @ 1Gbps */ + class_a_percent /= (1000000000.0 / 8); class_b_percent /= (1000000000.0 / 8); - class_a_idle = (u_int32_t)(class_a_percent * 2.0 * (float)linkrate + 0.5); - class_b_idle = (u_int32_t)(class_b_percent * 2.0 * (float)linkrate + 0.5); + class_a_idle = (u_int32_t)(class_a_percent * + 2.0 * (float)linkrate + 0.5); + class_b_idle = (u_int32_t)(class_b_percent * 2.0 * + (float)linkrate + 0.5); } if ((class_a_percent + class_b_percent) > 0.75) { - error = EINVAL; + error = -EINVAL; goto unlock; } tqavcc0 |= class_a_idle; tqavcc1 |= class_b_idle; /* - * hiCredit is the number of idleslope credits accumulated due to delay T + * hiCredit is the number of idleslope credits accumulated due to delay * * we assume the maxInterferenceSize is 18 + 4 + 1500 (1522). * Note: if EEE is enabled, we should use for maxInterferenceSize * the overhead of link recovery (a media-specific quantity). */ - tqavhc0 = 0x80000000 + (class_a_idle * 1522 / linkrate ); /* L.10 */ + tqavhc0 = 0x80000000 + (class_a_idle * 1522 / linkrate); /* L.10 */ /* * Class B high credit is is the same, except the delay - * is the MaxBurstSize of Class A + maxInterferenceSize of non-SR traffic + * is the MaxBurstSize of Class A + maxInterferenceSize of non-SR + * traffic * * L.41 * max Class B delay = (1522 + tpktsz_a) / (linkrate - class_a_idle) */ - tqavhc1 = 0x80000000 + (class_b_idle * ((1522 + tpktsz_a)/ (linkrate - class_a_idle))); + tqavhc1 = 0x80000000 + (class_b_idle * ((1522 + tpktsz_a) / + (linkrate - class_a_idle))); /* implicitly enable the Qav shaper */ tqavctrl |= E1000_TQAVCTRL_TX_ARB; @@ -1408,9 +1471,8 @@ igb_set_class_bandwidth(device_t *dev, E1000_WRITE_REG(hw, E1000_TQAVCTRL, tqavctrl); unlock: - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) error = errno; - } return error; } @@ -1434,9 +1496,12 @@ igb_set_class_bandwidth2(device_t *dev, float class_a_percent, class_b_percent; int error = 0; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; + adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; hw = &adapter->hw; @@ -1444,21 +1509,24 @@ igb_set_class_bandwidth2(device_t *dev, err = ioctl(adapter->ldev, IGB_LINKSPEED, &link); - if (err) return ENXIO; + if (err) + return -ENXIO; - if (0 == link.up) return EINVAL; + if (link.up == 0) + return -EINVAL; - if (link.speed < 100) return EINVAL; + if (link.speed < 100) + return -EINVAL; - if (link.duplex != FULL_DUPLEX ) return EINVAL; + if (link.duplex != FULL_DUPLEX) + return -EINVAL; - if( sem_wait( adapter->memlock ) != 0 ) { + if (sem_wait(adapter->memlock) != 0) return errno; - } tqavctrl = E1000_READ_REG(hw, E1000_TQAVCTRL); - if ((class_a_bytes_per_second + class_b_bytes_per_second) == 0 ) { + if ((class_a_bytes_per_second + class_b_bytes_per_second) == 0) { /* disable the Qav shaper */ tqavctrl &= ~E1000_TQAVCTRL_TX_ARB; E1000_WRITE_REG(hw, E1000_TQAVCTRL, tqavctrl); @@ -1470,60 +1538,69 @@ igb_set_class_bandwidth2(device_t *dev, linkrate = E1000_TQAVCC_LINKRATE; - // it is needed for Class B high credit calculations - // so we need to guess it - // TODO: check if it is right + /* it is needed for Class B high credit calculations + * so we need to guess it + * TODO: check if it is right + */ temp = class_a_bytes_per_second / 8000 - (12 + 8 + 18 + 4); - if (temp > 0) { + if (temp > 0) tpktsz_a = temp; - } else { + else tpktsz_a = 0; - // TODO: in igb_set_class_bandwidth if given tpktsz_a < 64 - // (for example 0) then the 64 value will be used even if - // there is no class_A streams (class_a is 0) - // I suspect that this is error, so we use 0 here. - } + /* TODO: in igb_set_class_bandwidth if given tpktsz_a < 64 + * (for example 0) then the 64 value will be used even if + * there is no class_A streams (class_a is 0) + * I suspect that this is error, so we use 0 here. + */ class_a_percent = class_a_bytes_per_second; class_b_percent = class_b_bytes_per_second; if (link.speed == 100) { - class_a_percent /= (100000000.0 / 8); /* bytes-per-sec @ 100Mbps */ + /* bytes-per-sec @ 100Mbps */ + class_a_percent /= (100000000.0 / 8); class_b_percent /= (100000000.0 / 8); - class_a_idle = (u_int32_t)(class_a_percent * 0.2 * (float)linkrate + 0.5); - class_b_idle = (u_int32_t)(class_b_percent * 0.2 * (float)linkrate + 0.5); + class_a_idle = (u_int32_t)(class_a_percent * 0.2 * + (float)linkrate + 0.5); + class_b_idle = (u_int32_t)(class_b_percent * 0.2 * + (float)linkrate + 0.5); } else { - class_a_percent /= (1000000000.0 / 8); /* bytes-per-sec @ 1Gbps */ + /* bytes-per-sec @ 1Gbps */ + class_a_percent /= (1000000000.0 / 8); class_b_percent /= (1000000000.0 / 8); - class_a_idle = (u_int32_t)(class_a_percent * 2.0 * (float)linkrate + 0.5); - class_b_idle = (u_int32_t)(class_b_percent * 2.0 * (float)linkrate + 0.5); + class_a_idle = (u_int32_t)(class_a_percent * 2.0 * + (float)linkrate + 0.5); + class_b_idle = (u_int32_t)(class_b_percent * 2.0 * + (float)linkrate + 0.5); } if ((class_a_percent + class_b_percent) > 0.75) { - error = EINVAL; + error = -EINVAL; goto unlock; } tqavcc0 |= class_a_idle; tqavcc1 |= class_b_idle; /* - * hiCredit is the number of idleslope credits accumulated due to delay T + * hiCredit is the number of idleslope credits accumulated due to delay * * we assume the maxInterferenceSize is 18 + 4 + 1500 (1522). * Note: if EEE is enabled, we should use for maxInterferenceSize * the overhead of link recovery (a media-specific quantity). */ - tqavhc0 = 0x80000000 + (class_a_idle * 1522 / linkrate ); /* L.10 */ + tqavhc0 = 0x80000000 + (class_a_idle * 1522 / linkrate); /* L.10 */ /* * Class B high credit is is the same, except the delay - * is the MaxBurstSize of Class A + maxInterferenceSize of non-SR traffic + * is the MaxBurstSize of Class A + maxInterferenceSize of non-SR + * traffic * * L.41 * max Class B delay = (1522 + tpktsz_a) / (linkrate - class_a_idle) */ - tqavhc1 = 0x80000000 + (class_b_idle * ((1522 + tpktsz_a)/ (linkrate - class_a_idle))); + tqavhc1 = 0x80000000 + (class_b_idle * ((1522 + tpktsz_a) / + (linkrate - class_a_idle))); /* implicitly enable the Qav shaper */ tqavctrl |= E1000_TQAVCTRL_TX_ARB; @@ -1534,9 +1611,8 @@ igb_set_class_bandwidth2(device_t *dev, E1000_WRITE_REG(hw, E1000_TQAVCTRL, tqavctrl); unlock: - if( sem_post( adapter->memlock ) != 0 ) { + if (sem_post(adapter->memlock) != 0) error = errno; - } return error; } @@ -1546,9 +1622,11 @@ int igb_get_mac_addr(device_t *dev, u_int8_t mac_addr[ETH_ADDR_LEN]) struct adapter *adapter; struct e1000_hw *hw; - if (NULL == dev) return EINVAL; + if (dev == NULL) + return -EINVAL; adapter = (struct adapter *)dev->private_data; - if (NULL == adapter) return ENXIO; + if (adapter == NULL) + return -ENXIO; hw = &adapter->hw; -- cgit v1.2.1 From 6ce4aaf6c2e2b54f460234abb44e92c3edfeb08e Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Thu, 11 Feb 2016 14:33:21 -0800 Subject: libigb: add support for rx queues Adding support for rx queues in libigb. Signed-off-by: Todd Fujinaka --- lib/igb/igb.c | 344 ++++++++++++++++++++++++++++++++++--------------- lib/igb/igb.h | 70 +++++----- lib/igb/igb_internal.h | 132 ++++++++++++------- 3 files changed, 360 insertions(+), 186 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 17ac0889..673c6ec9 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -64,17 +64,17 @@ *********************************************************************/ static igb_vendor_info_t igb_vendor_info_array[] = { - { 0x8086, E1000_DEV_ID_I210_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_I210_COPPER, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_I210_COPPER_FLASHLESS, - PCI_ANY_ID, PCI_ANY_ID, 0}, - { 0x8086, E1000_DEV_ID_I210_COPPER_IT, PCI_ANY_ID, PCI_ANY_ID, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_I210_COPPER_IT, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_I210_COPPER_OEM1, - PCI_ANY_ID, PCI_ANY_ID, 0}, - { 0x8086, E1000_DEV_ID_I210_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, - { 0x8086, E1000_DEV_ID_I210_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_I210_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_I210_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0}, { 0x8086, E1000_DEV_ID_I210_SERDES_FLASHLESS, - PCI_ANY_ID, PCI_ANY_ID, 0}, - { 0x8086, E1000_DEV_ID_I210_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0}, + { 0x8086, E1000_DEV_ID_I210_SGMII, PCI_ANY_ID, PCI_ANY_ID, 0}, /* required last entry */ { 0, 0, 0, 0, 0} }; @@ -82,20 +82,19 @@ static igb_vendor_info_t igb_vendor_info_array[] = { /********************************************************************* * Function prototypes *********************************************************************/ -static int igb_read_mac_addr(struct e1000_hw *hw); -static int igb_allocate_pci_resources(struct adapter *adapter); -static void igb_free_pci_resources(struct adapter *adapter); -static void igb_reset(struct adapter *adapter); -static int igb_allocate_queues(struct adapter *adapter); -static void igb_setup_transmit_structures(struct adapter *adapter); -static void igb_setup_transmit_ring(struct tx_ring *txr); -static void igb_initialize_transmit_units(struct adapter *adapter); -static void igb_free_transmit_structures(struct adapter *adapter); -static void igb_tx_ctx_setup(struct tx_ring *txr, - struct igb_packet *packet); - -int -igb_probe(device_t *dev) +static int igb_read_mac_addr(struct e1000_hw *hw); +static int igb_allocate_pci_resources(struct adapter *adapter); +static void igb_free_pci_resources(struct adapter *adapter); +static void igb_reset(struct adapter *adapter); +static int igb_allocate_queues(struct adapter *adapter); +static void igb_setup_transmit_structures(struct adapter *adapter); +static void igb_setup_transmit_ring(struct tx_ring *txr); +static void igb_initialize_transmit_units(struct adapter *adapter); +static void igb_free_transmit_structures(struct adapter *adapter); +static void igb_tx_ctx_setup(struct tx_ring *txr, +struct igb_packet *packet); + +int igb_probe(device_t *dev) { igb_vendor_info_t *ent; @@ -120,12 +119,11 @@ igb_probe(device_t *dev) #define IGB_SEM "igb_sem" -int -igb_attach(char *dev_path, device_t *pdev) +int igb_attach(char *dev_path, device_t *pdev) { - struct adapter *adapter; + struct adapter *adapter; struct igb_bind_cmd bind; - int error = 0; + int error = 0; if (pdev == NULL) return -EINVAL; @@ -229,11 +227,10 @@ igb_attach(char *dev_path, device_t *pdev) return error; } -int -igb_attach_tx(device_t *pdev) +int igb_attach_tx(device_t *pdev) { int error; - struct adapter *adapter; + struct adapter *adapter; if (pdev == NULL) return -EINVAL; @@ -270,10 +267,9 @@ igb_attach_tx(device_t *pdev) return error; } -int -igb_detach(device_t *dev) +int igb_detach(device_t *dev) { - struct adapter *adapter; + struct adapter *adapter; if (dev == NULL) return -EINVAL; @@ -282,7 +278,7 @@ igb_detach(device_t *dev) return -ENXIO; if (sem_wait(adapter->memlock) != 0) - goto -err_nolock; + goto err_nolock; igb_reset(adapter); @@ -301,14 +297,13 @@ igb_detach(device_t *dev) return 0; } -int -igb_suspend(device_t *dev) +int igb_suspend(device_t *dev) { - struct adapter *adapter; + struct adapter *adapter; struct tx_ring *txr; struct e1000_hw *hw; - u32 txdctl; - int i; + u32 txdctl; + int i; if (dev == NULL) return -EINVAL; @@ -339,14 +334,13 @@ igb_suspend(device_t *dev) return 0; } -int -igb_resume(device_t *dev) +int igb_resume(device_t *dev) { - struct adapter *adapter; + struct adapter *adapter; struct tx_ring *txr; struct e1000_hw *hw; - u32 txdctl; - int i; + u32 txdctl; + int i; int error; if (dev == NULL) @@ -384,10 +378,9 @@ igb_resume(device_t *dev) return error; } -int -igb_init(device_t *dev) +int igb_init(device_t *dev) { - struct adapter *adapter; + struct adapter *adapter; if (dev == NULL) return -EINVAL; @@ -447,8 +440,7 @@ igb_reset(struct adapter *adapter) } -static int -igb_read_mac_addr(struct e1000_hw *hw) +static int igb_read_mac_addr(struct e1000_hw *hw) { u32 rar_high; u32 rar_low; @@ -470,10 +462,9 @@ igb_read_mac_addr(struct e1000_hw *hw) } -static int -igb_allocate_pci_resources(struct adapter *adapter) +static int igb_allocate_pci_resources(struct adapter *adapter) { - int dev = adapter->ldev; + int dev = adapter->ldev; adapter->hw.hw_addr = (u8 *)mmap(NULL, adapter->csr.mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, @@ -494,10 +485,9 @@ igb_free_pci_resources(struct adapter *adapter) /* * Manage DMA'able memory. */ -int -igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *dma) +int igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *dma) { - struct adapter *adapter; + struct adapter *adapter; int error = 0; struct igb_buf_cmd ubuf; @@ -542,7 +532,7 @@ err: void igb_dma_free_page(device_t *dev, struct igb_dma_alloc *dma) { - struct adapter *adapter; + struct adapter *adapter; struct igb_buf_cmd ubuf; if (dev == NULL) @@ -581,8 +571,7 @@ igb_dma_free_page(device_t *dev, struct igb_dma_alloc *dma) * the descriptors associated with each, called only once at attach. * **********************************************************************/ -static int -igb_allocate_queues(struct adapter *adapter) +static int igb_allocate_queues(struct adapter *adapter) { struct igb_buf_cmd ubuf; int dev = adapter->ldev; @@ -592,7 +581,7 @@ igb_allocate_queues(struct adapter *adapter) adapter->tx_rings = (struct tx_ring *) malloc(sizeof(struct tx_ring) * adapter->num_queues); - if (adapter == NULL->tx_rings) { + if (adapter->tx_rings == NULL) { error = -ENOMEM; goto tx_fail; } @@ -633,7 +622,7 @@ igb_allocate_queues(struct adapter *adapter) malloc(sizeof(struct igb_tx_buffer) * adapter->num_tx_desc); - if (adapter == NULL->tx_rings[i].tx_buffers) { + if (adapter->tx_rings[i].tx_buffers == NULL) { error = -ENOMEM; goto tx_desc; } @@ -819,15 +808,14 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet) * **********************************************************************/ -int -igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet) +int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet) { struct adapter *adapter; struct tx_ring *txr; struct igb_tx_buffer *tx_buffer; union e1000_adv_tx_desc *txd = NULL; - u32 cmd_type_len, olinfo_status = 0; - int i, first, last = 0; + u32 cmd_type_len, olinfo_status = 0; + int i, first, last = 0; int error = 0; if (dev == NULL) @@ -949,7 +937,7 @@ unlock: void igb_trigger(device_t *dev, u_int32_t data) { - struct adapter *adapter; + struct adapter *adapter; if (dev == NULL) return; @@ -969,7 +957,7 @@ igb_trigger(device_t *dev, u_int32_t data) void igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data) { - struct adapter *adapter; + struct adapter *adapter; if (dev == NULL) return; @@ -984,7 +972,7 @@ igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data) void igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data) { - struct adapter *adapter; + struct adapter *adapter; if (dev == NULL) return; @@ -1001,7 +989,7 @@ igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data) int igb_lock(device_t *dev) { - struct adapter *adapter; + struct adapter *adapter; if (dev == NULL) return -ENODEV; @@ -1015,7 +1003,7 @@ int igb_lock(device_t *dev) int igb_unlock(device_t *dev) { - struct adapter *adapter; + struct adapter *adapter; if (dev == NULL) return -ENODEV; @@ -1143,6 +1131,162 @@ unlock: sem_post(adapter->memlock); } +/* + * Refresh mbuf buffers for RX descriptor rings + * - now keeps its own state so discards due to resource + * exhaustion are unnecessary, if an mbuf cannot be obtained + * it just returns, keeping its placeholder, thus it can simply + * be recalled to try again. + * + */ +void igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs) +{ + struct adapter *adapter; + struct igb_rx_buffer *rxbuf; + struct rx_ring *rxr; + struct igb_packet *cur_pkt; + int i, j, bufs_used, error; + bool refreshed = FALSE; + + if (dev == NULL) + return; + + adapter = (struct adapter *)dev->private_data; + if (adapter == NULL) + return; + + if (rxbuf_packets == NULL) + return; + + if (idx > 1) + return; + + rxr = &adapter->rx_rings[idx]; + i = j = rxr->next_to_refresh; + cur_pkt = *rxbuf_packets; + + /* + * Get one descriptor beyond + * our work mark to control + * the loop. + */ + if (++j == adapter->num_rx_desc) + j = 0; + + bufs_used = 0; + + while (bufs_used < num_bufs) { + rxbuf = &rxr->rx_buffers[i]; + + rxr->rx_base[i].read.pkt_addr = + htole64(cur_pkt->map.paddr + cur_pkt->offset); + refreshed = TRUE; /* I feel wefreshed :) */ + + i = j; /* our next is precalculated */ + rxr->next_to_refresh = i; + if (++j == adapter->num_rx_desc) + j = 0; + bufs_used++; + } +update: + if (refreshed) /* update tail */ + E1000_WRITE_REG(&adapter->hw, + E1000_RDT(rxr->me), rxr->next_to_refresh); +} + + +/********************************************************************** + * + * Examine each rx_buffer in the used queue. If the hardware is done + * processing the packet then return the linked list of associated resources. + * + **********************************************************************/ +void +igb_receive(device_t *dev, u_int32_t idx, struct igb_packet **received_packets, u_int32_t count) +{ + struct adapter *adapter; + int first, last, done, i; + struct rx_ring *rxr; + int processed = 0, rxdone = 0; + u32 ptype, staterr = 0; + union e1000_adv_rx_desc *cur; + struct igb_rx_buffer *rxbuf; + u16 hlen, plen, hdr, vtag, pkt_info; + bool eop = FALSE; + + if (dev == NULL) + return; + + adapter = (struct adapter *)dev->private_data; + if (adapter == NULL) + return; + + if (received_packets == NULL) + return; + + *received_packets = NULL; /* nothing reclaimed yet */ + + if (sem_wait(adapter->memlock) != 0) + return; + + for (i = 0; i < adapter->num_queues; i++) { + rxr = &adapter->rx_rings[i]; + + /* Main clean loop - receive packets until no more + * received_packets[] + */ + for (i = rxr->next_to_check; count != 0;) { + cur = &rxr->rx_base[i]; + staterr = le32toh(cur->wb.upper.status_error); + if ((staterr & E1000_RXD_STAT_DD) == 0) + break; + count--; + + cur->wb.upper.status_error = 0; + rxbuf = &rxr->rx_buffers[i]; + plen = le16toh(cur->wb.upper.length); + ptype = le32toh(cur->wb.lower.lo_dword.data) & + IGB_PKTTYPE_MASK; + vtag = le16toh(cur->wb.upper.vlan); + hdr = le16toh(cur->wb.lower.lo_dword.hs_rss.hdr_info); + pkt_info = + le16toh(cur->wb.lower.lo_dword.hs_rss.pkt_info); + eop = ((staterr & E1000_RXD_STAT_EOP) == + E1000_RXD_STAT_EOP); + + /* + * Free the frame (all segments) if we're at EOP and + * it's an error. + * + * The datasheet states that EOP + status is only valid + * for the final segment in a multi-segment frame. + */ + if (eop && + (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { + ++rxr->rx_discarded; + /* igb_rx_discard(rxr, i); XXX what does this do? shoudl we internally refresh the buffer to the end of the ring? */ + goto next_desc; + } + +next_desc: + /* Advance our pointers to the next descriptor. */ + if (++i == adapter->num_rx_desc) + i = 0; + /* add new packet to list of received packets to return XXX todo */ + if (rxr != NULL) { + rxr->next_to_check = i; + i = rxr->next_to_check; + rxdone++; + } + } + + rxr->next_to_check = i; + } + +unlock: + sem_post(adapter->memlock); +} + #define MAX_ITER 32 #define MIN_WALLCLOCK_TSC_WINDOW 80 /* cycles */ #define MIN_SYSCLOCK_WINDOW 72 /* ns */ @@ -1168,8 +1312,7 @@ static inline void __sync(void) : "memory"); } -int -igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc) +int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc) { u_int64_t t0 = 0, t1 = -1; u_int32_t duration = -1; @@ -1257,9 +1400,8 @@ struct timespec timespec_addns(struct timespec *a, unsigned long addns) #define TS2NS(ts) (((ts).tv_sec*1000000000)+(ts).tv_nsec) -int -igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, - struct timespec *system_time) +int igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, + struct timespec *system_time) { struct timespec t0 = { 0, 0 }, t1 = { .tv_sec = 4, .tv_nsec = 0 }; u_int32_t timh, timl, tsauxc; @@ -1322,23 +1464,19 @@ err: return error; } -int -igb_set_class_bandwidth(device_t *dev, - u_int32_t class_a, - u_int32_t class_b, - u_int32_t tpktsz_a, - u_int32_t tpktsz_b) +int igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, + u_int32_t tpktsz_a, u_int32_t tpktsz_b) { - u_int32_t tqavctrl; - u_int32_t tqavcc0, tqavcc1; - u_int32_t tqavhc0, tqavhc1; - u_int32_t class_a_idle, class_b_idle; - u_int32_t linkrate; - struct adapter *adapter; + u_int32_t tqavctrl; + u_int32_t tqavcc0, tqavcc1; + u_int32_t tqavhc0, tqavhc1; + u_int32_t class_a_idle, class_b_idle; + u_int32_t linkrate; + struct adapter *adapter; struct e1000_hw *hw; - struct igb_link_cmd link; - int err; - float class_a_percent, class_b_percent; + struct igb_link_cmd link; + int err; + float class_a_percent, class_b_percent; int error = 0; if (dev == NULL) @@ -1477,23 +1615,21 @@ igb_set_class_bandwidth(device_t *dev, return error; } -int -igb_set_class_bandwidth2(device_t *dev, - u_int32_t class_a_bytes_per_second, - u_int32_t class_b_bytes_per_second) +int igb_set_class_bandwidth2(device_t *dev, u_int32_t class_a_bytes_per_second, + u_int32_t class_b_bytes_per_second) { - u_int32_t tqavctrl; - u_int32_t tqavcc0, tqavcc1; - u_int32_t tqavhc0, tqavhc1; - u_int32_t class_a_idle, class_b_idle; - u_int32_t linkrate; - u_int32_t tpktsz_a; - int temp; - struct adapter *adapter; + u_int32_t tqavctrl; + u_int32_t tqavcc0, tqavcc1; + u_int32_t tqavhc0, tqavhc1; + u_int32_t class_a_idle, class_b_idle; + u_int32_t linkrate; + u_int32_t tpktsz_a; + int temp; + struct adapter *adapter; struct e1000_hw *hw; - struct igb_link_cmd link; - int err; - float class_a_percent, class_b_percent; + struct igb_link_cmd link; + int err; + float class_a_percent, class_b_percent; int error = 0; if (dev == NULL) @@ -1619,7 +1755,7 @@ igb_set_class_bandwidth2(device_t *dev, int igb_get_mac_addr(device_t *dev, u_int8_t mac_addr[ETH_ADDR_LEN]) { - struct adapter *adapter; + struct adapter *adapter; struct e1000_hw *hw; if (dev == NULL) diff --git a/lib/igb/igb.h b/lib/igb/igb.h index beddfc67..b340c2ba 100644 --- a/lib/igb/igb.h +++ b/lib/igb/igb.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2016, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -38,8 +38,8 @@ #include struct resource { - u_int64_t paddr; - u_int32_t mmap_size; + u_int64_t paddr; + u_int32_t mmap_size; }; /* datastructure used to transmit a timed packet */ @@ -47,24 +47,24 @@ struct resource { #define IGB_PACKET_LATCHTIME 2 /* grab a timestamp of transmission */ struct igb_packet { - struct resource map; /* bus_dma map for packet */ - unsigned int offset; /* offset into physical page */ - void *vaddr; - u_int32_t len; - u_int32_t flags; - u_int64_t attime; /* launchtime */ - u_int64_t dmatime; /* when dma tx desc wb*/ + struct resource map; /* bus_dma map for packet */ + unsigned int offset; /* offset into physical page */ + void *vaddr; + u_int32_t len; + u_int32_t flags; + u_int64_t attime; /* launchtime */ + u_int64_t dmatime; /* when dma tx desc wb*/ struct igb_packet *next; /* used in the clean routine */ }; typedef struct _device_t { - void *private_data; + void *private_data; u_int16_t pci_vendor_id; u_int16_t pci_device_id; u_int16_t domain; - u_int8_t bus; - u_int8_t dev; - u_int8_t func; + u_int8_t bus; + u_int8_t dev; + u_int8_t func; } device_t; /* @@ -72,30 +72,32 @@ typedef struct _device_t { * e1000_dma_malloc_page and e1000_dma_free_page. */ struct igb_dma_alloc { - u_int64_t dma_paddr; - void *dma_vaddr; - unsigned int mmap_size; + u_int64_t dma_paddr; + void *dma_vaddr; + unsigned int mmap_size; }; -int igb_probe( device_t *dev ); -int igb_attach(char *dev_path, device_t *pdev); +int igb_probe( device_t *dev ); +int igb_attach(char *dev_path, device_t *pdev); int igb_attach_tx( device_t *pdev ); -int igb_detach(device_t *dev); -int igb_suspend(device_t *dev); -int igb_resume(device_t *dev); -int igb_init(device_t *dev); -int igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *page); -void igb_dma_free_page(device_t *dev, struct igb_dma_alloc *page); -int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet); -void igb_clean(device_t *dev, struct igb_packet **cleaned_packets); -int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc); +int igb_detach(device_t *dev); +int igb_suspend(device_t *dev); +int igb_resume(device_t *dev); +int igb_init(device_t *dev); +int igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *page); +void igb_dma_free_page(device_t *dev, struct igb_dma_alloc *page); +int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet); +void igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs); +void igb_receive(device_t *dev, u_int32_t idx, struct igb_packet **received_packets, u_int32_t count); +void igb_clean(device_t *dev, struct igb_packet **cleaned_packets); +int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc); int igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, struct timespec *system_time ); -int igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, u_int32_t tpktsz_a, u_int32_t tpktsz_b); -int igb_set_class_bandwidth2(device_t *dev, u_int32_t class_a_bytes_per_second, u_int32_t class_b_bytes_per_second); +int igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, u_int32_t tpktsz_a, u_int32_t tpktsz_b); +int igb_set_class_bandwidth2(device_t *dev, u_int32_t class_a_bytes_per_second, u_int32_t class_b_bytes_per_second); -void igb_trigger(device_t *dev, u_int32_t data); -void igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data); -void igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data); +void igb_trigger(device_t *dev, u_int32_t data); +void igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data); +void igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data); int igb_lock( device_t *dev ); int igb_unlock( device_t *dev ); @@ -103,5 +105,3 @@ int igb_unlock( device_t *dev ); int igb_get_mac_addr(device_t *dev, u_int8_t mac_addr[6]); #endif /* _IGB_H_DEFINED_ */ - - diff --git a/lib/igb/igb_internal.h b/lib/igb/igb_internal.h index e6198d8d..7613a661 100644 --- a/lib/igb/igb_internal.h +++ b/lib/igb/igb_internal.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2016, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -91,72 +91,110 @@ #define TSYNC_PORT 319 /* UDP port for the protocol */ struct igb_tx_buffer { - int next_eop; /* Index of the desc to watch */ - struct igb_packet *packet; /* app-relevant handle */ + int next_eop; /* Index of the desc to watch */ + struct igb_packet *packet; /* app-relevant handle */ }; /* * Transmit ring: one per queue */ struct tx_ring { - struct adapter *adapter; - u32 me; - struct resource txdma; - struct e1000_tx_desc *tx_base; - struct igb_tx_buffer *tx_buffers; - u32 next_avail_desc; - u32 next_to_clean; - volatile u16 tx_avail; - - u32 bytes; - u32 packets; - - int tdt; - int tdh; - u64 no_desc_avail; - u64 tx_packets; - int queue_status; + struct adapter *adapter; + u32 me; + struct resource txdma; + struct e1000_tx_desc *tx_base; + struct igb_tx_buffer *tx_buffers; + u32 next_avail_desc; + u32 next_to_clean; + + volatile u16 tx_avail; + + u32 bytes; + u32 packets; + + int tdt; + int tdh; + u64 no_desc_avail; + u64 tx_packets; + int queue_status; +}; + +struct igb_rx_buffer { + int next_eop; /* Index of the desc to watch */ + struct igb_packet *packet; /* app-relevant handle */ +}; + +/* + * Receive ring: one per queue + */ +struct rx_ring { + struct adapter *adapter; + u32 me; + struct resource rxdma; + union e1000_adv_rx_desc *rx_base; + bool hdr_split; + u32 next_to_refresh; + u32 next_to_check; + struct igb_rx_buffer *rx_buffers; +#ifdef XXX_REMOVE_PACKET_SPLIT_OPTION + /* + * First/last mbuf pointers, for + * collecting multisegment RX packets. + **/ + struct mbuf *fmp; + struct mbuf *lmp; +#endif + u32 bytes; + u32 packets; + int rdt; + int rdh; + + /* Soft stats */ + u64 rx_split_packets; + u64 rx_discarded; + u64 rx_packets; + u64 rx_bytes; }; struct adapter { - struct e1000_hw hw; + struct e1000_hw hw; sem_t *memlock; - int ldev; /* file descriptor to igb */ + int ldev; /* file descriptor to igb */ - struct resource csr; - int max_frame_size; - int min_frame_size; - int igb_insert_vlan_header; - u16 num_queues; + struct resource csr; + int max_frame_size; + int min_frame_size; + int igb_insert_vlan_header; + u16 num_queues; /* Interface queues */ - struct igb_queue *queues; + struct igb_queue *queues; /* - * Transmit rings + * rings */ - struct tx_ring *tx_rings; - u16 num_tx_desc; - + struct tx_ring *tx_rings; + u16 num_tx_desc; + struct rx_ring *rx_rings; + u16 num_rx_desc; #ifdef IGB_IEEE1588 /* IEEE 1588 precision time support */ - struct cyclecounter cycles; - struct nettimer clock; - struct nettime_compare compare; - struct hwtstamp_ctrl hwtstamp; + struct cyclecounter cycles; + struct nettimer clock; + struct nettime_compare compare; + struct hwtstamp_ctrl hwtstamp; #endif - }; -/* ****************************************************************************** +/* * vendor_info_array * * This array contains the list of Subvendor/Subdevice IDs on which the driver * should load. * - * ******************************************************************************/ + */ typedef struct _igb_vendor_info_t { unsigned int vendor_id; unsigned int device_id; @@ -181,20 +219,20 @@ typedef struct _igb_vendor_info_t { #define IGB_BIND_NAMESZ 24 struct igb_bind_cmd { - char iface[IGB_BIND_NAMESZ]; - unsigned mmap_size; + char iface[IGB_BIND_NAMESZ]; + unsigned mmap_size; }; struct igb_buf_cmd { - u_int64_t physaddr; /* dma_addr_t is 64-bit */ - unsigned int queue; - unsigned int mmap_size; + u_int64_t physaddr; /* dma_addr_t is 64-bit */ + unsigned int queue; + unsigned int mmap_size; }; struct igb_link_cmd { - u_int32_t up; /* dma_addr_t is 64-bit */ - u_int32_t speed; - u_int32_t duplex; + u_int32_t up; /* dma_addr_t is 64-bit */ + u_int32_t speed; + u_int32_t duplex; }; -- cgit v1.2.1 From 11a5c39623608a48f614edb38b882ce653035263 Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Fri, 12 Feb 2016 15:05:04 -0800 Subject: libavb: add receive queues to openavb Signed-off-by: Todd Fujinaka --- lib/igb/e1000_defines.h | 3 +- lib/igb/e1000_osdep.h | 15 +- lib/igb/igb.c | 536 ++++++++++++++++++++++++++++++++++++++++++------ lib/igb/igb.h | 31 ++- lib/igb/igb_internal.h | 13 +- 5 files changed, 513 insertions(+), 85 deletions(-) diff --git a/lib/igb/e1000_defines.h b/lib/igb/e1000_defines.h index f13f0bb3..d08162bb 100644 --- a/lib/igb/e1000_defines.h +++ b/lib/igb/e1000_defines.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2016, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -60,6 +60,7 @@ #define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ #define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ #define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ +#define E1000_WUFC_FLEX_HQ 0x00004000 /* Flex Filters Host Queuing (AVB) */ #define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ #define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ #define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ diff --git a/lib/igb/e1000_osdep.h b/lib/igb/e1000_osdep.h index 53a8cee1..08600ee6 100644 --- a/lib/igb/e1000_osdep.h +++ b/lib/igb/e1000_osdep.h @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2012, Intel Corporation + Copyright (c) 2001-2016, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -39,13 +39,7 @@ #undef FALSE #define TRUE true #define FALSE false -#ifdef GCC_VERSION -#if ( GCC_VERSION < 3000 ) #define _Bool char -#endif -#else -#define _Bool char -#endif #ifndef bool #define bool _Bool #define true 1 @@ -77,10 +71,13 @@ typedef int8_t s8; /* Register READ/WRITE macros */ #define E1000_READ_REG(hw, reg) \ - (*(volatile u32 *)(((hw)->hw_addr + reg))) + (*(u32 *)(((hw)->hw_addr + reg))) #define E1000_WRITE_REG(hw, reg, value) \ - (*(volatile u32 *)(((hw)->hw_addr + reg)) = value) + (*(u32 *)(((hw)->hw_addr + reg)) = value) + +#define E1000_WRITE_REG_ARRAY(hw, reg, index, value) \ + E1000_WRITE_REG((hw), (reg) + ((index) << 2), (value)) #endif /* _OSDEP_H_ */ diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 673c6ec9..3c2ba3b8 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -87,12 +87,13 @@ static int igb_allocate_pci_resources(struct adapter *adapter); static void igb_free_pci_resources(struct adapter *adapter); static void igb_reset(struct adapter *adapter); static int igb_allocate_queues(struct adapter *adapter); +static int igb_allocate_rx_queues(struct adapter *adapter); static void igb_setup_transmit_structures(struct adapter *adapter); static void igb_setup_transmit_ring(struct tx_ring *txr); static void igb_initialize_transmit_units(struct adapter *adapter); static void igb_free_transmit_structures(struct adapter *adapter); -static void igb_tx_ctx_setup(struct tx_ring *txr, -struct igb_packet *packet); +static void igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet); +static void igb_free_receive_buffers(struct rx_ring *rxr); int igb_probe(device_t *dev) { @@ -198,8 +199,8 @@ int igb_attach(char *dev_path, device_t *pdev) adapter->min_frame_size = 64; /* - ** Copy the permanent MAC address out of the EEPROM - */ + * Copy the permanent MAC address out of the EEPROM + */ if (igb_read_mac_addr(&adapter->hw) < 0) { error = -EIO; goto err_late; @@ -244,8 +245,8 @@ int igb_attach_tx(device_t *pdev) return errno; /* - ** Allocate and Setup Queues - */ + * Allocate and Setup Queues + */ adapter->num_queues = 2; /* XXX parameterize this */ error = igb_allocate_queues(adapter); if (error) { @@ -254,10 +255,10 @@ int igb_attach_tx(device_t *pdev) } /* - ** Start from a known state, which means - ** reset the transmit queues we own to a known - ** starting state. - */ + * Start from a known state, which means + * reset the transmit queues we own to a known + * starting state. + */ igb_reset(adapter); release: @@ -267,6 +268,39 @@ int igb_attach_tx(device_t *pdev) return error; } +int igb_attach_rx(device_t *pdev) +{ + int error; + struct adapter *adapter; + + if (pdev == NULL) + return -EINVAL; + + adapter = (struct adapter *)pdev->private_data; + + if (adapter == NULL) + return -EINVAL; + + if (sem_wait(adapter->memlock) != 0) + return errno; + + /* + * Allocate and Setup Rx Queues + */ + adapter->num_queues = 2; /* XXX parameterize this */ + error = igb_allocate_rx_queues(adapter); + if (error) { + adapter->num_queues = 0; + goto release; + } + + release: + if (sem_post(adapter->memlock) != 0) + return errno; + + return error; +} + int igb_detach(device_t *dev) { struct adapter *adapter; @@ -285,6 +319,7 @@ int igb_detach(device_t *dev) sem_post(adapter->memlock); igb_free_transmit_structures(adapter); + /* XXX FIXME-ADD RX case */ igb_free_pci_resources(adapter); err_nolock: @@ -300,7 +335,7 @@ int igb_detach(device_t *dev) int igb_suspend(device_t *dev) { struct adapter *adapter; - struct tx_ring *txr; + struct tx_ring *txr; struct e1000_hw *hw; u32 txdctl; int i; @@ -328,6 +363,8 @@ int igb_suspend(device_t *dev) txr->queue_status = IGB_QUEUE_IDLE; } + /* XXX FIXME-ADD RX case */ + if (sem_post(adapter->memlock) != 0) return errno; @@ -337,7 +374,7 @@ int igb_suspend(device_t *dev) int igb_resume(device_t *dev) { struct adapter *adapter; - struct tx_ring *txr; + struct tx_ring *txr; struct e1000_hw *hw; u32 txdctl; int i; @@ -369,6 +406,8 @@ int igb_resume(device_t *dev) txr->queue_status = IGB_QUEUE_WORKING; } + /* XXX FIXME-ADD RX case */ + if (sem_post(adapter->memlock) != 0) return errno; @@ -397,6 +436,8 @@ int igb_init(device_t *dev) igb_setup_transmit_structures(adapter); igb_initialize_transmit_units(adapter); + /* XXX FIXME-ADD RX case */ + if (sem_post(adapter->memlock) != 0) return errno; @@ -406,7 +447,7 @@ int igb_init(device_t *dev) static void igb_reset(struct adapter *adapter) { - struct tx_ring *txr = adapter->tx_rings; + struct tx_ring *txr = adapter->tx_rings; struct e1000_hw *hw = &adapter->hw; u32 tctl, txdctl; int i; @@ -438,6 +479,7 @@ igb_reset(struct adapter *adapter) txr->queue_status = IGB_QUEUE_IDLE; } + /* XXX FIXME-ADD RX case */ } static int igb_read_mac_addr(struct e1000_hw *hw) @@ -476,8 +518,7 @@ static int igb_allocate_pci_resources(struct adapter *adapter) return 0; } -static void -igb_free_pci_resources(struct adapter *adapter) +static void igb_free_pci_resources(struct adapter *adapter) { munmap(adapter->hw.hw_addr, adapter->csr.mmap_size); } @@ -529,8 +570,7 @@ err: return error; } -void -igb_dma_free_page(device_t *dev, struct igb_dma_alloc *dma) +void igb_dma_free_page(device_t *dev, struct igb_dma_alloc *dma) { struct adapter *adapter; struct igb_buf_cmd ubuf; @@ -564,7 +604,6 @@ igb_dma_free_page(device_t *dev, struct igb_dma_alloc *dma) return; } - /********************************************************************* * * Allocate memory for the transmit rings, and then @@ -652,8 +691,7 @@ tx_fail: * Initialize a transmit ring. * **********************************************************************/ -static void -igb_setup_transmit_ring(struct tx_ring *txr) +static void igb_setup_transmit_ring(struct tx_ring *txr) { struct adapter *adapter = txr->adapter; @@ -677,8 +715,7 @@ igb_setup_transmit_ring(struct tx_ring *txr) * Initialize all transmit rings. * **********************************************************************/ -static void -igb_setup_transmit_structures(struct adapter *adapter) +static void igb_setup_transmit_structures(struct adapter *adapter) { struct tx_ring *txr = adapter->tx_rings; int i; @@ -692,10 +729,9 @@ igb_setup_transmit_structures(struct adapter *adapter) * Enable transmit unit. * **********************************************************************/ -static void -igb_initialize_transmit_units(struct adapter *adapter) +static void igb_initialize_transmit_units(struct adapter *adapter) { - struct tx_ring *txr = adapter->tx_rings; + struct tx_ring *txr = adapter->tx_rings; struct e1000_hw *hw = &adapter->hw; u32 tctl, txdctl; int i; @@ -729,11 +765,10 @@ igb_initialize_transmit_units(struct adapter *adapter) * Free all transmit rings. * **********************************************************************/ -static void -igb_free_transmit_structures(struct adapter *adapter) +static void igb_free_transmit_structures(struct adapter *adapter) { int i; - struct igb_buf_cmd ubuf; + struct igb_buf_cmd ubuf; for (i = 0; i < adapter->num_queues; i++) { if (adapter->tx_rings[i].tx_base) @@ -754,16 +789,14 @@ igb_free_transmit_structures(struct adapter *adapter) * Context Descriptor setup for VLAN or CSUM * **********************************************************************/ - -static void -igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet) +static void igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet) { struct adapter *adapter = txr->adapter; struct e1000_adv_tx_context_desc *TXD; - struct igb_tx_buffer *tx_buffer; + struct igb_tx_buffer *tx_buffer; u32 type_tucmd_mlhl; - int ctxd; - u_int64_t remapped_time; + int ctxd; + u_int64_t remapped_time; ctxd = txr->next_avail_desc; tx_buffer = &txr->tx_buffers[ctxd]; @@ -807,13 +840,12 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet) * been previously mapped with the provided dma_malloc_page routines. * **********************************************************************/ - int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet) { - struct adapter *adapter; - struct tx_ring *txr; - struct igb_tx_buffer *tx_buffer; - union e1000_adv_tx_desc *txd = NULL; + struct adapter *adapter; + struct tx_ring *txr; + struct igb_tx_buffer *tx_buffer; + union e1000_adv_tx_desc *txd = NULL; u32 cmd_type_len, olinfo_status = 0; int i, first, last = 0; int error = 0; @@ -858,11 +890,11 @@ int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet) tx_buffer = &txr->tx_buffers[first]; /* - ** Make sure we don't overrun the ring, - ** we need nsegs descriptors and one for - ** the context descriptor used for the - ** offloads. - */ + * Make sure we don't overrun the ring, + * we need nsegs descriptors and one for + * the context descriptor used for the + * offloads. + */ if (txr->tx_avail <= 2) { error = ENOSPC; goto unlock; @@ -903,7 +935,6 @@ int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet) txr->tx_avail--; tx_buffer->packet = packet; - /* * Last Descriptor of Packet * needs End Of Packet (EOP) @@ -934,8 +965,7 @@ unlock: return error; } -void -igb_trigger(device_t *dev, u_int32_t data) +void igb_trigger(device_t *dev, u_int32_t data) { struct adapter *adapter; @@ -954,8 +984,7 @@ igb_trigger(device_t *dev, u_int32_t data) return; } -void -igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data) +void igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data) { struct adapter *adapter; @@ -969,8 +998,7 @@ igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data) E1000_WRITE_REG(&(adapter->hw), reg, data); } -void -igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data) +void igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data) { struct adapter *adapter; @@ -1015,15 +1043,13 @@ int igb_unlock(device_t *dev) return sem_post(adapter->memlock); } - /********************************************************************** * * Examine each tx_buffer in the used queue. If the hardware is done * processing the packet then return the linked list of associated resources. * **********************************************************************/ -void -igb_clean(device_t *dev, struct igb_packet **cleaned_packets) +void igb_clean(device_t *dev, struct igb_packet **cleaned_packets) { struct e1000_tx_desc *tx_desc, *eop_desc; struct igb_packet *last_reclaimed; @@ -1131,6 +1157,270 @@ unlock: sem_post(adapter->memlock); } +/********************************************************************* + * + * Allocate memory for the receive rings, and then + * the descriptors associated with each, called only once at attach. + * + **********************************************************************/ +static int igb_allocate_rx_queues(struct adapter *adapter) +{ + struct igb_buf_cmd ubuf; + int dev = adapter->ldev; + int i, error = 0; + + /* allocate the RX ring struct memory */ + adapter->rx_rings = (struct rx_ring *) malloc(sizeof(struct rx_ring) * + adapter->num_queues); + + if (adapter->rx_rings == NULL) { + error = -ENOMEM; + goto rx_fail; + } + + memset(adapter->rx_rings, 0, sizeof(struct rx_ring) * + adapter->num_queues); + + for (i = 0; i < adapter->num_queues; i++) { + ubuf.queue = i; + error = ioctl(dev, IGB_MAP_RX_RING, &ubuf); + if (error < 0) { + error = EBUSY; + goto rx_desc; + } + adapter->rx_rings[i].rxdma.paddr = ubuf.physaddr; + adapter->rx_rings[i].rxdma.mmap_size = ubuf.mmap_size; + adapter->rx_rings[i].rx_base = NULL; + adapter->rx_rings[i].rx_base = + mmap(NULL, ubuf.mmap_size, PROT_READ | PROT_WRITE, + MAP_SHARED, adapter->ldev, ubuf.physaddr); + + if (adapter->rx_rings[i].rx_base == MAP_FAILED) { + error = -ENOMEM; + goto rx_desc; + } + + adapter->rx_rings[i].adapter = adapter; + adapter->rx_rings[i].me = i; + + adapter->num_rx_desc = ubuf.mmap_size / + sizeof(union e1000_adv_rx_desc); + + memset((void *)adapter->rx_rings[i].rx_base, 0, ubuf.mmap_size); + adapter->rx_rings[i].rx_buffers = + (struct igb_rx_buffer *) + malloc(sizeof(struct igb_rx_buffer) * + adapter->num_rx_desc); + + if (adapter->rx_rings[i].rx_buffers == NULL) { + error = -ENOMEM; + goto rx_desc; + } + + memset(adapter->rx_rings[i].rx_buffers, 0, + sizeof(struct igb_rx_buffer) * adapter->num_rx_desc); + } + + return 0; + +rx_desc: + for (i = 0; i < adapter->num_queues; i++) { + if (adapter->rx_rings[i].rx_base) + munmap(adapter->rx_rings[i].rx_base, + adapter->rx_rings[i].rxdma.mmap_size); + ubuf.queue = i; + ioctl(dev, IGB_UNMAP_RX_RING, &ubuf); + }; +rx_fail: + free(adapter->rx_rings); + adapter->rx_rings = NULL; + return error; +} + +static void igb_free_receive_ring(struct rx_ring *rxr) +{ + struct adapter *adapter = rxr->adapter; + struct igb_rx_buffer *rxbuf; + + for (int i = 0; i < adapter->num_rx_desc; i++) + rxbuf = &rxr->rx_buffers[i]; +} + +/* Initialize a receive ring. */ +static int igb_setup_receive_ring(struct rx_ring *rxr) +{ + struct adapter *adapter; + device_t dev; + struct igb_rx_buf *rxbuf; + int rsize, nsegs, error = 0; + + adapter = rxr->adapter; + + /* Clear the ring contents */ + sem_wait(adapter->memlock); + rsize = adapter->num_rx_desc * sizeof(union e1000_adv_rx_desc); + bzero((void *)rxr->rx_base, rsize); + + /* Free current RX buffer structures */ + igb_free_receive_ring(rxr); + + /* Setup our descriptor indices */ + rxr->next_to_check = 0; + rxr->next_to_refresh = adapter->num_rx_desc - 1; + rxr->rx_split_packets = 0; + rxr->rx_bytes = 0; + + sem_post(adapter->memlock); + return 0; + +fail: + igb_free_receive_ring(rxr); + sem_post(adapter->memlock); + return error; +} + +/* Initialize all receive rings. */ +static int igb_setup_receive_structures(struct adapter *adapter) +{ + struct rx_ring *rxr = adapter->rx_rings; + int i, j; + + for (i = 0; i < adapter->num_queues; i++, rxr++) + if (igb_setup_receive_ring(rxr)) + goto fail; + return 0; + +fail: + /* + * Free RX buffers allocated so far, we will only handle + * the rings that completed, the failing case will have + * cleaned up for itself. 'i' is the endpoint. + */ + for (j = 0; j < i; ++j) { + rxr = &adapter->rx_rings[j]; + sem_wait(adapter->memlock); + igb_free_receive_ring(rxr); + sem_post(adapter->memlock); + } + + return -ENOBUFS; +} + +/* Enable receive unit. */ +static void igb_initialize_receive_units(struct adapter *adapter) +{ + struct rx_ring *rxr = adapter->rx_rings; + struct e1000_hw *hw = &adapter->hw; + u32 rctl, rxcsum, psize, srrctl = 0; + + + /* + * Make sure receives are disabled while setting + * up the descriptor ring + */ + rctl = E1000_READ_REG(hw, E1000_RCTL); + E1000_WRITE_REG(hw, E1000_RCTL, rctl & ~E1000_RCTL_EN); + + rctl &= ~E1000_RCTL_LPE; + srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + rctl |= E1000_RCTL_SZ_2048; + + /* Setup the Base and Length of the Rx Descriptor Rings */ + for (int i = 0; i < adapter->num_queues; i++, rxr++) { + u64 bus_addr = rxr->rxdma.paddr; + u32 rxdctl; + + E1000_WRITE_REG(hw, E1000_RDLEN(i), + adapter->num_rx_desc * + sizeof(struct e1000_rx_desc)); + E1000_WRITE_REG(hw, E1000_RDBAH(i), + (uint32_t)(bus_addr >> 32)); + E1000_WRITE_REG(hw, E1000_RDBAL(i), + (uint32_t)bus_addr); + E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl); + + /* Enable this Queue */ + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); + rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; + rxdctl &= 0xFFF00000; + rxdctl |= IGB_RX_PTHRESH; + rxdctl |= IGB_RX_HTHRESH << 8; + rxdctl |= IGB_RX_WTHRESH << 16; + E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); + } + + /* + * Setup for RX MultiQueue + */ + rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); + + /* + * NOTE: Receive Full-Packet Checksum Offload + * is mutually exclusive with Multiqueue. However + * this is not the same as TCP/IP checksums which + * still work. + */ + rxcsum |= E1000_RXCSUM_PCSD; + + E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); + + /* Setup the Receive Control Register */ + rctl &= ~(3 << E1000_RCTL_MO_SHIFT); + rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_LBM_NO | + E1000_RCTL_RDMTS_HALF; + /* Strip CRC bytes. */ + rctl |= E1000_RCTL_SECRC; + /* Make sure VLAN Filters are off */ + rctl &= ~E1000_RCTL_VFE; + /* Don't store bad packets */ + rctl &= ~E1000_RCTL_SBP; + + /* Enable Receives */ + E1000_WRITE_REG(hw, E1000_RCTL, rctl); + + /* + * Setup the HW Rx Head and Tail Descriptor Pointers + * - needs to be after enable + */ + for (int i = 0; i < adapter->num_queues; i++) { + rxr = &adapter->rx_rings[i]; + E1000_WRITE_REG(hw, E1000_RDH(i), rxr->next_to_check); + E1000_WRITE_REG(hw, E1000_RDT(i), rxr->next_to_refresh); + } +} + +/* Free all receive rings. */ +static void igb_free_receive_structures(struct adapter *adapter) +{ + struct rx_ring *rxr = adapter->rx_rings; + int i; + + for (int i = 0; i < adapter->num_queues; i++, rxr++) + igb_free_receive_buffers(rxr); + + free(adapter->rx_rings); +} + + +/* Free receive ring data structures. */ +static void igb_free_receive_buffers(struct rx_ring *rxr) +{ + struct adapter *adapter = rxr->adapter; + struct igb_rx_buffer *rxbuf; + int i; + + /* Cleanup any existing buffers */ + if (rxr->rx_buffers != NULL) { + for (i = 0; i < adapter->num_rx_desc; i++) + rxbuf = &rxr->rx_buffers[i]; + + if (rxr->rx_buffers != NULL) { + free(rxr->rx_buffers); + rxr->rx_buffers = NULL; + } + } +} + /* * Refresh mbuf buffers for RX descriptor rings * - now keeps its own state so discards due to resource @@ -1139,7 +1429,8 @@ unlock: * be recalled to try again. * */ -void igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs) +void igb_refresh_buffers(device_t *dev, u_int32_t idx, + struct igb_packet **rxbuf_packets, u_int32_t num_bufs) { struct adapter *adapter; struct igb_rx_buffer *rxbuf; @@ -1201,8 +1492,8 @@ update: * processing the packet then return the linked list of associated resources. * **********************************************************************/ -void -igb_receive(device_t *dev, u_int32_t idx, struct igb_packet **received_packets, u_int32_t count) +void igb_receive(device_t *dev, u_int32_t idx, + struct igb_packet **received_packets, u_int32_t count) { struct adapter *adapter; int first, last, done, i; @@ -1264,7 +1555,13 @@ igb_receive(device_t *dev, u_int32_t idx, struct igb_packet **received_packets, if (eop && (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { ++rxr->rx_discarded; - /* igb_rx_discard(rxr, i); XXX what does this do? shoudl we internally refresh the buffer to the end of the ring? */ + /* + * igb_rx_discard(rxr, i); + * + * XXX what does this do? + * shoudl we internally refresh the buffer + * to the end of the ring? + */ goto next_desc; } @@ -1272,7 +1569,10 @@ next_desc: /* Advance our pointers to the next descriptor. */ if (++i == adapter->num_rx_desc) i = 0; - /* add new packet to list of received packets to return XXX todo */ + /* + * add new packet to list of received packets + * to return XXX todo + */ if (rxr != NULL) { rxr->next_to_check = i; i = rxr->next_to_check; @@ -1312,7 +1612,7 @@ static inline void __sync(void) : "memory"); } -int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc) +int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc) { u_int64_t t0 = 0, t1 = -1; u_int32_t duration = -1; @@ -1770,3 +2070,119 @@ int igb_get_mac_addr(device_t *dev, u_int8_t mac_addr[ETH_ADDR_LEN]) return 0; } +int igb_setup_flex_filter(device_t *dev, unsigned int queue_id, + unsigned int filter_id, unsigned int filter_len, + u_int8_t *filter, u_int8_t *mask) +{ + struct adapter *adapter; + struct e1000_hw *hw; + int i = 0, j, k; + u32 fhft; + u32 wufc; + + if (dev == NULL) + return -EINVAL; + + adapter = (struct adapter *)dev->private_data; + if (adapter == NULL) + return -ENXIO; + + if (filter_id > 7) + return -EINVAL; + + if (queue_id > 1) + return -EINVAL; + + if (filter_len > 128) + return -EINVAL; + + hw = &adapter->hw; + + /* + * example pattern to set to match on the following in a Magic Packet + * 0x00: xx xx xx xx xx xx xx xx xx xx xx xx 08 00 45 00 + * 0x10: xx xx xx xx xx xx xx 11 xx xx xx xx xx xx xx xx + * 0x20: xx xx xx xx 00 07 00 86 xx xx ff ff ff ff ff ff + * 0x30: m0 m1 m2 m3 m4 m5 xx xx xx xx xx xx xx xx xx xx + * + * Where m0-m5 are the 6 bytes of the mac address in network order + * + * example code follows + * + * ethertype should be IP which is 0x0800 + * pattern[0x0C] = 0x08; + * pattern[0x0D] = 0x00; + + * verify IPv4 and header length 20 + * pattern[0x0E] = 0x45; + * pattern[0x0F] = 0x00; + * mask[1] = 0xF0; + + * verify L3 protocol is UDP + * pattern[0x17] = 0x11; + * mask[2] = 0x80; + + * verify source and destination port numbers + * pattern[0x24] = 0x00; + * pattern[0x25] = 0x07; + * pattern[0x26] = 0x00; + * pattern[0x27] = 0x86; + * mask[4] = 0xF0; + + * add start pattern of 6 bytes all 0xFF + * memset(&pattern[0x2a], 0xff, 6); + * mask[5] = 0xFC; + + * add mac address + * memcpy(&pattern[0x30], hw->mac.addr, 6); + * mask[6] |= 0x3F; + */ + + while (i < filter_len) { + for (j = 0; j < 8; j += 4) { + fhft = 0; + for (k = 0; k < 4; k++) + fhft |= ((u32)(filter[i + j + k])) << (k * 8); + E1000_WRITE_REG_ARRAY(hw, E1000_FHFT(filter_id), + (i/2) + (j/4), fhft); + } + E1000_WRITE_REG_ARRAY(hw, E1000_FHFT(filter_id), + (i/2) + 2, mask[i/8]); + i += 8; + } + E1000_WRITE_REG_ARRAY(hw, E1000_FHFT(filter_id), + 63, (queue_id << 8) | filter_len); + E1000_WRITE_REG(hw, E1000_WUC, 0); + + wufc = E1000_READ_REG(hw, E1000_WUFC); + wufc |= (E1000_WUFC_FLX0 << filter_id) | E1000_WUFC_FLEX_HQ; + E1000_WRITE_REG(hw, E1000_WUFC, wufc); + + return 0; +} + +int igb_clear_flex_filter(device_t *dev, unsigned int filter_id) +{ + struct adapter *adapter; + struct e1000_hw *hw; + u32 wufc; + + if (dev == NULL) + return -EINVAL; + + adapter = (struct adapter *)dev->private_data; + if (adapter == NULL) + return -ENXIO; + + if (filter_id > 7) + return -EINVAL; + + + hw = &adapter->hw; + + wufc = E1000_READ_REG(hw, E1000_WUFC); + wufc &= ~(E1000_WUFC_FLX0 << filter_id); + E1000_WRITE_REG(hw, E1000_WUFC, wufc); + + return 0; +} diff --git a/lib/igb/igb.h b/lib/igb/igb.h index b340c2ba..32da344b 100644 --- a/lib/igb/igb.h +++ b/lib/igb/igb.h @@ -77,30 +77,39 @@ struct igb_dma_alloc { unsigned int mmap_size; }; -int igb_probe( device_t *dev ); +int igb_probe(device_t *dev); int igb_attach(char *dev_path, device_t *pdev); -int igb_attach_tx( device_t *pdev ); +int igb_attach_tx(device_t *pdev); int igb_detach(device_t *dev); int igb_suspend(device_t *dev); int igb_resume(device_t *dev); int igb_init(device_t *dev); int igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *page); void igb_dma_free_page(device_t *dev, struct igb_dma_alloc *page); -int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet); -void igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs); -void igb_receive(device_t *dev, u_int32_t idx, struct igb_packet **received_packets, u_int32_t count); +int igb_xmit(device_t *dev, unsigned int queue_index, + struct igb_packet *packet); +void igb_refresh_buffers(device_t *dev, u_int32_t idx, + struct igb_packet **rxbuf_packets, u_int32_t num_bufs); +void igb_receive(device_t *dev, u_int32_t idx, + struct igb_packet **received_packets, u_int32_t count); void igb_clean(device_t *dev, struct igb_packet **cleaned_packets); int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc); -int igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, struct timespec *system_time ); -int igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, u_int32_t tpktsz_a, u_int32_t tpktsz_b); -int igb_set_class_bandwidth2(device_t *dev, u_int32_t class_a_bytes_per_second, u_int32_t class_b_bytes_per_second); - +int igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, + struct timespec *system_time); +int igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, + u_int32_t tpktsz_a, u_int32_t tpktsz_b); +int igb_set_class_bandwidth2(device_t *dev, u_int32_t class_a_bytes_per_second, + u_int32_t class_b_bytes_per_second); +int igb_setup_flex_filter(device_t *dev, unsigned int queue_id, + unsigned int filter_id, unsigned int filter_len, + u_int8_t *filter, u_int8_t *mask); +int igb_clear_flex_filter(device_t *dev, unsigned int filter_id); void igb_trigger(device_t *dev, u_int32_t data); void igb_readreg(device_t *dev, u_int32_t reg, u_int32_t *data); void igb_writereg(device_t *dev, u_int32_t reg, u_int32_t data); -int igb_lock( device_t *dev ); -int igb_unlock( device_t *dev ); +int igb_lock(device_t *dev); +int igb_unlock(device_t *dev); int igb_get_mac_addr(device_t *dev, u_int8_t mac_addr[6]); diff --git a/lib/igb/igb_internal.h b/lib/igb/igb_internal.h index 7613a661..7950a37c 100644 --- a/lib/igb/igb_internal.h +++ b/lib/igb/igb_internal.h @@ -48,9 +48,14 @@ #define ETHER_ALIGN 2 #define IGB_TX_BUFFER_SIZE ((uint32_t) 1514) -#define IGB_TX_PTHRESH 8 -#define IGB_TX_HTHRESH 1 -#define IGB_TX_WTHRESH 16 + +#define IGB_RX_PTHRESH 8 +#define IGB_RX_HTHRESH 8 +#define IGB_RX_WTHRESH 4 + +#define IGB_TX_PTHRESH 8 +#define IGB_TX_HTHRESH 1 +#define IGB_TX_WTHRESH 16 /* * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be @@ -107,7 +112,7 @@ struct tx_ring { u32 next_avail_desc; u32 next_to_clean; - volatile u16 tx_avail; + u16 tx_avail; u32 bytes; u32 packets; -- cgit v1.2.1 From ed4981e9574cd995286482f4d543c4b06f8cedb7 Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Wed, 24 Feb 2016 15:01:44 -0800 Subject: libavb: add some more rx code to libavb Add some more RX code for libavb. Signed-off-by: Todd Fujinaka --- lib/igb/igb.c | 104 +++++++++++++++++++++++++++++++++++++++++++------ lib/igb/igb_internal.h | 8 ---- 2 files changed, 92 insertions(+), 20 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 3c2ba3b8..97733e2e 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -89,9 +89,12 @@ static void igb_reset(struct adapter *adapter); static int igb_allocate_queues(struct adapter *adapter); static int igb_allocate_rx_queues(struct adapter *adapter); static void igb_setup_transmit_structures(struct adapter *adapter); +static int igb_setup_receive_structures(struct adapter *adapter); static void igb_setup_transmit_ring(struct tx_ring *txr); static void igb_initialize_transmit_units(struct adapter *adapter); +static void igb_initialize_receive_units(struct adapter *adapter); static void igb_free_transmit_structures(struct adapter *adapter); +static void igb_free_receive_structures(struct adapter *adapter); static void igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet); static void igb_free_receive_buffers(struct rx_ring *rxr); @@ -318,9 +321,9 @@ int igb_detach(device_t *dev) sem_post(adapter->memlock); - igb_free_transmit_structures(adapter); - /* XXX FIXME-ADD RX case */ igb_free_pci_resources(adapter); + igb_free_transmit_structures(adapter); + igb_free_receive_structures(adapter); err_nolock: sem_close(adapter->memlock); @@ -336,8 +339,9 @@ int igb_suspend(device_t *dev) { struct adapter *adapter; struct tx_ring *txr; + struct rx_ring *rxr; struct e1000_hw *hw; - u32 txdctl; + u32 txdctl, srrctl; int i; if (dev == NULL) @@ -347,6 +351,7 @@ int igb_suspend(device_t *dev) return -ENXIO; txr = adapter->tx_rings; + rxr = adapter->rx_rings; hw = &adapter->hw; txdctl = 0; @@ -363,7 +368,29 @@ int igb_suspend(device_t *dev) txr->queue_status = IGB_QUEUE_IDLE; } - /* XXX FIXME-ADD RX case */ + srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + + for (int i = 0; i < adapter->num_queues; i++, rxr++) { + u64 bus_addr = rxr->rxdma.paddr; + u32 rxdctl; + + E1000_WRITE_REG(hw, E1000_RDLEN(i), + adapter->num_rx_desc * + sizeof(struct e1000_rx_desc)); + E1000_WRITE_REG(hw, E1000_RDBAH(i), + (uint32_t)(bus_addr >> 32)); + E1000_WRITE_REG(hw, E1000_RDBAL(i), + (uint32_t)bus_addr); + E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl); + /* Enable this Queue */ + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); + rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; + rxdctl &= 0xFFF00000; + rxdctl |= IGB_RX_PTHRESH; + rxdctl |= IGB_RX_HTHRESH << 8; + rxdctl |= IGB_RX_WTHRESH << 16; + E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); + } if (sem_post(adapter->memlock) != 0) return errno; @@ -375,8 +402,9 @@ int igb_resume(device_t *dev) { struct adapter *adapter; struct tx_ring *txr; + struct rx_ring *rxr; struct e1000_hw *hw; - u32 txdctl; + u32 txdctl, srrctl; int i; int error; @@ -387,6 +415,7 @@ int igb_resume(device_t *dev) return -ENXIO; txr = adapter->tx_rings; + rxr = adapter->rx_rings; hw = &adapter->hw; txdctl = 0; @@ -406,7 +435,30 @@ int igb_resume(device_t *dev) txr->queue_status = IGB_QUEUE_WORKING; } - /* XXX FIXME-ADD RX case */ + srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + + for (int i = 0; i < adapter->num_queues; i++, rxr++) { + u64 bus_addr = rxr->rxdma.paddr; + u32 rxdctl; + + E1000_WRITE_REG(hw, E1000_RDLEN(i), + adapter->num_rx_desc * + sizeof(struct e1000_rx_desc)); + E1000_WRITE_REG(hw, E1000_RDBAH(i), + (uint32_t)(bus_addr >> 32)); + E1000_WRITE_REG(hw, E1000_RDBAL(i), + (uint32_t)bus_addr); + E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl); + /* Enable this Queue */ + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); + rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; + rxdctl &= 0xFFF00000; + rxdctl |= IGB_RX_PTHRESH; + rxdctl |= IGB_RX_HTHRESH << 8; + rxdctl |= IGB_RX_WTHRESH << 16; + E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); + } + if (sem_post(adapter->memlock) != 0) return errno; @@ -436,7 +488,8 @@ int igb_init(device_t *dev) igb_setup_transmit_structures(adapter); igb_initialize_transmit_units(adapter); - /* XXX FIXME-ADD RX case */ + igb_setup_receive_structures(adapter); + igb_initialize_receive_units(adapter); if (sem_post(adapter->memlock) != 0) return errno; @@ -448,8 +501,9 @@ static void igb_reset(struct adapter *adapter) { struct tx_ring *txr = adapter->tx_rings; + struct rx_ring *rxr = adapter->rx_rings; struct e1000_hw *hw = &adapter->hw; - u32 tctl, txdctl; + u32 tctl, txdctl, srrctl; int i; tctl = txdctl = 0; @@ -466,11 +520,12 @@ igb_reset(struct adapter *adapter) /* reset the descriptor head/tail */ E1000_WRITE_REG(hw, E1000_TDLEN(i), - adapter->num_tx_desc * sizeof(struct e1000_tx_desc)); + adapter->num_tx_desc * + sizeof(struct e1000_tx_desc)); E1000_WRITE_REG(hw, E1000_TDBAH(i), - (u_int32_t)(bus_addr >> 32)); + (u_int32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_TDBAL(i), - (u_int32_t)bus_addr); + (u_int32_t)bus_addr); /* Setup the HW Tx Head and Tail descriptor pointers */ E1000_WRITE_REG(hw, E1000_TDT(i), 0); @@ -479,7 +534,32 @@ igb_reset(struct adapter *adapter) txr->queue_status = IGB_QUEUE_IDLE; } - /* XXX FIXME-ADD RX case */ + srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + + /* Setup the Base and Length of the Rx Descriptor Rings */ + for (int i = 0; i < adapter->num_queues; i++, rxr++) { + u64 bus_addr = rxr->rxdma.paddr; + u32 rxdctl; + + E1000_WRITE_REG(hw, E1000_RDLEN(i), + adapter->num_rx_desc * + sizeof(struct e1000_rx_desc)); + E1000_WRITE_REG(hw, E1000_RDBAH(i), + (uint32_t)(bus_addr >> 32)); + E1000_WRITE_REG(hw, E1000_RDBAL(i), + (uint32_t)bus_addr); + E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl); + + /* Enable this Queue */ + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); + rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; + rxdctl &= 0xFFF00000; + rxdctl |= IGB_RX_PTHRESH; + rxdctl |= IGB_RX_HTHRESH << 8; + rxdctl |= IGB_RX_WTHRESH << 16; + E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); + } + } static int igb_read_mac_addr(struct e1000_hw *hw) diff --git a/lib/igb/igb_internal.h b/lib/igb/igb_internal.h index 7950a37c..6741d1af 100644 --- a/lib/igb/igb_internal.h +++ b/lib/igb/igb_internal.h @@ -141,14 +141,6 @@ struct rx_ring { u32 next_to_refresh; u32 next_to_check; struct igb_rx_buffer *rx_buffers; -#ifdef XXX_REMOVE_PACKET_SPLIT_OPTION - /* - * First/last mbuf pointers, for - * collecting multisegment RX packets. - **/ - struct mbuf *fmp; - struct mbuf *lmp; -#endif u32 bytes; u32 packets; int rdt; -- cgit v1.2.1 From 45736d6e0d5fab3b38190cd46298c1455de5a62f Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Wed, 24 Feb 2016 15:13:25 -0800 Subject: simple_rx: add simple_rx (simpler simple_talker) Add a new simple rx test program. Signed-off-by: Todd Fujinaka --- examples/simple_rx/Makefile | 20 +++ examples/simple_rx/README | 22 ++++ examples/simple_rx/simple_rx.c | 291 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 333 insertions(+) create mode 100644 examples/simple_rx/Makefile create mode 100644 examples/simple_rx/README create mode 100644 examples/simple_rx/simple_rx.c diff --git a/examples/simple_rx/Makefile b/examples/simple_rx/Makefile new file mode 100644 index 00000000..1ac891a6 --- /dev/null +++ b/examples/simple_rx/Makefile @@ -0,0 +1,20 @@ +CC?=gcc +OPT=-O2 -g +CFLAGS=$(OPT) -Wall -Wextra -Wno-parentheses +INCFLAGS=-I../../lib/igb -I../common +LDLIBS=-ligb -lpci -lrt -lm -pthread +LDFLAGS=-L../../lib/igb + +all: simple_rx + +simple_rx: simple_rx.o + +simple_rx.o: simple_rx.c + $(CC) $(CFLAGS) $(INCFLAGS) -c simple_rx.c + +%: %.o + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ + +clean: + $(RM) simple_rx + $(RM) `find . -name "*~" -o -name "*.[oa]" -o -name "\#*\#" -o -name TAGS -o -name core -o -name "*.orig"` diff --git a/examples/simple_rx/README b/examples/simple_rx/README new file mode 100644 index 00000000..1e9580da --- /dev/null +++ b/examples/simple_rx/README @@ -0,0 +1,22 @@ +EXAMPLE APPLICATIONS + +The 'simple_rx' application illustrates the various steps to receive packets +directly into a user-space AVB application. + +The simple rx application requires root permissions to execute and +attach to the driver. + sudo ./simple_rx + +To exit the app, hit Ctrl-C. The application gracefully tears down +the connection to the driver. If the application unexpectedly aborts the +kernel-mode driver also reclaims the various buffers and attempts to clean up. +The application should be able to re-initialize and use the transmit queues +without restarting the driver. + +To build the application, you need to have the pciutils library +installed. the latest version can be downloaded from: + + < ftp://ftp.kernel.org/pub/software/utils/pciutils/ >. + +Download and extract the library, and run 'make;make install;make install-lib'. + diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c new file mode 100644 index 00000000..afb72b27 --- /dev/null +++ b/examples/simple_rx/simple_rx.c @@ -0,0 +1,291 @@ +/****************************************************************************** + + Copyright (c) 2012-2016, Intel Corporation + All rights reserved. + + 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. + + 3. Neither the name of the Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. + +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "igb.h" + +#define VERSION_STR "1.0" + +#define IGB_BIND_NAMESZ (24) + +#define PKT_SZ (1514) + +/* Global variable for signal handler */ +int *halt_rx_sig; + +/* globals */ + +static const char *version_str = "simple_rx v" VERSION_STR "\n" + "Copyright (c) 2012-2016, Intel Corporation\n"; + +unsigned char glob_station_addr[] = { 0, 0, 0, 0, 0, 0 }; +unsigned char glob_stream_id[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +/* IEEE 1722 reserved address */ +unsigned char glob_l2_dest_addr[] = { 0x91, 0xE0, 0xF0, 0x00, 0x0e, 0x80 }; +unsigned char glob_l3_dest_addr[] = { 224, 0, 0, 115 }; + +void sigint_handler(int signum) +{ + printf("got SIGINT\n"); + *halt_rx_sig = signum; +} + +int pci_connect(device_t *igb_dev) +{ + char devpath[IGB_BIND_NAMESZ]; + struct pci_access *pacc; + struct pci_dev *dev; + int err; + + memset(igb_dev, 0, sizeof(device_t)); + pacc = pci_alloc(); + pci_init(pacc); + pci_scan_bus(pacc); + for (dev = pacc->devices; dev; dev = dev->next) { + pci_fill_info(dev, + PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_CLASS); + igb_dev->pci_vendor_id = dev->vendor_id; + igb_dev->pci_device_id = dev->device_id; + igb_dev->domain = dev->domain; + igb_dev->bus = dev->bus; + igb_dev->dev = dev->dev; + igb_dev->func = dev->func; + snprintf(devpath, IGB_BIND_NAMESZ, "%04x:%02x:%02x.%d", + dev->domain, dev->bus, dev->dev, dev->func); + err = igb_probe(igb_dev); + + if (err) + continue; + + printf("attaching to %s\n", devpath); + err = igb_attach(devpath, igb_dev); + if (err || igb_attach_tx(igb_dev)) { + printf("attach failed! (%s)\n", strerror(errno)); + continue; + } + goto out; + } + pci_cleanup(pacc); + return -ENXIO; + out: pci_cleanup(pacc); + return 0; +} + +void l3_to_l2_multicast(unsigned char *l2, unsigned char *l3) +{ + l2[0] = 0x1; + l2[1] = 0x0; + l2[2] = 0x5e; + l2[3] = l3[1] & 0x7F; + l2[4] = l3[2]; + l2[5] = l3[3]; +} + +int get_mac_address(char *interface) +{ + struct ifreq if_request; + int lsock; + int rc; + + lsock = socket(PF_PACKET, SOCK_RAW, htons(0x800)); + if (lsock < 0) + return -1; + + memset(&if_request, 0, sizeof(if_request)); + strncpy(if_request.ifr_name, + interface, sizeof(if_request.ifr_name) - 1); + rc = ioctl(lsock, SIOCGIFHWADDR, &if_request); + if (rc < 0) { + close(lsock); + return -1; + } + + memcpy(glob_station_addr, if_request.ifr_hwaddr.sa_data, + sizeof(glob_station_addr)); + close(lsock); + return 0; +} + +static void usage(void) +{ + fprintf(stderr, "\n" + "usage: simple_rx [-h] -i interface-name\n" + "options:\n" + " -h show this message\n" + " -i specify interface for AVB connection\n" + " -t transport equal to 2 for 1722 or 3 for RTP\n" + "\n%s\n", version_str); + exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) +{ + /* int igb_shm_fd = -1; */ + struct igb_dma_alloc a_page; + struct igb_packet *tmp_packet; + struct igb_packet *received_packets; + struct igb_packet *free_packets; + char *interface = NULL; + u_int8_t filter_mask[64]; + device_t igb_dev; + unsigned i; + int c, rc = 0; + int err; + + for (;;) { + c = getopt(argc, argv, "hi:t:"); + if (c < 0) + break; + switch (c) { + case 'h': + usage(); + break; + case 'i': + if (interface) { + printf("only one interface per daemon is supported\n"); + usage(); + } + interface = strdup(optarg); + break; + } + } + + if (optind < argc) + usage(); + + if (interface == NULL) + usage(); + + err = pci_connect(&igb_dev); + if (err) { + printf("connect failed (%s) - are you running as root?\n", + strerror(errno)); + return errno; + } + err = igb_init(&igb_dev); + if (err) { + printf("init failed (%s) - is the driver really loaded?\n", + strerror(errno)); + return errno; + } + /* + * allocate a bunch of pages and + * stitch into a linked list of igb_packets ... + */ + + free_packets = NULL; + + for (i = 0; i < 128; i++) { + tmp_packet = malloc(sizeof(struct igb_packet)); + if (tmp_packet == NULL) { + printf("failed to allocate igb_packet memory!\n"); + return errno; + } + err = igb_dma_malloc_page(&igb_dev, &a_page); + if (err) { + printf("malloc failed (%s) - out of memory?\n", + strerror(errno)); + return errno; + } + tmp_packet->dmatime = 0; + tmp_packet->attime = 0; + tmp_packet->flags = 0; + tmp_packet->map.paddr = a_page.dma_paddr; + tmp_packet->map.mmap_size = a_page.mmap_size; + tmp_packet->offset = 0; + tmp_packet->vaddr = a_page.dma_vaddr + tmp_packet->offset; + tmp_packet->len = PKT_SZ; + tmp_packet->next = NULL; + + tmp_packet->next = free_packets; + free_packets = tmp_packet; + } + + igb_refresh_buffers(&igb_dev, 0, &free_packets, 128); + + filter_mask[0] = 0x3F; /* 1st 6 bytes of destination MAC address */ + igb_setup_flex_filter(&igb_dev, 0, 0, 6, + glob_l2_dest_addr, filter_mask); + + signal(SIGINT, sigint_handler); + rc = get_mac_address(interface); + if (rc) { + printf("failed to open interface\n"); + usage(); + } + + memset(glob_stream_id, 0, sizeof(glob_stream_id)); + memcpy(glob_stream_id, glob_station_addr, sizeof(glob_station_addr)); + + *halt_rx_sig = 0; + + rc = nice(-20); + + while (*halt_rx_sig) { + received_packets = NULL; + igb_receive(&igb_dev, 0, &received_packets, 1); + + if (received_packets == NULL) + continue; + + /* print out the received packet? what do do with it? */ + printf("received a packet !\n"); + /* put back for now */ + igb_refresh_buffers(&igb_dev, 0, &received_packets, 1); + + } + rc = nice(0); + + *halt_rx_sig = 1; + + igb_clear_flex_filter(&igb_dev, 0); + igb_dma_free_page(&igb_dev, &a_page); + err = igb_detach(&igb_dev); + + return EXIT_SUCCESS; +} -- cgit v1.2.1 From 884387dedcaf26889434e0c6ac7f5b27754d4d03 Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Thu, 25 Feb 2016 15:40:09 -0800 Subject: igb_avb: build fixes Add parens and include files to fix the build. Signed-off-by: Todd Fujinaka --- kmod/igb/igb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index 0140eb55..d8bbd73b 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -10103,8 +10103,8 @@ static int __igb_notify_lookup(struct device *dev, void *data) /* look at pci string - if its me, update the adapter pointer */ printk("checking against adapter name %s\n", pci_name(adapter->pdev)); - if !(strncmp(pci_name(adapter->pdev), adapter_lookup->pci_info, - IGB_BIND_NAMESZ)) + if (!(strncmp(pci_name(adapter->pdev), adapter_lookup->pci_info, + IGB_BIND_NAMESZ))) adapter_lookup->adapter = adapter; return E1000_SUCCESS; -- cgit v1.2.1 From 5453d417955fdff5dfe46b64837443096e78908b Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Mon, 29 Feb 2016 19:02:25 -0800 Subject: libigb: fix C99-centric code Remove unneeded C99 code from for loops, mainly. Signed-off-by: Todd Fujinaka --- lib/igb/igb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 97733e2e..062d5dd9 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -370,7 +370,7 @@ int igb_suspend(device_t *dev) srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; - for (int i = 0; i < adapter->num_queues; i++, rxr++) { + for (i = 0; i < adapter->num_queues; i++, rxr++) { u64 bus_addr = rxr->rxdma.paddr; u32 rxdctl; @@ -437,7 +437,7 @@ int igb_resume(device_t *dev) srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; - for (int i = 0; i < adapter->num_queues; i++, rxr++) { + for (i = 0; i < adapter->num_queues; i++, rxr++) { u64 bus_addr = rxr->rxdma.paddr; u32 rxdctl; @@ -537,7 +537,7 @@ igb_reset(struct adapter *adapter) srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; /* Setup the Base and Length of the Rx Descriptor Rings */ - for (int i = 0; i < adapter->num_queues; i++, rxr++) { + for (i = 0; i < adapter->num_queues; i++, rxr++) { u64 bus_addr = rxr->rxdma.paddr; u32 rxdctl; @@ -1321,8 +1321,9 @@ static void igb_free_receive_ring(struct rx_ring *rxr) { struct adapter *adapter = rxr->adapter; struct igb_rx_buffer *rxbuf; + int i; - for (int i = 0; i < adapter->num_rx_desc; i++) + for (i = 0; i < adapter->num_rx_desc; i++) rxbuf = &rxr->rx_buffers[i]; } @@ -1392,7 +1393,7 @@ static void igb_initialize_receive_units(struct adapter *adapter) struct rx_ring *rxr = adapter->rx_rings; struct e1000_hw *hw = &adapter->hw; u32 rctl, rxcsum, psize, srrctl = 0; - + int i; /* * Make sure receives are disabled while setting @@ -1406,7 +1407,7 @@ static void igb_initialize_receive_units(struct adapter *adapter) rctl |= E1000_RCTL_SZ_2048; /* Setup the Base and Length of the Rx Descriptor Rings */ - for (int i = 0; i < adapter->num_queues; i++, rxr++) { + for (i = 0; i < adapter->num_queues; i++, rxr++) { u64 bus_addr = rxr->rxdma.paddr; u32 rxdctl; @@ -1462,7 +1463,7 @@ static void igb_initialize_receive_units(struct adapter *adapter) * Setup the HW Rx Head and Tail Descriptor Pointers * - needs to be after enable */ - for (int i = 0; i < adapter->num_queues; i++) { + for (i = 0; i < adapter->num_queues; i++) { rxr = &adapter->rx_rings[i]; E1000_WRITE_REG(hw, E1000_RDH(i), rxr->next_to_check); E1000_WRITE_REG(hw, E1000_RDT(i), rxr->next_to_refresh); @@ -1475,7 +1476,7 @@ static void igb_free_receive_structures(struct adapter *adapter) struct rx_ring *rxr = adapter->rx_rings; int i; - for (int i = 0; i < adapter->num_queues; i++, rxr++) + for (i = 0; i < adapter->num_queues; i++, rxr++) igb_free_receive_buffers(rxr); free(adapter->rx_rings); -- cgit v1.2.1 From fffadead1bcde0e24a07c6ca3b4ab30be152db37 Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Mon, 29 Feb 2016 19:06:43 -0800 Subject: igb_avb: fix includes for clocksource The kernel moved timesync includes around again. Signed-off-by: Todd Fujinaka --- kmod/igb/igb_ptp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 60bdeb3b..744fa654 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -34,6 +34,7 @@ #include #include #include +#include #define INCVALUE_MASK 0x7fffffff #define ISGN 0x80000000 -- cgit v1.2.1 From 4b9bb9907a6668093b420562f663c7b06c5608aa Mon Sep 17 00:00:00 2001 From: Todd Fujinaka Date: Tue, 31 May 2016 20:28:14 -0700 Subject: igb_avb: fix some bugs in the multi rx-queues This isn't finished, but works better than before. Signed-off-by: Todd Fujinaka --- examples/simple_rx/Makefile | 5 +- examples/simple_rx/simple_rx.c | 158 +++++++++++++++--- kmod/igb/igb_main.c | 4 + lib/igb/igb.c | 358 +++++++++++++++++++---------------------- lib/igb/igb.h | 8 +- 5 files changed, 321 insertions(+), 212 deletions(-) diff --git a/examples/simple_rx/Makefile b/examples/simple_rx/Makefile index 1ac891a6..86ec4b2b 100644 --- a/examples/simple_rx/Makefile +++ b/examples/simple_rx/Makefile @@ -7,11 +7,14 @@ LDFLAGS=-L../../lib/igb all: simple_rx -simple_rx: simple_rx.o +simple_rx: igb.o simple_rx.o simple_rx.o: simple_rx.c $(CC) $(CFLAGS) $(INCFLAGS) -c simple_rx.c +igb.o: ../../lib/igb/igb.c + make -C ../../igb igb.o + %: %.o $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index afb72b27..d22b9e07 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -43,8 +43,11 @@ #include #include #include +#include #include +#include + #include #include "igb.h" @@ -56,7 +59,7 @@ #define PKT_SZ (1514) /* Global variable for signal handler */ -int *halt_rx_sig; +volatile int halt_rx_sig; /* globals */ @@ -66,13 +69,14 @@ static const char *version_str = "simple_rx v" VERSION_STR "\n" unsigned char glob_station_addr[] = { 0, 0, 0, 0, 0, 0 }; unsigned char glob_stream_id[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* IEEE 1722 reserved address */ -unsigned char glob_l2_dest_addr[] = { 0x91, 0xE0, 0xF0, 0x00, 0x0e, 0x80 }; +/* unsigned char glob_l2_dest_addr[] = { 0x91, 0xE0, 0xF0, 0x00, 0x0e, 0x80 }; */ +unsigned char glob_l2_dest_addr[] = {0xa0, 0x36, 0x9f, 0x10, 0xcd, 0xe6 }; unsigned char glob_l3_dest_addr[] = { 224, 0, 0, 115 }; void sigint_handler(int signum) { printf("got SIGINT\n"); - *halt_rx_sig = signum; + halt_rx_sig = 0; } int pci_connect(device_t *igb_dev) @@ -97,17 +101,26 @@ int pci_connect(device_t *igb_dev) igb_dev->func = dev->func; snprintf(devpath, IGB_BIND_NAMESZ, "%04x:%02x:%02x.%d", dev->domain, dev->bus, dev->dev, dev->func); + err = igb_probe(igb_dev); if (err) continue; printf("attaching to %s\n", devpath); - err = igb_attach(devpath, igb_dev); - if (err || igb_attach_tx(igb_dev)) { + + if (igb_attach(devpath, igb_dev)) { printf("attach failed! (%s)\n", strerror(errno)); continue; } + if (igb_attach_tx(igb_dev)) { + printf("tx attach failed! (%s)\n", strerror(err)); + continue; + } + if (igb_attach_rx(igb_dev)) { + printf("rx attach failed! (%s)\n", strerror(err)); + continue; + } goto out; } pci_cleanup(pacc); @@ -151,6 +164,88 @@ int get_mac_address(char *interface) return 0; } +int mrpd_init_protocol_socket(u_int16_t etype, int *sock, + unsigned char *multicast_addr, char *interface) +{ + struct sockaddr_ll addr; + struct ifreq if_request; + int lsock; + int rc; + struct packet_mreq multicast_req; + + if (NULL == sock) + return -1; + if (NULL == multicast_addr) + return -1; + + memset(&multicast_req, 0, sizeof(multicast_req)); + *sock = -1; + + lsock = socket(PF_PACKET, SOCK_RAW, htons(etype)); + if (lsock < 0) + return -1; + + memset(&if_request, 0, sizeof(if_request)); + + strncpy(if_request.ifr_name, interface, sizeof(if_request.ifr_name) - 1); + + rc = ioctl(lsock, SIOCGIFHWADDR, &if_request); + if (rc < 0) { + close(lsock); + return -1; + } + + memcpy(glob_l2_dest_addr, if_request.ifr_hwaddr.sa_data, + sizeof(glob_l2_dest_addr)); + + memset(&if_request, 0, sizeof(if_request)); + + strncpy(if_request.ifr_name, interface, sizeof(if_request.ifr_name)-1); + + rc = ioctl(lsock, SIOCGIFINDEX, &if_request); + if (rc < 0) { + close(lsock); + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sll_ifindex = if_request.ifr_ifindex; + addr.sll_family = AF_PACKET; + addr.sll_protocol = htons(etype); + + rc = bind(lsock, (struct sockaddr *)&addr, sizeof(addr)); + if (0 != rc) { +#if LOG_ERRORS + fprintf(stderr, "%s - Error on bind %s", __FUNCTION__, strerror(errno)); +#endif + close(lsock); + return -1; + } + + rc = setsockopt(lsock, SOL_SOCKET, SO_BINDTODEVICE, interface, + strlen(interface)); + if (0 != rc) { + close(lsock); + return -1; + } + + multicast_req.mr_ifindex = if_request.ifr_ifindex; + multicast_req.mr_type = PACKET_MR_MULTICAST; + multicast_req.mr_alen = 6; + memcpy(multicast_req.mr_address, multicast_addr, 6); + + rc = setsockopt(lsock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, + &multicast_req, sizeof(multicast_req)); + if (0 != rc) { + close(lsock); + return -1; + } + + *sock = lsock; + + return 0; +} + static void usage(void) { fprintf(stderr, "\n" @@ -166,16 +261,18 @@ static void usage(void) int main(int argc, char *argv[]) { /* int igb_shm_fd = -1; */ - struct igb_dma_alloc a_page; - struct igb_packet *tmp_packet; struct igb_packet *received_packets; struct igb_packet *free_packets; + struct igb_packet *tmp_packet; + struct igb_dma_alloc a_page; + unsigned char test_filter[128]; char *interface = NULL; u_int8_t filter_mask[64]; device_t igb_dev; unsigned i; int c, rc = 0; int err; + int sock; for (;;) { c = getopt(argc, argv, "hi:t:"); @@ -204,33 +301,32 @@ int main(int argc, char *argv[]) err = pci_connect(&igb_dev); if (err) { printf("connect failed (%s) - are you running as root?\n", - strerror(errno)); - return errno; + strerror(err)); + return err; } err = igb_init(&igb_dev); if (err) { printf("init failed (%s) - is the driver really loaded?\n", - strerror(errno)); - return errno; + strerror(err)); + return err; } /* * allocate a bunch of pages and * stitch into a linked list of igb_packets ... */ - free_packets = NULL; for (i = 0; i < 128; i++) { tmp_packet = malloc(sizeof(struct igb_packet)); if (tmp_packet == NULL) { printf("failed to allocate igb_packet memory!\n"); - return errno; + return err; } err = igb_dma_malloc_page(&igb_dev, &a_page); if (err) { printf("malloc failed (%s) - out of memory?\n", - strerror(errno)); - return errno; + strerror(err)); + return err; } tmp_packet->dmatime = 0; tmp_packet->attime = 0; @@ -248,9 +344,33 @@ int main(int argc, char *argv[]) igb_refresh_buffers(&igb_dev, 0, &free_packets, 128); +#if 0 filter_mask[0] = 0x3F; /* 1st 6 bytes of destination MAC address */ igb_setup_flex_filter(&igb_dev, 0, 0, 6, glob_l2_dest_addr, filter_mask); +#endif + +#if 1 + memset(filter_mask, 0, sizeof(filter_mask)); + memset(test_filter, 0, sizeof(test_filter)); + + /* ethertype */ +// test_filter[0x0C] = 0x86; +// test_filter[0x0D] = 0x22; + + /* mac address */ +// test_filter[0x30] = 0xa0; +// test_filter[0x31] = 0x36; +// test_filter[0x32] = 0x9f; +// filter_mask[6] |= 0x3F; + + filter_mask[1] = 0x30; + + igb_setup_flex_filter(&igb_dev, 0, 0, 16, + test_filter, filter_mask); +#endif + + mrpd_init_protocol_socket(0x2272, &sock, glob_l2_dest_addr, interface); signal(SIGINT, sigint_handler); rc = get_mac_address(interface); @@ -262,13 +382,13 @@ int main(int argc, char *argv[]) memset(glob_stream_id, 0, sizeof(glob_stream_id)); memcpy(glob_stream_id, glob_station_addr, sizeof(glob_station_addr)); - *halt_rx_sig = 0; + halt_rx_sig = 1; rc = nice(-20); - while (*halt_rx_sig) { + while (halt_rx_sig) { received_packets = NULL; - igb_receive(&igb_dev, 0, &received_packets, 1); + igb_receive(&igb_dev, &received_packets, 1); if (received_packets == NULL) continue; @@ -281,7 +401,7 @@ int main(int argc, char *argv[]) } rc = nice(0); - *halt_rx_sig = 1; + halt_rx_sig = 0; igb_clear_flex_filter(&igb_dev, 0); igb_dma_free_page(&igb_dev, &a_page); diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index d8bbd73b..9b46fe48 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -4051,6 +4051,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, hw->fc.requested_mode == e1000_fc_rx_pause))) srrctl |= E1000_SRRCTL_DROP_EN; + /* turn off header split */ + srrctl &= 0xF3FFFFFF; + srrctl |= 0x02000000; + E1000_WRITE_REG(hw, E1000_SRRCTL(reg_idx), srrctl); /* set filtering for VMDQ pools */ diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 062d5dd9..cdd6c84e 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -89,7 +89,7 @@ static void igb_reset(struct adapter *adapter); static int igb_allocate_queues(struct adapter *adapter); static int igb_allocate_rx_queues(struct adapter *adapter); static void igb_setup_transmit_structures(struct adapter *adapter); -static int igb_setup_receive_structures(struct adapter *adapter); +static void igb_setup_receive_structures(struct adapter *adapter); static void igb_setup_transmit_ring(struct tx_ring *txr); static void igb_initialize_transmit_units(struct adapter *adapter); static void igb_initialize_receive_units(struct adapter *adapter); @@ -147,6 +147,7 @@ int igb_attach(char *dev_path, device_t *pdev) adapter = (struct adapter *)pdev->private_data; adapter->ldev = open("/dev/igb_avb", O_RDWR); + if (adapter->ldev < 0) { error = -ENXIO; goto err_prebind; @@ -154,11 +155,13 @@ int igb_attach(char *dev_path, device_t *pdev) adapter->memlock = sem_open(IGB_SEM, O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, 1); + if (adapter->memlock == ((sem_t *)SEM_FAILED)) { error = errno; close(adapter->ldev); goto err_prebind; } + if (sem_wait(adapter->memlock) != 0) { error = errno; close(adapter->ldev); @@ -189,6 +192,7 @@ int igb_attach(char *dev_path, device_t *pdev) /* Set MAC type early for PCI setup */ adapter->hw.mac.type = e1000_i210; + /* Setup PCI resources */ error = igb_allocate_pci_resources(adapter); if (error) @@ -216,18 +220,18 @@ int igb_attach(char *dev_path, device_t *pdev) return 0; - err_late: - err_pci: +err_late: +err_pci: igb_free_pci_resources(adapter); - err_bind: +err_bind: sem_post(adapter->memlock); sem_close(adapter->memlock); close(adapter->ldev); - err_prebind: +err_prebind: free(pdev->private_data); pdev->private_data = NULL; - err_gen: +err_gen: return error; } @@ -245,11 +249,9 @@ int igb_attach_tx(device_t *pdev) return -EINVAL; if (sem_wait(adapter->memlock) != 0) - return errno; + return -errno; - /* - * Allocate and Setup Queues - */ + /* Allocate and Setup Queues */ adapter->num_queues = 2; /* XXX parameterize this */ error = igb_allocate_queues(adapter); if (error) { @@ -264,9 +266,9 @@ int igb_attach_tx(device_t *pdev) */ igb_reset(adapter); - release: +release: if (sem_post(adapter->memlock) != 0) - return errno; + return -errno; return error; } @@ -297,7 +299,7 @@ int igb_attach_rx(device_t *pdev) goto release; } - release: +release: if (sem_post(adapter->memlock) != 0) return errno; @@ -325,7 +327,7 @@ int igb_detach(device_t *dev) igb_free_transmit_structures(adapter); igb_free_receive_structures(adapter); - err_nolock: +err_nolock: sem_close(adapter->memlock); close(adapter->ldev); @@ -341,7 +343,7 @@ int igb_suspend(device_t *dev) struct tx_ring *txr; struct rx_ring *rxr; struct e1000_hw *hw; - u32 txdctl, srrctl; + u32 txdctl, srrctl = 0; int i; if (dev == NULL) @@ -404,9 +406,8 @@ int igb_resume(device_t *dev) struct tx_ring *txr; struct rx_ring *rxr; struct e1000_hw *hw; - u32 txdctl, srrctl; + u32 txdctl, srrctl = 0; int i; - int error; if (dev == NULL) return -EINVAL; @@ -459,14 +460,10 @@ int igb_resume(device_t *dev) E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); } - if (sem_post(adapter->memlock) != 0) return errno; return 0; - - err_lockfail: - return error; } int igb_init(device_t *dev) @@ -503,63 +500,72 @@ igb_reset(struct adapter *adapter) struct tx_ring *txr = adapter->tx_rings; struct rx_ring *rxr = adapter->rx_rings; struct e1000_hw *hw = &adapter->hw; - u32 tctl, txdctl, srrctl; + u32 txdctl, srrctl; int i; - tctl = txdctl = 0; - - /* Setup the Tx Descriptor Rings, leave queues idle */ - for (i = 0; i < adapter->num_queues; i++, txr++) { - u64 bus_addr = txr->txdma.paddr; - - /* idle the queue */ - txdctl |= IGB_TX_PTHRESH; - txdctl |= IGB_TX_HTHRESH << 8; - txdctl |= IGB_TX_WTHRESH << 16; - E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl); - - /* reset the descriptor head/tail */ - E1000_WRITE_REG(hw, E1000_TDLEN(i), - adapter->num_tx_desc * - sizeof(struct e1000_tx_desc)); - E1000_WRITE_REG(hw, E1000_TDBAH(i), - (u_int32_t)(bus_addr >> 32)); - E1000_WRITE_REG(hw, E1000_TDBAL(i), - (u_int32_t)bus_addr); + srrctl = 0; + txdctl = 0; - /* Setup the HW Tx Head and Tail descriptor pointers */ - E1000_WRITE_REG(hw, E1000_TDT(i), 0); - E1000_WRITE_REG(hw, E1000_TDH(i), 0); + /* Set up the Tx Descriptor Rings, leave queues idle */ + if (adapter->tx_rings == NULL) + printf("txr null\n"); + else { + for (i = 0; i < adapter->num_queues; i++, txr++) { + u64 bus_addr = txr->txdma.paddr; + + /* idle the queue */ + txdctl |= IGB_TX_PTHRESH; + txdctl |= IGB_TX_HTHRESH << 8; + txdctl |= IGB_TX_WTHRESH << 16; + E1000_WRITE_REG(hw, E1000_TXDCTL(i), txdctl); + + /* reset the descriptor head/tail */ + E1000_WRITE_REG(hw, E1000_TDLEN(i), + adapter->num_tx_desc * + sizeof(struct e1000_tx_desc)); + E1000_WRITE_REG(hw, E1000_TDBAH(i), + (u_int32_t)(bus_addr >> 32)); + E1000_WRITE_REG(hw, E1000_TDBAL(i), + (u_int32_t)bus_addr); + + /* Setup the HW Tx Head and Tail descriptor pointers */ + E1000_WRITE_REG(hw, E1000_TDT(i), 0); + E1000_WRITE_REG(hw, E1000_TDH(i), 0); - txr->queue_status = IGB_QUEUE_IDLE; + txr->queue_status = IGB_QUEUE_IDLE; + } } srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; /* Setup the Base and Length of the Rx Descriptor Rings */ - for (i = 0; i < adapter->num_queues; i++, rxr++) { - u64 bus_addr = rxr->rxdma.paddr; - u32 rxdctl; + if (adapter->rx_rings == NULL) + printf("rxr null\n"); + else { - E1000_WRITE_REG(hw, E1000_RDLEN(i), - adapter->num_rx_desc * - sizeof(struct e1000_rx_desc)); - E1000_WRITE_REG(hw, E1000_RDBAH(i), - (uint32_t)(bus_addr >> 32)); - E1000_WRITE_REG(hw, E1000_RDBAL(i), - (uint32_t)bus_addr); - E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl); + for (i = 0; i < adapter->num_queues; i++, rxr++) { + u64 bus_addr = rxr->rxdma.paddr; + u32 rxdctl; - /* Enable this Queue */ - rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); - rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; - rxdctl &= 0xFFF00000; - rxdctl |= IGB_RX_PTHRESH; - rxdctl |= IGB_RX_HTHRESH << 8; - rxdctl |= IGB_RX_WTHRESH << 16; - E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); + E1000_WRITE_REG(hw, E1000_RDLEN(i), + adapter->num_rx_desc * + sizeof(struct e1000_rx_desc)); + E1000_WRITE_REG(hw, E1000_RDBAH(i), + (uint32_t)(bus_addr >> 32)); + E1000_WRITE_REG(hw, E1000_RDBAL(i), + (uint32_t)bus_addr); + E1000_WRITE_REG(hw, E1000_SRRCTL(i), srrctl); + + /* Enable this Queue */ + rxdctl = E1000_READ_REG(hw, E1000_RXDCTL(i)); + rxdctl |= E1000_RXDCTL_QUEUE_ENABLE; + rxdctl &= 0xFFF00000; + rxdctl |= IGB_RX_PTHRESH; + rxdctl |= IGB_RX_HTHRESH << 8; + rxdctl |= IGB_RX_WTHRESH << 16; + E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl); + } } - } static int igb_read_mac_addr(struct e1000_hw *hw) @@ -610,7 +616,7 @@ int igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *dma) { struct adapter *adapter; int error = 0; - struct igb_buf_cmd ubuf; + struct igb_buf_cmd ubuf; if (dev == NULL) return -EINVAL; @@ -633,7 +639,8 @@ int igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *dma) if (error < 0) { error = -ENOMEM; - goto err; } + goto err; + } dma->dma_paddr = ubuf.physaddr; dma->mmap_size = ubuf.mmap_size; @@ -680,7 +687,7 @@ void igb_dma_free_page(device_t *dev, struct igb_dma_alloc *dma) dma->dma_vaddr = NULL; dma->mmap_size = 0; - err: +err: return; } @@ -766,11 +773,7 @@ tx_fail: return error; } -/********************************************************************* - * - * Initialize a transmit ring. - * - **********************************************************************/ +/* Initialize a transmit ring. */ static void igb_setup_transmit_ring(struct tx_ring *txr) { struct adapter *adapter = txr->adapter; @@ -790,11 +793,7 @@ static void igb_setup_transmit_ring(struct tx_ring *txr) txr->tx_avail = adapter->num_tx_desc; } -/********************************************************************* - * - * Initialize all transmit rings. - * - **********************************************************************/ +/* Initialize all transmit rings. */ static void igb_setup_transmit_structures(struct adapter *adapter) { struct tx_ring *txr = adapter->tx_rings; @@ -804,19 +803,14 @@ static void igb_setup_transmit_structures(struct adapter *adapter) igb_setup_transmit_ring(txr); } -/********************************************************************* - * - * Enable transmit unit. - * - **********************************************************************/ +/*Enable transmit unit. */ static void igb_initialize_transmit_units(struct adapter *adapter) { struct tx_ring *txr = adapter->tx_rings; struct e1000_hw *hw = &adapter->hw; - u32 tctl, txdctl; + u32 txdctl; int i; - tctl = 0; txdctl = 0; /* Setup the Tx Descriptor Rings */ @@ -840,11 +834,7 @@ static void igb_initialize_transmit_units(struct adapter *adapter) } -/********************************************************************* - * - * Free all transmit rings. - * - **********************************************************************/ +/* Free all transmit rings. */ static void igb_free_transmit_structures(struct adapter *adapter) { int i; @@ -863,12 +853,7 @@ static void igb_free_transmit_structures(struct adapter *adapter) adapter->tx_rings = NULL; } - -/********************************************************************* - * - * Context Descriptor setup for VLAN or CSUM - * - **********************************************************************/ +/* Context Descriptor setup for VLAN or CSUM */ static void igb_tx_ctx_setup(struct tx_ring *txr, struct igb_packet *packet) { struct adapter *adapter = txr->adapter; @@ -1179,6 +1164,9 @@ void igb_clean(device_t *dev, struct igb_packet **cleaned_packets) done = last; while (eop_desc->upper.fields.status & E1000_TXD_STAT_DD) { + if (tx_buffer->packet) + last_reclaimed = tx_buffer->packet; + /* We clean the range of the packet */ while (first != done) { if (tx_buffer->packet) { @@ -1232,8 +1220,6 @@ void igb_clean(device_t *dev, struct igb_packet **cleaned_packets) if (txr->tx_avail >= IGB_QUEUE_THRESHOLD) txr->queue_status &= ~IGB_QUEUE_DEPLETED; } - -unlock: sem_post(adapter->memlock); } @@ -1319,28 +1305,32 @@ rx_fail: static void igb_free_receive_ring(struct rx_ring *rxr) { - struct adapter *adapter = rxr->adapter; + struct adapter *adapter = rxr->adapter; struct igb_rx_buffer *rxbuf; int i; - for (i = 0; i < adapter->num_rx_desc; i++) + for (i = 0; i < adapter->num_rx_desc; i++) { rxbuf = &rxr->rx_buffers[i]; + rxbuf->next_eop = 0; + rxbuf->packet = NULL; + } } /* Initialize a receive ring. */ -static int igb_setup_receive_ring(struct rx_ring *rxr) +static void igb_setup_receive_ring(struct rx_ring *rxr) { - struct adapter *adapter; - device_t dev; - struct igb_rx_buf *rxbuf; - int rsize, nsegs, error = 0; + struct adapter *adapter = rxr->adapter; - adapter = rxr->adapter; /* Clear the ring contents */ - sem_wait(adapter->memlock); - rsize = adapter->num_rx_desc * sizeof(union e1000_adv_rx_desc); - bzero((void *)rxr->rx_base, rsize); +// sem_wait(adapter->memlock); +// rsize = adapter->num_rx_desc * sizeof(union e1000_adv_rx_desc); +// bzero((void *)rxr->rx_base, rsize); + memset((void *)rxr->rx_base, 0, + (sizeof(union e1000_adv_rx_desc)) * adapter->num_rx_desc); + + memset(rxr->rx_buffers, 0, sizeof(struct igb_rx_buffer) * + rxr->adapter->num_rx_desc); /* Free current RX buffer structures */ igb_free_receive_ring(rxr); @@ -1351,40 +1341,23 @@ static int igb_setup_receive_ring(struct rx_ring *rxr) rxr->rx_split_packets = 0; rxr->rx_bytes = 0; - sem_post(adapter->memlock); - return 0; +// sem_post(adapter->memlock); +// return 0; -fail: - igb_free_receive_ring(rxr); - sem_post(adapter->memlock); - return error; +//fail: +// igb_free_receive_ring(rxr); +// sem_post(adapter->memlock); +// return error; } /* Initialize all receive rings. */ -static int igb_setup_receive_structures(struct adapter *adapter) +static void igb_setup_receive_structures(struct adapter *adapter) { struct rx_ring *rxr = adapter->rx_rings; - int i, j; + int i; for (i = 0; i < adapter->num_queues; i++, rxr++) - if (igb_setup_receive_ring(rxr)) - goto fail; - return 0; - -fail: - /* - * Free RX buffers allocated so far, we will only handle - * the rings that completed, the failing case will have - * cleaned up for itself. 'i' is the endpoint. - */ - for (j = 0; j < i; ++j) { - rxr = &adapter->rx_rings[j]; - sem_wait(adapter->memlock); - igb_free_receive_ring(rxr); - sem_post(adapter->memlock); - } - - return -ENOBUFS; + igb_setup_receive_ring(rxr); } /* Enable receive unit. */ @@ -1392,7 +1365,7 @@ static void igb_initialize_receive_units(struct adapter *adapter) { struct rx_ring *rxr = adapter->rx_rings; struct e1000_hw *hw = &adapter->hw; - u32 rctl, rxcsum, psize, srrctl = 0; + u32 rctl, rxcsum, srrctl = 0; int i; /* @@ -1432,17 +1405,11 @@ static void igb_initialize_receive_units(struct adapter *adapter) /* * Setup for RX MultiQueue + * Non RSS setup */ rxcsum = E1000_READ_REG(hw, E1000_RXCSUM); - - /* - * NOTE: Receive Full-Packet Checksum Offload - * is mutually exclusive with Multiqueue. However - * this is not the same as TCP/IP checksums which - * still work. - */ - rxcsum |= E1000_RXCSUM_PCSD; - + rxcsum |= E1000_RXCSUM_IPPCSE; + /* rxcsum &= ~E1000_RXCSUM_TUOFL; */ E1000_WRITE_REG(hw, E1000_RXCSUM, rxcsum); /* Setup the Receive Control Register */ @@ -1492,9 +1459,11 @@ static void igb_free_receive_buffers(struct rx_ring *rxr) /* Cleanup any existing buffers */ if (rxr->rx_buffers != NULL) { - for (i = 0; i < adapter->num_rx_desc; i++) + for (i = 0; i < adapter->num_rx_desc; i++) { rxbuf = &rxr->rx_buffers[i]; - + rxbuf->next_eop = 0; + rxbuf->packet = NULL; + } if (rxr->rx_buffers != NULL) { free(rxr->rx_buffers); rxr->rx_buffers = NULL; @@ -1513,11 +1482,10 @@ static void igb_free_receive_buffers(struct rx_ring *rxr) void igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs) { + struct igb_packet *cur_pkt; struct adapter *adapter; - struct igb_rx_buffer *rxbuf; struct rx_ring *rxr; - struct igb_packet *cur_pkt; - int i, j, bufs_used, error; + u_int32_t i, j, bufs_used; bool refreshed = FALSE; if (dev == NULL) @@ -1548,8 +1516,6 @@ void igb_refresh_buffers(device_t *dev, u_int32_t idx, bufs_used = 0; while (bufs_used < num_bufs) { - rxbuf = &rxr->rx_buffers[i]; - rxr->rx_base[i].read.pkt_addr = htole64(cur_pkt->map.paddr + cur_pkt->offset); refreshed = TRUE; /* I feel wefreshed :) */ @@ -1560,7 +1526,7 @@ void igb_refresh_buffers(device_t *dev, u_int32_t idx, j = 0; bufs_used++; } -update: + if (refreshed) /* update tail */ E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), rxr->next_to_refresh); @@ -1573,18 +1539,15 @@ update: * processing the packet then return the linked list of associated resources. * **********************************************************************/ -void igb_receive(device_t *dev, u_int32_t idx, - struct igb_packet **received_packets, u_int32_t count) +void igb_receive(device_t *dev, struct igb_packet **received_packets, + u_int32_t count) { struct adapter *adapter; - int first, last, done, i; struct rx_ring *rxr; - int processed = 0, rxdone = 0; - u32 ptype, staterr = 0; union e1000_adv_rx_desc *cur; - struct igb_rx_buffer *rxbuf; - u16 hlen, plen, hdr, vtag, pkt_info; + int i, rxdone = 0; bool eop = FALSE; + u32 staterr = 0; if (dev == NULL) return; @@ -1598,23 +1561,37 @@ void igb_receive(device_t *dev, u_int32_t idx, *received_packets = NULL; /* nothing reclaimed yet */ +#ifdef XXX_LOCK if (sem_wait(adapter->memlock) != 0) return; +#endif for (i = 0; i < adapter->num_queues; i++) { - rxr = &adapter->rx_rings[i]; + rxr = &(adapter->rx_rings[i]); /* Main clean loop - receive packets until no more * received_packets[] */ - for (i = rxr->next_to_check; count != 0;) { - cur = &rxr->rx_base[i]; + for (desc = rxr->next_to_check; count != 0;) { + cur = &(rxr->rx_base[desc]); + if (i%2) + printf("\033[2A"); + + printf("desc.status_error=%x desc.length=%x desc.vlan=%x desc.rss=%x desc.pkt_info=%x desc.hdr_info=%x\n", + cur->wb.upper.status_error, + cur->wb.upper.length, + cur->wb.upper.vlan, + cur->wb.lower.hi_dword.rss, + cur->wb.lower.lo_dword.hs_rss.pkt_info, + cur->wb.lower.lo_dword.hs_rss.hdr_info); + staterr = le32toh(cur->wb.upper.status_error); if ((staterr & E1000_RXD_STAT_DD) == 0) break; count--; cur->wb.upper.status_error = 0; + /* rxbuf = &rxr->rx_buffers[i]; plen = le16toh(cur->wb.upper.length); ptype = le32toh(cur->wb.lower.lo_dword.data) & @@ -1623,6 +1600,7 @@ void igb_receive(device_t *dev, u_int32_t idx, hdr = le16toh(cur->wb.lower.lo_dword.hs_rss.hdr_info); pkt_info = le16toh(cur->wb.lower.lo_dword.hs_rss.pkt_info); + */ eop = ((staterr & E1000_RXD_STAT_EOP) == E1000_RXD_STAT_EOP); @@ -1640,7 +1618,7 @@ void igb_receive(device_t *dev, u_int32_t idx, * igb_rx_discard(rxr, i); * * XXX what does this do? - * shoudl we internally refresh the buffer + * should we internally refresh the buffer * to the end of the ring? */ goto next_desc; @@ -1648,24 +1626,25 @@ void igb_receive(device_t *dev, u_int32_t idx, next_desc: /* Advance our pointers to the next descriptor. */ - if (++i == adapter->num_rx_desc) - i = 0; + if (++desc == adapter->num_rx_desc) + desc = 0; /* * add new packet to list of received packets * to return XXX todo */ if (rxr != NULL) { - rxr->next_to_check = i; - i = rxr->next_to_check; + rxr->next_to_check = desc; + desc = rxr->next_to_check; rxdone++; } } - rxr->next_to_check = i; + rxr->next_to_check = desc; } -unlock: +#ifdef XXX_LOCK sem_post(adapter->memlock); +#endif } #define MAX_ITER 32 @@ -1989,7 +1968,7 @@ int igb_set_class_bandwidth(device_t *dev, u_int32_t class_a, u_int32_t class_b, E1000_WRITE_REG(hw, E1000_TQAVCC(1), tqavcc1); E1000_WRITE_REG(hw, E1000_TQAVCTRL, tqavctrl); - unlock: +unlock: if (sem_post(adapter->memlock) != 0) error = errno; @@ -2127,7 +2106,7 @@ int igb_set_class_bandwidth2(device_t *dev, u_int32_t class_a_bytes_per_second, E1000_WRITE_REG(hw, E1000_TQAVCC(1), tqavcc1); E1000_WRITE_REG(hw, E1000_TQAVCTRL, tqavctrl); - unlock: +unlock: if (sem_post(adapter->memlock) != 0) error = errno; @@ -2157,9 +2136,8 @@ int igb_setup_flex_filter(device_t *dev, unsigned int queue_id, { struct adapter *adapter; struct e1000_hw *hw; - int i = 0, j, k; - u32 fhft; - u32 wufc; + u32 i = 0, j, k; + u32 fhft, wufc; if (dev == NULL) return -EINVAL; @@ -2191,31 +2169,31 @@ int igb_setup_flex_filter(device_t *dev, unsigned int queue_id, * example code follows * * ethertype should be IP which is 0x0800 - * pattern[0x0C] = 0x08; - * pattern[0x0D] = 0x00; + * filter[0x0C] = 0x08; + * filter[0x0D] = 0x00; * verify IPv4 and header length 20 - * pattern[0x0E] = 0x45; - * pattern[0x0F] = 0x00; + * filter[0x0E] = 0x45; + * filter[0x0F] = 0x00; * mask[1] = 0xF0; * verify L3 protocol is UDP - * pattern[0x17] = 0x11; + * filter[0x17] = 0x11; * mask[2] = 0x80; * verify source and destination port numbers - * pattern[0x24] = 0x00; - * pattern[0x25] = 0x07; - * pattern[0x26] = 0x00; - * pattern[0x27] = 0x86; + * filter[0x24] = 0x00; + * filter[0x25] = 0x07; + * filter[0x26] = 0x00; + * filter[0x27] = 0x86; * mask[4] = 0xF0; - * add start pattern of 6 bytes all 0xFF - * memset(&pattern[0x2a], 0xff, 6); +* add start filter of 6 bytes all 0xFF + * memset(&filter[0x2a], 0xff, 6); * mask[5] = 0xFC; * add mac address - * memcpy(&pattern[0x30], hw->mac.addr, 6); + * memcpy(&filter[0x30], hw->mac.addr, 6); * mask[6] |= 0x3F; */ @@ -2231,9 +2209,11 @@ int igb_setup_flex_filter(device_t *dev, unsigned int queue_id, (i/2) + 2, mask[i/8]); i += 8; } + E1000_WRITE_REG_ARRAY(hw, E1000_FHFT(filter_id), 63, (queue_id << 8) | filter_len); - E1000_WRITE_REG(hw, E1000_WUC, 0); + + E1000_WRITE_REG(hw, E1000_WUC, 0x21); /* XXX is this right ? */ wufc = E1000_READ_REG(hw, E1000_WUFC); wufc |= (E1000_WUFC_FLX0 << filter_id) | E1000_WUFC_FLEX_HQ; diff --git a/lib/igb/igb.h b/lib/igb/igb.h index 32da344b..51021c7e 100644 --- a/lib/igb/igb.h +++ b/lib/igb/igb.h @@ -79,6 +79,7 @@ struct igb_dma_alloc { int igb_probe(device_t *dev); int igb_attach(char *dev_path, device_t *pdev); +int igb_attach_rx(device_t *pdev); int igb_attach_tx(device_t *pdev); int igb_detach(device_t *dev); int igb_suspend(device_t *dev); @@ -89,9 +90,10 @@ void igb_dma_free_page(device_t *dev, struct igb_dma_alloc *page); int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet); void igb_refresh_buffers(device_t *dev, u_int32_t idx, - struct igb_packet **rxbuf_packets, u_int32_t num_bufs); -void igb_receive(device_t *dev, u_int32_t idx, - struct igb_packet **received_packets, u_int32_t count); + struct igb_packet **rxbuf_packets, + u_int32_t num_bufs); +void igb_receive(device_t *dev, struct igb_packet **received_packets, + u_int32_t count); void igb_clean(device_t *dev, struct igb_packet **cleaned_packets); int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc); int igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, -- cgit v1.2.1 From 19f1811baa503c5dc0543c43ad8016f1adb41ae5 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 13:59:44 +0900 Subject: igb_avb: fix compile errors --- examples/simple_rx/Makefile | 11 ++++++----- lib/igb/igb.c | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/simple_rx/Makefile b/examples/simple_rx/Makefile index 86ec4b2b..a728233b 100644 --- a/examples/simple_rx/Makefile +++ b/examples/simple_rx/Makefile @@ -1,19 +1,20 @@ CC?=gcc OPT=-O2 -g CFLAGS=$(OPT) -Wall -Wextra -Wno-parentheses -INCFLAGS=-I../../lib/igb -I../common +IGBDIR=../../lib/igb +INCFLAGS=-I$(IGBDIR) -I../common LDLIBS=-ligb -lpci -lrt -lm -pthread -LDFLAGS=-L../../lib/igb +LDFLAGS=-L$(IGBDIR) all: simple_rx -simple_rx: igb.o simple_rx.o +simple_rx: $(IGBDIR)/igb.o simple_rx.o simple_rx.o: simple_rx.c $(CC) $(CFLAGS) $(INCFLAGS) -c simple_rx.c -igb.o: ../../lib/igb/igb.c - make -C ../../igb igb.o +igb.o: $(IGBDIR)/igb.c + make -C $(IGBDIR) igb.o %: %.o $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ diff --git a/lib/igb/igb.c b/lib/igb/igb.c index cdd6c84e..678c7815 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1548,6 +1548,7 @@ void igb_receive(device_t *dev, struct igb_packet **received_packets, int i, rxdone = 0; bool eop = FALSE; u32 staterr = 0; + u32 desc = 0; if (dev == NULL) return; -- cgit v1.2.1 From 58fe9799318fe218b359210fe0f66c6936f8f54b Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 14:15:02 +0900 Subject: libigb: fix the RX descriptor type Use the Advanced descriptor one buffer type --- lib/igb/igb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 678c7815..4f21392d 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -371,6 +371,7 @@ int igb_suspend(device_t *dev) } srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; for (i = 0; i < adapter->num_queues; i++, rxr++) { u64 bus_addr = rxr->rxdma.paddr; @@ -378,7 +379,7 @@ int igb_suspend(device_t *dev) E1000_WRITE_REG(hw, E1000_RDLEN(i), adapter->num_rx_desc * - sizeof(struct e1000_rx_desc)); + sizeof(union e1000_adv_rx_desc)); E1000_WRITE_REG(hw, E1000_RDBAH(i), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_RDBAL(i), @@ -437,6 +438,7 @@ int igb_resume(device_t *dev) } srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; for (i = 0; i < adapter->num_queues; i++, rxr++) { u64 bus_addr = rxr->rxdma.paddr; @@ -444,7 +446,7 @@ int igb_resume(device_t *dev) E1000_WRITE_REG(hw, E1000_RDLEN(i), adapter->num_rx_desc * - sizeof(struct e1000_rx_desc)); + sizeof(union e1000_adv_rx_desc)); E1000_WRITE_REG(hw, E1000_RDBAH(i), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_RDBAL(i), @@ -537,6 +539,7 @@ igb_reset(struct adapter *adapter) } srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; /* Setup the Base and Length of the Rx Descriptor Rings */ if (adapter->rx_rings == NULL) @@ -549,7 +552,7 @@ igb_reset(struct adapter *adapter) E1000_WRITE_REG(hw, E1000_RDLEN(i), adapter->num_rx_desc * - sizeof(struct e1000_rx_desc)); + sizeof(union e1000_adv_rx_desc)); E1000_WRITE_REG(hw, E1000_RDBAH(i), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_RDBAL(i), @@ -1377,6 +1380,7 @@ static void igb_initialize_receive_units(struct adapter *adapter) rctl &= ~E1000_RCTL_LPE; srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT; + srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; rctl |= E1000_RCTL_SZ_2048; /* Setup the Base and Length of the Rx Descriptor Rings */ @@ -1386,7 +1390,7 @@ static void igb_initialize_receive_units(struct adapter *adapter) E1000_WRITE_REG(hw, E1000_RDLEN(i), adapter->num_rx_desc * - sizeof(struct e1000_rx_desc)); + sizeof(union e1000_adv_rx_desc)); E1000_WRITE_REG(hw, E1000_RDBAH(i), (uint32_t)(bus_addr >> 32)); E1000_WRITE_REG(hw, E1000_RDBAL(i), -- cgit v1.2.1 From ae8048419a3ff3dcee1b3a59f413512feca9bb0a Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 14:40:01 +0900 Subject: libigb: disable the RX queue during the configuration Disable the RX queue during its initialization. Otherwise unexpected packet drop could happen. --- lib/igb/igb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 4f21392d..319a5574 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -550,6 +550,9 @@ igb_reset(struct adapter *adapter) u64 bus_addr = rxr->rxdma.paddr; u32 rxdctl; + /* Disable this Queue */ + E1000_WRITE_REG(hw, E1000_RXDCTL(i), 0); + E1000_WRITE_REG(hw, E1000_RDLEN(i), adapter->num_rx_desc * sizeof(union e1000_adv_rx_desc)); @@ -1388,6 +1391,9 @@ static void igb_initialize_receive_units(struct adapter *adapter) u64 bus_addr = rxr->rxdma.paddr; u32 rxdctl; + /* Disable this Queue */ + E1000_WRITE_REG(hw, E1000_RXDCTL(i), 0); + E1000_WRITE_REG(hw, E1000_RDLEN(i), adapter->num_rx_desc * sizeof(union e1000_adv_rx_desc)); -- cgit v1.2.1 From 831aa4e97608626e7ec7c2cdd5649da8be85f14f Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 15:04:12 +0900 Subject: libigb: fix igb_receive() to return a received packet Note that currently this API can handle only one packet at a time. So it is highly recomendded that the caller side should call this API with the 3rd argument "count = 1". --- lib/igb/igb.c | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 319a5574..178eb7a7 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1343,7 +1343,7 @@ static void igb_setup_receive_ring(struct rx_ring *rxr) /* Setup our descriptor indices */ rxr->next_to_check = 0; - rxr->next_to_refresh = adapter->num_rx_desc - 1; + rxr->next_to_refresh = 0; rxr->rx_split_packets = 0; rxr->rx_bytes = 0; @@ -1526,8 +1526,12 @@ void igb_refresh_buffers(device_t *dev, u_int32_t idx, bufs_used = 0; while (bufs_used < num_bufs) { + if (!cur_pkt) + break; rxr->rx_base[i].read.pkt_addr = htole64(cur_pkt->map.paddr + cur_pkt->offset); + rxr->rx_buffers[i].packet = cur_pkt; + refreshed = TRUE; /* I feel wefreshed :) */ i = j; /* our next is precalculated */ @@ -1535,6 +1539,7 @@ void igb_refresh_buffers(device_t *dev, u_int32_t idx, if (++j == adapter->num_rx_desc) j = 0; bufs_used++; + cur_pkt = cur_pkt->next; } if (refreshed) /* update tail */ @@ -1615,26 +1620,38 @@ void igb_receive(device_t *dev, struct igb_packet **received_packets, eop = ((staterr & E1000_RXD_STAT_EOP) == E1000_RXD_STAT_EOP); - /* - * Free the frame (all segments) if we're at EOP and - * it's an error. - * - * The datasheet states that EOP + status is only valid - * for the final segment in a multi-segment frame. - */ - if (eop && - (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) { - ++rxr->rx_discarded; + if (eop) { /* - * igb_rx_discard(rxr, i); + * Free the frame (all segments) if we're at EOP and + * it's an error. * - * XXX what does this do? - * should we internally refresh the buffer - * to the end of the ring? + * The datasheet states that EOP + status is only valid + * for the final segment in a multi-segment frame. */ - goto next_desc; + if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { + ++rxr->rx_discarded; + /* + * igb_rx_discard(rxr, i); + * + * XXX what does this do? + * should we internally refresh the buffer + * to the end of the ring? + */ + printf ("discard error packet\n"); + igb_refresh_buffers(dev, i, + &rxr->rx_buffers[desc].packet, 1); + } else + { + if (!*received_packets) + *received_packets = rxr->rx_buffers[desc].packet; + rxr->rx_buffers[desc].packet->len = cur->wb.upper.length; + } + } else { + /* multi-segment frame is not supported yet */ + printf ("discard non-eop packet\n"); + igb_refresh_buffers(dev, i, + &rxr->rx_buffers[desc].packet, 1); } - next_desc: /* Advance our pointers to the next descriptor. */ if (++desc == adapter->num_rx_desc) -- cgit v1.2.1 From fa294ba6e8ae83e856d4b9dc8cdaa5e16f3bb268 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 15:24:53 +0900 Subject: libigb: fix receive rings memory leak --- lib/igb/igb.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 178eb7a7..2b1648cd 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1452,11 +1452,20 @@ static void igb_free_receive_structures(struct adapter *adapter) { struct rx_ring *rxr = adapter->rx_rings; int i; + struct igb_buf_cmd ubuf; - for (i = 0; i < adapter->num_queues; i++, rxr++) + for (i = 0; i < adapter->num_queues; i++, rxr++) { + if (rxr->rx_base) { + memset(rxr->rx_base, 0, rxr->rxdma.mmap_size); + munmap(rxr->rx_base, rxr->rxdma.mmap_size); + } + ubuf.queue = i; + ioctl(adapter->ldev, IGB_UNMAP_RX_RING, &ubuf); igb_free_receive_buffers(rxr); + } free(adapter->rx_rings); + adapter->rx_rings = NULL; } -- cgit v1.2.1 From 8262ca39f31a4ea0c374b6e9b9863761218a7eba Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 15:40:24 +0900 Subject: libigb: disable the debug messages in igb_receive() --- lib/igb/igb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 2b1648cd..5f9adee5 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1599,6 +1599,7 @@ void igb_receive(device_t *dev, struct igb_packet **received_packets, */ for (desc = rxr->next_to_check; count != 0;) { cur = &(rxr->rx_base[desc]); +#ifdef DEBUG if (i%2) printf("\033[2A"); @@ -1609,7 +1610,7 @@ void igb_receive(device_t *dev, struct igb_packet **received_packets, cur->wb.lower.hi_dword.rss, cur->wb.lower.lo_dword.hs_rss.pkt_info, cur->wb.lower.lo_dword.hs_rss.hdr_info); - +#endif staterr = le32toh(cur->wb.upper.status_error); if ((staterr & E1000_RXD_STAT_DD) == 0) break; -- cgit v1.2.1 From a5dd9fd2938d6d13f3a13ec4b58eb869381f2fe9 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 16:10:16 +0900 Subject: igb_avb: fix resource leaks in Tx and Rx rings --- kmod/igb/igb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index 9b46fe48..739bf1b2 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -10337,7 +10337,7 @@ static long igb_unmapbuf(struct file *file, void __user *arg, int ring) return -ENOENT; } - if ((ring == IGB_MAPRING) || (ring == IGB_MAP_TX_RING)) { + if ((ring == IGB_UNMAP_TX_RING)) { /* its easy to figure out what to free on the rings ... */ if (req.queue >= 3) return -EINVAL; @@ -10346,7 +10346,7 @@ static long igb_unmapbuf(struct file *file, void __user *arg, int ring) return -EINVAL; adapter->uring_tx_init &= ~(1 << req.queue); - } else if (ring == IGB_MAP_RX_RING) { + } else if (ring == IGB_UNMAP_RX_RING) { /* its easy to figure out what to free on the rings ... */ if (req.queue >= 3) return -EINVAL; -- cgit v1.2.1 From ff46d106faec78f521bac41feddb191f517bee40 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 17:39:17 +0900 Subject: simple_rx: fixed memory leaks and filter configurations --- examples/simple_rx/simple_rx.c | 118 +++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 45 deletions(-) diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index d22b9e07..36356629 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include #include @@ -57,6 +59,11 @@ #define IGB_BIND_NAMESZ (24) #define PKT_SZ (1514) +#define PKT_NUM (256) + +#ifndef ETH_P_IEEE1722 +#define ETH_P_IEEE1722 0x22F0 +#endif /* Global variable for signal handler */ volatile int halt_rx_sig; @@ -75,6 +82,7 @@ unsigned char glob_l3_dest_addr[] = { 224, 0, 0, 115 }; void sigint_handler(int signum) { + (void)signum; printf("got SIGINT\n"); halt_rx_sig = 0; } @@ -113,14 +121,14 @@ int pci_connect(device_t *igb_dev) printf("attach failed! (%s)\n", strerror(errno)); continue; } - if (igb_attach_tx(igb_dev)) { - printf("tx attach failed! (%s)\n", strerror(err)); - continue; - } if (igb_attach_rx(igb_dev)) { printf("rx attach failed! (%s)\n", strerror(err)); continue; } + if (igb_attach_tx(igb_dev)) { + printf("tx attach failed! (%s)\n", strerror(err)); + continue; + } goto out; } pci_cleanup(pacc); @@ -261,10 +269,10 @@ static void usage(void) int main(int argc, char *argv[]) { /* int igb_shm_fd = -1; */ - struct igb_packet *received_packets; - struct igb_packet *free_packets; - struct igb_packet *tmp_packet; - struct igb_dma_alloc a_page; + struct igb_packet *received_packets = NULL; + struct igb_packet *free_packets = NULL; + struct igb_packet *tmp_packet = NULL; + struct igb_dma_alloc dma_pages[PKT_NUM]; unsigned char test_filter[128]; char *interface = NULL; u_int8_t filter_mask[64]; @@ -273,6 +281,8 @@ int main(int argc, char *argv[]) int c, rc = 0; int err; int sock; + struct ethhdr *ethhdr = NULL; + u_int16_t *vlan_ethtype = NULL; for (;;) { c = getopt(argc, argv, "hi:t:"); @@ -298,6 +308,9 @@ int main(int argc, char *argv[]) if (interface == NULL) usage(); + free_packets = NULL; + memset (dma_pages, 0, sizeof(dma_pages)); + err = pci_connect(&igb_dev); if (err) { printf("connect failed (%s) - are you running as root?\n", @@ -314,61 +327,53 @@ int main(int argc, char *argv[]) * allocate a bunch of pages and * stitch into a linked list of igb_packets ... */ - free_packets = NULL; - for (i = 0; i < 128; i++) { - tmp_packet = malloc(sizeof(struct igb_packet)); - if (tmp_packet == NULL) { - printf("failed to allocate igb_packet memory!\n"); - return err; - } - err = igb_dma_malloc_page(&igb_dev, &a_page); + for (i = 0; i < PKT_NUM; i++) { + err = igb_dma_malloc_page(&igb_dev, &dma_pages[i]); if (err) { printf("malloc failed (%s) - out of memory?\n", strerror(err)); - return err; + goto exit; + } + + tmp_packet = calloc(1, sizeof(struct igb_packet)); + if (tmp_packet == NULL) { + printf("failed to allocate igb_packet memory!\n"); + err = -errno; + goto exit; } tmp_packet->dmatime = 0; tmp_packet->attime = 0; tmp_packet->flags = 0; - tmp_packet->map.paddr = a_page.dma_paddr; - tmp_packet->map.mmap_size = a_page.mmap_size; + tmp_packet->map.paddr = dma_pages[i].dma_paddr; + tmp_packet->map.mmap_size = dma_pages[i].mmap_size; tmp_packet->offset = 0; - tmp_packet->vaddr = a_page.dma_vaddr + tmp_packet->offset; + tmp_packet->vaddr = dma_pages[i].dma_vaddr + tmp_packet->offset; tmp_packet->len = PKT_SZ; - tmp_packet->next = NULL; + memset(tmp_packet->vaddr, 0, PKT_SZ); tmp_packet->next = free_packets; free_packets = tmp_packet; - } - - igb_refresh_buffers(&igb_dev, 0, &free_packets, 128); -#if 0 - filter_mask[0] = 0x3F; /* 1st 6 bytes of destination MAC address */ - igb_setup_flex_filter(&igb_dev, 0, 0, 6, - glob_l2_dest_addr, filter_mask); -#endif + igb_refresh_buffers(&igb_dev, 0, &free_packets, 1); + } -#if 1 + /* filtering example */ memset(filter_mask, 0, sizeof(filter_mask)); memset(test_filter, 0, sizeof(test_filter)); - /* ethertype */ -// test_filter[0x0C] = 0x86; -// test_filter[0x0D] = 0x22; - - /* mac address */ -// test_filter[0x30] = 0xa0; -// test_filter[0x31] = 0x36; -// test_filter[0x32] = 0x9f; -// filter_mask[6] |= 0x3F; + /* accept the IEEE1722 packets with a VLAN tag */ + ethhdr = (struct ethhdr *)test_filter; + ethhdr->h_proto = htons(ETH_P_8021Q); + + vlan_ethtype = (u_int16_t*)(test_filter + ETH_HLEN + 2); + *vlan_ethtype = htons(ETH_P_IEEE1722); filter_mask[1] = 0x30; + filter_mask[2] = 0x03; igb_setup_flex_filter(&igb_dev, 0, 0, 16, test_filter, filter_mask); -#endif mrpd_init_protocol_socket(0x2272, &sock, glob_l2_dest_addr, interface); @@ -387,6 +392,7 @@ int main(int argc, char *argv[]) rc = nice(-20); while (halt_rx_sig) { + received_packets = NULL; igb_receive(&igb_dev, &received_packets, 1); @@ -394,18 +400,40 @@ int main(int argc, char *argv[]) continue; /* print out the received packet? what do do with it? */ - printf("received a packet !\n"); + printf("received a packet ! hex dump (the first 32 bytes)\n"); + for (i = 0; i < 32; i++) { + printf ("%02x ", ((u8*)received_packets->vaddr)[i]); + } + printf ("\n\n"); + /* put back for now */ igb_refresh_buffers(&igb_dev, 0, &received_packets, 1); - } + + err = EXIT_SUCCESS; +exit: rc = nice(0); halt_rx_sig = 0; igb_clear_flex_filter(&igb_dev, 0); - igb_dma_free_page(&igb_dev, &a_page); - err = igb_detach(&igb_dev); - return EXIT_SUCCESS; + for (i = 0; i < PKT_NUM; i++) { + if (dma_pages[i].dma_paddr != 0) + igb_dma_free_page(&igb_dev, &dma_pages[i]); + } + while (free_packets) { + tmp_packet = free_packets; + free_packets = free_packets->next; + if (tmp_packet) { + free(tmp_packet); + } + } + + igb_detach(&igb_dev); + + if (interface) + free (interface); + + return err; } -- cgit v1.2.1 From ff1695f177fc4a136b314af6b8912d08edad0fe2 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 30 Jun 2016 17:43:52 +0900 Subject: simple_talker: add calling of igb_attach_rx () Current libigb expects application attaches to the RX queue even if it uses only the TX side features. This should be fixed in future. As a temporary fix this patch makes simple_talker call igb_attach_rx(). --- examples/simple_talker/simple_talker.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/simple_talker/simple_talker.c b/examples/simple_talker/simple_talker.c index 38636b90..4abc8212 100644 --- a/examples/simple_talker/simple_talker.c +++ b/examples/simple_talker/simple_talker.c @@ -383,10 +383,18 @@ int pci_connect(device_t *igb_dev) } printf("attaching to %s\n", devpath); err = igb_attach(devpath, igb_dev); - if ( err || igb_attach_tx( igb_dev )) { + if (err) { printf("attach failed! (%s)\n", strerror(errno)); continue; } + if (igb_attach_rx(igb_dev)) { + printf("rx attach failed! (%s)\n", strerror(errno)); + continue; + } + if (igb_attach_tx(igb_dev)) { + printf("tx attach failed! (%s)\n", strerror(errno)); + continue; + } goto out; } pci_cleanup(pacc); -- cgit v1.2.1 From c1e7ef4843832376d2e57f5e66bccc7c5129c831 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 7 Jul 2016 15:12:52 +0900 Subject: libigb: avoid rx initialization if rx was not attached --- lib/igb/igb.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 5f9adee5..7bbef6a9 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -325,7 +325,8 @@ int igb_detach(device_t *dev) igb_free_pci_resources(adapter); igb_free_transmit_structures(adapter); - igb_free_receive_structures(adapter); + if (adapter->rx_rings) + igb_free_receive_structures(adapter); err_nolock: sem_close(adapter->memlock); @@ -487,8 +488,10 @@ int igb_init(device_t *dev) igb_setup_transmit_structures(adapter); igb_initialize_transmit_units(adapter); - igb_setup_receive_structures(adapter); - igb_initialize_receive_units(adapter); + if (adapter->rx_rings) { + igb_setup_receive_structures(adapter); + igb_initialize_receive_units(adapter); + } if (sem_post(adapter->memlock) != 0) return errno; -- cgit v1.2.1 From 5155115f62f7f7bd980d5d28c14582b8e601fe49 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Mon, 11 Jul 2016 15:37:27 +0900 Subject: libigb: fix igb_receive() to return a linked packet list --- lib/igb/igb.c | 63 +++++++++++++++++++++++++++++++++++------------------------ lib/igb/igb.h | 4 ++-- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 7bbef6a9..002a348e 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1566,32 +1566,41 @@ void igb_refresh_buffers(device_t *dev, u_int32_t idx, * processing the packet then return the linked list of associated resources. * **********************************************************************/ -void igb_receive(device_t *dev, struct igb_packet **received_packets, - u_int32_t count) +int igb_receive(device_t *dev, struct igb_packet **received_packets, + u_int32_t *count) { struct adapter *adapter; struct rx_ring *rxr; union e1000_adv_rx_desc *cur; - int i, rxdone = 0; + int i; bool eop = FALSE; - u32 staterr = 0; - u32 desc = 0; + u_int32_t staterr = 0; + u_int32_t desc = 0; + u_int32_t max_pkt = 0; + struct igb_packet *curr_pkt = NULL; + struct igb_packet *prev_pkt = NULL; if (dev == NULL) - return; + return -EINVAL; adapter = (struct adapter *)dev->private_data; if (adapter == NULL) - return; + return -ENXIO; + + if (count == NULL) + return -EINVAL; + + max_pkt = *count; + *count = 0; if (received_packets == NULL) - return; + return -EINVAL; *received_packets = NULL; /* nothing reclaimed yet */ #ifdef XXX_LOCK if (sem_wait(adapter->memlock) != 0) - return; + return errno; #endif for (i = 0; i < adapter->num_queues; i++) { @@ -1600,7 +1609,7 @@ void igb_receive(device_t *dev, struct igb_packet **received_packets, /* Main clean loop - receive packets until no more * received_packets[] */ - for (desc = rxr->next_to_check; count != 0;) { + for (desc = rxr->next_to_check; *count < max_pkt;) { cur = &(rxr->rx_base[desc]); #ifdef DEBUG if (i%2) @@ -1617,7 +1626,6 @@ void igb_receive(device_t *dev, struct igb_packet **received_packets, staterr = le32toh(cur->wb.upper.status_error); if ((staterr & E1000_RXD_STAT_DD) == 0) break; - count--; cur->wb.upper.status_error = 0; /* @@ -1653,14 +1661,26 @@ void igb_receive(device_t *dev, struct igb_packet **received_packets, printf ("discard error packet\n"); igb_refresh_buffers(dev, i, &rxr->rx_buffers[desc].packet, 1); - } else - { - if (!*received_packets) - *received_packets = rxr->rx_buffers[desc].packet; - rxr->rx_buffers[desc].packet->len = cur->wb.upper.length; + } else { + /* + * add new packet to list of received packets + * to return + */ + curr_pkt = rxr->rx_buffers[desc].packet; + curr_pkt->len = cur->wb.upper.length; + + if (*received_packets == NULL) + *received_packets = curr_pkt; + if (prev_pkt) + prev_pkt->next = curr_pkt; + prev_pkt = curr_pkt; + (*count)++; + + ++rxr->rx_packets; } } else { /* multi-segment frame is not supported yet */ + ++rxr->rx_discarded; printf ("discard non-eop packet\n"); igb_refresh_buffers(dev, i, &rxr->rx_buffers[desc].packet, 1); @@ -1669,15 +1689,6 @@ next_desc: /* Advance our pointers to the next descriptor. */ if (++desc == adapter->num_rx_desc) desc = 0; - /* - * add new packet to list of received packets - * to return XXX todo - */ - if (rxr != NULL) { - rxr->next_to_check = desc; - desc = rxr->next_to_check; - rxdone++; - } } rxr->next_to_check = desc; @@ -1686,6 +1697,8 @@ next_desc: #ifdef XXX_LOCK sem_post(adapter->memlock); #endif + + return 0; } #define MAX_ITER 32 diff --git a/lib/igb/igb.h b/lib/igb/igb.h index 51021c7e..16e6fb30 100644 --- a/lib/igb/igb.h +++ b/lib/igb/igb.h @@ -92,8 +92,8 @@ int igb_xmit(device_t *dev, unsigned int queue_index, void igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs); -void igb_receive(device_t *dev, struct igb_packet **received_packets, - u_int32_t count); +int igb_receive(device_t *dev, struct igb_packet **received_packets, + u_int32_t *count); void igb_clean(device_t *dev, struct igb_packet **cleaned_packets); int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc); int igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, -- cgit v1.2.1 From 5c04e4b124e5eaa37ad7f5ab294f532c1af15d80 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Mon, 11 Jul 2016 16:03:17 +0900 Subject: libigb: code clean up --- lib/igb/igb.c | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 002a348e..d5dd08e6 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1332,9 +1332,6 @@ static void igb_setup_receive_ring(struct rx_ring *rxr) /* Clear the ring contents */ -// sem_wait(adapter->memlock); -// rsize = adapter->num_rx_desc * sizeof(union e1000_adv_rx_desc); -// bzero((void *)rxr->rx_base, rsize); memset((void *)rxr->rx_base, 0, (sizeof(union e1000_adv_rx_desc)) * adapter->num_rx_desc); @@ -1349,14 +1346,6 @@ static void igb_setup_receive_ring(struct rx_ring *rxr) rxr->next_to_refresh = 0; rxr->rx_split_packets = 0; rxr->rx_bytes = 0; - -// sem_post(adapter->memlock); -// return 0; - -//fail: -// igb_free_receive_ring(rxr); -// sem_post(adapter->memlock); -// return error; } /* Initialize all receive rings. */ @@ -1598,11 +1587,6 @@ int igb_receive(device_t *dev, struct igb_packet **received_packets, *received_packets = NULL; /* nothing reclaimed yet */ -#ifdef XXX_LOCK - if (sem_wait(adapter->memlock) != 0) - return errno; -#endif - for (i = 0; i < adapter->num_queues; i++) { rxr = &(adapter->rx_rings[i]); @@ -1651,13 +1635,6 @@ int igb_receive(device_t *dev, struct igb_packet **received_packets, */ if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { ++rxr->rx_discarded; - /* - * igb_rx_discard(rxr, i); - * - * XXX what does this do? - * should we internally refresh the buffer - * to the end of the ring? - */ printf ("discard error packet\n"); igb_refresh_buffers(dev, i, &rxr->rx_buffers[desc].packet, 1); @@ -1694,10 +1671,6 @@ next_desc: rxr->next_to_check = desc; } -#ifdef XXX_LOCK - sem_post(adapter->memlock); -#endif - return 0; } -- cgit v1.2.1 From 395dc8bc5cd396c905702324f353a2cb59417489 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Mon, 11 Jul 2016 18:37:20 +0900 Subject: Revert "simple_talker: add calling of igb_attach_rx ()" This reverts commit ff1695f177fc4a136b314af6b8912d08edad0fe2. --- examples/simple_talker/simple_talker.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/examples/simple_talker/simple_talker.c b/examples/simple_talker/simple_talker.c index 4abc8212..38636b90 100644 --- a/examples/simple_talker/simple_talker.c +++ b/examples/simple_talker/simple_talker.c @@ -383,18 +383,10 @@ int pci_connect(device_t *igb_dev) } printf("attaching to %s\n", devpath); err = igb_attach(devpath, igb_dev); - if (err) { + if ( err || igb_attach_tx( igb_dev )) { printf("attach failed! (%s)\n", strerror(errno)); continue; } - if (igb_attach_rx(igb_dev)) { - printf("rx attach failed! (%s)\n", strerror(errno)); - continue; - } - if (igb_attach_tx(igb_dev)) { - printf("tx attach failed! (%s)\n", strerror(errno)); - continue; - } goto out; } pci_cleanup(pacc); -- cgit v1.2.1 From d868578117b7b063b3ac5ea7af37fd4c5cc0fe76 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Tue, 12 Jul 2016 14:08:16 +0900 Subject: simple_rx: add Makefile and adopt the libigb API change --- Makefile | 9 ++++++++- examples/simple_rx/simple_rx.c | 29 ++++++++++++----------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 19cd87a9..65a1c6a5 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,14 @@ simple_listener: $(call descend,examples/$@) simple_listener_clean: - $(call descend,examples/simple_listener/,clean) + $(call descend,examples/simple_rx/,clean) + +simple_rx: + $(MAKE) lib + $(call descend,examples/$@) + +simple_rx_clean: + $(call descend,examples/simple_rx/,clean) mrp_client: $(call descend,examples/$@) diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index 36356629..92339ca6 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -76,8 +76,7 @@ static const char *version_str = "simple_rx v" VERSION_STR "\n" unsigned char glob_station_addr[] = { 0, 0, 0, 0, 0, 0 }; unsigned char glob_stream_id[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* IEEE 1722 reserved address */ -/* unsigned char glob_l2_dest_addr[] = { 0x91, 0xE0, 0xF0, 0x00, 0x0e, 0x80 }; */ -unsigned char glob_l2_dest_addr[] = {0xa0, 0x36, 0x9f, 0x10, 0xcd, 0xe6 }; +unsigned char glob_l2_dest_addr[] = { 0x91, 0xE0, 0xF0, 0x00, 0x0e, 0x80 }; unsigned char glob_l3_dest_addr[] = { 224, 0, 0, 115 }; void sigint_handler(int signum) @@ -203,9 +202,6 @@ int mrpd_init_protocol_socket(u_int16_t etype, int *sock, return -1; } - memcpy(glob_l2_dest_addr, if_request.ifr_hwaddr.sa_data, - sizeof(glob_l2_dest_addr)); - memset(&if_request, 0, sizeof(if_request)); strncpy(if_request.ifr_name, interface, sizeof(if_request.ifr_name)-1); @@ -270,7 +266,7 @@ int main(int argc, char *argv[]) { /* int igb_shm_fd = -1; */ struct igb_packet *received_packets = NULL; - struct igb_packet *free_packets = NULL; + struct igb_packet *free_packets[PKT_NUM]; struct igb_packet *tmp_packet = NULL; struct igb_dma_alloc dma_pages[PKT_NUM]; unsigned char test_filter[128]; @@ -283,6 +279,7 @@ int main(int argc, char *argv[]) int sock; struct ethhdr *ethhdr = NULL; u_int16_t *vlan_ethtype = NULL; + u_int32_t count; for (;;) { c = getopt(argc, argv, "hi:t:"); @@ -308,8 +305,8 @@ int main(int argc, char *argv[]) if (interface == NULL) usage(); - free_packets = NULL; memset (dma_pages, 0, sizeof(dma_pages)); + memset (free_packets, 0, sizeof(free_packets)); err = pci_connect(&igb_dev); if (err) { @@ -352,10 +349,11 @@ int main(int argc, char *argv[]) tmp_packet->len = PKT_SZ; memset(tmp_packet->vaddr, 0, PKT_SZ); - tmp_packet->next = free_packets; - free_packets = tmp_packet; + if (i != 0) + tmp_packet->next = free_packets[i-1]; + free_packets[i] = tmp_packet; - igb_refresh_buffers(&igb_dev, 0, &free_packets, 1); + igb_refresh_buffers(&igb_dev, 0, free_packets, 1); } /* filtering example */ @@ -394,7 +392,8 @@ int main(int argc, char *argv[]) while (halt_rx_sig) { received_packets = NULL; - igb_receive(&igb_dev, &received_packets, 1); + count = 1; + igb_receive(&igb_dev, &received_packets, &count); if (received_packets == NULL) continue; @@ -421,12 +420,8 @@ exit: for (i = 0; i < PKT_NUM; i++) { if (dma_pages[i].dma_paddr != 0) igb_dma_free_page(&igb_dev, &dma_pages[i]); - } - while (free_packets) { - tmp_packet = free_packets; - free_packets = free_packets->next; - if (tmp_packet) { - free(tmp_packet); + if (free_packets[i]) { + free(free_packets[i]); } } -- cgit v1.2.1 From b3db665789ddba61b20817f5c9c11fab9d4d78a9 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Tue, 12 Jul 2016 14:12:54 +0900 Subject: libigb: add DEBUG macro --- lib/igb/igb.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index d5dd08e6..71fb915e 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -53,6 +53,8 @@ #include "e1000_82575.h" #include "igb_internal.h" +#undef DEBUG + /********************************************************************* * PCI Device ID Table * @@ -512,9 +514,11 @@ igb_reset(struct adapter *adapter) txdctl = 0; /* Set up the Tx Descriptor Rings, leave queues idle */ - if (adapter->tx_rings == NULL) + if (adapter->tx_rings == NULL) { +#if DEBUG printf("txr null\n"); - else { +#endif + } else { for (i = 0; i < adapter->num_queues; i++, txr++) { u64 bus_addr = txr->txdma.paddr; @@ -545,9 +549,11 @@ igb_reset(struct adapter *adapter) srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF; /* Setup the Base and Length of the Rx Descriptor Rings */ - if (adapter->rx_rings == NULL) + if (adapter->rx_rings == NULL) { +#if DEBUG printf("rxr null\n"); - else { +#endif + } else { for (i = 0; i < adapter->num_queues; i++, rxr++) { u64 bus_addr = rxr->rxdma.paddr; -- cgit v1.2.1 From 75c3743c9421f4eb86dfca9af7e24a2e21b3244e Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 14 Jul 2016 15:30:18 +0900 Subject: libigb: code clean-up --- lib/igb/igb.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 71fb915e..0d525ffb 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1618,16 +1618,7 @@ int igb_receive(device_t *dev, struct igb_packet **received_packets, break; cur->wb.upper.status_error = 0; - /* - rxbuf = &rxr->rx_buffers[i]; - plen = le16toh(cur->wb.upper.length); - ptype = le32toh(cur->wb.lower.lo_dword.data) & - IGB_PKTTYPE_MASK; - vtag = le16toh(cur->wb.upper.vlan); - hdr = le16toh(cur->wb.lower.lo_dword.hs_rss.hdr_info); - pkt_info = - le16toh(cur->wb.lower.lo_dword.hs_rss.pkt_info); - */ + eop = ((staterr & E1000_RXD_STAT_EOP) == E1000_RXD_STAT_EOP); -- cgit v1.2.1 From b9baf83ea2bfe88a9ac03b6b4e177abce3f30f6d Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 14 Jul 2016 15:42:36 +0900 Subject: libigb: add a queue index parameter to igb_receive --- lib/igb/igb.c | 131 ++++++++++++++++++++++++++++++---------------------------- lib/igb/igb.h | 4 +- 2 files changed, 69 insertions(+), 66 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 0d525ffb..669dbef2 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1561,8 +1561,8 @@ void igb_refresh_buffers(device_t *dev, u_int32_t idx, * processing the packet then return the linked list of associated resources. * **********************************************************************/ -int igb_receive(device_t *dev, struct igb_packet **received_packets, - u_int32_t *count) +int igb_receive(device_t *dev, unsigned int queue_index, + struct igb_packet **received_packets, u_int32_t *count) { struct adapter *adapter; struct rx_ring *rxr; @@ -1582,6 +1582,13 @@ int igb_receive(device_t *dev, struct igb_packet **received_packets, if (adapter == NULL) return -ENXIO; + if (queue_index > adapter->num_queues) + return -EINVAL; + + rxr = &(adapter->rx_rings[queue_index]); + if (!rxr) + return -EINVAL; + if (count == NULL) return -EINVAL; @@ -1593,81 +1600,77 @@ int igb_receive(device_t *dev, struct igb_packet **received_packets, *received_packets = NULL; /* nothing reclaimed yet */ - for (i = 0; i < adapter->num_queues; i++) { - rxr = &(adapter->rx_rings[i]); - - /* Main clean loop - receive packets until no more - * received_packets[] - */ - for (desc = rxr->next_to_check; *count < max_pkt;) { - cur = &(rxr->rx_base[desc]); + /* Main clean loop - receive packets until no more + * received_packets[] + */ + for (desc = rxr->next_to_check; *count < max_pkt;) { + cur = &(rxr->rx_base[desc]); #ifdef DEBUG - if (i%2) - printf("\033[2A"); - - printf("desc.status_error=%x desc.length=%x desc.vlan=%x desc.rss=%x desc.pkt_info=%x desc.hdr_info=%x\n", - cur->wb.upper.status_error, - cur->wb.upper.length, - cur->wb.upper.vlan, - cur->wb.lower.hi_dword.rss, - cur->wb.lower.lo_dword.hs_rss.pkt_info, - cur->wb.lower.lo_dword.hs_rss.hdr_info); + if (i%2) + printf("\033[2A"); + + printf("desc.status_error=%x desc.length=%x desc.vlan=%x desc.rss=%x desc.pkt_info=%x desc.hdr_info=%x\n", + cur->wb.upper.status_error, + cur->wb.upper.length, + cur->wb.upper.vlan, + cur->wb.lower.hi_dword.rss, + cur->wb.lower.lo_dword.hs_rss.pkt_info, + cur->wb.lower.lo_dword.hs_rss.hdr_info); #endif - staterr = le32toh(cur->wb.upper.status_error); - if ((staterr & E1000_RXD_STAT_DD) == 0) - break; + staterr = le32toh(cur->wb.upper.status_error); + if ((staterr & E1000_RXD_STAT_DD) == 0) + break; - cur->wb.upper.status_error = 0; + cur->wb.upper.status_error = 0; - eop = ((staterr & E1000_RXD_STAT_EOP) == - E1000_RXD_STAT_EOP); + eop = ((staterr & E1000_RXD_STAT_EOP) == + E1000_RXD_STAT_EOP); - if (eop) { + if (eop) { + /* + * Free the frame (all segments) if we're at EOP and + * it's an error. + * + * The datasheet states that EOP + status is only valid + * for the final segment in a multi-segment frame. + */ + if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { + ++rxr->rx_discarded; + printf ("discard error packet\n"); + igb_refresh_buffers(dev, i, + &rxr->rx_buffers[desc].packet, 1); + } else { /* - * Free the frame (all segments) if we're at EOP and - * it's an error. - * - * The datasheet states that EOP + status is only valid - * for the final segment in a multi-segment frame. + * add new packet to list of received packets + * to return */ - if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { - ++rxr->rx_discarded; - printf ("discard error packet\n"); - igb_refresh_buffers(dev, i, - &rxr->rx_buffers[desc].packet, 1); - } else { - /* - * add new packet to list of received packets - * to return - */ - curr_pkt = rxr->rx_buffers[desc].packet; - curr_pkt->len = cur->wb.upper.length; + curr_pkt = rxr->rx_buffers[desc].packet; + curr_pkt->len = cur->wb.upper.length; - if (*received_packets == NULL) - *received_packets = curr_pkt; - if (prev_pkt) - prev_pkt->next = curr_pkt; - prev_pkt = curr_pkt; - (*count)++; + if (*received_packets == NULL) + *received_packets = curr_pkt; + if (prev_pkt) + prev_pkt->next = curr_pkt; + prev_pkt = curr_pkt; + (*count)++; - ++rxr->rx_packets; - } - } else { - /* multi-segment frame is not supported yet */ - ++rxr->rx_discarded; - printf ("discard non-eop packet\n"); - igb_refresh_buffers(dev, i, - &rxr->rx_buffers[desc].packet, 1); + ++rxr->rx_packets; } -next_desc: - /* Advance our pointers to the next descriptor. */ - if (++desc == adapter->num_rx_desc) - desc = 0; + } else { + /* multi-segment frame is not supported yet */ + ++rxr->rx_discarded; + printf ("discard non-eop packet\n"); + igb_refresh_buffers(dev, i, + &rxr->rx_buffers[desc].packet, 1); } - - rxr->next_to_check = desc; +next_desc: + /* Advance our pointers to the next descriptor. */ + if (++desc == adapter->num_rx_desc) + desc = 0; } + rxr->next_to_check = desc; + return 0; } diff --git a/lib/igb/igb.h b/lib/igb/igb.h index 16e6fb30..b8c33bb7 100644 --- a/lib/igb/igb.h +++ b/lib/igb/igb.h @@ -92,8 +92,8 @@ int igb_xmit(device_t *dev, unsigned int queue_index, void igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs); -int igb_receive(device_t *dev, struct igb_packet **received_packets, - u_int32_t *count); +int igb_receive(device_t *dev, unsigned int queue_index, + struct igb_packet **received_packets, u_int32_t *count); void igb_clean(device_t *dev, struct igb_packet **cleaned_packets); int igb_get_wallclock(device_t *dev, u_int64_t *curtime, u_int64_t *rdtsc); int igb_gettime(device_t *dev, clockid_t clk_id, u_int64_t *curtime, -- cgit v1.2.1 From 676ace98b864efd244dd5c8ef456e5f83857ff4a Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Thu, 14 Jul 2016 22:47:42 +0900 Subject: simple_rx: re-implemented based on simple_talker with the new igb RX API --- Makefile | 4 +- examples/simple_rx/Makefile | 22 +- examples/simple_rx/README | 2 +- examples/simple_rx/simple_rx.c | 889 +++++++++++++++++++++++++++++------------ 4 files changed, 653 insertions(+), 264 deletions(-) diff --git a/Makefile b/Makefile index 65a1c6a5..7cfff1bb 100644 --- a/Makefile +++ b/Makefile @@ -124,10 +124,10 @@ avtp_pipeline_doc: lib $(MAKE) -s -C lib/avtp_pipeline -f avtp_pipeline.mk doc examples_all: simple_talker simple_listener mrp_client live_stream jackd-talker \ - jackd-listener + jackd-listener simple_rx examples_all_clean: simple_talker_clean simple_listener_clean mrp_client_clean \ - jackd-talker_clean jackd-listener_clean live_stream_clean + jackd-talker_clean jackd-listener_clean live_stream_clean simple_rx_clean all: igb lib daemons_all examples_all avtp_pipeline diff --git a/examples/simple_rx/Makefile b/examples/simple_rx/Makefile index a728233b..e15601ea 100644 --- a/examples/simple_rx/Makefile +++ b/examples/simple_rx/Makefile @@ -1,24 +1,26 @@ -CC?=gcc -OPT=-O2 -g -CFLAGS=$(OPT) -Wall -Wextra -Wno-parentheses -IGBDIR=../../lib/igb -INCFLAGS=-I$(IGBDIR) -I../common -LDLIBS=-ligb -lpci -lrt -lm -pthread -LDFLAGS=-L$(IGBDIR) +CC ?= gcc +OPT = -O2 -g +CFLAGS = $(OPT) -Wall -Wextra -Wno-parentheses +IGBDIR = ../../lib/igb +INCFLAGS = -I../../daemons/mrpd -I../common -I../../daemons/common -I$(IGBDIR) +LDLIBS = -lpcap -lsndfile -pthread -lpci all: simple_rx -simple_rx: $(IGBDIR)/igb.o simple_rx.o +simple_rx: simple_rx.o ../common/listener_mrp_client.o $(IGBDIR)/igb.o simple_rx.o: simple_rx.c $(CC) $(CFLAGS) $(INCFLAGS) -c simple_rx.c -igb.o: $(IGBDIR)/igb.c +../common/listener_mrp_client.o: ../common/listener_mrp_client.c ../common/listener_mrp_client.h + make -C ../common/ listener_mrp_client.o + +$(IGBDIR)/igb.o: $(IGBDIR)/igb.c make -C $(IGBDIR) igb.o %: %.o $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ clean: - $(RM) simple_rx + $(RM) simple_listener $(RM) `find . -name "*~" -o -name "*.[oa]" -o -name "\#*\#" -o -name TAGS -o -name core -o -name "*.orig"` diff --git a/examples/simple_rx/README b/examples/simple_rx/README index 1e9580da..bc15390c 100644 --- a/examples/simple_rx/README +++ b/examples/simple_rx/README @@ -5,7 +5,7 @@ directly into a user-space AVB application. The simple rx application requires root permissions to execute and attach to the driver. - sudo ./simple_rx + sudo ./simple_rx -i enp3s0 -f out.wav To exit the app, hit Ctrl-C. The application gracefully tears down the connection to the driver. If the application unexpectedly aborts the diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index 92339ca6..caf387ea 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -1,6 +1,29 @@ +/* +Copyright (c) 2013 Katja Rohloff + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + /****************************************************************************** - Copyright (c) 2012-2016, Intel Corporation + Copyright (c) 2016, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,58 +55,239 @@ ******************************************************************************/ #include -#include -#include #include -#include -#include -#include -#include + +#include +#include + +#include +#include +#include +#include + #include -#include #include #include #include #include #include -#include - -#include - -#include #include "igb.h" +#include "listener_mrp_client.h" -#define VERSION_STR "1.0" +#define DEBUG 0 +#define PCAP 0 +#define LIBSND 1 +#define DIRECT_RX 1 + +#if DIRECT_RX +#undef PCAP +#endif +#define VERSION_STR "1.1" + +#define ETHERNET_HEADER_SIZE (18) +#define SEVENTEEN22_HEADER_PART1_SIZE (4) +#define STREAM_ID_SIZE (8) +#define SEVENTEEN22_HEADER_PART2_SIZE (10) +#define SIX1883_HEADER_SIZE (10) +#define HEADER_SIZE (ETHERNET_HEADER_SIZE \ + + SEVENTEEN22_HEADER_PART1_SIZE \ + + STREAM_ID_SIZE \ + + SEVENTEEN22_HEADER_PART2_SIZE \ + + SIX1883_HEADER_SIZE) +#define SAMPLES_PER_SECOND (48000) +#define SAMPLES_PER_FRAME (6) +#define CHANNELS (2) + +#if DIRECT_RX #define IGB_BIND_NAMESZ (24) +#define IGB_QUEUE_0 (0) -#define PKT_SZ (1514) -#define PKT_NUM (256) +#define PKT_SZ (2048) +#define PKT_NUM (256) #ifndef ETH_P_IEEE1722 #define ETH_P_IEEE1722 0x22F0 #endif +struct myqelem { + struct myqelem *q_forw; + struct myqelem *q_back; + void *q_data; +}; +#endif /* DIRECT_RX */ + +struct mrp_listener_ctx *ctx_sig;//Context pointer for signal handler + +struct ethernet_header{ + u_char dst[6]; + u_char src[6]; + u_char stuff[4]; + u_char type[2]; +}; + +/* globals */ + +static const char *version_str = "simple_listener v" VERSION_STR "\n" + "Copyright (c) 2012, Intel Corporation\n"; + +pcap_t* glob_pcap_handle; +u_char glob_ether_type[] = { 0x22, 0xf0 }; +SNDFILE* glob_snd_file; + +#if DIRECT_RX /* Global variable for signal handler */ volatile int halt_rx_sig; -/* globals */ +struct myqelem *glob_pkt_head = NULL; +struct myqelem *glob_page_head = NULL; +struct igb_packet *glob_rx_packets[PKT_NUM]; +struct igb_dma_alloc glob_dma_pages[PKT_NUM]; -static const char *version_str = "simple_rx v" VERSION_STR "\n" - "Copyright (c) 2012-2016, Intel Corporation\n"; +/* used to configure the device to accept multicast packets */ +int glob_sock = -1; -unsigned char glob_station_addr[] = { 0, 0, 0, 0, 0, 0 }; -unsigned char glob_stream_id[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -/* IEEE 1722 reserved address */ -unsigned char glob_l2_dest_addr[] = { 0x91, 0xE0, 0xF0, 0x00, 0x0e, 0x80 }; -unsigned char glob_l3_dest_addr[] = { 224, 0, 0, 115 }; +void igb_stop_rx(device_t *igb_dev); +void cleanup(void); +#endif /* DIRECT_RX */ + +static void help() +{ + fprintf(stderr, "\n" + "Usage: listener [-h] -i interface -f file_name.wav" + "\n" + "Options:\n" + " -h show this message\n" + " -i specify interface for AVB connection\n" + " -f set the name of the output wav-file\n" + "\n" "%s" "\n", version_str); + exit(EXIT_FAILURE); +} + +void pcap_callback(u_char* args, const struct pcap_pkthdr* packet_header, const u_char* packet) +{ + unsigned char* test_stream_id; + struct ethernet_header* eth_header; + uint32_t *buf; + uint32_t frame[2] = { 0 , 0 }; + int i; + struct mrp_listener_ctx *ctx = (struct mrp_listener_ctx*) args; + (void) packet_header; /* unused */ + +#if DEBUG + fprintf(stdout,"Got packet.\n"); +#endif /* DEBUG*/ + + eth_header = (struct ethernet_header*)(packet); + +#if DEBUG + fprintf(stdout,"Ether Type: 0x%02x%02x\n", eth_header->type[0], eth_header->type[1]); +#endif /* DEBUG*/ + + if (0 == memcmp(glob_ether_type,eth_header->type,sizeof(eth_header->type))) + { + test_stream_id = (unsigned char*)(packet + ETHERNET_HEADER_SIZE + SEVENTEEN22_HEADER_PART1_SIZE); + +#if DEBUG + fprintf(stderr, "Received stream id: %02x%02x%02x%02x%02x%02x%02x%02x\n ", + test_stream_id[0], test_stream_id[1], + test_stream_id[2], test_stream_id[3], + test_stream_id[4], test_stream_id[5], + test_stream_id[6], test_stream_id[7]); +#endif /* DEBUG*/ + + if (0 == memcmp(test_stream_id, ctx->stream_id, sizeof(STREAM_ID_SIZE))) + { + +#if DEBUG + fprintf(stdout,"Stream ids matched.\n"); +#endif /* DEBUG*/ + buf = (uint32_t*) (packet + HEADER_SIZE); + for(i = 0; i < SAMPLES_PER_FRAME * CHANNELS; i += 2) + { + memcpy(&frame[0], &buf[i], sizeof(frame)); + + frame[0] = ntohl(frame[0]); /* convert to host-byte order */ + frame[1] = ntohl(frame[1]); + frame[0] &= 0x00ffffff; /* ignore leading label */ + frame[1] &= 0x00ffffff; + frame[0] <<= 8; /* left-align remaining PCM-24 sample */ + frame[1] <<= 8; + + sf_writef_int(glob_snd_file, (const int *)frame, 1); + } + } + } +} void sigint_handler(int signum) { - (void)signum; - printf("got SIGINT\n"); + fprintf(stdout,"Received signal %d:leaving...\n", signum); + +#if PCAP + if (NULL != glob_pcap_handle) + { + pcap_breakloop(glob_pcap_handle); + pcap_close(glob_pcap_handle); + } +#endif /* PCAP */ + +#if DIRECT_RX halt_rx_sig = 0; +#endif /* DIRECT_RX */ +} + +#if DIRECT_RX +int join_mcast(char *interface, struct mrp_listener_ctx *ctx) +{ + struct sockaddr_ll addr; + struct ifreq if_request; + int rc; + struct packet_mreq multicast_req; + + if (NULL == ctx) + return -1; + + glob_sock = socket(PF_PACKET, SOCK_RAW, htons(0x2272)); + if (glob_sock < 0) + return -1; + + memset(&if_request, 0, sizeof(if_request)); + strncpy(if_request.ifr_name, interface, sizeof(if_request.ifr_name)-1); + + rc = ioctl(glob_sock, SIOCGIFINDEX, &if_request); + if (rc < 0) { + /* glob_sock will be closed by cleanup() */ + return -1; + } + + memset(&addr, 0, sizeof(addr)); + addr.sll_ifindex = if_request.ifr_ifindex; + addr.sll_family = AF_PACKET; + addr.sll_protocol = htons(0x2272); + + rc = bind(glob_sock, (struct sockaddr *)&addr, sizeof(addr)); + if (0 != rc) + return -1; + + rc = setsockopt(glob_sock, SOL_SOCKET, SO_BINDTODEVICE, interface, + strlen(interface)); + if (0 != rc) + return -1; + + memset(&multicast_req, 0, sizeof(multicast_req)); + multicast_req.mr_ifindex = if_request.ifr_ifindex; + multicast_req.mr_type = PACKET_MR_MULTICAST; + multicast_req.mr_alen = 6; + memcpy(multicast_req.mr_address, (void*)ctx->dst_mac, 6); + + rc = setsockopt(glob_sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, + &multicast_req, sizeof(multicast_req)); + if (0 != rc) + return -1; + + return 0; } int pci_connect(device_t *igb_dev) @@ -132,303 +336,486 @@ int pci_connect(device_t *igb_dev) } pci_cleanup(pacc); return -ENXIO; - out: pci_cleanup(pacc); +out: + pci_cleanup(pacc); return 0; } -void l3_to_l2_multicast(unsigned char *l2, unsigned char *l3) +int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) { - l2[0] = 0x1; - l2[1] = 0x0; - l2[2] = 0x5e; - l2[3] = l3[1] & 0x7F; - l2[4] = l3[2]; - l2[5] = l3[3]; + int rc = -1; + int err; + + uint32_t i; + uint32_t count = 0; + + struct myqelem *page_qelem = NULL; + struct myqelem *prev_page_qelem = NULL; + struct myqelem *pkt_qelem = NULL; + struct myqelem *prev_pkt_qelem = NULL; + + struct igb_dma_alloc *a_page = NULL; + struct igb_packet *a_packet = NULL; + + uint8_t test_filter[128]; + uint8_t filter_mask[64]; + struct ethhdr *ethhdr = NULL; + uint16_t *ethtype = NULL; + + if (0 != pci_connect(igb_dev)) + goto out; + + if (0 != igb_init(igb_dev)) + goto out; + + memset (glob_dma_pages, 0, sizeof(glob_dma_pages)); + memset (glob_rx_packets, 0, sizeof(glob_rx_packets)); + + while (count < PKT_NUM) { + page_qelem = calloc(1, sizeof(struct myqelem)); + if (!page_qelem) + goto out; + + if (!glob_page_head) + glob_page_head = page_qelem; + + a_page = (struct igb_dma_alloc*)calloc(1, sizeof(struct igb_dma_alloc)); + if (!a_page) + goto out; + + err = igb_dma_malloc_page(igb_dev, a_page); + if (err) { + printf("malloc failed (%s) - out of memory?\n", + strerror(err)); + goto out; + } + + if (a_page->mmap_size < PKT_SZ) + goto out; + + page_qelem->q_data = (void*)a_page; + insque(page_qelem, prev_page_qelem); + prev_page_qelem = page_qelem; + + /* divide the dma page into buffers for packets */ + for (i = 0; i < a_page->mmap_size/PKT_SZ; i++) { + pkt_qelem = calloc(1, sizeof(struct myqelem)); + if (!pkt_qelem) + goto out; + + if (!glob_pkt_head) + glob_pkt_head = pkt_qelem; + + a_packet = (struct igb_packet*)calloc(1, sizeof(struct igb_packet)); + if (a_packet == NULL) { + printf("failed to allocate igb_packet memory!\n"); + err = -errno; + goto out; + } + + a_packet->dmatime = 0; + a_packet->attime = 0; + a_packet->flags = 0; + a_packet->map.paddr = a_page->dma_paddr; + a_packet->map.mmap_size = a_page->mmap_size; + a_packet->offset = (i * PKT_SZ); + a_packet->vaddr = a_page->dma_vaddr + a_packet->offset; + a_packet->len = PKT_SZ; + memset(a_packet->vaddr, 0, a_packet->len); + if (prev_pkt_qelem) + ((struct igb_packet*)prev_pkt_qelem->q_data)->next = a_packet; + + igb_refresh_buffers(igb_dev, IGB_QUEUE_0, &a_packet, 1); + + pkt_qelem->q_data = (void*)a_packet; + insque(pkt_qelem, prev_pkt_qelem); + prev_pkt_qelem = pkt_qelem; + + count++; + } + } + + /* filtering example */ + memset(filter_mask, 0, sizeof(filter_mask)); + memset(test_filter, 0, sizeof(test_filter)); + + /* the filter for IEEE1722 w/o a VLAN tag */ + + /* accept packets toward the dst mac */ + ethhdr = (struct ethhdr *)test_filter; + memcpy((void*)ethhdr->h_dest, (void*)ctx->dst_mac, ETH_ALEN); + + /* ethtype in ethernet frame = IEEE1722 */ + ethhdr->h_proto = htons(ETH_P_IEEE1722); + + filter_mask[0] = 0x3F; /* 00111111b = dst mac */ + filter_mask[1] = 0x30; /* 00110000b = ethtype */ + + /* install the filter on queue0 */ + igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 0, ETH_HLEN, + test_filter, filter_mask); + + /* the filter for IEEE1722 with VLAN */ + + /* ethtype in ethernet frame = 802.1Q */ + ethhdr->h_proto = htons(ETH_P_8021Q); + + /* real ethtype = IEEE1722 */ + ethtype = (uint16_t*)(test_filter + ETH_HLEN + 2); + *ethtype = htons(ETH_P_IEEE1722); + + filter_mask[2] = 0x03; /* 00000011b = ethtype after a vlan tag */ + + /* install the filter on queue0 */ + igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 1, ETHERNET_HEADER_SIZE, + test_filter, filter_mask); + + rc = 0; +out: + if (rc != 0) + igb_stop_rx(igb_dev); + + return rc; } -int get_mac_address(char *interface) +void igb_stop_rx(device_t *igb_dev) { - struct ifreq if_request; - int lsock; - int rc; + struct myqelem *qelem = NULL; - lsock = socket(PF_PACKET, SOCK_RAW, htons(0x800)); - if (lsock < 0) - return -1; + igb_clear_flex_filter(igb_dev, 0); + igb_clear_flex_filter(igb_dev, 1); - memset(&if_request, 0, sizeof(if_request)); - strncpy(if_request.ifr_name, - interface, sizeof(if_request.ifr_name) - 1); - rc = ioctl(lsock, SIOCGIFHWADDR, &if_request); - if (rc < 0) { - close(lsock); - return -1; + while (glob_pkt_head) { + qelem = glob_pkt_head; + glob_pkt_head = qelem->q_forw; + if (qelem->q_data) + free(qelem->q_data); + free(qelem); } - memcpy(glob_station_addr, if_request.ifr_hwaddr.sa_data, - sizeof(glob_station_addr)); - close(lsock); - return 0; + while (glob_page_head) { + qelem = glob_page_head; + glob_page_head = qelem->q_forw; + if (qelem->q_data){ + igb_dma_free_page(igb_dev, (struct igb_dma_alloc*)qelem->q_data); + free(qelem->q_data); + } + free(qelem); + } + + igb_detach(igb_dev); } -int mrpd_init_protocol_socket(u_int16_t etype, int *sock, - unsigned char *multicast_addr, char *interface) +void igb_process_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) { - struct sockaddr_ll addr; - struct ifreq if_request; - int lsock; - int rc; - struct packet_mreq multicast_req; + uint32_t i; + uint32_t count; + uint8_t *packet; + uint32_t *buf; + uint32_t frame[2] = { 0 , 0 }; + uint8_t *test_stream_id; - if (NULL == sock) - return -1; - if (NULL == multicast_addr) - return -1; + struct igb_packet *igb_pkt = NULL; + struct ethhdr* eth_hdr; + uint16_t *ethtype = NULL; - memset(&multicast_req, 0, sizeof(multicast_req)); - *sock = -1; + halt_rx_sig = 1; - lsock = socket(PF_PACKET, SOCK_RAW, htons(etype)); - if (lsock < 0) - return -1; + while (halt_rx_sig) { - memset(&if_request, 0, sizeof(if_request)); + /* put back */ + if (igb_pkt) { + igb_refresh_buffers(igb_dev, IGB_QUEUE_0, &igb_pkt, 1); + igb_pkt = NULL; + } - strncpy(if_request.ifr_name, interface, sizeof(if_request.ifr_name) - 1); + count = 1; + igb_receive(igb_dev, IGB_QUEUE_0, &igb_pkt, &count); + if (igb_pkt == NULL) { + continue; + } - rc = ioctl(lsock, SIOCGIFHWADDR, &if_request); - if (rc < 0) { - close(lsock); - return -1; - } + packet = igb_pkt->vaddr; + eth_hdr = (struct ethhdr*)(packet); + switch (htons(eth_hdr->h_proto)) { + case ETH_P_8021Q: + ethtype = (uint16_t*)(packet + ETH_HLEN + 2); + if (*ethtype != htons(ETH_P_IEEE1722)) + continue; /* drop the packet */ + break; + case ETH_P_IEEE1722: + break; + default: + continue; /* drop the packet */ + break; + } - memset(&if_request, 0, sizeof(if_request)); + test_stream_id = (uint8_t*)(packet + ETHERNET_HEADER_SIZE + + SEVENTEEN22_HEADER_PART1_SIZE); + buf = (uint32_t*)(packet + HEADER_SIZE); - strncpy(if_request.ifr_name, interface, sizeof(if_request.ifr_name)-1); + if (ETH_P_IEEE1722 == htons(eth_hdr->h_proto)) { + /* I210 would strip the VLAN tag field when CTRL.VME = 1b */ + /* pull 4 bytes the VLAN tag size */ + test_stream_id = ((uint8_t*)test_stream_id - 4); + buf = ((uint32_t*)buf - 1); + } - rc = ioctl(lsock, SIOCGIFINDEX, &if_request); - if (rc < 0) { - close(lsock); - return -1; - } + if (0 == memcmp(test_stream_id, ctx->stream_id, STREAM_ID_SIZE)) + { + for(i = 0; i < SAMPLES_PER_FRAME * CHANNELS; i += 2) + { + memcpy(&frame[0], &buf[i], sizeof(frame)); - memset(&addr, 0, sizeof(addr)); - addr.sll_ifindex = if_request.ifr_ifindex; - addr.sll_family = AF_PACKET; - addr.sll_protocol = htons(etype); + frame[0] = ntohl(frame[0]); /* convert to host-byte order */ + frame[1] = ntohl(frame[1]); + frame[0] &= 0x00ffffff; /* ignore leading label */ + frame[1] &= 0x00ffffff; + frame[0] <<= 8; /* left-align remaining PCM-24 sample */ + frame[1] <<= 8; - rc = bind(lsock, (struct sockaddr *)&addr, sizeof(addr)); - if (0 != rc) { -#if LOG_ERRORS - fprintf(stderr, "%s - Error on bind %s", __FUNCTION__, strerror(errno)); -#endif - close(lsock); - return -1; + sf_writef_int(glob_snd_file, (const int *)frame, 1); + } + } } +} - rc = setsockopt(lsock, SOL_SOCKET, SO_BINDTODEVICE, interface, - strlen(interface)); - if (0 != rc) { - close(lsock); - return -1; - } +void cleanup(void) +{ + int ret; - multicast_req.mr_ifindex = if_request.ifr_ifindex; - multicast_req.mr_type = PACKET_MR_MULTICAST; - multicast_req.mr_alen = 6; - memcpy(multicast_req.mr_address, multicast_addr, 6); + if (0 != ctx_sig->talker) { + ret = send_leave(ctx_sig); + if (ret) + printf("send_leave failed\n"); + } - rc = setsockopt(lsock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, - &multicast_req, sizeof(multicast_req)); - if (0 != rc) { - close(lsock); - return -1; + if (2 > ctx_sig->control_socket) + { + close(ctx_sig->control_socket); + ctx_sig->control_socket = -1; + ret = mrp_disconnect(ctx_sig); + if (ret) + printf("mrp_disconnect failed\n"); } - *sock = lsock; +#if LIBSND + if (glob_snd_file) { + sf_write_sync(glob_snd_file); + sf_close(glob_snd_file); + glob_snd_file = NULL; + } +#endif /* LIBSND */ - return 0; -} + if (glob_sock >= 0) { + close (glob_sock); + glob_sock = -1; + } -static void usage(void) -{ - fprintf(stderr, "\n" - "usage: simple_rx [-h] -i interface-name\n" - "options:\n" - " -h show this message\n" - " -i specify interface for AVB connection\n" - " -t transport equal to 2 for 1722 or 3 for RTP\n" - "\n%s\n", version_str); - exit(EXIT_FAILURE); + halt_rx_sig = 0; } +#endif /* DIRECT_RX */ int main(int argc, char *argv[]) { - /* int igb_shm_fd = -1; */ - struct igb_packet *received_packets = NULL; - struct igb_packet *free_packets[PKT_NUM]; - struct igb_packet *tmp_packet = NULL; - struct igb_dma_alloc dma_pages[PKT_NUM]; - unsigned char test_filter[128]; - char *interface = NULL; - u_int8_t filter_mask[64]; + char* file_name = NULL; + char* dev = NULL; +#if PCAP + char errbuf[PCAP_ERRBUF_SIZE]; + struct bpf_program comp_filter_exp; /* The compiled filter expression */ + char filter_exp[100]; /* The filter expression */ +#endif + struct mrp_listener_ctx *ctx = malloc(sizeof(struct mrp_listener_ctx)); + struct mrp_domain_attr *class_a = malloc(sizeof(struct mrp_domain_attr)); + struct mrp_domain_attr *class_b = malloc(sizeof(struct mrp_domain_attr)); + +#if LIBSND + SF_INFO* sf_info = NULL; +#endif /* LIBSND */ + +#if DIRECT_RX device_t igb_dev; - unsigned i; - int c, rc = 0; - int err; - int sock; - struct ethhdr *ethhdr = NULL; - u_int16_t *vlan_ethtype = NULL; - u_int32_t count; +#endif /* DIRECT_RX */ - for (;;) { - c = getopt(argc, argv, "hi:t:"); - if (c < 0) - break; - switch (c) { + ctx_sig = ctx; + signal(SIGINT, sigint_handler); + + int c,rc; + while((c = getopt(argc, argv, "hi:f:")) > 0) + { + switch (c) + { case 'h': - usage(); + help(); break; case 'i': - if (interface) { - printf("only one interface per daemon is supported\n"); - usage(); - } - interface = strdup(optarg); + dev = strdup(optarg); + break; + case 'f': + file_name = strdup(optarg); break; + default: + fprintf(stderr, "Unrecognized option!\n"); } } - if (optind < argc) - usage(); + if ((NULL == dev) || (NULL == file_name)) + help(); - if (interface == NULL) - usage(); + rc = mrp_listener_client_init(ctx); + if (rc) + { + printf("failed to initialize global variables\n"); + goto out; + } - memset (dma_pages, 0, sizeof(dma_pages)); - memset (free_packets, 0, sizeof(free_packets)); + if (create_socket(ctx)) + { + fprintf(stderr, "Socket creation failed.\n"); + rc = EXIT_FAILURE; + goto out; + } - err = pci_connect(&igb_dev); - if (err) { - printf("connect failed (%s) - are you running as root?\n", - strerror(err)); - return err; + rc = mrp_monitor(ctx); + if (rc) + { + printf("failed creating MRP monitor thread\n"); + goto out; } - err = igb_init(&igb_dev); - if (err) { - printf("init failed (%s) - is the driver really loaded?\n", - strerror(err)); - return err; + rc=mrp_get_domain(ctx, class_a, class_b); + if (rc) + { + printf("failed calling mrp_get_domain()\n"); + goto out; } - /* - * allocate a bunch of pages and - * stitch into a linked list of igb_packets ... - */ - for (i = 0; i < PKT_NUM; i++) { - err = igb_dma_malloc_page(&igb_dev, &dma_pages[i]); - if (err) { - printf("malloc failed (%s) - out of memory?\n", - strerror(err)); - goto exit; - } + printf("detected domain Class A PRIO=%d VID=%04x...\n",class_a->priority,class_a->vid); - tmp_packet = calloc(1, sizeof(struct igb_packet)); - if (tmp_packet == NULL) { - printf("failed to allocate igb_packet memory!\n"); - err = -errno; - goto exit; - } - tmp_packet->dmatime = 0; - tmp_packet->attime = 0; - tmp_packet->flags = 0; - tmp_packet->map.paddr = dma_pages[i].dma_paddr; - tmp_packet->map.mmap_size = dma_pages[i].mmap_size; - tmp_packet->offset = 0; - tmp_packet->vaddr = dma_pages[i].dma_vaddr + tmp_packet->offset; - tmp_packet->len = PKT_SZ; - - memset(tmp_packet->vaddr, 0, PKT_SZ); - if (i != 0) - tmp_packet->next = free_packets[i-1]; - free_packets[i] = tmp_packet; - - igb_refresh_buffers(&igb_dev, 0, free_packets, 1); + rc = report_domain_status(class_a,ctx); + if (rc) { + printf("report_domain_status failed\n"); + goto out; } - /* filtering example */ - memset(filter_mask, 0, sizeof(filter_mask)); - memset(test_filter, 0, sizeof(test_filter)); - - /* accept the IEEE1722 packets with a VLAN tag */ - ethhdr = (struct ethhdr *)test_filter; - ethhdr->h_proto = htons(ETH_P_8021Q); - - vlan_ethtype = (u_int16_t*)(test_filter + ETH_HLEN + 2); - *vlan_ethtype = htons(ETH_P_IEEE1722); - - filter_mask[1] = 0x30; - filter_mask[2] = 0x03; - - igb_setup_flex_filter(&igb_dev, 0, 0, 16, - test_filter, filter_mask); - - mrpd_init_protocol_socket(0x2272, &sock, glob_l2_dest_addr, interface); - - signal(SIGINT, sigint_handler); - rc = get_mac_address(interface); + rc = join_vlan(class_a, ctx); if (rc) { - printf("failed to open interface\n"); - usage(); + printf("join_vlan failed\n"); + goto out; } - memset(glob_stream_id, 0, sizeof(glob_stream_id)); - memcpy(glob_stream_id, glob_station_addr, sizeof(glob_station_addr)); + fprintf(stdout,"Waiting for talker...\n"); + await_talker(ctx); - halt_rx_sig = 1; +#if DEBUG + fprintf(stdout,"Send ready-msg...\n"); +#endif /* DEBUG */ + rc = send_ready(ctx); + if (rc) { + printf("send_ready failed\n"); + goto out; + } - rc = nice(-20); +#if LIBSND + sf_info = (SF_INFO*)malloc(sizeof(SF_INFO)); - while (halt_rx_sig) { + memset(sf_info, 0, sizeof(SF_INFO)); - received_packets = NULL; - count = 1; - igb_receive(&igb_dev, &received_packets, &count); + sf_info->samplerate = SAMPLES_PER_SECOND; + sf_info->channels = CHANNELS; + sf_info->format = SF_FORMAT_WAV | SF_FORMAT_PCM_24; - if (received_packets == NULL) - continue; + if (0 == sf_format_check(sf_info)) + { + fprintf(stderr, "Wrong format."); + rc = EXIT_FAILURE; + goto out; + } - /* print out the received packet? what do do with it? */ - printf("received a packet ! hex dump (the first 32 bytes)\n"); - for (i = 0; i < 32; i++) { - printf ("%02x ", ((u8*)received_packets->vaddr)[i]); - } - printf ("\n\n"); + if (NULL == (glob_snd_file = sf_open(file_name, SFM_WRITE, sf_info))) + { + fprintf(stderr, "Could not create file."); + rc = EXIT_FAILURE; + goto out; + } + fprintf(stdout,"Created file called %s\n", file_name); +#endif /* LIBSND */ + +#if PCAP + /** session, get session handler */ + /* take promiscuous vs. non-promiscuous sniffing? (0 or 1) */ + glob_pcap_handle = pcap_open_live(dev, BUFSIZ, 1, -1, errbuf); + if (NULL == glob_pcap_handle) + { + fprintf(stderr, "Could not open device %s: %s\n", dev, errbuf); + rc = EXIT_FAILURE; + goto out; + } - /* put back for now */ - igb_refresh_buffers(&igb_dev, 0, &received_packets, 1); +#if DEBUG + fprintf(stdout,"Got session pcap handler.\n"); +#endif /* DEBUG */ + /* compile and apply filter */ + sprintf(filter_exp,"ether dst %02x:%02x:%02x:%02x:%02x:%02x",ctx->dst_mac[0],ctx->dst_mac[1],ctx->dst_mac[2],ctx->dst_mac[3],ctx->dst_mac[4],ctx->dst_mac[5]); + if (-1 == pcap_compile(glob_pcap_handle, &comp_filter_exp, filter_exp, 0, PCAP_NETMASK_UNKNOWN)) + { + fprintf(stderr, "Could not parse filter %s: %s\n", filter_exp, pcap_geterr(glob_pcap_handle)); + rc = EXIT_FAILURE; + goto out; } - err = EXIT_SUCCESS; -exit: - rc = nice(0); + if (-1 == pcap_setfilter(glob_pcap_handle, &comp_filter_exp)) + { + fprintf(stderr, "Could not install filter %s: %s\n", filter_exp, pcap_geterr(glob_pcap_handle)); + rc = EXIT_FAILURE; + goto out; + } - halt_rx_sig = 0; +#if DEBUG + fprintf(stdout,"Compiled and applied filter.\n"); +#endif /* DEBUG */ - igb_clear_flex_filter(&igb_dev, 0); + /** loop forever and call callback-function for every received packet */ + pcap_loop(glob_pcap_handle, -1, pcap_callback, (u_char*)ctx); +#endif /* PCAP */ - for (i = 0; i < PKT_NUM; i++) { - if (dma_pages[i].dma_paddr != 0) - igb_dma_free_page(&igb_dev, &dma_pages[i]); - if (free_packets[i]) { - free(free_packets[i]); - } +#if DIRECT_RX + if (0 != join_mcast(dev, ctx)) { + fprintf(stderr, "Could not join the mcast group\n"); + rc = EXIT_FAILURE; + goto out; } - igb_detach(&igb_dev); + if (0 != igb_start_rx(&igb_dev, ctx)) { + fprintf(stderr, "Could not start the igb device\n"); + rc = EXIT_FAILURE; + goto out; + } - if (interface) - free (interface); + igb_process_rx(&igb_dev, ctx); - return err; +#endif + rc = EXIT_SUCCESS; +out: +#if DIRECT_RX + igb_stop_rx(&igb_dev); + cleanup(); +#endif /* DIRECT_RX */ + + if (ctx) + free(ctx); + if (class_a) + free(class_a); + if (class_b) + free(class_b); + if (dev) + free(dev); + if (file_name) + free(file_name); +#if LIBSND + if (sf_info) + free(sf_info); +#endif /* LIBSND */ + + return rc; } + -- cgit v1.2.1 From c0f137c6aad01e6338f983d9455e1055ff43ddde Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Mon, 18 Jul 2016 21:09:36 +0900 Subject: libigb: add mutex lock to each RX queue --- lib/igb/igb.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- lib/igb/igb.h | 2 +- lib/igb/igb_internal.h | 2 ++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 669dbef2..e1b73118 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1263,6 +1263,17 @@ static int igb_allocate_rx_queues(struct adapter *adapter) adapter->num_queues); for (i = 0; i < adapter->num_queues; i++) { + + if (sem_init(&adapter->rx_rings[i].lock, 0, 1) != 0) { + error = errno; + goto rx_desc; + } + + if (sem_wait(&adapter->rx_rings[i].lock) != 0) { + error = errno; + goto rx_desc; + } + ubuf.queue = i; error = ioctl(dev, IGB_MAP_RX_RING, &ubuf); if (error < 0) { @@ -1300,6 +1311,11 @@ static int igb_allocate_rx_queues(struct adapter *adapter) memset(adapter->rx_rings[i].rx_buffers, 0, sizeof(struct igb_rx_buffer) * adapter->num_rx_desc); + + if (sem_post(&adapter->rx_rings[i].lock) != 0) { + error = errno; + goto rx_desc; + } } return 0; @@ -1311,6 +1327,8 @@ rx_desc: adapter->rx_rings[i].rxdma.mmap_size); ubuf.queue = i; ioctl(dev, IGB_UNMAP_RX_RING, &ubuf); + + sem_destroy(&adapter->rx_rings[i].lock); }; rx_fail: free(adapter->rx_rings); @@ -1336,6 +1354,7 @@ static void igb_setup_receive_ring(struct rx_ring *rxr) { struct adapter *adapter = rxr->adapter; + (void)sem_wait(&rxr->lock); /* Clear the ring contents */ memset((void *)rxr->rx_base, 0, @@ -1352,6 +1371,8 @@ static void igb_setup_receive_ring(struct rx_ring *rxr) rxr->next_to_refresh = 0; rxr->rx_split_packets = 0; rxr->rx_bytes = 0; + + (void)sem_post(&rxr->lock); } /* Initialize all receive rings. */ @@ -1453,6 +1474,8 @@ static void igb_free_receive_structures(struct adapter *adapter) struct igb_buf_cmd ubuf; for (i = 0; i < adapter->num_queues; i++, rxr++) { + (void)sem_wait(&adapter->rx_rings[i].lock); + if (rxr->rx_base) { memset(rxr->rx_base, 0, rxr->rxdma.mmap_size); munmap(rxr->rx_base, rxr->rxdma.mmap_size); @@ -1460,6 +1483,8 @@ static void igb_free_receive_structures(struct adapter *adapter) ubuf.queue = i; ioctl(adapter->ldev, IGB_UNMAP_RX_RING, &ubuf); igb_free_receive_buffers(rxr); + + (void)sem_destroy(&adapter->rx_rings[i].lock); } free(adapter->rx_rings); @@ -1496,7 +1521,7 @@ static void igb_free_receive_buffers(struct rx_ring *rxr) * be recalled to try again. * */ -void igb_refresh_buffers(device_t *dev, u_int32_t idx, +int igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs) { struct igb_packet *cur_pkt; @@ -1506,19 +1531,25 @@ void igb_refresh_buffers(device_t *dev, u_int32_t idx, bool refreshed = FALSE; if (dev == NULL) - return; + return -EINVAL; adapter = (struct adapter *)dev->private_data; if (adapter == NULL) - return; + return -EINVAL; if (rxbuf_packets == NULL) - return; + return -EINVAL; if (idx > 1) - return; + return -EINVAL; rxr = &adapter->rx_rings[idx]; + if (rxr == NULL) + return -EINVAL; + + if (sem_trywait(&rxr->lock) != 0) + return errno; /* EAGAIN */ + i = j = rxr->next_to_refresh; cur_pkt = *rxbuf_packets; @@ -1552,6 +1583,9 @@ void igb_refresh_buffers(device_t *dev, u_int32_t idx, if (refreshed) /* update tail */ E1000_WRITE_REG(&adapter->hw, E1000_RDT(rxr->me), rxr->next_to_refresh); + + if (sem_post(&rxr->lock) != 0) + return errno; } @@ -1600,6 +1634,9 @@ int igb_receive(device_t *dev, unsigned int queue_index, *received_packets = NULL; /* nothing reclaimed yet */ + if (sem_trywait(&rxr->lock) != 0) + return errno; /* EAGAIN */ + /* Main clean loop - receive packets until no more * received_packets[] */ @@ -1671,6 +1708,9 @@ next_desc: rxr->next_to_check = desc; + if (sem_post(&rxr->lock) != 0) + return errno; + return 0; } diff --git a/lib/igb/igb.h b/lib/igb/igb.h index b8c33bb7..85b8d74e 100644 --- a/lib/igb/igb.h +++ b/lib/igb/igb.h @@ -89,7 +89,7 @@ int igb_dma_malloc_page(device_t *dev, struct igb_dma_alloc *page); void igb_dma_free_page(device_t *dev, struct igb_dma_alloc *page); int igb_xmit(device_t *dev, unsigned int queue_index, struct igb_packet *packet); -void igb_refresh_buffers(device_t *dev, u_int32_t idx, +int igb_refresh_buffers(device_t *dev, u_int32_t idx, struct igb_packet **rxbuf_packets, u_int32_t num_bufs); int igb_receive(device_t *dev, unsigned int queue_index, diff --git a/lib/igb/igb_internal.h b/lib/igb/igb_internal.h index 6741d1af..ebf7d1d8 100644 --- a/lib/igb/igb_internal.h +++ b/lib/igb/igb_internal.h @@ -151,6 +151,8 @@ struct rx_ring { u64 rx_discarded; u64 rx_packets; u64 rx_bytes; + + sem_t lock; }; struct adapter { -- cgit v1.2.1 From 556f4caf0eb4ea7452cabfd070447585ab4af037 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Tue, 19 Jul 2016 11:46:21 +0900 Subject: libigb: fix klocwork warnings --- lib/igb/igb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index e1b73118..30b8a68e 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1586,6 +1586,8 @@ int igb_refresh_buffers(device_t *dev, u_int32_t idx, if (sem_post(&rxr->lock) != 0) return errno; + + return 0; } @@ -1601,7 +1603,6 @@ int igb_receive(device_t *dev, unsigned int queue_index, struct adapter *adapter; struct rx_ring *rxr; union e1000_adv_rx_desc *cur; - int i; bool eop = FALSE; u_int32_t staterr = 0; u_int32_t desc = 0; @@ -1674,7 +1675,7 @@ int igb_receive(device_t *dev, unsigned int queue_index, if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) { ++rxr->rx_discarded; printf ("discard error packet\n"); - igb_refresh_buffers(dev, i, + igb_refresh_buffers(dev, queue_index, &rxr->rx_buffers[desc].packet, 1); } else { /* @@ -1697,7 +1698,7 @@ int igb_receive(device_t *dev, unsigned int queue_index, /* multi-segment frame is not supported yet */ ++rxr->rx_discarded; printf ("discard non-eop packet\n"); - igb_refresh_buffers(dev, i, + igb_refresh_buffers(dev, queue_index, &rxr->rx_buffers[desc].packet, 1); } next_desc: -- cgit v1.2.1 From d8472a5217b8b7df2b166342d8927bba22760749 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Tue, 19 Jul 2016 11:47:43 +0900 Subject: simple_rx: fix klocwork warnings --- examples/simple_rx/simple_rx.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index caf387ea..7808108b 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -383,6 +383,10 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) if (!a_page) goto out; + page_qelem->q_data = (void*)a_page; + insque(page_qelem, prev_page_qelem); + prev_page_qelem = page_qelem; + err = igb_dma_malloc_page(igb_dev, a_page); if (err) { printf("malloc failed (%s) - out of memory?\n", @@ -393,10 +397,6 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) if (a_page->mmap_size < PKT_SZ) goto out; - page_qelem->q_data = (void*)a_page; - insque(page_qelem, prev_page_qelem); - prev_page_qelem = page_qelem; - /* divide the dma page into buffers for packets */ for (i = 0; i < a_page->mmap_size/PKT_SZ; i++) { pkt_qelem = calloc(1, sizeof(struct myqelem)); @@ -637,10 +637,17 @@ int main(int argc, char *argv[]) device_t igb_dev; #endif /* DIRECT_RX */ + int c,rc; + + if ((NULL == ctx) || (NULL == class_a) || (NULL == class_b)) { + fprintf(stderr, "failed allocating memory\n"); + rc = EXIT_FAILURE; + goto out; + } + ctx_sig = ctx; signal(SIGINT, sigint_handler); - int c,rc; while((c = getopt(argc, argv, "hi:f:")) > 0) { switch (c) @@ -717,6 +724,11 @@ int main(int argc, char *argv[]) #if LIBSND sf_info = (SF_INFO*)malloc(sizeof(SF_INFO)); + if (NULL == sf_info) { + fprintf(stderr, "failed allocating memory\n"); + rc = EXIT_FAILURE; + goto out; + } memset(sf_info, 0, sizeof(SF_INFO)); -- cgit v1.2.1 From 062544a7f50b10c69da2d59acfa2783277b95006 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Wed, 20 Jul 2016 14:15:36 +0900 Subject: simple_rx: delete unnecessary filter --- examples/simple_rx/simple_rx.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index 7808108b..16b91bbd 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -439,24 +439,12 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) memset(filter_mask, 0, sizeof(filter_mask)); memset(test_filter, 0, sizeof(test_filter)); - /* the filter for IEEE1722 w/o a VLAN tag */ + /* the filter for IEEE1722 with VLAN */ - /* accept packets toward the dst mac */ + /* accept packets toward the multicast dst mac given by MRP */ ethhdr = (struct ethhdr *)test_filter; memcpy((void*)ethhdr->h_dest, (void*)ctx->dst_mac, ETH_ALEN); - /* ethtype in ethernet frame = IEEE1722 */ - ethhdr->h_proto = htons(ETH_P_IEEE1722); - - filter_mask[0] = 0x3F; /* 00111111b = dst mac */ - filter_mask[1] = 0x30; /* 00110000b = ethtype */ - - /* install the filter on queue0 */ - igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 0, ETH_HLEN, - test_filter, filter_mask); - - /* the filter for IEEE1722 with VLAN */ - /* ethtype in ethernet frame = 802.1Q */ ethhdr->h_proto = htons(ETH_P_8021Q); @@ -464,6 +452,8 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) ethtype = (uint16_t*)(test_filter + ETH_HLEN + 2); *ethtype = htons(ETH_P_IEEE1722); + filter_mask[0] = 0x3F; /* 00111111b = dst mac */ + filter_mask[1] = 0x30; /* 00110000b = ethtype */ filter_mask[2] = 0x03; /* 00000011b = ethtype after a vlan tag */ /* install the filter on queue0 */ @@ -483,7 +473,6 @@ void igb_stop_rx(device_t *igb_dev) struct myqelem *qelem = NULL; igb_clear_flex_filter(igb_dev, 0); - igb_clear_flex_filter(igb_dev, 1); while (glob_pkt_head) { qelem = glob_pkt_head; -- cgit v1.2.1 From 231b8a7eefd9d74d13342dbb0ff3c8d55f495dad Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Wed, 20 Jul 2016 14:15:36 +0900 Subject: simple_rx: delete unnecessary filter --- examples/simple_rx/simple_rx.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index 7808108b..d03579da 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -439,24 +439,12 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) memset(filter_mask, 0, sizeof(filter_mask)); memset(test_filter, 0, sizeof(test_filter)); - /* the filter for IEEE1722 w/o a VLAN tag */ + /* the filter for IEEE1722 with VLAN */ - /* accept packets toward the dst mac */ + /* accept packets toward the multicast dst mac given by MRP */ ethhdr = (struct ethhdr *)test_filter; memcpy((void*)ethhdr->h_dest, (void*)ctx->dst_mac, ETH_ALEN); - /* ethtype in ethernet frame = IEEE1722 */ - ethhdr->h_proto = htons(ETH_P_IEEE1722); - - filter_mask[0] = 0x3F; /* 00111111b = dst mac */ - filter_mask[1] = 0x30; /* 00110000b = ethtype */ - - /* install the filter on queue0 */ - igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 0, ETH_HLEN, - test_filter, filter_mask); - - /* the filter for IEEE1722 with VLAN */ - /* ethtype in ethernet frame = 802.1Q */ ethhdr->h_proto = htons(ETH_P_8021Q); @@ -464,10 +452,12 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) ethtype = (uint16_t*)(test_filter + ETH_HLEN + 2); *ethtype = htons(ETH_P_IEEE1722); + filter_mask[0] = 0x3F; /* 00111111b = dst mac */ + filter_mask[1] = 0x30; /* 00110000b = ethtype */ filter_mask[2] = 0x03; /* 00000011b = ethtype after a vlan tag */ /* install the filter on queue0 */ - igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 1, ETHERNET_HEADER_SIZE, + igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 0, ETHERNET_HEADER_SIZE, test_filter, filter_mask); rc = 0; @@ -483,7 +473,6 @@ void igb_stop_rx(device_t *igb_dev) struct myqelem *qelem = NULL; igb_clear_flex_filter(igb_dev, 0); - igb_clear_flex_filter(igb_dev, 1); while (glob_pkt_head) { qelem = glob_pkt_head; -- cgit v1.2.1 From 73f33cdc63b84f1fd54a53ee3f8566ffe9b731a9 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Wed, 20 Jul 2016 14:47:55 +0900 Subject: Revert "simple_rx: delete unnecessary filter" This reverts commit 231b8a7eefd9d74d13342dbb0ff3c8d55f495dad. --- examples/simple_rx/simple_rx.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index d03579da..7808108b 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -439,12 +439,24 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) memset(filter_mask, 0, sizeof(filter_mask)); memset(test_filter, 0, sizeof(test_filter)); - /* the filter for IEEE1722 with VLAN */ + /* the filter for IEEE1722 w/o a VLAN tag */ - /* accept packets toward the multicast dst mac given by MRP */ + /* accept packets toward the dst mac */ ethhdr = (struct ethhdr *)test_filter; memcpy((void*)ethhdr->h_dest, (void*)ctx->dst_mac, ETH_ALEN); + /* ethtype in ethernet frame = IEEE1722 */ + ethhdr->h_proto = htons(ETH_P_IEEE1722); + + filter_mask[0] = 0x3F; /* 00111111b = dst mac */ + filter_mask[1] = 0x30; /* 00110000b = ethtype */ + + /* install the filter on queue0 */ + igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 0, ETH_HLEN, + test_filter, filter_mask); + + /* the filter for IEEE1722 with VLAN */ + /* ethtype in ethernet frame = 802.1Q */ ethhdr->h_proto = htons(ETH_P_8021Q); @@ -452,12 +464,10 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) ethtype = (uint16_t*)(test_filter + ETH_HLEN + 2); *ethtype = htons(ETH_P_IEEE1722); - filter_mask[0] = 0x3F; /* 00111111b = dst mac */ - filter_mask[1] = 0x30; /* 00110000b = ethtype */ filter_mask[2] = 0x03; /* 00000011b = ethtype after a vlan tag */ /* install the filter on queue0 */ - igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 0, ETHERNET_HEADER_SIZE, + igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 1, ETHERNET_HEADER_SIZE, test_filter, filter_mask); rc = 0; @@ -473,6 +483,7 @@ void igb_stop_rx(device_t *igb_dev) struct myqelem *qelem = NULL; igb_clear_flex_filter(igb_dev, 0); + igb_clear_flex_filter(igb_dev, 1); while (glob_pkt_head) { qelem = glob_pkt_head; -- cgit v1.2.1 From 300cda83b66041872e9971df3010064c91a80ad8 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Wed, 20 Jul 2016 14:48:56 +0900 Subject: simple_rx: delete unnecessary filter --- examples/simple_rx/simple_rx.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index 7808108b..a8942e20 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -439,24 +439,12 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) memset(filter_mask, 0, sizeof(filter_mask)); memset(test_filter, 0, sizeof(test_filter)); - /* the filter for IEEE1722 w/o a VLAN tag */ + /* the filter for IEEE1722 with VLAN */ - /* accept packets toward the dst mac */ + /* accept packets toward the multicast dst mac given by MRP */ ethhdr = (struct ethhdr *)test_filter; memcpy((void*)ethhdr->h_dest, (void*)ctx->dst_mac, ETH_ALEN); - /* ethtype in ethernet frame = IEEE1722 */ - ethhdr->h_proto = htons(ETH_P_IEEE1722); - - filter_mask[0] = 0x3F; /* 00111111b = dst mac */ - filter_mask[1] = 0x30; /* 00110000b = ethtype */ - - /* install the filter on queue0 */ - igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 0, ETH_HLEN, - test_filter, filter_mask); - - /* the filter for IEEE1722 with VLAN */ - /* ethtype in ethernet frame = 802.1Q */ ethhdr->h_proto = htons(ETH_P_8021Q); @@ -464,10 +452,12 @@ int igb_start_rx(device_t *igb_dev, struct mrp_listener_ctx *ctx) ethtype = (uint16_t*)(test_filter + ETH_HLEN + 2); *ethtype = htons(ETH_P_IEEE1722); + filter_mask[0] = 0x3F; /* 00111111b = dst mac */ + filter_mask[1] = 0x30; /* 00110000b = ethtype */ filter_mask[2] = 0x03; /* 00000011b = ethtype after a vlan tag */ /* install the filter on queue0 */ - igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 1, ETHERNET_HEADER_SIZE, + igb_setup_flex_filter(igb_dev, IGB_QUEUE_0, 0, ETHERNET_HEADER_SIZE, test_filter, filter_mask); rc = 0; @@ -483,7 +473,6 @@ void igb_stop_rx(device_t *igb_dev) struct myqelem *qelem = NULL; igb_clear_flex_filter(igb_dev, 0); - igb_clear_flex_filter(igb_dev, 1); while (glob_pkt_head) { qelem = glob_pkt_head; -- cgit v1.2.1 From acafabd2481160f7e91cfcfad2009cff6166498b Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Wed, 20 Jul 2016 17:22:47 +0900 Subject: libigb: make igb_receive return negative value when no packet is available --- lib/igb/igb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 30b8a68e..76857966 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -1712,6 +1712,12 @@ next_desc: if (sem_post(&rxr->lock) != 0) return errno; + if (*received_packets == NULL) { + /* nothing reclaimed yet */ + errno = EAGAIN; + return errno; + } + return 0; } -- cgit v1.2.1 From c3b0b4b9191e2d6bedabdcf4df17d11d9e540e22 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Tue, 26 Jul 2016 14:16:08 +0900 Subject: libigb: initialize the TX queues only when igb_attach_tx has been called. Currently application has to call igb_attach_tx to initialize the igb driver even if it is a pure listener application and no need to use the TX feature. This patch removes the unnecessary dependencies. As a result, Talker should call: igb_attach igb_attach_tx igb_init Listener should call: igb_attach igb_attach_rx igb_init Application acting both Talker & Listener should call igb_attach igb_attach_tx igb_attach_rx igb_init --- lib/igb/igb.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/igb/igb.c b/lib/igb/igb.c index 76857966..30885862 100644 --- a/lib/igb/igb.c +++ b/lib/igb/igb.c @@ -326,7 +326,10 @@ int igb_detach(device_t *dev) sem_post(adapter->memlock); igb_free_pci_resources(adapter); - igb_free_transmit_structures(adapter); + + if (adapter->tx_rings) + igb_free_transmit_structures(adapter); + if (adapter->rx_rings) igb_free_receive_structures(adapter); @@ -487,8 +490,10 @@ int igb_init(device_t *dev) igb_reset(adapter); /* Prepare transmit descriptors and buffers */ - igb_setup_transmit_structures(adapter); - igb_initialize_transmit_units(adapter); + if (adapter->tx_rings) { + igb_setup_transmit_structures(adapter); + igb_initialize_transmit_units(adapter); + } if (adapter->rx_rings) { igb_setup_receive_structures(adapter); -- cgit v1.2.1 From 75c2440830d9fd966f1ed23cfdfca53b38fb0f06 Mon Sep 17 00:00:00 2001 From: Toshiki Nishioka Date: Tue, 26 Jul 2016 14:31:57 +0900 Subject: simple_rx: remove the call of igb_attach_tx --- examples/simple_rx/simple_rx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/simple_rx/simple_rx.c b/examples/simple_rx/simple_rx.c index a8942e20..8d90f81a 100644 --- a/examples/simple_rx/simple_rx.c +++ b/examples/simple_rx/simple_rx.c @@ -328,10 +328,6 @@ int pci_connect(device_t *igb_dev) printf("rx attach failed! (%s)\n", strerror(err)); continue; } - if (igb_attach_tx(igb_dev)) { - printf("tx attach failed! (%s)\n", strerror(err)); - continue; - } goto out; } pci_cleanup(pacc); -- cgit v1.2.1 From 264304cff7752c00e6bc437f665e9bac92c0fd81 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Wed, 31 Aug 2016 09:29:47 -0400 Subject: gPTP - windows build update to cmdline parameter parsing. See issue #463. --- daemons/gptp/windows/daemon_cl/daemon_cl.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/daemons/gptp/windows/daemon_cl/daemon_cl.cpp b/daemons/gptp/windows/daemon_cl/daemon_cl.cpp index 2e5e98db..4c879103 100644 --- a/daemons/gptp/windows/daemon_cl/daemon_cl.cpp +++ b/daemons/gptp/windows/daemon_cl/daemon_cl.cpp @@ -47,7 +47,8 @@ static bool exit_flag; void print_usage( char *arg0 ) { fprintf( stderr, "%s " - "[-R ] \n", + "[-R ] \n" + "where is a MAC address entered as xx-xx-xx-xx-xx-xx\n", arg0 ); } @@ -121,8 +122,15 @@ int _tmain(int argc, _TCHAR* argv[]) ipc = NULL; } + // If there are no arguments, output usage + if (1 == argc) { + print_usage(argv[0]); + return -1; + } + + /* Process optional arguments */ - for( i = 1; i < argc-1; ++i ) { + for( i = 1; i < argc; ++i ) { if( ispunct(argv[i][0]) ) { if( toupper( argv[i][1] ) == 'H' ) { print_usage( argv[0] ); @@ -145,12 +153,11 @@ int _tmain(int argc, _TCHAR* argv[]) } } + // the last argument is supposed to be a MAC address, so decrement argv index to read it + i--; + // Create Low level network interface object uint8_t local_addr_ostr[ETHER_ADDR_OCTETS]; - if( i >= argc ) { - print_usage( argv[0] ); - return -1; - } parseMacAddr( argv[i], local_addr_ostr ); LinkLayerAddress local_addr(local_addr_ostr); portInit.net_label = &local_addr; -- cgit v1.2.1 From 5abb3581d8c8898751b580267d3b9d57c60ea5e0 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Fri, 26 Aug 2016 16:17:40 -0400 Subject: gPTP: check for NULL qualified_announce before processing STATE_CHANGE_EVENT (could be NULLed out by sync timeout --- daemons/gptp/common/ieee1588port.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 34edf4d1..2a38ac4c 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -598,7 +598,8 @@ void IEEE1588Port::processEvent(Event e) case STATE_CHANGE_EVENT: if (!automotive_profile) { // BMCA is not active with Automotive Profile - if ( clock->getPriority1() != 255 ) { + if ( clock->getPriority1() != 255 && qualified_announce != NULL ) { + int number_ports, j; PTPMessageAnnounce *EBest = NULL; char EBestClockIdentity[PTP_CLOCK_IDENTITY_LENGTH]; -- cgit v1.2.1 From 3baa02a76e0ec4274b0e29b11610cc5366f523a4 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Sat, 27 Aug 2016 14:01:39 -0400 Subject: gPTP: check for NULL announce packet (in case of sync timeout on another port) --- daemons/gptp/common/ieee1588clock.cpp | 3 +++ daemons/gptp/common/ieee1588port.cpp | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/daemons/gptp/common/ieee1588clock.cpp b/daemons/gptp/common/ieee1588clock.cpp index ab6f47ac..ac9b1aea 100644 --- a/daemons/gptp/common/ieee1588clock.cpp +++ b/daemons/gptp/common/ieee1588clock.cpp @@ -424,6 +424,9 @@ bool IEEE1588Clock::isBetterThan(PTPMessageAnnounce * msg) unsigned char that1[14]; uint16_t tmp; + if (msg == NULL) + return true; + this1[0] = priority1; that1[0] = msg->getGrandmasterPriority1(); diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 2a38ac4c..3dd0a9f3 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -618,13 +618,17 @@ void IEEE1588Port::processEvent(Event e) } if (EBest == NULL) { EBest = ports[j]->calculateERBest(); - } else { + }else if (ports[j]->calculateERBest()) { if (ports[j]->calculateERBest()->isBetterThan(EBest)) { EBest = ports[j]->calculateERBest(); } } } + if (EBest == NULL) { + break; + } + /* Check if we've changed */ { -- cgit v1.2.1 From d5c340ce4604823c75e37ed6474f6991ff29e398 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Thu, 8 Sep 2016 09:18:43 -0400 Subject: gPTP: minor whitespace correction to ieee1588port.cpp --- daemons/gptp/common/ieee1588port.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 3dd0a9f3..5fb9be8f 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -618,7 +618,7 @@ void IEEE1588Port::processEvent(Event e) } if (EBest == NULL) { EBest = ports[j]->calculateERBest(); - }else if (ports[j]->calculateERBest()) { + } else if (ports[j]->calculateERBest()) { if (ports[j]->calculateERBest()->isBetterThan(EBest)) { EBest = ports[j]->calculateERBest(); } -- cgit v1.2.1 From 121758de6f131730d0c7a6659d5496c563bea03e Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Thu, 8 Sep 2016 09:20:34 -0400 Subject: Revert "gPTP: check for NULL qualified_announce before processing STATE_CHANGE_EVENT (could be NULLed out by sync timeout" This reverts commit 23b79a5622296828f639ddeb990f2ed9db834fc2. --- daemons/gptp/common/ieee1588port.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 5fb9be8f..e23fab3f 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -598,8 +598,7 @@ void IEEE1588Port::processEvent(Event e) case STATE_CHANGE_EVENT: if (!automotive_profile) { // BMCA is not active with Automotive Profile - if ( clock->getPriority1() != 255 && qualified_announce != NULL ) { - + if ( clock->getPriority1() != 255 ) { int number_ports, j; PTPMessageAnnounce *EBest = NULL; char EBestClockIdentity[PTP_CLOCK_IDENTITY_LENGTH]; -- cgit v1.2.1 From 0520fe4f606a910babb39527fdebbe776355aa17 Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Tue, 6 Sep 2016 13:55:14 -0600 Subject: gPTP: Remove timestamper_init call on link up The Linux hardware timestamper init is only designed to be called once upon creation. Calling it on every link up event results in resource leaks. Therefore the call has been removed. A substitute, timestamper_reset, has been added in its place. It currently only calls the init_phy_delay function, since there are no other exposed methods in the HWTimestamper interface that were clearly appropriate. We may also want to add a call to reset the frequency adjustment, but that is not currently available in the HWTimestamper interface. --- daemons/gptp/common/avbts_port.hpp | 6 ++++++ daemons/gptp/common/ieee1588port.cpp | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/daemons/gptp/common/avbts_port.hpp b/daemons/gptp/common/avbts_port.hpp index 5fd35f4d..5e37120b 100644 --- a/daemons/gptp/common/avbts_port.hpp +++ b/daemons/gptp/common/avbts_port.hpp @@ -1138,6 +1138,12 @@ class IEEE1588Port { */ void timestamper_init(void); + /** + * @brief Resets the hwtimestamper + */ + void timestamper_reset(void); + + /** * @brief Gets RX timestamp based on port identity * @param sourcePortIdentity [in] Source port identity diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index e23fab3f..f270be4d 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -207,6 +207,13 @@ void IEEE1588Port::timestamper_init(void) } } +void IEEE1588Port::timestamper_reset(void) +{ + if( _hw_timestamper != NULL ) { + _hw_timestamper->init_phy_delay(this->link_delay); + } +} + bool IEEE1588Port::init_port(int delay[4]) { if (!OSNetworkInterfaceFactory::buildInterface @@ -764,7 +771,7 @@ void IEEE1588Port::processEvent(Event e) linkUpCount++; } } - this->timestamper_init(); + this->timestamper_reset(); break; case LINKDOWN: -- cgit v1.2.1 From 385e498287b403ccbe6292636f2099e01b6e14e1 Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Tue, 6 Sep 2016 14:25:04 -0600 Subject: gPTP: HWTimestamper_reset calls resetFrequencyAdjustment This plumbs a new method for HWTimestamper (default implementation does nothing) and for the generic Linux interface, it resets the timestamper frequency adjustment. Link up events on Linux should now reset the timestamper frequency adjustment. --- daemons/gptp/common/ieee1588.hpp | 7 +++++++ daemons/gptp/common/ieee1588port.cpp | 1 + daemons/gptp/linux/src/linux_hal_generic.cpp | 7 +++++++ daemons/gptp/linux/src/linux_hal_generic.hpp | 6 ++++++ 4 files changed, 21 insertions(+) diff --git a/daemons/gptp/common/ieee1588.hpp b/daemons/gptp/common/ieee1588.hpp index 79746862..d901c0c0 100644 --- a/daemons/gptp/common/ieee1588.hpp +++ b/daemons/gptp/common/ieee1588.hpp @@ -477,6 +477,13 @@ public: ( InterfaceLabel *iface_label, OSNetworkInterface *iface ) { return true; } + /** + * @brief Reset the hardware timestamp unit + * @return void + */ + virtual void HWTimestamper_reset(void) { + } + /** * @brief This method is called before the object is de-allocated. * @return void diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index f270be4d..0e0a021b 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -211,6 +211,7 @@ void IEEE1588Port::timestamper_reset(void) { if( _hw_timestamper != NULL ) { _hw_timestamper->init_phy_delay(this->link_delay); + _hw_timestamper->HWTimestamper_reset(); } } diff --git a/daemons/gptp/linux/src/linux_hal_generic.cpp b/daemons/gptp/linux/src/linux_hal_generic.cpp index 1dbcbc18..041e733f 100644 --- a/daemons/gptp/linux/src/linux_hal_generic.cpp +++ b/daemons/gptp/linux/src/linux_hal_generic.cpp @@ -269,6 +269,13 @@ bool LinuxTimestamperGeneric::HWTimestamper_init return true; } +void LinuxTimestamperGeneric::HWTimestamper_reset() +{ + if( !resetFrequencyAdjustment() ) { + GPTP_LOG_ERROR( "Failed to reset (zero) frequency adjustment" ); + } +} + int LinuxTimestamperGeneric::HWTimestamper_txtimestamp ( PortIdentity *identity, uint16_t sequenceId, Timestamp ×tamp, unsigned &clock_value, bool last ) { diff --git a/daemons/gptp/linux/src/linux_hal_generic.hpp b/daemons/gptp/linux/src/linux_hal_generic.hpp index abe1f276..8cd476e5 100644 --- a/daemons/gptp/linux/src/linux_hal_generic.hpp +++ b/daemons/gptp/linux/src/linux_hal_generic.hpp @@ -102,6 +102,12 @@ public: virtual bool HWTimestamper_init ( InterfaceLabel *iface_label, OSNetworkInterface *iface ); + /** + * @brief Reset the Hardware timestamp interface + * @return void + */ + virtual void HWTimestamper_reset(); + /** * @brief Inserts a new timestamp to the beginning of the * RX timestamp list. -- cgit v1.2.1 From 69c89739419d56426198e654e550aee9e09ae523 Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Mon, 12 Sep 2016 12:11:24 -0600 Subject: igb: Fix alloc size for igb_private_data Previous allocation was for the size of a pointer, not the structure. This caused kernel memory corruption when the igb_avb driver was used for streaming. --- kmod/igb/igb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index 79dead8f..7b13c1d6 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -10542,7 +10542,7 @@ static int igb_open_file(struct inode *inode, struct file *file) struct igb_private_data *igb_priv = NULL; int ret = 0; - igb_priv = kzalloc(sizeof(struct igb_private_data *), GFP_KERNEL); + igb_priv = kzalloc(sizeof(struct igb_private_data), GFP_KERNEL); if (igb_priv == NULL) { ret = -ENOMEM; goto out; -- cgit v1.2.1 From 05d838dfe7e33e3adf041879c3ca0f1bfdfab4d5 Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Thu, 16 Jun 2016 10:06:28 -0600 Subject: avtp_pipeline: Change DOS line endings to UNIX line endings --- lib/avtp_pipeline/include/openavb_log_pub.h | 492 +++---- lib/avtp_pipeline/include/openavb_platform_pub.h | 84 +- lib/avtp_pipeline/include/openavb_types_base_pub.h | 240 ++-- lib/avtp_pipeline/inih/ini.c | 584 ++++---- lib/avtp_pipeline/inih/ini.h | 144 +- .../intf_logger/openavb_intf_logger.c | 402 +++--- .../intf_tonegen/openavb_intf_tonegen.c | 1048 +++++++------- .../intf_viewer/openavb_intf_viewer.c | 1040 +++++++------- lib/avtp_pipeline/mcr/openavb_mcr_hal_pub.h | 130 +- .../platform/Linux/openavb_ether_osal.c | 78 +- .../platform/Linux/openavb_ether_osal.h | 58 +- lib/avtp_pipeline/platform/Linux/openavb_osal.c | 110 +- .../platform/Linux/openavb_osal_endpoint.c | 112 +- .../platform/Linux/openavb_time_osal.c | 413 +++--- .../platform/Linux/openavb_time_osal.h | 60 +- .../platform/platTCAL/GNU/openavb_mem_tcal.c | 78 +- .../platform/platTCAL/GNU/openavb_mem_tcal.h | 74 +- .../platform/platTCAL/GNU/openavb_mem_tcal_pub.h | 76 +- .../platform/platTCAL/GNU/openavb_tcal_pub.h | 76 +- .../platform/platTCAL/GNU/openavb_time_tcal_pub.h | 98 +- .../platTCAL/GNU/openavb_types_base_tcal_pub.h | 80 +- .../platform/platTCAL/GNU/openavb_warnings_tcal.h | 74 +- .../platTCAL/GNU/rawsock/openavb_rawsock_tcal.h | 118 +- .../platform/x86_i210/mcr/openavb_mcr_hal.c | 124 +- .../platform/x86_i210/mcr/openavb_mcr_hal.h | 74 +- lib/avtp_pipeline/platform/x86_i210/openavb_hal.h | 76 +- .../platform/x86_i210/openavb_time_hal.c | 144 +- .../platform/x86_i210/openavb_time_hal.h | 68 +- .../tl/openavb_listener_no_endpoint.c | 160 +-- lib/avtp_pipeline/tl/openavb_talker_no_endpoint.c | 302 ++-- lib/avtp_pipeline/tl/openavb_tl.c | 1468 ++++++++++---------- lib/avtp_pipeline/tl/openavb_tl_no_endpoint.c | 268 ++-- lib/avtp_pipeline/util/openavb_queue.c | 392 +++--- 33 files changed, 4372 insertions(+), 4373 deletions(-) diff --git a/lib/avtp_pipeline/include/openavb_log_pub.h b/lib/avtp_pipeline/include/openavb_log_pub.h index 92a93c98..9ae5f1e0 100644 --- a/lib/avtp_pipeline/include/openavb_log_pub.h +++ b/lib/avtp_pipeline/include/openavb_log_pub.h @@ -1,246 +1,246 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE SUMMARY : A simple logging facility for use during -* development. -*/ - -#ifndef OPENAVB_LOG_PUB_H -#define OPENAVB_LOG_PUB_H 1 - -// ******** -// Merge Issue -// TODO: Restructure to remove #ifdef code. -// ******** - -#include "openavb_platform_pub.h" -#include -#include -#include - -#include "openavb_types_pub.h" - -// Uncomment AVB_LOG_ON to enable logging. -#define AVB_LOG_ON 1 - -// Uncomment AVB_LOG_ON_OVERRIDE to override all AVB_LOG_ON usage in the stack to ensure all logs are off. -//#define AVB_LOG_ON_OVERRIDE 1 - -#ifdef AVB_LOG_ON_OVERRIDE -#ifdef AVB_LOG_ON -#undef AVB_LOG_ON -#endif -#endif - -#define AVB_LOG_LEVEL_NONE 0 -#define AVB_LOG_LEVEL_ERROR 1 -#define AVB_LOG_LEVEL_WARNING 2 -#define AVB_LOG_LEVEL_INFO 3 -#define AVB_LOG_LEVEL_STATUS 4 -#define AVB_LOG_LEVEL_DEBUG 5 -#define AVB_LOG_LEVEL_VERBOSE 6 - -// Special case development logging levels for use with AVB_LOGF_DEV and AVB_LOG_DEV -#define AVB_LOG_LEVEL_DEV_ON AVB_LOG_LEVEL_NONE -#define AVB_LOG_LEVEL_DEV_OFF AVB_LOG_LEVEL_VERBOSE + 1 - -// Default log level, can override in source files -#ifndef AVB_LOG_LEVEL -//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_ERROR -//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_INFO -#define AVB_LOG_LEVEL AVB_LOG_LEVEL_STATUS -//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_DEBUG -//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_VERBOSE -#endif - -#ifndef AVB_LOG_COMPANY -#define AVB_LOG_COMPANY "OPENAVB" -#endif - -#ifndef AVB_LOG_COMPONENT -#define AVB_LOG_COMPONENT "AVB Stack" -#endif - -// Log format options and sizes. Uncomment to include the formatted info. -#define LOG_MSG_LEN 1024 - -// The length of the full message -#define LOG_FULL_MSG_LEN 1024 - -static const bool OPENAVB_LOG_TIME_INFO = FALSE; -#define LOG_TIME_LEN 9 -//#define LOG_TIME_LEN 1 - -static const bool OPENAVB_LOG_TIMESTAMP_INFO = TRUE; -#define LOG_TIMESTAMP_LEN 32 -//#define LOG_TIMESTAMP_LEN 1 - -static const bool OPENAVB_LOG_FILE_INFO = FALSE; -//#define LOG_FILE_LEN 256 -#define LOG_FILE_LEN 1 - -static const bool OPENAVB_LOG_PROC_INFO = FALSE; -//#define LOG_PROC_LEN 64 -#define LOG_PROC_LEN 1 - -static const bool OPENAVB_LOG_THREAD_INFO = FALSE; -//#define LOG_THREAD_LEN 64 -#define LOG_THREAD_LEN 1 - -#define LOG_RT_MSG_LEN 256 -//#define LOG_RT_MSG_LEN 1 - -#define AVB_LOG_OUTPUT_FD stderr -//#define AVB_LOG_OUTPUT_FD stdout - -// When OPENAVB_LOG_FROM_THREAD the message output will be output from a separate thread/task -// Primary intended use is for debugging. -// It is expected that OPENAVB_LOG_PULL_MODE will not be used at the same time as this optoin. -static const bool OPENAVB_LOG_FROM_THREAD = TRUE; - -// When OPENAVB_LOG_PULL_MODE the messages will be queued and can be pulled using the -// avbLogGetMsg() call. This could be from an logger interface module or host application. -// It is expected that OPENAVB_LOG_FROM_THREAD will not be used at the same time as this option. -static const bool OPENAVB_LOG_PULL_MODE = FALSE; - -// When using the OPENAVB_LOG_FROM_THREAD option. These defines control the behavior of the msg queue -#define LOG_QUEUE_MSG_LEN 256 -#define LOG_QUEUE_MSG_SIZE (LOG_QUEUE_MSG_LEN + 1) -#define LOG_QUEUE_MSG_CNT 82 -#define LOG_QUEUE_SLEEP_MSEC 100 - -// RT (RealTime logging) related defines -#define LOG_RT_QUEUE_CNT 128 -#define LOG_RT_BEGIN TRUE -#define LOG_RT_ITEM TRUE -#define LOG_RT_END TRUE -typedef enum { - LOG_RT_DATATYPE_NONE, - LOG_RT_DATATYPE_CONST_STR, - LOG_RT_DATATYPE_NOW_TS, - LOG_RT_DATATYPE_U16, - LOG_RT_DATATYPE_S16, - LOG_RT_DATATYPE_U32, - LOG_RT_DATATYPE_S32, - LOG_RT_DATATYPE_U64, - LOG_RT_DATATYPE_S64, - LOG_RT_DATATYPE_FLOAT -} log_rt_datatype_t; - - -#define LOG_VARX(x, y) x ## y -#define LOG_VAR(x, y) LOG_VARX(x, y) - -// Log a message once. Technically once every 4.2 billion attempts. Usage: LOG_ONCE AVB_LOG_INFO(...) -#define IF_LOG_ONCE() static U32 LOG_VAR(logOnce,__LINE__); if (!LOG_VAR(logOnce,__LINE__)++) - -// Log a message at an interval. Usage: LOG_INTERVAL(100) AVB_LOG_INFO(...) -#define IF_LOG_INTERVAL(x) static U32 LOG_VAR(logOnce,__LINE__); if (!(LOG_VAR(logOnce,__LINE__)++ % (x - 1))) - - -#define ETH_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x" -#define ETH_OCTETS(a) (a)[0],(a)[1],(a)[2],(a)[3],(a)[4],(a)[5] - -#define STREAMID_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x/%d" -#define STREAMID_ARGS(s) (s)->addr[0],(s)->addr[1],(s)->addr[2],(s)->addr[3],(s)->addr[4],(s)->addr[5],(s)->uniqueID - -void avbLogInit(void); - -void avbLogExit(void); - -void avbLogFn( - int level, - const char *tag, - const char *company, - const char *component, - const char *path, - int line, - const char *fmt, - ...); - -void avbLogRT(int level, bool bBegin, bool bItem, bool bEnd, char *pFormat, log_rt_datatype_t dataType, void *pVar); - - -#define avbLogFn2(level, tag, company, component, path, line, fmt, ...) \ - ({\ - if (level <= AVB_LOG_LEVEL) \ - avbLogFn(0, tag, company, component, path, line, fmt, __VA_ARGS__); \ - }) - -#ifdef AVB_LOG_ON -#define AVB_LOGF_DEV(LEVEL, FMT, ...) avbLogFn2(LEVEL, "DEV", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) -#define AVB_LOGF_ERROR(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_ERROR, "ERROR", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) -#define AVB_LOGF_WARNING(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_WARNING, "WARNING", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) -#define AVB_LOGF_INFO(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_INFO, "INFO", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) -#define AVB_LOGF_STATUS(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_STATUS, "STATUS", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) -#define AVB_LOGF_DEBUG(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_DEBUG, "DEBUG", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) -#define AVB_LOGF_VERBOSE(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_VERBOSE, "VERBOSE", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) -#define AVB_LOG_DEV(LEVEL, FMT, ...) avbLogFn2(LEVEL, "DEV", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) -#define AVB_LOG_ERROR(MSG) avbLogFn2(AVB_LOG_LEVEL_ERROR, "ERROR", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) -#define AVB_LOG_WARNING(MSG) avbLogFn2(AVB_LOG_LEVEL_WARNING, "WARNING", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) -#define AVB_LOG_INFO(MSG) avbLogFn2(AVB_LOG_LEVEL_INFO, "INFO", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) -#define AVB_LOG_STATUS(MSG) avbLogFn2(AVB_LOG_LEVEL_STATUS, "STATUS", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) -#define AVB_LOG_DEBUG(MSG) avbLogFn2(AVB_LOG_LEVEL_DEBUG, "DEBUG", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) -#define AVB_LOG_VERBOSE(MSG) avbLogFn2(AVB_LOG_LEVEL_VERBOSE, "VERBOSE", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) -#define AVB_LOGRT_ERROR(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_ERROR, BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_WARNING(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_WARNING, BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_INFO(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_INFO, BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_STATUS(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_STATUS, BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_DEBUG(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_DEBUG, BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_VERBOSE(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_VERBOSE, BEGIN, ITEM, END, FMT, TYPE, VAL) -#else -#define AVB_LOGF_DEV(LEVEL, FMT, ...) -#define AVB_LOGF_ERROR(FMT, ...) -#define AVB_LOGF_WARNING(FMT, ...) -#define AVB_LOGF_INFO(FMT, ...) -#define AVB_LOGF_STATUS(FMT, ...) -#define AVB_LOGF_DEBUG(FMT, ...) -#define AVB_LOGF_VERBOSE(FMT, ...) -#define AVB_LOG_DEV(LEVEL, FMT, ...) -#define AVB_LOG_ERROR(MSG) -#define AVB_LOG_WARNING(MSG) -#define AVB_LOG_INFO(MSG) -#define AVB_LOG_STATUS(MSG) -#define AVB_LOG_DEBUG(MSG) -#define AVB_LOG_VERBOSE(MSG) -#define AVB_LOGRT_ERROR(BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_WARNING(BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_INFO(BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_STATUS(BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_DEBUG(BEGIN, ITEM, END, FMT, TYPE, VAL) -#define AVB_LOGRT_VERBOSE(BEGIN, ITEM, END, FMT, TYPE, VAL) -#endif // AVB_LOG_ON - -// Get a queued log message. Intended to be used with the OPENAVB_LOG_PULL_MODE option. -// Message will not be null terminated. -U32 avbLogGetMsg(U8 *pBuf, U32 bufSize); - -#endif // OPENAVB_LOG_PUB_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : A simple logging facility for use during +* development. +*/ + +#ifndef OPENAVB_LOG_PUB_H +#define OPENAVB_LOG_PUB_H 1 + +// ******** +// Merge Issue +// TODO: Restructure to remove #ifdef code. +// ******** + +#include "openavb_platform_pub.h" +#include +#include +#include + +#include "openavb_types_pub.h" + +// Uncomment AVB_LOG_ON to enable logging. +#define AVB_LOG_ON 1 + +// Uncomment AVB_LOG_ON_OVERRIDE to override all AVB_LOG_ON usage in the stack to ensure all logs are off. +//#define AVB_LOG_ON_OVERRIDE 1 + +#ifdef AVB_LOG_ON_OVERRIDE +#ifdef AVB_LOG_ON +#undef AVB_LOG_ON +#endif +#endif + +#define AVB_LOG_LEVEL_NONE 0 +#define AVB_LOG_LEVEL_ERROR 1 +#define AVB_LOG_LEVEL_WARNING 2 +#define AVB_LOG_LEVEL_INFO 3 +#define AVB_LOG_LEVEL_STATUS 4 +#define AVB_LOG_LEVEL_DEBUG 5 +#define AVB_LOG_LEVEL_VERBOSE 6 + +// Special case development logging levels for use with AVB_LOGF_DEV and AVB_LOG_DEV +#define AVB_LOG_LEVEL_DEV_ON AVB_LOG_LEVEL_NONE +#define AVB_LOG_LEVEL_DEV_OFF AVB_LOG_LEVEL_VERBOSE + 1 + +// Default log level, can override in source files +#ifndef AVB_LOG_LEVEL +//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_ERROR +//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_INFO +#define AVB_LOG_LEVEL AVB_LOG_LEVEL_STATUS +//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_DEBUG +//#define AVB_LOG_LEVEL AVB_LOG_LEVEL_VERBOSE +#endif + +#ifndef AVB_LOG_COMPANY +#define AVB_LOG_COMPANY "OPENAVB" +#endif + +#ifndef AVB_LOG_COMPONENT +#define AVB_LOG_COMPONENT "AVB Stack" +#endif + +// Log format options and sizes. Uncomment to include the formatted info. +#define LOG_MSG_LEN 1024 + +// The length of the full message +#define LOG_FULL_MSG_LEN 1024 + +static const bool OPENAVB_LOG_TIME_INFO = FALSE; +#define LOG_TIME_LEN 9 +//#define LOG_TIME_LEN 1 + +static const bool OPENAVB_LOG_TIMESTAMP_INFO = TRUE; +#define LOG_TIMESTAMP_LEN 32 +//#define LOG_TIMESTAMP_LEN 1 + +static const bool OPENAVB_LOG_FILE_INFO = FALSE; +//#define LOG_FILE_LEN 256 +#define LOG_FILE_LEN 1 + +static const bool OPENAVB_LOG_PROC_INFO = FALSE; +//#define LOG_PROC_LEN 64 +#define LOG_PROC_LEN 1 + +static const bool OPENAVB_LOG_THREAD_INFO = FALSE; +//#define LOG_THREAD_LEN 64 +#define LOG_THREAD_LEN 1 + +#define LOG_RT_MSG_LEN 256 +//#define LOG_RT_MSG_LEN 1 + +#define AVB_LOG_OUTPUT_FD stderr +//#define AVB_LOG_OUTPUT_FD stdout + +// When OPENAVB_LOG_FROM_THREAD the message output will be output from a separate thread/task +// Primary intended use is for debugging. +// It is expected that OPENAVB_LOG_PULL_MODE will not be used at the same time as this optoin. +static const bool OPENAVB_LOG_FROM_THREAD = TRUE; + +// When OPENAVB_LOG_PULL_MODE the messages will be queued and can be pulled using the +// avbLogGetMsg() call. This could be from an logger interface module or host application. +// It is expected that OPENAVB_LOG_FROM_THREAD will not be used at the same time as this option. +static const bool OPENAVB_LOG_PULL_MODE = FALSE; + +// When using the OPENAVB_LOG_FROM_THREAD option. These defines control the behavior of the msg queue +#define LOG_QUEUE_MSG_LEN 256 +#define LOG_QUEUE_MSG_SIZE (LOG_QUEUE_MSG_LEN + 1) +#define LOG_QUEUE_MSG_CNT 82 +#define LOG_QUEUE_SLEEP_MSEC 100 + +// RT (RealTime logging) related defines +#define LOG_RT_QUEUE_CNT 128 +#define LOG_RT_BEGIN TRUE +#define LOG_RT_ITEM TRUE +#define LOG_RT_END TRUE +typedef enum { + LOG_RT_DATATYPE_NONE, + LOG_RT_DATATYPE_CONST_STR, + LOG_RT_DATATYPE_NOW_TS, + LOG_RT_DATATYPE_U16, + LOG_RT_DATATYPE_S16, + LOG_RT_DATATYPE_U32, + LOG_RT_DATATYPE_S32, + LOG_RT_DATATYPE_U64, + LOG_RT_DATATYPE_S64, + LOG_RT_DATATYPE_FLOAT +} log_rt_datatype_t; + + +#define LOG_VARX(x, y) x ## y +#define LOG_VAR(x, y) LOG_VARX(x, y) + +// Log a message once. Technically once every 4.2 billion attempts. Usage: LOG_ONCE AVB_LOG_INFO(...) +#define IF_LOG_ONCE() static U32 LOG_VAR(logOnce,__LINE__); if (!LOG_VAR(logOnce,__LINE__)++) + +// Log a message at an interval. Usage: LOG_INTERVAL(100) AVB_LOG_INFO(...) +#define IF_LOG_INTERVAL(x) static U32 LOG_VAR(logOnce,__LINE__); if (!(LOG_VAR(logOnce,__LINE__)++ % (x - 1))) + + +#define ETH_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x" +#define ETH_OCTETS(a) (a)[0],(a)[1],(a)[2],(a)[3],(a)[4],(a)[5] + +#define STREAMID_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x/%d" +#define STREAMID_ARGS(s) (s)->addr[0],(s)->addr[1],(s)->addr[2],(s)->addr[3],(s)->addr[4],(s)->addr[5],(s)->uniqueID + +void avbLogInit(void); + +void avbLogExit(void); + +void avbLogFn( + int level, + const char *tag, + const char *company, + const char *component, + const char *path, + int line, + const char *fmt, + ...); + +void avbLogRT(int level, bool bBegin, bool bItem, bool bEnd, char *pFormat, log_rt_datatype_t dataType, void *pVar); + + +#define avbLogFn2(level, tag, company, component, path, line, fmt, ...) \ + ({\ + if (level <= AVB_LOG_LEVEL) \ + avbLogFn(0, tag, company, component, path, line, fmt, __VA_ARGS__); \ + }) + +#ifdef AVB_LOG_ON +#define AVB_LOGF_DEV(LEVEL, FMT, ...) avbLogFn2(LEVEL, "DEV", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) +#define AVB_LOGF_ERROR(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_ERROR, "ERROR", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) +#define AVB_LOGF_WARNING(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_WARNING, "WARNING", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) +#define AVB_LOGF_INFO(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_INFO, "INFO", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) +#define AVB_LOGF_STATUS(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_STATUS, "STATUS", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) +#define AVB_LOGF_DEBUG(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_DEBUG, "DEBUG", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) +#define AVB_LOGF_VERBOSE(FMT, ...) avbLogFn2(AVB_LOG_LEVEL_VERBOSE, "VERBOSE", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) +#define AVB_LOG_DEV(LEVEL, FMT, ...) avbLogFn2(LEVEL, "DEV", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, FMT, __VA_ARGS__) +#define AVB_LOG_ERROR(MSG) avbLogFn2(AVB_LOG_LEVEL_ERROR, "ERROR", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) +#define AVB_LOG_WARNING(MSG) avbLogFn2(AVB_LOG_LEVEL_WARNING, "WARNING", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) +#define AVB_LOG_INFO(MSG) avbLogFn2(AVB_LOG_LEVEL_INFO, "INFO", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) +#define AVB_LOG_STATUS(MSG) avbLogFn2(AVB_LOG_LEVEL_STATUS, "STATUS", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) +#define AVB_LOG_DEBUG(MSG) avbLogFn2(AVB_LOG_LEVEL_DEBUG, "DEBUG", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) +#define AVB_LOG_VERBOSE(MSG) avbLogFn2(AVB_LOG_LEVEL_VERBOSE, "VERBOSE", AVB_LOG_COMPANY, AVB_LOG_COMPONENT, __FILE__, __LINE__, "%s", MSG) +#define AVB_LOGRT_ERROR(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_ERROR, BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_WARNING(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_WARNING, BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_INFO(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_INFO, BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_STATUS(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_STATUS, BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_DEBUG(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_DEBUG, BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_VERBOSE(BEGIN, ITEM, END, FMT, TYPE, VAL) avbLogRT(AVB_LOG_LEVEL_VERBOSE, BEGIN, ITEM, END, FMT, TYPE, VAL) +#else +#define AVB_LOGF_DEV(LEVEL, FMT, ...) +#define AVB_LOGF_ERROR(FMT, ...) +#define AVB_LOGF_WARNING(FMT, ...) +#define AVB_LOGF_INFO(FMT, ...) +#define AVB_LOGF_STATUS(FMT, ...) +#define AVB_LOGF_DEBUG(FMT, ...) +#define AVB_LOGF_VERBOSE(FMT, ...) +#define AVB_LOG_DEV(LEVEL, FMT, ...) +#define AVB_LOG_ERROR(MSG) +#define AVB_LOG_WARNING(MSG) +#define AVB_LOG_INFO(MSG) +#define AVB_LOG_STATUS(MSG) +#define AVB_LOG_DEBUG(MSG) +#define AVB_LOG_VERBOSE(MSG) +#define AVB_LOGRT_ERROR(BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_WARNING(BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_INFO(BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_STATUS(BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_DEBUG(BEGIN, ITEM, END, FMT, TYPE, VAL) +#define AVB_LOGRT_VERBOSE(BEGIN, ITEM, END, FMT, TYPE, VAL) +#endif // AVB_LOG_ON + +// Get a queued log message. Intended to be used with the OPENAVB_LOG_PULL_MODE option. +// Message will not be null terminated. +U32 avbLogGetMsg(U8 *pBuf, U32 bufSize); + +#endif // OPENAVB_LOG_PUB_H diff --git a/lib/avtp_pipeline/include/openavb_platform_pub.h b/lib/avtp_pipeline/include/openavb_platform_pub.h index 61233712..8be98866 100644 --- a/lib/avtp_pipeline/include/openavb_platform_pub.h +++ b/lib/avtp_pipeline/include/openavb_platform_pub.h @@ -1,42 +1,42 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE : Public interface for platform specific functionality -*/ - -#ifndef _OPENAVB_PLATFORM_PUB_H -#define _OPENAVB_PLATFORM_PUB_H - -#include "openavb_types_pub.h" -#include "openavb_osal_pub.h" -#include "openavb_mem_tcal_pub.h" - -#endif // _OPENAVB_PLATFORM_PUB_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE : Public interface for platform specific functionality +*/ + +#ifndef _OPENAVB_PLATFORM_PUB_H +#define _OPENAVB_PLATFORM_PUB_H + +#include "openavb_types_pub.h" +#include "openavb_osal_pub.h" +#include "openavb_mem_tcal_pub.h" + +#endif // _OPENAVB_PLATFORM_PUB_H diff --git a/lib/avtp_pipeline/include/openavb_types_base_pub.h b/lib/avtp_pipeline/include/openavb_types_base_pub.h index f568477a..1d03e80a 100644 --- a/lib/avtp_pipeline/include/openavb_types_base_pub.h +++ b/lib/avtp_pipeline/include/openavb_types_base_pub.h @@ -1,120 +1,120 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE : Public AVB Base Types (have no dependencies) -*/ - -#ifndef AVB_TYPES_BASE_PUB_H -#define AVB_TYPES_BASE_PUB_H 1 - -#include "openavb_types_base_tcal_pub.h" -#include -#include - -/** \file - * Common Base AVB Types that are exposed outside of the AVB - * stack. - */ - -/* - * Useful types for OPENAVB AVB - * - */ -/// Number of nanoseconds in second -#define NANOSECONDS_PER_SECOND (1000000000ULL) -/// Number of nanoseconds in milisecond -#define NANOSECONDS_PER_MSEC (1000000L) -/// Number of nanoseconds in microsecond -#define NANOSECONDS_PER_USEC (1000L) -/// Number of microseconds in second -#define MICROSECONDS_PER_SECOND (1000000L) -/// Number of microseconds in milisecond -#define MICROSECONDS_PER_MSEC (1000L) - -#ifndef TRUE // possible confict with gboolean -/// True boolean value -#define TRUE true -/// False boolean value -#define FALSE false -#endif - -#ifndef NULL -/// Null pointer value -#define NULL 0 -#endif - -/// Signed 8 bit type -typedef int8_t S8; -/// Unsigned 8 bit type -typedef uint8_t U8; -/// Signed 16 bit type -typedef int16_t S16; -/// Unsigned 16 bit type -typedef uint16_t U16; -/// Signed 32 bit type -typedef int32_t S32; -/// Unsigned 32 bit type -typedef uint32_t U32; -/// Signed 64 bit type -typedef int64_t S64; -/// Unsigned 64 bit type -typedef uint64_t U64; - -/// Describes role of the host -typedef enum { - /// Role undefined or wrong handle - AVB_ROLE_UNDEFINED = 0, - /// Host acts as a talker - AVB_ROLE_TALKER, - /// Host acts as a listener - AVB_ROLE_LISTENER -} avb_role_t; - - - -/// Supported AVB classes. -typedef enum { - /// Stream reservation class A. 8000 packets per second - SR_CLASS_A, - /// Stream reservation class B. 4000 packets per second - SR_CLASS_B, -// SR_CLASS_C, -// SR_CLASS_D, - /// Number of supported stream reservation classes - MAX_AVB_SR_CLASSES -} SRClassIdx_t; - -/// Regular -#define SR_RANK_REGULAR 1 -/// Emergency -#define SR_RANK_EMERGENCY 0 - -#endif // AVB_TYPES_BASE_PUB_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE : Public AVB Base Types (have no dependencies) +*/ + +#ifndef AVB_TYPES_BASE_PUB_H +#define AVB_TYPES_BASE_PUB_H 1 + +#include "openavb_types_base_tcal_pub.h" +#include +#include + +/** \file + * Common Base AVB Types that are exposed outside of the AVB + * stack. + */ + +/* + * Useful types for OPENAVB AVB + * + */ +/// Number of nanoseconds in second +#define NANOSECONDS_PER_SECOND (1000000000ULL) +/// Number of nanoseconds in milisecond +#define NANOSECONDS_PER_MSEC (1000000L) +/// Number of nanoseconds in microsecond +#define NANOSECONDS_PER_USEC (1000L) +/// Number of microseconds in second +#define MICROSECONDS_PER_SECOND (1000000L) +/// Number of microseconds in milisecond +#define MICROSECONDS_PER_MSEC (1000L) + +#ifndef TRUE // possible confict with gboolean +/// True boolean value +#define TRUE true +/// False boolean value +#define FALSE false +#endif + +#ifndef NULL +/// Null pointer value +#define NULL 0 +#endif + +/// Signed 8 bit type +typedef int8_t S8; +/// Unsigned 8 bit type +typedef uint8_t U8; +/// Signed 16 bit type +typedef int16_t S16; +/// Unsigned 16 bit type +typedef uint16_t U16; +/// Signed 32 bit type +typedef int32_t S32; +/// Unsigned 32 bit type +typedef uint32_t U32; +/// Signed 64 bit type +typedef int64_t S64; +/// Unsigned 64 bit type +typedef uint64_t U64; + +/// Describes role of the host +typedef enum { + /// Role undefined or wrong handle + AVB_ROLE_UNDEFINED = 0, + /// Host acts as a talker + AVB_ROLE_TALKER, + /// Host acts as a listener + AVB_ROLE_LISTENER +} avb_role_t; + + + +/// Supported AVB classes. +typedef enum { + /// Stream reservation class A. 8000 packets per second + SR_CLASS_A, + /// Stream reservation class B. 4000 packets per second + SR_CLASS_B, +// SR_CLASS_C, +// SR_CLASS_D, + /// Number of supported stream reservation classes + MAX_AVB_SR_CLASSES +} SRClassIdx_t; + +/// Regular +#define SR_RANK_REGULAR 1 +/// Emergency +#define SR_RANK_EMERGENCY 0 + +#endif // AVB_TYPES_BASE_PUB_H diff --git a/lib/avtp_pipeline/inih/ini.c b/lib/avtp_pipeline/inih/ini.c index 4fad5c51..0f32fa56 100644 --- a/lib/avtp_pipeline/inih/ini.c +++ b/lib/avtp_pipeline/inih/ini.c @@ -1,292 +1,292 @@ -/* inih -- simple .INI file parser - -inih is released under the New BSD license (see LICENSE.txt). Go to the project -home page for more info: - -http://code.google.com/p/inih/ - -*/ - -#include -#include -#include -#include -#include "ini.h" - -#if !INI_USE_STACK -#include -#endif - -#define MAX_SECTION 50 -#define MAX_NAME 50 - -/* Strip whitespace chars off end of given string, in place. Return s. */ -static char* rstrip(char* s) -{ - char* p = s + strlen(s); - while (p > s && isspace(*--p)) - *p = '\0'; - return s; -} - -/* Return pointer to first non-whitespace char in given string. */ -static char* lskip(const char* s) -{ - while (*s && isspace(*s)) - s++; - return (char*)s; -} - -/* Return pointer to first char c or ';' comment in given string, or pointer to - null at end of string if neither found. ';' must be prefixed by a whitespace - character to register as a comment. */ -static char* find_char_or_comment(const char* s, char c) -{ - int was_whitespace = 0; - while (*s && *s != c && !(was_whitespace && *s == ';')) { - was_whitespace = isspace(*s); - s++; - } - return (char*)s; -} - -/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ -static char* strncpy0(char* dest, const char* src, size_t size) -{ - strncpy(dest, src, size); - dest[size - 1] = '\0'; - return dest; -} - -/* See documentation in header file. */ -int ini_parse_file(FILE* file, - int (*handler)(void*, const char*, const char*, - const char*), - void* user) -{ - /* Uses a fair bit of stack (use heap instead if you need to) */ -#if INI_USE_STACK - char line[INI_MAX_LINE]; -#else - char* line; -#endif - char section[MAX_SECTION] = ""; - char prev_name[MAX_NAME] = ""; - - char* start; - char* end; - char* name; - char* value; - int lineno = 0; - int error = 0; - -#if !INI_USE_STACK - line = (char*)malloc(INI_MAX_LINE); - if (!line) { - return -2; - } -#endif - - /* Scan through file line by line */ - while (fgets(line, INI_MAX_LINE, file) != NULL) { - lineno++; - - start = line; -#if INI_ALLOW_BOM - if (lineno == 1 && (unsigned char)start[0] == 0xEF && - (unsigned char)start[1] == 0xBB && - (unsigned char)start[2] == 0xBF) { - start += 3; - } -#endif - start = lskip(rstrip(start)); - - if (*start == ';' || *start == '#') { - /* Per Python ConfigParser, allow '#' comments at start of line */ - } -#if INI_ALLOW_MULTILINE - else if (*prev_name && *start && start > line) { - /* Non-black line with leading whitespace, treat as continuation - of previous name's value (as per Python ConfigParser). */ - if (!handler(user, section, prev_name, start) && !error) - error = lineno; - } -#endif - else if (*start == '[') { - /* A "[section]" line */ - end = find_char_or_comment(start + 1, ']'); - if (*end == ']') { - *end = '\0'; - strncpy0(section, start + 1, sizeof(section)); - *prev_name = '\0'; - } - else if (!error) { - /* No ']' found on section line */ - error = lineno; - } - } - else if (*start && *start != ';') { - /* Not a comment, must be a name[=:]value pair */ - end = find_char_or_comment(start, '='); - if (*end != '=') { - end = find_char_or_comment(start, ':'); - } - if (*end == '=' || *end == ':') { - *end = '\0'; - name = rstrip(start); - value = lskip(end + 1); - end = find_char_or_comment(value, '\0'); - if (*end == ';') - *end = '\0'; - rstrip(value); - - /* Valid name[=:]value pair found, call handler */ - strncpy0(prev_name, name, sizeof(prev_name)); - if (!handler(user, section, name, value) && !error) - error = lineno; - } - else if (!error) { - /* No '=' or ':' found on name[=:]value line */ - error = lineno; - } - } - } - -#if !INI_USE_STACK - free(line); -#endif - - return error; -} - -#define NULL_CHAR '\0' -#define COMMA ',' - -int ini_parse_override(char *override, - int (*handler)(void*, const char*, const char*, - const char*), - void* user) -{ -#if INI_USE_STACK - char line[INI_MAX_LINE]; -#else - char* line; -#endif - char section[MAX_SECTION] = ""; - char *name, *value; - - char *src = override; - int error = -1; - int i, j; - -#if !INI_USE_STACK - line = (char*)malloc(INI_MAX_LINE); - if (!line) { - return -2; - } -#endif - - while (*src != NULL_CHAR) - { - if (*src == COMMA) { - src++; - } - else if (*src == '[') { - // section - src++; // skip opening delim - for (i = 0; i < MAX_SECTION; i++) { - section[i] = *src++; - if (section[i] == NULL_CHAR) { - // error, section not completed - goto out; - } - else if (section[i] == ']') { - section[i] = NULL_CHAR; - break; - } - } - if (i > MAX_SECTION) - goto out; // error, overflowed buffer - } - else { - // name/value - name = &line[0]; - for (i = 0; i < MAX_NAME; i++) { - line[i] = *src++; - if (line[i] == NULL_CHAR) { - // error, name not completed - goto out; - } - else if (line[i] == COMMA) { - // error, no value - goto out; - } - else if (line[i] == '=') { - line[i] = NULL_CHAR; - break; - } - } - if (i > MAX_NAME) - goto out; // error, overflowed buffer - - value = &line[i + 1]; - for (j = i + 1; j < INI_MAX_LINE; j++) { - line[j] = *src++; - if (line[j] == ',') { - line[j] = NULL_CHAR; - break; - } - if (line[j] == NULL_CHAR) { - src--; // oops! - break; - } - - } - if (j > INI_MAX_LINE) - goto out; // error, overflowed buffer - - if (!handler(user, section, name, value) && !error) - error = -3; - } - } - - // all parsed! - error = 0; - - out: -#if !INI_USE_STACK - free(line); -#endif - return error; -} - -/* See documentation in header file. */ -int ini_parse(const char* filename, - int (*handler)(void*, const char*, const char*, const char*), - void* user) -{ - FILE* file; - int error; - char *pvtFilename = strdup(filename); - if (!pvtFilename) { - return -1; - } - - char *override = strchr(pvtFilename, COMMA); - if (override) - *override++ = '\0'; - - file = fopen(pvtFilename, "r"); - if (!file) { - free (pvtFilename); - return -1; - } - error = ini_parse_file(file, handler, user); - - if (error == 0 && override) - error = ini_parse_override(override, handler, user); - fclose(file); - free (pvtFilename); - - return error; -} +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +http://code.google.com/p/inih/ + +*/ + +#include +#include +#include +#include +#include "ini.h" + +#if !INI_USE_STACK +#include +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace(*--p)) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace(*s)) + s++; + return (char*)s; +} + +/* Return pointer to first char c or ';' comment in given string, or pointer to + null at end of string if neither found. ';' must be prefixed by a whitespace + character to register as a comment. */ +static char* find_char_or_comment(const char* s, char c) +{ + int was_whitespace = 0; + while (*s && *s != c && !(was_whitespace && *s == ';')) { + was_whitespace = isspace(*s); + s++; + } + return (char*)s; +} + +/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + strncpy(dest, src, size); + dest[size - 1] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, + int (*handler)(void*, const char*, const char*, + const char*), + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; +#else + char* line; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)malloc(INI_MAX_LINE); + if (!line) { + return -2; + } +#endif + + /* Scan through file line by line */ + while (fgets(line, INI_MAX_LINE, file) != NULL) { + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (*start == ';' || *start == '#') { + /* Per Python ConfigParser, allow '#' comments at start of line */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-black line with leading whitespace, treat as continuation + of previous name's value (as per Python ConfigParser). */ + if (!handler(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_char_or_comment(start + 1, ']'); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start && *start != ';') { + /* Not a comment, must be a name[=:]value pair */ + end = find_char_or_comment(start, '='); + if (*end != '=') { + end = find_char_or_comment(start, ':'); + } + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = lskip(end + 1); + end = find_char_or_comment(value, '\0'); + if (*end == ';') + *end = '\0'; + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!handler(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ + error = lineno; + } + } + } + +#if !INI_USE_STACK + free(line); +#endif + + return error; +} + +#define NULL_CHAR '\0' +#define COMMA ',' + +int ini_parse_override(char *override, + int (*handler)(void*, const char*, const char*, + const char*), + void* user) +{ +#if INI_USE_STACK + char line[INI_MAX_LINE]; +#else + char* line; +#endif + char section[MAX_SECTION] = ""; + char *name, *value; + + char *src = override; + int error = -1; + int i, j; + +#if !INI_USE_STACK + line = (char*)malloc(INI_MAX_LINE); + if (!line) { + return -2; + } +#endif + + while (*src != NULL_CHAR) + { + if (*src == COMMA) { + src++; + } + else if (*src == '[') { + // section + src++; // skip opening delim + for (i = 0; i < MAX_SECTION; i++) { + section[i] = *src++; + if (section[i] == NULL_CHAR) { + // error, section not completed + goto out; + } + else if (section[i] == ']') { + section[i] = NULL_CHAR; + break; + } + } + if (i > MAX_SECTION) + goto out; // error, overflowed buffer + } + else { + // name/value + name = &line[0]; + for (i = 0; i < MAX_NAME; i++) { + line[i] = *src++; + if (line[i] == NULL_CHAR) { + // error, name not completed + goto out; + } + else if (line[i] == COMMA) { + // error, no value + goto out; + } + else if (line[i] == '=') { + line[i] = NULL_CHAR; + break; + } + } + if (i > MAX_NAME) + goto out; // error, overflowed buffer + + value = &line[i + 1]; + for (j = i + 1; j < INI_MAX_LINE; j++) { + line[j] = *src++; + if (line[j] == ',') { + line[j] = NULL_CHAR; + break; + } + if (line[j] == NULL_CHAR) { + src--; // oops! + break; + } + + } + if (j > INI_MAX_LINE) + goto out; // error, overflowed buffer + + if (!handler(user, section, name, value) && !error) + error = -3; + } + } + + // all parsed! + error = 0; + + out: +#if !INI_USE_STACK + free(line); +#endif + return error; +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, + int (*handler)(void*, const char*, const char*, const char*), + void* user) +{ + FILE* file; + int error; + char *pvtFilename = strdup(filename); + if (!pvtFilename) { + return -1; + } + + char *override = strchr(pvtFilename, COMMA); + if (override) + *override++ = '\0'; + + file = fopen(pvtFilename, "r"); + if (!file) { + free (pvtFilename); + return -1; + } + error = ini_parse_file(file, handler, user); + + if (error == 0 && override) + error = ini_parse_override(override, handler, user); + fclose(file); + free (pvtFilename); + + return error; +} diff --git a/lib/avtp_pipeline/inih/ini.h b/lib/avtp_pipeline/inih/ini.h index 9ebfd492..984d52b7 100644 --- a/lib/avtp_pipeline/inih/ini.h +++ b/lib/avtp_pipeline/inih/ini.h @@ -1,72 +1,72 @@ -/* inih -- simple .INI file parser - -inih is released under the New BSD license (see LICENSE.txt). Go to the project -home page for more info: - -http://code.google.com/p/inih/ - -*/ - -#ifndef __INI_H__ -#define __INI_H__ - -/* Make this header file easier to include in C++ code */ -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* Parse given INI-style file. May have [section]s, name=value pairs - (whitespace stripped), and comments starting with ';' (semicolon). Section - is "" if name=value pair parsed before any section heading. name:value - pairs are also supported as a concession to Python's ConfigParser. - - For each name=value pair parsed, call handler function with given user - pointer as well as section, name, and value (data only valid for duration - of handler call). Handler should return nonzero on success, zero on error. - - Returns 0 on success, line number of first error on parse error (doesn't - stop on first error), -1 on file open error, or -2 on memory allocation - error (only when INI_USE_STACK is zero). -*/ -int ini_parse(const char* filename, - int (*handler)(void* user, const char* section, - const char* name, const char* value), - void* user); - -/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't - close the file when it's finished -- the caller must do that. */ -int ini_parse_file(FILE* file, - int (*handler)(void* user, const char* section, - const char* name, const char* value), - void* user); - -/* Nonzero to allow multi-line value parsing, in the style of Python's - ConfigParser. If allowed, ini_parse() will call the handler with the same - name for each subsequent line parsed. */ -#ifndef INI_ALLOW_MULTILINE -#define INI_ALLOW_MULTILINE 1 -#endif - -/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of - the file. See http://code.google.com/p/inih/issues/detail?id=21 */ -#ifndef INI_ALLOW_BOM -#define INI_ALLOW_BOM 1 -#endif - -/* Nonzero to use stack, zero to use heap (malloc/free). */ -#ifndef INI_USE_STACK -#define INI_USE_STACK 1 -#endif - -/* Maximum line length for any line in INI file. */ -#ifndef INI_MAX_LINE -#define INI_MAX_LINE 512 -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __INI_H__ */ +/* inih -- simple .INI file parser + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +http://code.google.com/p/inih/ + +*/ + +#ifndef __INI_H__ +#define __INI_H__ + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's ConfigParser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, + int (*handler)(void* user, const char* section, + const char* name, const char* value), + void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, + int (*handler)(void* user, const char* section, + const char* name, const char* value), + void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + ConfigParser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See http://code.google.com/p/inih/issues/detail?id=21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Nonzero to use stack, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file. */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 512 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __INI_H__ */ diff --git a/lib/avtp_pipeline/intf_logger/openavb_intf_logger.c b/lib/avtp_pipeline/intf_logger/openavb_intf_logger.c index 38adaecc..91417d0c 100644 --- a/lib/avtp_pipeline/intf_logger/openavb_intf_logger.c +++ b/lib/avtp_pipeline/intf_logger/openavb_intf_logger.c @@ -1,201 +1,201 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* Usage Notes: It is expected that there will be at most only 1 logger -* interface module running. -*/ - -#include -#include -#include "openavb_types_pub.h" -#include "openavb_trace_pub.h" -#include "openavb_mediaq_pub.h" -#include "openavb_intf_pub.h" - -#define AVB_LOG_COMPONENT "Logger Interface" -#include "openavb_log_pub.h" - -typedef struct { - ///////////// - // Config data - ///////////// - // Ignore timestamp at listener. - bool ignoreTimestamp; - - ///////////// - // Variable data - ///////////// -} pvt_data_t; - - -// Each configuration name value pair for this mapping will result in this callback being called. -void openavbIntfLoggerCfgCB(media_q_t *pMediaQ, const char *name, const char *value) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - if (pMediaQ) { - //char *pEnd; - //long tmp; - - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return; - } - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -void openavbIntfLoggerGenInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// A call to this callback indicates that this interface module will be -// a talker. Any talker initialization can be done in this function. -void openavbIntfLoggerTxInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - - if (pMediaQ) { - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return; - } - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// This callback will be called for each AVB transmit interval. Commonly this will be -// 4000 or 8000 times per second. -bool openavbIntfLoggerTxCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); - if (pMediaQ) { - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return FALSE; - } - - media_q_item_t *pMediaQItem = openavbMediaQHeadLock(pMediaQ); - if (pMediaQItem) { - U32 dataLen = avbLogGetMsg(pMediaQItem->pPubData, pMediaQItem->itemSize); - if (dataLen) { - pMediaQItem->dataLen = dataLen; - openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); - openavbMediaQHeadPush(pMediaQ); - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return TRUE; - } - else { - openavbMediaQHeadUnlock(pMediaQ); - } - } - else { - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return FALSE; // Media queue full - } - } - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return FALSE; -} - -// A call to this callback indicates that this interface module will be -// a listener. Any listener initialization can be done in this function. -void openavbIntfLoggerRxInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// This callback is called when acting as a listener. -bool openavbIntfLoggerRxCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return FALSE; -} - -// This callback will be called when the stream is closing. -void openavbIntfLoggerEndCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// General shutdown callback regardless if a talker or listener. Called once during openavbTLClose() -void openavbIntfLoggerGenEndCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - if (pMediaQ) { - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return; - } - } - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// Main initialization entry point into the interface module -extern bool DLL_EXPORT openavbIntfLoggerInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - - if (pMediaQ) { - pMediaQ->pPvtIntfInfo = calloc(1, sizeof(pvt_data_t)); // Memory freed by the media queue when the media queue is destroyed. - - if (!pMediaQ->pPvtIntfInfo) { - AVB_LOG_ERROR("Unable to allocate memory for AVTP interface module."); - return FALSE; - } - - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - - pIntfCB->intf_cfg_cb = openavbIntfLoggerCfgCB; - pIntfCB->intf_gen_init_cb = openavbIntfLoggerGenInitCB; - pIntfCB->intf_tx_init_cb = openavbIntfLoggerTxInitCB; - pIntfCB->intf_tx_cb = openavbIntfLoggerTxCB; - pIntfCB->intf_rx_init_cb = openavbIntfLoggerRxInitCB; - pIntfCB->intf_rx_cb = openavbIntfLoggerRxCB; - pIntfCB->intf_end_cb = openavbIntfLoggerEndCB; - pIntfCB->intf_gen_end_cb = openavbIntfLoggerGenEndCB; - - pPvtData->ignoreTimestamp = FALSE; - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); - return TRUE; -} +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* Usage Notes: It is expected that there will be at most only 1 logger +* interface module running. +*/ + +#include +#include +#include "openavb_types_pub.h" +#include "openavb_trace_pub.h" +#include "openavb_mediaq_pub.h" +#include "openavb_intf_pub.h" + +#define AVB_LOG_COMPONENT "Logger Interface" +#include "openavb_log_pub.h" + +typedef struct { + ///////////// + // Config data + ///////////// + // Ignore timestamp at listener. + bool ignoreTimestamp; + + ///////////// + // Variable data + ///////////// +} pvt_data_t; + + +// Each configuration name value pair for this mapping will result in this callback being called. +void openavbIntfLoggerCfgCB(media_q_t *pMediaQ, const char *name, const char *value) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + if (pMediaQ) { + //char *pEnd; + //long tmp; + + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return; + } + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +void openavbIntfLoggerGenInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// A call to this callback indicates that this interface module will be +// a talker. Any talker initialization can be done in this function. +void openavbIntfLoggerTxInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + + if (pMediaQ) { + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return; + } + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// This callback will be called for each AVB transmit interval. Commonly this will be +// 4000 or 8000 times per second. +bool openavbIntfLoggerTxCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); + if (pMediaQ) { + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return FALSE; + } + + media_q_item_t *pMediaQItem = openavbMediaQHeadLock(pMediaQ); + if (pMediaQItem) { + U32 dataLen = avbLogGetMsg(pMediaQItem->pPubData, pMediaQItem->itemSize); + if (dataLen) { + pMediaQItem->dataLen = dataLen; + openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); + openavbMediaQHeadPush(pMediaQ); + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return TRUE; + } + else { + openavbMediaQHeadUnlock(pMediaQ); + } + } + else { + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return FALSE; // Media queue full + } + } + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return FALSE; +} + +// A call to this callback indicates that this interface module will be +// a listener. Any listener initialization can be done in this function. +void openavbIntfLoggerRxInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// This callback is called when acting as a listener. +bool openavbIntfLoggerRxCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return FALSE; +} + +// This callback will be called when the stream is closing. +void openavbIntfLoggerEndCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// General shutdown callback regardless if a talker or listener. Called once during openavbTLClose() +void openavbIntfLoggerGenEndCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + if (pMediaQ) { + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return; + } + } + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// Main initialization entry point into the interface module +extern bool DLL_EXPORT openavbIntfLoggerInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + + if (pMediaQ) { + pMediaQ->pPvtIntfInfo = calloc(1, sizeof(pvt_data_t)); // Memory freed by the media queue when the media queue is destroyed. + + if (!pMediaQ->pPvtIntfInfo) { + AVB_LOG_ERROR("Unable to allocate memory for AVTP interface module."); + return FALSE; + } + + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + + pIntfCB->intf_cfg_cb = openavbIntfLoggerCfgCB; + pIntfCB->intf_gen_init_cb = openavbIntfLoggerGenInitCB; + pIntfCB->intf_tx_init_cb = openavbIntfLoggerTxInitCB; + pIntfCB->intf_tx_cb = openavbIntfLoggerTxCB; + pIntfCB->intf_rx_init_cb = openavbIntfLoggerRxInitCB; + pIntfCB->intf_rx_cb = openavbIntfLoggerRxCB; + pIntfCB->intf_end_cb = openavbIntfLoggerEndCB; + pIntfCB->intf_gen_end_cb = openavbIntfLoggerGenEndCB; + + pPvtData->ignoreTimestamp = FALSE; + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); + return TRUE; +} diff --git a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c index d9b214a8..b2a1bf23 100644 --- a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c +++ b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c @@ -1,524 +1,524 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE SUMMARY : Tone generator interface module. Talker only. -* -* - This interface module generates and audio tone for use with -6 and AAF mappings -* - Requires an OSAL sin implementation of reasonable performance. -*/ - -#include -#include -#include -#include "openavb_platform_pub.h" -#include "openavb_osal_pub.h" -#include "openavb_types_pub.h" -#include "openavb_trace_pub.h" -#include "openavb_mediaq_pub.h" -#include "openavb_map_uncmp_audio_pub.h" -#include "openavb_map_aaf_audio_pub.h" -#include "openavb_intf_pub.h" - -#define AVB_LOG_COMPONENT "Tone Gen Interface" -#include "openavb_log_pub.h" - -#define PI 3.14159265358979f - -typedef struct { - ///////////// - // Config data - ///////////// - // intf_nv_tone_hz: The tone hz to generate - U32 toneHz; - - // intf_nv_on_off_interval_msec: Interval for turning tone on and off. A value of zero will keep the tone on. - U32 onOffIntervalMSec; - - // Simple melody - char *pMelodyString; - - // intf_nv_audio_rate - avb_audio_rate_t audioRate; - - // intf_nv_audio_type - avb_audio_bit_depth_t audioType; - - // intf_nv_audio_bit_depth - avb_audio_bit_depth_t audioBitDepth; - - // intf_nv_audio_endian - avb_audio_bit_depth_t audioEndian; - - // intf_nv_channels - avb_audio_channels_t audioChannels; - - ///////////// - // Variable data - ///////////// - - // Packing interval - U32 intervalCounter; - - // Keeps track of if the tone is currently on or off - U32 freq; - - // Keeps track of how long before toggling the tone on / off - U32 freqCountdown; - - // Ratio precalc - float ratio; - - // Index to into the melody string - U32 melodyIdx; - - // Length of the melody string - U32 melodyLen; - -} pvt_data_t; - -#define MSEC_PER_COUNT 250 -static void xGetMelodyToneAndDuration(char note, char count, U32 *freq, U32 *sampleMSec) -{ - switch (note) { - case 'A': - *freq = 220; - break; - case 'B': - *freq = 246; - break; - case 'C': - *freq = 261; - break; - case 'D': - *freq = 293; - break; - case 'E': - *freq = 329; - break; - case 'F': - *freq = 349; - break; - case 'G': - *freq = 391; - break; - case 'a': - *freq = 440; - break; - case 'b': - *freq = 493; - break; - case 'c': - *freq = 523; - break; - case 'd': - *freq = 587; - break; - case 'e': - *freq = 659; - break; - case 'f': - *freq = 698; - break; - case 'g': - *freq = 783; - break; - case '-': - default: - *freq = 0; - break; - } - - switch (count) { - case '1': - *sampleMSec = MSEC_PER_COUNT * 1; - break; - case '2': - *sampleMSec = MSEC_PER_COUNT * 2; - break; - case '3': - *sampleMSec = MSEC_PER_COUNT * 3; - break; - case '4': - *sampleMSec = MSEC_PER_COUNT * 4; - break; - default: - *sampleMSec = MSEC_PER_COUNT * 4; - break; - } -} - -static bool xSupportedMappingFormat(media_q_t *pMediaQ) -{ - if (pMediaQ) { - if (pMediaQ->pMediaQDataFormat) { - if (strcmp(pMediaQ->pMediaQDataFormat, MapUncmpAudioMediaQDataFormat) == 0 || strcmp(pMediaQ->pMediaQDataFormat, MapAVTPAudioMediaQDataFormat) == 0) { - return TRUE; - } - } - } - return FALSE; -} - -// Each configuration name value pair for this mapping will result in this callback being called. -void openavbIntfToneGenCfgCB(media_q_t *pMediaQ, const char *name, const char *value) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - - char *pEnd; - U32 val; - - if (pMediaQ) { - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return; - } - - media_q_pub_map_uncmp_audio_info_t *pPubMapUncmpAudioInfo; - pPubMapUncmpAudioInfo = (media_q_pub_map_uncmp_audio_info_t *)pMediaQ->pPubMapInfo; - if (!pPubMapUncmpAudioInfo) { - AVB_LOG_ERROR("Public map data for audio info not allocated."); - return; - } - - if (strcmp(name, "intf_nv_tone_hz") == 0) { - pPvtData->toneHz = strtol(value, &pEnd, 10); - } - - else if (strcmp(name, "intf_nv_on_off_interval_msec") == 0) { - pPvtData->onOffIntervalMSec = strtol(value, &pEnd, 10); - } - - else if (strcmp(name, "intf_nv_melody_string") == 0) { - if (pPvtData->pMelodyString) - free(pPvtData->pMelodyString); - pPvtData->pMelodyString = strdup(value); - if (pPvtData->pMelodyString) { - pPvtData->melodyLen = strlen(pPvtData->pMelodyString); - } - } - - else if (strcmp(name, "intf_nv_audio_rate") == 0) { - val = strtol(value, &pEnd, 10); - // TODO: Should check for specific values - if (val >= AVB_AUDIO_RATE_8KHZ && val <= AVB_AUDIO_RATE_192KHZ) { - pPvtData->audioRate = (avb_audio_rate_t)val; - } - else { - AVB_LOG_ERROR("Invalid audio rate configured for intf_nv_audio_rate."); - pPvtData->audioRate = AVB_AUDIO_RATE_44_1KHZ; - } - - // Give the audio parameters to the mapping module. - if (xSupportedMappingFormat(pMediaQ)) { - pPubMapUncmpAudioInfo->audioRate = pPvtData->audioRate; - } - } - - else if (strcmp(name, "intf_nv_audio_bit_depth") == 0) { - val = strtol(value, &pEnd, 10); - // TODO: Should check for specific values - if (val >= AVB_AUDIO_BIT_DEPTH_1BIT && val <= AVB_AUDIO_BIT_DEPTH_64BIT) { - pPvtData->audioBitDepth = (avb_audio_bit_depth_t)val; - } - else { - AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_bits."); - pPvtData->audioBitDepth = AVB_AUDIO_BIT_DEPTH_24BIT; - } - - // Give the audio parameters to the mapping module. - if (xSupportedMappingFormat(pMediaQ)) { - pPubMapUncmpAudioInfo->audioBitDepth = pPvtData->audioBitDepth; - } - } - - else if (strcmp(name, "intf_nv_audio_type") == 0) { - if (strncasecmp(value, "float", 5) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_FLOAT; - else if (strncasecmp(value, "sign", 4) == 0 || strncasecmp(value, "int", 4) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_INT; - else if (strncasecmp(value, "unsign", 6) == 0 || strncasecmp(value, "uint", 4) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_UINT; - else { - AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_type."); - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_UNSPEC; - } - - // Give the audio parameters to the mapping module. - if (xSupportedMappingFormat(pMediaQ)) { - pPubMapUncmpAudioInfo->audioType = (avb_audio_type_t)pPvtData->audioType; - } - } - - else if (strcmp(name, "intf_nv_audio_endian") == 0) { - if (strncasecmp(value, "big", 3) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_BIG; - else if (strncasecmp(value, "little", 6) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_LITTLE; - else { - AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_endian."); - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_UNSPEC; - } - - // Give the audio parameters to the mapping module. - if (xSupportedMappingFormat(pMediaQ)) { - pPubMapUncmpAudioInfo->audioEndian = (avb_audio_endian_t)pPvtData->audioEndian; - } - } - - else if (strcmp(name, "intf_nv_audio_channels") == 0) { - val = strtol(value, &pEnd, 10); - // TODO: Should check for specific values - if (val >= AVB_AUDIO_CHANNELS_1 && val <= AVB_AUDIO_CHANNELS_8) { - pPvtData->audioChannels = (avb_audio_channels_t)val; - } - else { - AVB_LOG_ERROR("Invalid audio channels configured for intf_nv_audio_channels."); - pPvtData->audioChannels = (avb_audio_channels_t)AVB_AUDIO_CHANNELS_2; - } - - // Give the audio parameters to the mapping module. - if (xSupportedMappingFormat(pMediaQ)) { - pPubMapUncmpAudioInfo->audioChannels = pPvtData->audioChannels; - } - } - - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -void openavbIntfToneGenGenInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// A call to this callback indicates that this interface module will be -// a talker. Any talker initialization can be done in this function. -void openavbIntfToneGenTxInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - - if (pMediaQ) { - - // U8 b; - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return; - } - - media_q_pub_map_uncmp_audio_info_t *pPubMapUncmpAudioInfo; - pPubMapUncmpAudioInfo = (media_q_pub_map_uncmp_audio_info_t *)pMediaQ->pPubMapInfo; - if (!pPubMapUncmpAudioInfo) { - AVB_LOG_ERROR("Public map data for audio info not allocated."); - return; - } - - // Will get toggle on at the first tx cb - if (pPvtData->onOffIntervalMSec > 0) { - pPvtData->freq = pPvtData->toneHz; - pPvtData->freqCountdown = 0; - } - else { - pPvtData->freq = 0; - pPvtData->freqCountdown = 0; - } - - pPvtData->melodyIdx = 0; - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// This callback will be called for each AVB transmit interval. Commonly this will be -// 4000 or 8000 times per second. -bool openavbIntfToneGenTxCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); - - if (pMediaQ) { - media_q_pub_map_uncmp_audio_info_t *pPubMapUncmpAudioInfo = pMediaQ->pPubMapInfo; - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return FALSE; - } - - if (pPvtData->intervalCounter++ % pPubMapUncmpAudioInfo->packingFactor != 0) - return TRUE; - - media_q_item_t *pMediaQItem = openavbMediaQHeadLock(pMediaQ); - if (pMediaQItem) { - if (pMediaQItem->itemSize < pPubMapUncmpAudioInfo->itemSize) { - AVB_LOG_ERROR("Media queue item not large enough for samples"); - } - - // Tone on - static U32 runningFrameCnt = 0; - U32 frameCnt; - U32 channelCnt; - U32 idx = 0; - for (frameCnt = 0; frameCnt < pPubMapUncmpAudioInfo->framesPerItem; frameCnt++) { - - // Check for tone on / off toggle - if (!pPvtData->freqCountdown) { - if (pPvtData->pMelodyString) { - // Melody logic - U32 intervalMSec; - xGetMelodyToneAndDuration( - pPvtData->pMelodyString[pPvtData->melodyIdx], - pPvtData->pMelodyString[pPvtData->melodyIdx + 1], - &pPvtData->freq, &intervalMSec); - pPvtData->melodyIdx += 2; - - pPvtData->freqCountdown = (pPubMapUncmpAudioInfo->audioRate / 1000) * intervalMSec; - if (pPvtData->melodyIdx >= pPvtData->melodyLen) - pPvtData->melodyIdx = 0; - } - else { - // Fixed tone - if (pPvtData->onOffIntervalMSec > 0) { - if (pPvtData->freq == 0) - pPvtData->freq = pPvtData->toneHz; - else - pPvtData->freq = 0; - pPvtData->freqCountdown = (pPubMapUncmpAudioInfo->audioRate / 1000) * pPvtData->onOffIntervalMSec; - } - else { - pPvtData->freqCountdown = pPubMapUncmpAudioInfo->audioRate; // Just run steady for 1 sec - } - } - pPvtData->ratio = pPvtData->freq / (float)pPubMapUncmpAudioInfo->audioRate; - } - pPvtData->freqCountdown--; - - - float value = SIN(2 * PI * (runningFrameCnt++ % pPubMapUncmpAudioInfo->audioRate) * pPvtData->ratio); - - if (pPubMapUncmpAudioInfo->itemSampleSizeBytes == 2) { - // 16 bit audio - S16 sample = (S16)(value * 15000); - for (channelCnt = 0; channelCnt < pPubMapUncmpAudioInfo->audioChannels; channelCnt++) { - unsigned char c; - U8 *pData = pMediaQItem->pPubData; - c = (unsigned)sample % 256; - pData[idx++] = c; - c = (unsigned)sample / 256 % 256; - pData[idx++] = c; - } - } - else { - // CORE_TODO - AVB_LOG_ERROR("Audio sample size format not implemented yet for tone generator interface module"); - } - } - - pMediaQItem->dataLen = pPubMapUncmpAudioInfo->itemSize; - - openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); - openavbMediaQHeadPush(pMediaQ); - - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return TRUE; - } - else { - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return FALSE; // Media queue full - } - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return FALSE; -} - -// A call to this callback indicates that this interface module will be -// a listener. Any listener initialization can be done in this function. -void openavbIntfToneGenRxInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// This callback is called when acting as a listener. -bool openavbIntfToneGenRxCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return FALSE; -} - -// This callback will be called when the interface needs to be closed. All shutdown should -// occur in this function. -void openavbIntfToneGenEndCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -void openavbIntfToneGenGenEndCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// Main initialization entry point into the interface module -extern DLL_EXPORT bool openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - - if (pMediaQ) { - pMediaQ->pPvtIntfInfo = calloc(1, sizeof(pvt_data_t)); // Memory freed by the media queue when the media queue is destroyed. - - if (!pMediaQ->pPvtIntfInfo) { - AVB_LOG_ERROR("Unable to allocate memory for AVTP interface module."); - return FALSE; - } - - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - - pIntfCB->intf_cfg_cb = openavbIntfToneGenCfgCB; - pIntfCB->intf_gen_init_cb = openavbIntfToneGenGenInitCB; - pIntfCB->intf_tx_init_cb = openavbIntfToneGenTxInitCB; - pIntfCB->intf_tx_cb = openavbIntfToneGenTxCB; - pIntfCB->intf_rx_init_cb = openavbIntfToneGenRxInitCB; - pIntfCB->intf_rx_cb = openavbIntfToneGenRxCB; - pIntfCB->intf_end_cb = openavbIntfToneGenEndCB; - pIntfCB->intf_gen_end_cb = openavbIntfToneGenGenEndCB; - - pPvtData->intervalCounter = 0; - pPvtData->melodyIdx = 0; - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); - return TRUE; -} +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : Tone generator interface module. Talker only. +* +* - This interface module generates and audio tone for use with -6 and AAF mappings +* - Requires an OSAL sin implementation of reasonable performance. +*/ + +#include +#include +#include +#include "openavb_platform_pub.h" +#include "openavb_osal_pub.h" +#include "openavb_types_pub.h" +#include "openavb_trace_pub.h" +#include "openavb_mediaq_pub.h" +#include "openavb_map_uncmp_audio_pub.h" +#include "openavb_map_aaf_audio_pub.h" +#include "openavb_intf_pub.h" + +#define AVB_LOG_COMPONENT "Tone Gen Interface" +#include "openavb_log_pub.h" + +#define PI 3.14159265358979f + +typedef struct { + ///////////// + // Config data + ///////////// + // intf_nv_tone_hz: The tone hz to generate + U32 toneHz; + + // intf_nv_on_off_interval_msec: Interval for turning tone on and off. A value of zero will keep the tone on. + U32 onOffIntervalMSec; + + // Simple melody + char *pMelodyString; + + // intf_nv_audio_rate + avb_audio_rate_t audioRate; + + // intf_nv_audio_type + avb_audio_bit_depth_t audioType; + + // intf_nv_audio_bit_depth + avb_audio_bit_depth_t audioBitDepth; + + // intf_nv_audio_endian + avb_audio_bit_depth_t audioEndian; + + // intf_nv_channels + avb_audio_channels_t audioChannels; + + ///////////// + // Variable data + ///////////// + + // Packing interval + U32 intervalCounter; + + // Keeps track of if the tone is currently on or off + U32 freq; + + // Keeps track of how long before toggling the tone on / off + U32 freqCountdown; + + // Ratio precalc + float ratio; + + // Index to into the melody string + U32 melodyIdx; + + // Length of the melody string + U32 melodyLen; + +} pvt_data_t; + +#define MSEC_PER_COUNT 250 +static void xGetMelodyToneAndDuration(char note, char count, U32 *freq, U32 *sampleMSec) +{ + switch (note) { + case 'A': + *freq = 220; + break; + case 'B': + *freq = 246; + break; + case 'C': + *freq = 261; + break; + case 'D': + *freq = 293; + break; + case 'E': + *freq = 329; + break; + case 'F': + *freq = 349; + break; + case 'G': + *freq = 391; + break; + case 'a': + *freq = 440; + break; + case 'b': + *freq = 493; + break; + case 'c': + *freq = 523; + break; + case 'd': + *freq = 587; + break; + case 'e': + *freq = 659; + break; + case 'f': + *freq = 698; + break; + case 'g': + *freq = 783; + break; + case '-': + default: + *freq = 0; + break; + } + + switch (count) { + case '1': + *sampleMSec = MSEC_PER_COUNT * 1; + break; + case '2': + *sampleMSec = MSEC_PER_COUNT * 2; + break; + case '3': + *sampleMSec = MSEC_PER_COUNT * 3; + break; + case '4': + *sampleMSec = MSEC_PER_COUNT * 4; + break; + default: + *sampleMSec = MSEC_PER_COUNT * 4; + break; + } +} + +static bool xSupportedMappingFormat(media_q_t *pMediaQ) +{ + if (pMediaQ) { + if (pMediaQ->pMediaQDataFormat) { + if (strcmp(pMediaQ->pMediaQDataFormat, MapUncmpAudioMediaQDataFormat) == 0 || strcmp(pMediaQ->pMediaQDataFormat, MapAVTPAudioMediaQDataFormat) == 0) { + return TRUE; + } + } + } + return FALSE; +} + +// Each configuration name value pair for this mapping will result in this callback being called. +void openavbIntfToneGenCfgCB(media_q_t *pMediaQ, const char *name, const char *value) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + + char *pEnd; + U32 val; + + if (pMediaQ) { + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return; + } + + media_q_pub_map_uncmp_audio_info_t *pPubMapUncmpAudioInfo; + pPubMapUncmpAudioInfo = (media_q_pub_map_uncmp_audio_info_t *)pMediaQ->pPubMapInfo; + if (!pPubMapUncmpAudioInfo) { + AVB_LOG_ERROR("Public map data for audio info not allocated."); + return; + } + + if (strcmp(name, "intf_nv_tone_hz") == 0) { + pPvtData->toneHz = strtol(value, &pEnd, 10); + } + + else if (strcmp(name, "intf_nv_on_off_interval_msec") == 0) { + pPvtData->onOffIntervalMSec = strtol(value, &pEnd, 10); + } + + else if (strcmp(name, "intf_nv_melody_string") == 0) { + if (pPvtData->pMelodyString) + free(pPvtData->pMelodyString); + pPvtData->pMelodyString = strdup(value); + if (pPvtData->pMelodyString) { + pPvtData->melodyLen = strlen(pPvtData->pMelodyString); + } + } + + else if (strcmp(name, "intf_nv_audio_rate") == 0) { + val = strtol(value, &pEnd, 10); + // TODO: Should check for specific values + if (val >= AVB_AUDIO_RATE_8KHZ && val <= AVB_AUDIO_RATE_192KHZ) { + pPvtData->audioRate = (avb_audio_rate_t)val; + } + else { + AVB_LOG_ERROR("Invalid audio rate configured for intf_nv_audio_rate."); + pPvtData->audioRate = AVB_AUDIO_RATE_44_1KHZ; + } + + // Give the audio parameters to the mapping module. + if (xSupportedMappingFormat(pMediaQ)) { + pPubMapUncmpAudioInfo->audioRate = pPvtData->audioRate; + } + } + + else if (strcmp(name, "intf_nv_audio_bit_depth") == 0) { + val = strtol(value, &pEnd, 10); + // TODO: Should check for specific values + if (val >= AVB_AUDIO_BIT_DEPTH_1BIT && val <= AVB_AUDIO_BIT_DEPTH_64BIT) { + pPvtData->audioBitDepth = (avb_audio_bit_depth_t)val; + } + else { + AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_bits."); + pPvtData->audioBitDepth = AVB_AUDIO_BIT_DEPTH_24BIT; + } + + // Give the audio parameters to the mapping module. + if (xSupportedMappingFormat(pMediaQ)) { + pPubMapUncmpAudioInfo->audioBitDepth = pPvtData->audioBitDepth; + } + } + + else if (strcmp(name, "intf_nv_audio_type") == 0) { + if (strncasecmp(value, "float", 5) == 0) + pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_FLOAT; + else if (strncasecmp(value, "sign", 4) == 0 || strncasecmp(value, "int", 4) == 0) + pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_INT; + else if (strncasecmp(value, "unsign", 6) == 0 || strncasecmp(value, "uint", 4) == 0) + pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_UINT; + else { + AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_type."); + pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_UNSPEC; + } + + // Give the audio parameters to the mapping module. + if (xSupportedMappingFormat(pMediaQ)) { + pPubMapUncmpAudioInfo->audioType = (avb_audio_type_t)pPvtData->audioType; + } + } + + else if (strcmp(name, "intf_nv_audio_endian") == 0) { + if (strncasecmp(value, "big", 3) == 0) + pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_BIG; + else if (strncasecmp(value, "little", 6) == 0) + pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_LITTLE; + else { + AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_endian."); + pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_UNSPEC; + } + + // Give the audio parameters to the mapping module. + if (xSupportedMappingFormat(pMediaQ)) { + pPubMapUncmpAudioInfo->audioEndian = (avb_audio_endian_t)pPvtData->audioEndian; + } + } + + else if (strcmp(name, "intf_nv_audio_channels") == 0) { + val = strtol(value, &pEnd, 10); + // TODO: Should check for specific values + if (val >= AVB_AUDIO_CHANNELS_1 && val <= AVB_AUDIO_CHANNELS_8) { + pPvtData->audioChannels = (avb_audio_channels_t)val; + } + else { + AVB_LOG_ERROR("Invalid audio channels configured for intf_nv_audio_channels."); + pPvtData->audioChannels = (avb_audio_channels_t)AVB_AUDIO_CHANNELS_2; + } + + // Give the audio parameters to the mapping module. + if (xSupportedMappingFormat(pMediaQ)) { + pPubMapUncmpAudioInfo->audioChannels = pPvtData->audioChannels; + } + } + + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +void openavbIntfToneGenGenInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// A call to this callback indicates that this interface module will be +// a talker. Any talker initialization can be done in this function. +void openavbIntfToneGenTxInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + + if (pMediaQ) { + + // U8 b; + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return; + } + + media_q_pub_map_uncmp_audio_info_t *pPubMapUncmpAudioInfo; + pPubMapUncmpAudioInfo = (media_q_pub_map_uncmp_audio_info_t *)pMediaQ->pPubMapInfo; + if (!pPubMapUncmpAudioInfo) { + AVB_LOG_ERROR("Public map data for audio info not allocated."); + return; + } + + // Will get toggle on at the first tx cb + if (pPvtData->onOffIntervalMSec > 0) { + pPvtData->freq = pPvtData->toneHz; + pPvtData->freqCountdown = 0; + } + else { + pPvtData->freq = 0; + pPvtData->freqCountdown = 0; + } + + pPvtData->melodyIdx = 0; + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// This callback will be called for each AVB transmit interval. Commonly this will be +// 4000 or 8000 times per second. +bool openavbIntfToneGenTxCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); + + if (pMediaQ) { + media_q_pub_map_uncmp_audio_info_t *pPubMapUncmpAudioInfo = pMediaQ->pPubMapInfo; + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return FALSE; + } + + if (pPvtData->intervalCounter++ % pPubMapUncmpAudioInfo->packingFactor != 0) + return TRUE; + + media_q_item_t *pMediaQItem = openavbMediaQHeadLock(pMediaQ); + if (pMediaQItem) { + if (pMediaQItem->itemSize < pPubMapUncmpAudioInfo->itemSize) { + AVB_LOG_ERROR("Media queue item not large enough for samples"); + } + + // Tone on + static U32 runningFrameCnt = 0; + U32 frameCnt; + U32 channelCnt; + U32 idx = 0; + for (frameCnt = 0; frameCnt < pPubMapUncmpAudioInfo->framesPerItem; frameCnt++) { + + // Check for tone on / off toggle + if (!pPvtData->freqCountdown) { + if (pPvtData->pMelodyString) { + // Melody logic + U32 intervalMSec; + xGetMelodyToneAndDuration( + pPvtData->pMelodyString[pPvtData->melodyIdx], + pPvtData->pMelodyString[pPvtData->melodyIdx + 1], + &pPvtData->freq, &intervalMSec); + pPvtData->melodyIdx += 2; + + pPvtData->freqCountdown = (pPubMapUncmpAudioInfo->audioRate / 1000) * intervalMSec; + if (pPvtData->melodyIdx >= pPvtData->melodyLen) + pPvtData->melodyIdx = 0; + } + else { + // Fixed tone + if (pPvtData->onOffIntervalMSec > 0) { + if (pPvtData->freq == 0) + pPvtData->freq = pPvtData->toneHz; + else + pPvtData->freq = 0; + pPvtData->freqCountdown = (pPubMapUncmpAudioInfo->audioRate / 1000) * pPvtData->onOffIntervalMSec; + } + else { + pPvtData->freqCountdown = pPubMapUncmpAudioInfo->audioRate; // Just run steady for 1 sec + } + } + pPvtData->ratio = pPvtData->freq / (float)pPubMapUncmpAudioInfo->audioRate; + } + pPvtData->freqCountdown--; + + + float value = SIN(2 * PI * (runningFrameCnt++ % pPubMapUncmpAudioInfo->audioRate) * pPvtData->ratio); + + if (pPubMapUncmpAudioInfo->itemSampleSizeBytes == 2) { + // 16 bit audio + S16 sample = (S16)(value * 15000); + for (channelCnt = 0; channelCnt < pPubMapUncmpAudioInfo->audioChannels; channelCnt++) { + unsigned char c; + U8 *pData = pMediaQItem->pPubData; + c = (unsigned)sample % 256; + pData[idx++] = c; + c = (unsigned)sample / 256 % 256; + pData[idx++] = c; + } + } + else { + // CORE_TODO + AVB_LOG_ERROR("Audio sample size format not implemented yet for tone generator interface module"); + } + } + + pMediaQItem->dataLen = pPubMapUncmpAudioInfo->itemSize; + + openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); + openavbMediaQHeadPush(pMediaQ); + + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return TRUE; + } + else { + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return FALSE; // Media queue full + } + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return FALSE; +} + +// A call to this callback indicates that this interface module will be +// a listener. Any listener initialization can be done in this function. +void openavbIntfToneGenRxInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// This callback is called when acting as a listener. +bool openavbIntfToneGenRxCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return FALSE; +} + +// This callback will be called when the interface needs to be closed. All shutdown should +// occur in this function. +void openavbIntfToneGenEndCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +void openavbIntfToneGenGenEndCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// Main initialization entry point into the interface module +extern DLL_EXPORT bool openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + + if (pMediaQ) { + pMediaQ->pPvtIntfInfo = calloc(1, sizeof(pvt_data_t)); // Memory freed by the media queue when the media queue is destroyed. + + if (!pMediaQ->pPvtIntfInfo) { + AVB_LOG_ERROR("Unable to allocate memory for AVTP interface module."); + return FALSE; + } + + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + + pIntfCB->intf_cfg_cb = openavbIntfToneGenCfgCB; + pIntfCB->intf_gen_init_cb = openavbIntfToneGenGenInitCB; + pIntfCB->intf_tx_init_cb = openavbIntfToneGenTxInitCB; + pIntfCB->intf_tx_cb = openavbIntfToneGenTxCB; + pIntfCB->intf_rx_init_cb = openavbIntfToneGenRxInitCB; + pIntfCB->intf_rx_cb = openavbIntfToneGenRxCB; + pIntfCB->intf_end_cb = openavbIntfToneGenEndCB; + pIntfCB->intf_gen_end_cb = openavbIntfToneGenGenEndCB; + + pPvtData->intervalCounter = 0; + pPvtData->melodyIdx = 0; + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); + return TRUE; +} diff --git a/lib/avtp_pipeline/intf_viewer/openavb_intf_viewer.c b/lib/avtp_pipeline/intf_viewer/openavb_intf_viewer.c index 3ad743ca..0e406dc6 100755 --- a/lib/avtp_pipeline/intf_viewer/openavb_intf_viewer.c +++ b/lib/avtp_pipeline/intf_viewer/openavb_intf_viewer.c @@ -1,520 +1,520 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE SUMMARY : Viewer interface module. -* -* This interface module is only a listener and is used to simply display -* contents recieved in a number of different formats. Additionally it is -* mapping type aware and can display header values for different mappings -*/ - -#include -#include -#include "openavb_platform_pub.h" -#include "openavb_types_pub.h" -#include "openavb_trace_pub.h" -#include "openavb_mediaq_pub.h" -#include "openavb_intf_pub.h" - -#define AVB_LOG_COMPONENT "Viewer Interface" -#include "openavb_log_pub.h" - -typedef enum { - VIEWER_MODE_DETAIL = 0, - VIEWER_MODE_MAPPING_AWARE = 1, - VIEWER_MODE_AVTP_TIMESTAMP = 2, - VIEWER_MODE_LATENCY = 3, - VIEWER_MODE_SELECTIVE_TIMESTAMP = 4, - VIEWER_MODE_LATE = 5, - VIEWER_MODE_GAP = 6, -} viewer_mode_t; - -typedef struct { - ///////////// - // Config data - ///////////// - viewer_mode_t viewType; - - // Frequency of output - U32 viewInterval; - - // Offest into the raw frame to output - U32 rawOffset; - - // Length of the raw frame to output - U32 rawLength; - - // Ignore timestamp at listener. - bool ignoreTimestamp; - - ///////////// - // Variable data - ///////////// - U32 servicedCount; - - S64 accumLateNS; - - S32 maxLateNS; - - U64 accumGapNS; - - U32 maxGapNS; - - U64 prevNowTime; - - S64 accumAvtpDeltaNS; - - S32 maxAvtpDeltaNS; - - U64 prevAvtpTimestampTime; - - U32 skipCountdown; - - float jitter; - - S32 avgForJitter; - -} pvt_data_t; - -// Each configuration name value pair for this mapping will result in this callback being called. -void openavbIntfViewerCfgCB(media_q_t *pMediaQ, const char *name, const char *value) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - - if (pMediaQ) { - char *pEnd; - long tmp; - - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return; - } - - // intf_nv_view_type: Type of viewing output. 0 = raw, 1 = mapping aware, 2 = timestamps only, 3 = latency output, 4 = Selective timestamp error reporting - if (strcmp(name, "intf_nv_view_type") == 0) { - pPvtData->viewType = (viewer_mode_t)strtol(value, &pEnd, 10); - } - - else if (strcmp(name, "intf_nv_view_interval") == 0) { - pPvtData->viewInterval = strtol(value, &pEnd, 10); - if (pPvtData->viewInterval == 0) { - pPvtData->viewInterval = 1000; - } - } - - else if (strcmp(name, "intf_nv_raw_offset") == 0) { - pPvtData->rawOffset = strtol(value, &pEnd, 10); - } - - else if (strcmp(name, "intf_nv_raw_length") == 0) { - pPvtData->rawLength = strtol(value, &pEnd, 10); - if (pPvtData->rawLength < 1) - pPvtData->rawLength = 1000; - } - - else if (strcmp(name, "intf_nv_ignore_timestamp") == 0) { - tmp = strtol(value, &pEnd, 10); - if (*pEnd == '\0' && tmp == 1) { - pPvtData->ignoreTimestamp = (tmp == 1); - } - } - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -void openavbIntfViewerGenInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// No talker functionality in this interface -void openavbIntfViewerTxInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// No talker functionality in this interface -bool openavbIntfViewerTxCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return FALSE; -} - -// A call to this callback indicates that this interface module will be -// a listener. Any listener initialization can be done in this function. -void openavbIntfViewerRxInitCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - - if (pMediaQ) { - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return; - } - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// This callback is called when acting as a listener. -bool openavbIntfViewerRxCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); - if (pMediaQ) { - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - if (!pPvtData) { - AVB_LOG_ERROR("Private interface module data not allocated."); - return FALSE; - } - - media_q_item_t *pMediaQItem = openavbMediaQTailLock(pMediaQ, pPvtData->ignoreTimestamp); - if (pMediaQItem) { - - // The skip countdown allow the viewer modes to set a number of packets to ignore - // after logging to reduce or eliminate the logging from affecting the stats. - if (pPvtData->skipCountdown) - pPvtData->skipCountdown--; - - if (pMediaQItem->dataLen && !pPvtData->skipCountdown) { - pPvtData->servicedCount++; - - if (pPvtData->viewType == VIEWER_MODE_DETAIL) { - U32 avtpTimestamp; - U64 avtpTimestampTime; - bool avtpTimestampValid; - U32 nowTimestamp; - U64 nowTimestampTime; - bool nowTimestampValid; - U64 nowTime; - S32 lateNS = 0; - U64 gapNS = 0; - - avtpTimestamp = openavbAvtpTimeGetAvtpTimestamp(pMediaQItem->pAvtpTime); - avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); - avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); - - openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); - nowTimestamp = openavbAvtpTimeGetAvtpTimestamp(pMediaQItem->pAvtpTime); - nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); - nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); - - CLOCK_GETTIME64(OPENAVB_CLOCK_REALTIME, &nowTime); - - if (avtpTimestampValid && nowTimestampValid) { - lateNS = nowTimestampTime - avtpTimestampTime; - if (lateNS > pPvtData->maxLateNS) { - pPvtData->maxLateNS = lateNS; - } - pPvtData->accumLateNS += lateNS; - - if (pPvtData->servicedCount > 1) { - gapNS = nowTime - pPvtData->prevNowTime; - if (gapNS > pPvtData->maxGapNS) { - pPvtData->maxGapNS = gapNS; - } - pPvtData->accumGapNS += gapNS; - } - pPvtData->prevNowTime = nowTime; - - if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { - S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; - S32 gapAvg = pPvtData->accumGapNS / (pPvtData->servicedCount - 1); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "****************************", LOG_RT_DATATYPE_CONST_STR, NULL); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Packets: %u", LOG_RT_DATATYPE_U32, &pPvtData->servicedCount); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "AVTP Timestamp: %u NS", LOG_RT_DATATYPE_U32, &avtpTimestamp); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Now Timestamp: %u NS", LOG_RT_DATATYPE_U32, &nowTimestamp); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late: %d NS", LOG_RT_DATATYPE_S32, &lateNS); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late Avg: %d NS", LOG_RT_DATATYPE_S32, &lateAvg); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late Max: %d NS", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap: %u NS", LOG_RT_DATATYPE_U32, &gapNS); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap Avg: %u NS", LOG_RT_DATATYPE_U32, &gapAvg); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap Max: %u NS", LOG_RT_DATATYPE_U32, &pPvtData->maxGapNS); - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Data length: %u", LOG_RT_DATATYPE_U32, &pMediaQItem->dataLen); - - pPvtData->accumLateNS = 0; - pPvtData->maxLateNS = 0; - pPvtData->accumGapNS = 0; - pPvtData->maxGapNS = 0; - pPvtData->prevNowTime = 0; - pPvtData->servicedCount = 0; - pPvtData->skipCountdown = 10; - } - } - } - - else if (pPvtData->viewType == VIEWER_MODE_MAPPING_AWARE) { - } - - else if (pPvtData->viewType == VIEWER_MODE_AVTP_TIMESTAMP) { - U64 avtpTimestampTime; - bool avtpTimestampValid; - S32 deltaNS = 0; - - avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); - avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); - - if (avtpTimestampValid) { - if (pPvtData->servicedCount > 1) { - deltaNS = avtpTimestampTime - pPvtData->prevAvtpTimestampTime; - if (deltaNS > pPvtData->maxAvtpDeltaNS) { - pPvtData->maxAvtpDeltaNS = deltaNS; - } - pPvtData->accumAvtpDeltaNS += deltaNS; - - if (pPvtData->avgForJitter != 0) { - S32 deltaJitter = pPvtData->avgForJitter - deltaNS; - if (deltaJitter < 0) deltaJitter = -deltaJitter; - pPvtData->jitter += (1.0/16.0) * ((float)deltaJitter - pPvtData->jitter); - } - } - pPvtData->prevAvtpTimestampTime = avtpTimestampTime; - - if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { - S32 deltaAvg = pPvtData->accumAvtpDeltaNS / (pPvtData->servicedCount - 1); - U32 jitter = (U32)(pPvtData->jitter); - - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta: %d NS ", LOG_RT_DATATYPE_S32, &deltaNS); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta Avg: %d NS ", LOG_RT_DATATYPE_S32, &deltaAvg); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxAvtpDeltaNS); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); - - pPvtData->accumAvtpDeltaNS = 0; - pPvtData->maxAvtpDeltaNS = 0; - pPvtData->servicedCount = 0; - pPvtData->prevAvtpTimestampTime = 0; - pPvtData->skipCountdown = 10; - pPvtData->jitter = 0.0; - pPvtData->avgForJitter = deltaAvg; - } - } - } - - else if (pPvtData->viewType == VIEWER_MODE_LATENCY) { - U64 avtpTimestampTime; - bool avtpTimestampValid; - U64 nowTimestampTime; - bool nowTimestampValid; - S32 lateNS = 0; - - avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); - avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); - - openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); - nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); - nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); - - if (avtpTimestampValid && nowTimestampValid) { - lateNS = nowTimestampTime - avtpTimestampTime; - if (lateNS > pPvtData->maxLateNS) { - pPvtData->maxLateNS = lateNS; - } - pPvtData->accumLateNS += lateNS; - - if (pPvtData->avgForJitter != 0) { - S32 lateJitter = pPvtData->avgForJitter - lateNS; - if (lateJitter < 0) lateJitter = -lateJitter; - pPvtData->jitter += (1.0/16.0) * ((float)lateJitter - pPvtData->jitter); - } - - if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { - S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; - U32 jitter = (U32)(pPvtData->jitter); - - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Latency: %d NS ", LOG_RT_DATATYPE_S32, &lateNS); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Latency Avg: %d NS ", LOG_RT_DATATYPE_S32, &lateAvg); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Latency Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); - - pPvtData->accumLateNS = 0; - pPvtData->maxLateNS = 0; - pPvtData->servicedCount = 0; - pPvtData->skipCountdown = 10; - pPvtData->jitter = 0.0; - pPvtData->avgForJitter = lateAvg; - } - } - } - - else if (pPvtData->viewType == VIEWER_MODE_SELECTIVE_TIMESTAMP) { - } - - else if (pPvtData->viewType == VIEWER_MODE_LATE) { - U64 avtpTimestampTime; - bool avtpTimestampValid; - U64 nowTimestampTime; - bool nowTimestampValid; - S32 lateNS = 0; - - avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); - avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); - - openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); - nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); - nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); - - if (avtpTimestampValid && nowTimestampValid) { - lateNS = nowTimestampTime - avtpTimestampTime; - if (lateNS > pPvtData->maxLateNS) { - pPvtData->maxLateNS = lateNS; - } - pPvtData->accumLateNS += lateNS; - - if (pPvtData->avgForJitter != 0) { - S32 lateJitter = pPvtData->avgForJitter - lateNS; - if (lateJitter < 0) lateJitter = -lateJitter; - pPvtData->jitter += (1.0/16.0) * ((float)lateJitter - pPvtData->jitter); - } - - if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { - S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; - U32 jitter = (U32)(pPvtData->jitter); - - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Late: %d NS ", LOG_RT_DATATYPE_S32, &lateNS); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Late Avg: %d NS ", LOG_RT_DATATYPE_S32, &lateAvg); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Late Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); - - pPvtData->accumLateNS = 0; - pPvtData->maxLateNS = 0; - pPvtData->servicedCount = 0; - pPvtData->skipCountdown = 10; - pPvtData->jitter = 0.0; - pPvtData->avgForJitter = lateAvg; - } - } - } - - else if (pPvtData->viewType == VIEWER_MODE_GAP) { - U64 nowTime; - U64 gapNS = 0; - - CLOCK_GETTIME64(OPENAVB_CLOCK_REALTIME, &nowTime); - - if (pPvtData->servicedCount > 1) { - gapNS = nowTime - pPvtData->prevNowTime; - if (gapNS > pPvtData->maxGapNS) { - pPvtData->maxGapNS = gapNS; - } - pPvtData->accumGapNS += gapNS; - - if (pPvtData->avgForJitter != 0) { - S32 gapJitter = pPvtData->avgForJitter - gapNS; - if (gapJitter < 0) gapJitter = -gapJitter; - pPvtData->jitter += (1.0/16.0) * ((float)gapJitter - pPvtData->jitter); - } - } - pPvtData->prevNowTime = nowTime; - - if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { - S32 gapAvg = pPvtData->accumGapNS / (pPvtData->servicedCount - 1); - U32 jitter = (U32)(pPvtData->jitter); - - AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Gap: %d NS ", LOG_RT_DATATYPE_S32, &gapNS); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Gap Avg: %d NS ", LOG_RT_DATATYPE_S32, &gapAvg); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Gap Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxGapNS); - AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); - - pPvtData->accumGapNS = 0; - pPvtData->maxGapNS = 0; - pPvtData->prevNowTime = 0; - pPvtData->servicedCount = 0; - pPvtData->skipCountdown = 10; - pPvtData->jitter = 0.0; - pPvtData->avgForJitter = gapAvg; - } - } - - } - openavbMediaQTailPull(pMediaQ); - } - } - AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); - return TRUE; -} - - -// This callback will be called when the interface needs to be closed. All shutdown should -// occur in this function. -void openavbIntfViewerEndCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -void openavbIntfViewerGenEndCB(media_q_t *pMediaQ) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - AVB_TRACE_EXIT(AVB_TRACE_INTF); -} - -// Main initialization entry point into the interface module -extern DLL_EXPORT bool openavbIntfViewerInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) -{ - AVB_TRACE_ENTRY(AVB_TRACE_INTF); - - if (pMediaQ) { - pMediaQ->pPvtIntfInfo = calloc(1, sizeof(pvt_data_t)); // Memory freed by the media queue when the media queue is destroyed. - - if (!pMediaQ->pPvtIntfInfo) { - AVB_LOG_ERROR("Unable to allocate memory for AVTP interface module."); - return FALSE; - } - - pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; - - pIntfCB->intf_cfg_cb = openavbIntfViewerCfgCB; - pIntfCB->intf_gen_init_cb = openavbIntfViewerGenInitCB; - pIntfCB->intf_tx_init_cb = openavbIntfViewerTxInitCB; - pIntfCB->intf_tx_cb = openavbIntfViewerTxCB; - pIntfCB->intf_rx_init_cb = openavbIntfViewerRxInitCB; - pIntfCB->intf_rx_cb = openavbIntfViewerRxCB; - pIntfCB->intf_end_cb = openavbIntfViewerEndCB; - pIntfCB->intf_gen_end_cb = openavbIntfViewerGenEndCB; - - pPvtData->viewType = VIEWER_MODE_DETAIL; - pPvtData->viewInterval = 1000; - pPvtData->rawOffset = 0; - pPvtData->rawLength = 20; - pPvtData->ignoreTimestamp = FALSE; - pPvtData->skipCountdown = 0; - pPvtData->jitter = 0.0; - pPvtData->avgForJitter = 0; - } - - AVB_TRACE_EXIT(AVB_TRACE_INTF); - return TRUE; -} +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : Viewer interface module. +* +* This interface module is only a listener and is used to simply display +* contents recieved in a number of different formats. Additionally it is +* mapping type aware and can display header values for different mappings +*/ + +#include +#include +#include "openavb_platform_pub.h" +#include "openavb_types_pub.h" +#include "openavb_trace_pub.h" +#include "openavb_mediaq_pub.h" +#include "openavb_intf_pub.h" + +#define AVB_LOG_COMPONENT "Viewer Interface" +#include "openavb_log_pub.h" + +typedef enum { + VIEWER_MODE_DETAIL = 0, + VIEWER_MODE_MAPPING_AWARE = 1, + VIEWER_MODE_AVTP_TIMESTAMP = 2, + VIEWER_MODE_LATENCY = 3, + VIEWER_MODE_SELECTIVE_TIMESTAMP = 4, + VIEWER_MODE_LATE = 5, + VIEWER_MODE_GAP = 6, +} viewer_mode_t; + +typedef struct { + ///////////// + // Config data + ///////////// + viewer_mode_t viewType; + + // Frequency of output + U32 viewInterval; + + // Offest into the raw frame to output + U32 rawOffset; + + // Length of the raw frame to output + U32 rawLength; + + // Ignore timestamp at listener. + bool ignoreTimestamp; + + ///////////// + // Variable data + ///////////// + U32 servicedCount; + + S64 accumLateNS; + + S32 maxLateNS; + + U64 accumGapNS; + + U32 maxGapNS; + + U64 prevNowTime; + + S64 accumAvtpDeltaNS; + + S32 maxAvtpDeltaNS; + + U64 prevAvtpTimestampTime; + + U32 skipCountdown; + + float jitter; + + S32 avgForJitter; + +} pvt_data_t; + +// Each configuration name value pair for this mapping will result in this callback being called. +void openavbIntfViewerCfgCB(media_q_t *pMediaQ, const char *name, const char *value) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + + if (pMediaQ) { + char *pEnd; + long tmp; + + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return; + } + + // intf_nv_view_type: Type of viewing output. 0 = raw, 1 = mapping aware, 2 = timestamps only, 3 = latency output, 4 = Selective timestamp error reporting + if (strcmp(name, "intf_nv_view_type") == 0) { + pPvtData->viewType = (viewer_mode_t)strtol(value, &pEnd, 10); + } + + else if (strcmp(name, "intf_nv_view_interval") == 0) { + pPvtData->viewInterval = strtol(value, &pEnd, 10); + if (pPvtData->viewInterval == 0) { + pPvtData->viewInterval = 1000; + } + } + + else if (strcmp(name, "intf_nv_raw_offset") == 0) { + pPvtData->rawOffset = strtol(value, &pEnd, 10); + } + + else if (strcmp(name, "intf_nv_raw_length") == 0) { + pPvtData->rawLength = strtol(value, &pEnd, 10); + if (pPvtData->rawLength < 1) + pPvtData->rawLength = 1000; + } + + else if (strcmp(name, "intf_nv_ignore_timestamp") == 0) { + tmp = strtol(value, &pEnd, 10); + if (*pEnd == '\0' && tmp == 1) { + pPvtData->ignoreTimestamp = (tmp == 1); + } + } + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +void openavbIntfViewerGenInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// No talker functionality in this interface +void openavbIntfViewerTxInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// No talker functionality in this interface +bool openavbIntfViewerTxCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return FALSE; +} + +// A call to this callback indicates that this interface module will be +// a listener. Any listener initialization can be done in this function. +void openavbIntfViewerRxInitCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + + if (pMediaQ) { + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return; + } + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// This callback is called when acting as a listener. +bool openavbIntfViewerRxCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF_DETAIL); + if (pMediaQ) { + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + if (!pPvtData) { + AVB_LOG_ERROR("Private interface module data not allocated."); + return FALSE; + } + + media_q_item_t *pMediaQItem = openavbMediaQTailLock(pMediaQ, pPvtData->ignoreTimestamp); + if (pMediaQItem) { + + // The skip countdown allow the viewer modes to set a number of packets to ignore + // after logging to reduce or eliminate the logging from affecting the stats. + if (pPvtData->skipCountdown) + pPvtData->skipCountdown--; + + if (pMediaQItem->dataLen && !pPvtData->skipCountdown) { + pPvtData->servicedCount++; + + if (pPvtData->viewType == VIEWER_MODE_DETAIL) { + U32 avtpTimestamp; + U64 avtpTimestampTime; + bool avtpTimestampValid; + U32 nowTimestamp; + U64 nowTimestampTime; + bool nowTimestampValid; + U64 nowTime; + S32 lateNS = 0; + U64 gapNS = 0; + + avtpTimestamp = openavbAvtpTimeGetAvtpTimestamp(pMediaQItem->pAvtpTime); + avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); + avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); + + openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); + nowTimestamp = openavbAvtpTimeGetAvtpTimestamp(pMediaQItem->pAvtpTime); + nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); + nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); + + CLOCK_GETTIME64(OPENAVB_CLOCK_REALTIME, &nowTime); + + if (avtpTimestampValid && nowTimestampValid) { + lateNS = nowTimestampTime - avtpTimestampTime; + if (lateNS > pPvtData->maxLateNS) { + pPvtData->maxLateNS = lateNS; + } + pPvtData->accumLateNS += lateNS; + + if (pPvtData->servicedCount > 1) { + gapNS = nowTime - pPvtData->prevNowTime; + if (gapNS > pPvtData->maxGapNS) { + pPvtData->maxGapNS = gapNS; + } + pPvtData->accumGapNS += gapNS; + } + pPvtData->prevNowTime = nowTime; + + if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { + S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; + S32 gapAvg = pPvtData->accumGapNS / (pPvtData->servicedCount - 1); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "****************************", LOG_RT_DATATYPE_CONST_STR, NULL); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Packets: %u", LOG_RT_DATATYPE_U32, &pPvtData->servicedCount); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "AVTP Timestamp: %u NS", LOG_RT_DATATYPE_U32, &avtpTimestamp); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Now Timestamp: %u NS", LOG_RT_DATATYPE_U32, &nowTimestamp); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late: %d NS", LOG_RT_DATATYPE_S32, &lateNS); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late Avg: %d NS", LOG_RT_DATATYPE_S32, &lateAvg); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Late Max: %d NS", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap: %u NS", LOG_RT_DATATYPE_U32, &gapNS); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap Avg: %u NS", LOG_RT_DATATYPE_U32, &gapAvg); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Gap Max: %u NS", LOG_RT_DATATYPE_U32, &pPvtData->maxGapNS); + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, LOG_RT_END, "Data length: %u", LOG_RT_DATATYPE_U32, &pMediaQItem->dataLen); + + pPvtData->accumLateNS = 0; + pPvtData->maxLateNS = 0; + pPvtData->accumGapNS = 0; + pPvtData->maxGapNS = 0; + pPvtData->prevNowTime = 0; + pPvtData->servicedCount = 0; + pPvtData->skipCountdown = 10; + } + } + } + + else if (pPvtData->viewType == VIEWER_MODE_MAPPING_AWARE) { + } + + else if (pPvtData->viewType == VIEWER_MODE_AVTP_TIMESTAMP) { + U64 avtpTimestampTime; + bool avtpTimestampValid; + S32 deltaNS = 0; + + avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); + avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); + + if (avtpTimestampValid) { + if (pPvtData->servicedCount > 1) { + deltaNS = avtpTimestampTime - pPvtData->prevAvtpTimestampTime; + if (deltaNS > pPvtData->maxAvtpDeltaNS) { + pPvtData->maxAvtpDeltaNS = deltaNS; + } + pPvtData->accumAvtpDeltaNS += deltaNS; + + if (pPvtData->avgForJitter != 0) { + S32 deltaJitter = pPvtData->avgForJitter - deltaNS; + if (deltaJitter < 0) deltaJitter = -deltaJitter; + pPvtData->jitter += (1.0/16.0) * ((float)deltaJitter - pPvtData->jitter); + } + } + pPvtData->prevAvtpTimestampTime = avtpTimestampTime; + + if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { + S32 deltaAvg = pPvtData->accumAvtpDeltaNS / (pPvtData->servicedCount - 1); + U32 jitter = (U32)(pPvtData->jitter); + + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta: %d NS ", LOG_RT_DATATYPE_S32, &deltaNS); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta Avg: %d NS ", LOG_RT_DATATYPE_S32, &deltaAvg); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "AVTP Timestamp Delta Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxAvtpDeltaNS); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); + + pPvtData->accumAvtpDeltaNS = 0; + pPvtData->maxAvtpDeltaNS = 0; + pPvtData->servicedCount = 0; + pPvtData->prevAvtpTimestampTime = 0; + pPvtData->skipCountdown = 10; + pPvtData->jitter = 0.0; + pPvtData->avgForJitter = deltaAvg; + } + } + } + + else if (pPvtData->viewType == VIEWER_MODE_LATENCY) { + U64 avtpTimestampTime; + bool avtpTimestampValid; + U64 nowTimestampTime; + bool nowTimestampValid; + S32 lateNS = 0; + + avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); + avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); + + openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); + nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); + nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); + + if (avtpTimestampValid && nowTimestampValid) { + lateNS = nowTimestampTime - avtpTimestampTime; + if (lateNS > pPvtData->maxLateNS) { + pPvtData->maxLateNS = lateNS; + } + pPvtData->accumLateNS += lateNS; + + if (pPvtData->avgForJitter != 0) { + S32 lateJitter = pPvtData->avgForJitter - lateNS; + if (lateJitter < 0) lateJitter = -lateJitter; + pPvtData->jitter += (1.0/16.0) * ((float)lateJitter - pPvtData->jitter); + } + + if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { + S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; + U32 jitter = (U32)(pPvtData->jitter); + + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Latency: %d NS ", LOG_RT_DATATYPE_S32, &lateNS); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Latency Avg: %d NS ", LOG_RT_DATATYPE_S32, &lateAvg); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Latency Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); + + pPvtData->accumLateNS = 0; + pPvtData->maxLateNS = 0; + pPvtData->servicedCount = 0; + pPvtData->skipCountdown = 10; + pPvtData->jitter = 0.0; + pPvtData->avgForJitter = lateAvg; + } + } + } + + else if (pPvtData->viewType == VIEWER_MODE_SELECTIVE_TIMESTAMP) { + } + + else if (pPvtData->viewType == VIEWER_MODE_LATE) { + U64 avtpTimestampTime; + bool avtpTimestampValid; + U64 nowTimestampTime; + bool nowTimestampValid; + S32 lateNS = 0; + + avtpTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); + avtpTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); + + openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); + nowTimestampTime = openavbAvtpTimeGetAvtpTimeNS(pMediaQItem->pAvtpTime); + nowTimestampValid = openavbAvtpTimeTimestampIsValid(pMediaQItem->pAvtpTime); + + if (avtpTimestampValid && nowTimestampValid) { + lateNS = nowTimestampTime - avtpTimestampTime; + if (lateNS > pPvtData->maxLateNS) { + pPvtData->maxLateNS = lateNS; + } + pPvtData->accumLateNS += lateNS; + + if (pPvtData->avgForJitter != 0) { + S32 lateJitter = pPvtData->avgForJitter - lateNS; + if (lateJitter < 0) lateJitter = -lateJitter; + pPvtData->jitter += (1.0/16.0) * ((float)lateJitter - pPvtData->jitter); + } + + if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { + S32 lateAvg = pPvtData->accumLateNS / pPvtData->servicedCount; + U32 jitter = (U32)(pPvtData->jitter); + + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Late: %d NS ", LOG_RT_DATATYPE_S32, &lateNS); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Late Avg: %d NS ", LOG_RT_DATATYPE_S32, &lateAvg); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Late Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxLateNS); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); + + pPvtData->accumLateNS = 0; + pPvtData->maxLateNS = 0; + pPvtData->servicedCount = 0; + pPvtData->skipCountdown = 10; + pPvtData->jitter = 0.0; + pPvtData->avgForJitter = lateAvg; + } + } + } + + else if (pPvtData->viewType == VIEWER_MODE_GAP) { + U64 nowTime; + U64 gapNS = 0; + + CLOCK_GETTIME64(OPENAVB_CLOCK_REALTIME, &nowTime); + + if (pPvtData->servicedCount > 1) { + gapNS = nowTime - pPvtData->prevNowTime; + if (gapNS > pPvtData->maxGapNS) { + pPvtData->maxGapNS = gapNS; + } + pPvtData->accumGapNS += gapNS; + + if (pPvtData->avgForJitter != 0) { + S32 gapJitter = pPvtData->avgForJitter - gapNS; + if (gapJitter < 0) gapJitter = -gapJitter; + pPvtData->jitter += (1.0/16.0) * ((float)gapJitter - pPvtData->jitter); + } + } + pPvtData->prevNowTime = nowTime; + + if ((pPvtData->servicedCount % pPvtData->viewInterval) == 0) { + S32 gapAvg = pPvtData->accumGapNS / (pPvtData->servicedCount - 1); + U32 jitter = (U32)(pPvtData->jitter); + + AVB_LOGRT_INFO(LOG_RT_BEGIN, LOG_RT_ITEM, FALSE, "Gap: %d NS ", LOG_RT_DATATYPE_S32, &gapNS); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Gap Avg: %d NS ", LOG_RT_DATATYPE_S32, &gapAvg); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, FALSE, "Gap Max: %d NS ", LOG_RT_DATATYPE_S32, &pPvtData->maxGapNS); + AVB_LOGRT_INFO(FALSE, LOG_RT_ITEM, LOG_RT_END, "Jitter: %d", LOG_RT_DATATYPE_S32, &jitter); + + pPvtData->accumGapNS = 0; + pPvtData->maxGapNS = 0; + pPvtData->prevNowTime = 0; + pPvtData->servicedCount = 0; + pPvtData->skipCountdown = 10; + pPvtData->jitter = 0.0; + pPvtData->avgForJitter = gapAvg; + } + } + + } + openavbMediaQTailPull(pMediaQ); + } + } + AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); + return TRUE; +} + + +// This callback will be called when the interface needs to be closed. All shutdown should +// occur in this function. +void openavbIntfViewerEndCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +void openavbIntfViewerGenEndCB(media_q_t *pMediaQ) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + +// Main initialization entry point into the interface module +extern DLL_EXPORT bool openavbIntfViewerInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + + if (pMediaQ) { + pMediaQ->pPvtIntfInfo = calloc(1, sizeof(pvt_data_t)); // Memory freed by the media queue when the media queue is destroyed. + + if (!pMediaQ->pPvtIntfInfo) { + AVB_LOG_ERROR("Unable to allocate memory for AVTP interface module."); + return FALSE; + } + + pvt_data_t *pPvtData = pMediaQ->pPvtIntfInfo; + + pIntfCB->intf_cfg_cb = openavbIntfViewerCfgCB; + pIntfCB->intf_gen_init_cb = openavbIntfViewerGenInitCB; + pIntfCB->intf_tx_init_cb = openavbIntfViewerTxInitCB; + pIntfCB->intf_tx_cb = openavbIntfViewerTxCB; + pIntfCB->intf_rx_init_cb = openavbIntfViewerRxInitCB; + pIntfCB->intf_rx_cb = openavbIntfViewerRxCB; + pIntfCB->intf_end_cb = openavbIntfViewerEndCB; + pIntfCB->intf_gen_end_cb = openavbIntfViewerGenEndCB; + + pPvtData->viewType = VIEWER_MODE_DETAIL; + pPvtData->viewInterval = 1000; + pPvtData->rawOffset = 0; + pPvtData->rawLength = 20; + pPvtData->ignoreTimestamp = FALSE; + pPvtData->skipCountdown = 0; + pPvtData->jitter = 0.0; + pPvtData->avgForJitter = 0; + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); + return TRUE; +} diff --git a/lib/avtp_pipeline/mcr/openavb_mcr_hal_pub.h b/lib/avtp_pipeline/mcr/openavb_mcr_hal_pub.h index ac2eca21..e1d19b43 100644 --- a/lib/avtp_pipeline/mcr/openavb_mcr_hal_pub.h +++ b/lib/avtp_pipeline/mcr/openavb_mcr_hal_pub.h @@ -1,65 +1,65 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE : Public interface for media clock recovery -*/ - -#ifndef OPENAVB_MCR_HAL_PUB_H -#define OPENAVB_MCR_HAL_PUB_H - -#include "openavb_platform_pub.h" -#include "openavb_types_base_pub.h" - -#define HAL_INIT_MCR_V2(packetRate, pushInterval, timestampInterval, recoveryInterval) halInitMCR(packetRate, pushInterval, timestampInterval, recoveryInterval) -#define HAL_CLOSE_MCR_V2() halCloseMCR() -#define HAL_PUSH_MCR_V2() halPushMCR() - -// Initialize HAL MCR -bool halInitMCR(U32 packetRate, U32 pushInterval, U32 timeStampInterval, U32 recoveryInterval); - -// Close HAL MCR -bool halCloseMCR(void); - -// Push MCR Event -bool halPushMCR(void); - -// MCR timer adjustment. Negative value speed up the media clock. Positive values slow the media clock. -// Will take effect during the next clock recovery interval. This is completely indepentant from pure MCR and -// allows for adjustments based on media buffer levels. The value past in works as credit with each -// MCR timer cycle bump up and down the clock temporarily. -void halAdjustMCRNSec(S32 adjNSec); - -// The granularity is used to set coarseness of the values that will be passed into halAdjustMCRNSec. -// This is used to balance if the timestamps or values from halAdjustMCRNSec are used to adjust the clock. -void halAdjustMCRGranularityNSec(U32 adjGranularityNSec); - - -#endif // OPENAVB_MCR_HAL_PUB_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE : Public interface for media clock recovery +*/ + +#ifndef OPENAVB_MCR_HAL_PUB_H +#define OPENAVB_MCR_HAL_PUB_H + +#include "openavb_platform_pub.h" +#include "openavb_types_base_pub.h" + +#define HAL_INIT_MCR_V2(packetRate, pushInterval, timestampInterval, recoveryInterval) halInitMCR(packetRate, pushInterval, timestampInterval, recoveryInterval) +#define HAL_CLOSE_MCR_V2() halCloseMCR() +#define HAL_PUSH_MCR_V2() halPushMCR() + +// Initialize HAL MCR +bool halInitMCR(U32 packetRate, U32 pushInterval, U32 timeStampInterval, U32 recoveryInterval); + +// Close HAL MCR +bool halCloseMCR(void); + +// Push MCR Event +bool halPushMCR(void); + +// MCR timer adjustment. Negative value speed up the media clock. Positive values slow the media clock. +// Will take effect during the next clock recovery interval. This is completely indepentant from pure MCR and +// allows for adjustments based on media buffer levels. The value past in works as credit with each +// MCR timer cycle bump up and down the clock temporarily. +void halAdjustMCRNSec(S32 adjNSec); + +// The granularity is used to set coarseness of the values that will be passed into halAdjustMCRNSec. +// This is used to balance if the timestamps or values from halAdjustMCRNSec are used to adjust the clock. +void halAdjustMCRGranularityNSec(U32 adjGranularityNSec); + + +#endif // OPENAVB_MCR_HAL_PUB_H diff --git a/lib/avtp_pipeline/platform/Linux/openavb_ether_osal.c b/lib/avtp_pipeline/platform/Linux/openavb_ether_osal.c index 95239bf0..753d3dfa 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_ether_osal.c +++ b/lib/avtp_pipeline/platform/Linux/openavb_ether_osal.c @@ -1,39 +1,39 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#include "openavb_ether_osal.h" - -// MAC address is retrieved differently for Linux -bool osalGetMacAddr(U8 *macAddr) -{ - return TRUE; -} - - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#include "openavb_ether_osal.h" + +// MAC address is retrieved differently for Linux +bool osalGetMacAddr(U8 *macAddr) +{ + return TRUE; +} + + diff --git a/lib/avtp_pipeline/platform/Linux/openavb_ether_osal.h b/lib/avtp_pipeline/platform/Linux/openavb_ether_osal.h index a75d2ac6..95ddb88b 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_ether_osal.h +++ b/lib/avtp_pipeline/platform/Linux/openavb_ether_osal.h @@ -1,32 +1,32 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ #ifndef OPENAVB_ETHER_OSAL_H #define OPENAVB_ETHER_OSAL_H 1 diff --git a/lib/avtp_pipeline/platform/Linux/openavb_osal.c b/lib/avtp_pipeline/platform/Linux/openavb_osal.c index ba960ff6..94c42ab0 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_osal.c +++ b/lib/avtp_pipeline/platform/Linux/openavb_osal.c @@ -1,55 +1,55 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#include "openavb_platform.h" -#include "openavb_ether_hal.h" -#include "openavb_osal.h" -#include "openavb_qmgr.h" - -#define AVB_LOG_COMPONENT "osal" -#include "openavb_pub.h" -#include "openavb_log.h" - -extern DLL_EXPORT bool osalAVBInitialize(const char* ifname) -{ - avbLogInit(); - osalAVBTimeInit(); - openavbQmgrInitialize(FQTSS_MODE_HW_CLASS, 0, ifname, 0, 0, 0); - return TRUE; -} - -extern DLL_EXPORT bool osalAVBFinalize(void) -{ - openavbQmgrFinalize(); - osalAVBTimeClose(); - avbLogExit(); - return TRUE; -} - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#include "openavb_platform.h" +#include "openavb_ether_hal.h" +#include "openavb_osal.h" +#include "openavb_qmgr.h" + +#define AVB_LOG_COMPONENT "osal" +#include "openavb_pub.h" +#include "openavb_log.h" + +extern DLL_EXPORT bool osalAVBInitialize(const char* ifname) +{ + avbLogInit(); + osalAVBTimeInit(); + openavbQmgrInitialize(FQTSS_MODE_HW_CLASS, 0, ifname, 0, 0, 0); + return TRUE; +} + +extern DLL_EXPORT bool osalAVBFinalize(void) +{ + openavbQmgrFinalize(); + osalAVBTimeClose(); + avbLogExit(); + return TRUE; +} + diff --git a/lib/avtp_pipeline/platform/Linux/openavb_osal_endpoint.c b/lib/avtp_pipeline/platform/Linux/openavb_osal_endpoint.c index 593155f4..5862c7d4 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_osal_endpoint.c +++ b/lib/avtp_pipeline/platform/Linux/openavb_osal_endpoint.c @@ -1,56 +1,56 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#include "openavb_platform.h" -#include "openavb_ether_hal.h" -#include "openavb_osal.h" -#include "openavb_qmgr.h" -#include "openavb_endpoint.h" - -#define AVB_LOG_COMPONENT "osal" -#include "openavb_pub.h" -#include "openavb_log.h" - -extern DLL_EXPORT bool osalAVBInitialize(const char* ifname) -{ - avbLogInit(); - osalAVBTimeInit(); - startEndpoint(FQTSS_MODE_HW_CLASS, 0, ifname, 0, 0, 0); - return TRUE; -} - -extern DLL_EXPORT bool osalAVBFinalize(void) -{ - stopEndpoint(); - osalAVBTimeClose(); - avbLogExit(); - return TRUE; -} - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#include "openavb_platform.h" +#include "openavb_ether_hal.h" +#include "openavb_osal.h" +#include "openavb_qmgr.h" +#include "openavb_endpoint.h" + +#define AVB_LOG_COMPONENT "osal" +#include "openavb_pub.h" +#include "openavb_log.h" + +extern DLL_EXPORT bool osalAVBInitialize(const char* ifname) +{ + avbLogInit(); + osalAVBTimeInit(); + startEndpoint(FQTSS_MODE_HW_CLASS, 0, ifname, 0, 0, 0); + return TRUE; +} + +extern DLL_EXPORT bool osalAVBFinalize(void) +{ + stopEndpoint(); + osalAVBTimeClose(); + avbLogExit(); + return TRUE; +} + diff --git a/lib/avtp_pipeline/platform/Linux/openavb_time_osal.c b/lib/avtp_pipeline/platform/Linux/openavb_time_osal.c index b287cf13..1ea07652 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_time_osal.c +++ b/lib/avtp_pipeline/platform/Linux/openavb_time_osal.c @@ -1,207 +1,206 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#include -#include -#include -#include - -#include "igb.h" -#include "avb.h" - -#include "openavb_platform.h" -#include "openavb_time_osal.h" -#include "openavb_time_hal.h" -#include "openavb_trace.h" - -#define AVB_LOG_COMPONENT "osalTime" -#include "openavb_pub.h" -#include "openavb_log.h" - -//#include "openavb_time_util_osal.h" - -static pthread_mutex_t gOSALTimeInitMutex = PTHREAD_MUTEX_INITIALIZER; -#define LOCK() pthread_mutex_lock(&gOSALTimeInitMutex) -#define UNLOCK() pthread_mutex_unlock(&gOSALTimeInitMutex) - -static bool bInitialized = FALSE; -static int gIgbShmFd = -1; -static char *gIgbMmap = NULL; -gPtpTimeData gPtpTD; - -static bool x_timeInit(void) { - AVB_TRACE_ENTRY(AVB_TRACE_TIME); - - if (!halTimeInitialize()) { - AVB_LOG_ERROR("HAL Time Init failed"); - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; - } - - if (gptpinit(&gIgbShmFd, &gIgbMmap) < 0) { - AVB_LOG_ERROR("GPTP init failed"); - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; - } - - if (gptpgetdata(gIgbMmap, &gPtpTD) < 0) { - AVB_LOG_ERROR("GPTP data fetch failed"); - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; - } - - AVB_LOGF_INFO("local_time = %" PRIu64, gPtpTD.local_time); - AVB_LOGF_INFO("ml_phoffset = %" PRId64 ", ls_phoffset = %" PRId64, gPtpTD.ml_phoffset, gPtpTD.ls_phoffset); - AVB_LOGF_INFO("ml_freqffset = %Lf, ls_freqoffset = %Lf", gPtpTD.ml_freqoffset, gPtpTD.ls_freqoffset); - - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; -} - -static bool x_getPTPTime(U64 *timeNsec) { - AVB_TRACE_ENTRY(AVB_TRACE_TIME); - - if (gptpgetdata(gIgbMmap, &gPtpTD) < 0) { - AVB_LOG_ERROR("GPTP data fetch failed"); - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; - } - - uint64_t now_local; - uint64_t update_8021as; - int64_t delta_8021as; - int64_t delta_local; - - if (gptplocaltime(&gPtpTD, &now_local)) { - update_8021as = gPtpTD.local_time - gPtpTD.ml_phoffset; - delta_local = now_local - gPtpTD.local_time; - delta_8021as = gPtpTD.ml_freqoffset * delta_local; - *timeNsec = update_8021as + delta_8021as; - - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; - } - - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; -} - -bool osalAVBTimeInit(void) { - AVB_TRACE_ENTRY(AVB_TRACE_TIME); - - LOCK(); - if (!bInitialized) { - if (x_timeInit()) - bInitialized = TRUE; - } - UNLOCK(); - - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; -} - -bool osalAVBTimeClose(void) { - AVB_TRACE_ENTRY(AVB_TRACE_TIME); - - gptpdeinit(&gIgbShmFd, &gIgbMmap); - - halTimeFinalize(); - - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; -} - -bool osalClockGettime(openavb_clockId_t openavbClockId, struct timespec *getTime) { - AVB_TRACE_ENTRY(AVB_TRACE_TIME); - - if (openavbClockId < OPENAVB_CLOCK_WALLTIME) { - clockid_t clockId = CLOCK_MONOTONIC; - switch (openavbClockId) { - case OPENAVB_CLOCK_REALTIME: - clockId = CLOCK_REALTIME; - break; - case OPENAVB_CLOCK_MONOTONIC: - clockId = CLOCK_MONOTONIC; - break; - case OPENAVB_TIMER_CLOCK: - clockId = CLOCK_MONOTONIC; - break; - case OPENAVB_CLOCK_WALLTIME: - break; - } - if (!clock_gettime(clockId, getTime)) return TRUE; - } - else if (openavbClockId == OPENAVB_CLOCK_WALLTIME) { - U64 timeNsec; - if (!x_getPTPTime(&timeNsec)) { - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; - } - getTime->tv_sec = timeNsec / NANOSECONDS_PER_SECOND; - getTime->tv_nsec = timeNsec % NANOSECONDS_PER_SECOND; - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; - } - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; -} - -bool osalClockGettime64(openavb_clockId_t openavbClockId, U64 *timeNsec) { - if (openavbClockId < OPENAVB_CLOCK_WALLTIME) { - clockid_t clockId = CLOCK_MONOTONIC; - switch (openavbClockId) { - case OPENAVB_CLOCK_REALTIME: - clockId = CLOCK_REALTIME; - break; - case OPENAVB_CLOCK_MONOTONIC: - clockId = CLOCK_MONOTONIC; - break; - case OPENAVB_TIMER_CLOCK: - clockId = CLOCK_MONOTONIC; - break; - case OPENAVB_CLOCK_WALLTIME: - break; - } - struct timespec getTime; - if (!clock_gettime(clockId, &getTime)) { - *timeNsec = ((U64)getTime.tv_sec * (U64)NANOSECONDS_PER_SECOND) + (U64)getTime.tv_nsec; - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; - } - } - else if (openavbClockId == OPENAVB_CLOCK_WALLTIME) { - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return x_getPTPTime(timeNsec); - } - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; -} - - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#include +#include +#include +#include + +#include "igb.h" +#include "avb.h" + +#include "openavb_platform.h" +#include "openavb_time_osal.h" +#include "openavb_time_hal.h" +#include "openavb_trace.h" + +#define AVB_LOG_COMPONENT "osalTime" +#include "openavb_pub.h" +#include "openavb_log.h" + +//#include "openavb_time_util_osal.h" + +static pthread_mutex_t gOSALTimeInitMutex = PTHREAD_MUTEX_INITIALIZER; +#define LOCK() pthread_mutex_lock(&gOSALTimeInitMutex) +#define UNLOCK() pthread_mutex_unlock(&gOSALTimeInitMutex) + +static bool bInitialized = FALSE; +static int gIgbShmFd = -1; +static char *gIgbMmap = NULL; +gPtpTimeData gPtpTD; + +static bool x_timeInit(void) { + AVB_TRACE_ENTRY(AVB_TRACE_TIME); + + if (!halTimeInitialize()) { + AVB_LOG_ERROR("HAL Time Init failed"); + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; + } + + if (gptpinit(&gIgbShmFd, &gIgbMmap) < 0) { + AVB_LOG_ERROR("GPTP init failed"); + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; + } + + if (gptpgetdata(gIgbMmap, &gPtpTD) < 0) { + AVB_LOG_ERROR("GPTP data fetch failed"); + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; + } + + AVB_LOGF_INFO("local_time = %" PRIu64, gPtpTD.local_time); + AVB_LOGF_INFO("ml_phoffset = %" PRId64 ", ls_phoffset = %" PRId64, gPtpTD.ml_phoffset, gPtpTD.ls_phoffset); + AVB_LOGF_INFO("ml_freqffset = %Lf, ls_freqoffset = %Lf", gPtpTD.ml_freqoffset, gPtpTD.ls_freqoffset); + + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; +} + +static bool x_getPTPTime(U64 *timeNsec) { + AVB_TRACE_ENTRY(AVB_TRACE_TIME); + + if (gptpgetdata(gIgbMmap, &gPtpTD) < 0) { + AVB_LOG_ERROR("GPTP data fetch failed"); + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; + } + + uint64_t now_local; + uint64_t update_8021as; + int64_t delta_8021as; + int64_t delta_local; + + if (gptplocaltime(&gPtpTD, &now_local)) { + update_8021as = gPtpTD.local_time - gPtpTD.ml_phoffset; + delta_local = now_local - gPtpTD.local_time; + delta_8021as = gPtpTD.ml_freqoffset * delta_local; + *timeNsec = update_8021as + delta_8021as; + + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; + } + + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; +} + +bool osalAVBTimeInit(void) { + AVB_TRACE_ENTRY(AVB_TRACE_TIME); + + LOCK(); + if (!bInitialized) { + if (x_timeInit()) + bInitialized = TRUE; + } + UNLOCK(); + + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; +} + +bool osalAVBTimeClose(void) { + AVB_TRACE_ENTRY(AVB_TRACE_TIME); + + gptpdeinit(&gIgbShmFd, &gIgbMmap); + + halTimeFinalize(); + + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; +} + +bool osalClockGettime(openavb_clockId_t openavbClockId, struct timespec *getTime) { + AVB_TRACE_ENTRY(AVB_TRACE_TIME); + + if (openavbClockId < OPENAVB_CLOCK_WALLTIME) { + clockid_t clockId = CLOCK_MONOTONIC; + switch (openavbClockId) { + case OPENAVB_CLOCK_REALTIME: + clockId = CLOCK_REALTIME; + break; + case OPENAVB_CLOCK_MONOTONIC: + clockId = CLOCK_MONOTONIC; + break; + case OPENAVB_TIMER_CLOCK: + clockId = CLOCK_MONOTONIC; + break; + case OPENAVB_CLOCK_WALLTIME: + break; + } + if (!clock_gettime(clockId, getTime)) return TRUE; + } + else if (openavbClockId == OPENAVB_CLOCK_WALLTIME) { + U64 timeNsec; + if (!x_getPTPTime(&timeNsec)) { + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; + } + getTime->tv_sec = timeNsec / NANOSECONDS_PER_SECOND; + getTime->tv_nsec = timeNsec % NANOSECONDS_PER_SECOND; + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; + } + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; +} + +bool osalClockGettime64(openavb_clockId_t openavbClockId, U64 *timeNsec) { + if (openavbClockId < OPENAVB_CLOCK_WALLTIME) { + clockid_t clockId = CLOCK_MONOTONIC; + switch (openavbClockId) { + case OPENAVB_CLOCK_REALTIME: + clockId = CLOCK_REALTIME; + break; + case OPENAVB_CLOCK_MONOTONIC: + clockId = CLOCK_MONOTONIC; + break; + case OPENAVB_TIMER_CLOCK: + clockId = CLOCK_MONOTONIC; + break; + case OPENAVB_CLOCK_WALLTIME: + break; + } + struct timespec getTime; + if (!clock_gettime(clockId, &getTime)) { + *timeNsec = ((U64)getTime.tv_sec * (U64)NANOSECONDS_PER_SECOND) + (U64)getTime.tv_nsec; + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; + } + } + else if (openavbClockId == OPENAVB_CLOCK_WALLTIME) { + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return x_getPTPTime(timeNsec); + } + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; +} + diff --git a/lib/avtp_pipeline/platform/Linux/openavb_time_osal.h b/lib/avtp_pipeline/platform/Linux/openavb_time_osal.h index 3fa07afd..293f7c3c 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_time_osal.h +++ b/lib/avtp_pipeline/platform/Linux/openavb_time_osal.h @@ -1,33 +1,33 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + #ifndef _OPENAVB_TIME_OSAL_H #define _OPENAVB_TIME_OSAL_H diff --git a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal.c b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal.c index deb113b9..260c69f2 100644 --- a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal.c +++ b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal.c @@ -1,39 +1,39 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#include - -void tcalGetHeapInfo(unsigned int *ttlMallocHeap, unsigned int *freeMallocHeap) -{ - struct mallinfo minfo = mallinfo(); - - *ttlMallocHeap = (minfo.arena + minfo.fordblks); - *freeMallocHeap = minfo.fordblks; -} +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#include + +void tcalGetHeapInfo(unsigned int *ttlMallocHeap, unsigned int *freeMallocHeap) +{ + struct mallinfo minfo = mallinfo(); + + *ttlMallocHeap = (minfo.arena + minfo.fordblks); + *freeMallocHeap = minfo.fordblks; +} diff --git a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal.h b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal.h index 046ab971..6060be93 100644 --- a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal.h +++ b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal.h @@ -1,37 +1,37 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef OPENAVB_MEM_TCAL_H -#define OPENAVB_MEM_TCAL_H 1 - -void tcalGetHeapInfo(unsigned int *ttlMallocHeap, unsigned int *freeMallocHeap); - -#endif // OPENAVB_MEM_TCAL_H - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef OPENAVB_MEM_TCAL_H +#define OPENAVB_MEM_TCAL_H 1 + +void tcalGetHeapInfo(unsigned int *ttlMallocHeap, unsigned int *freeMallocHeap); + +#endif // OPENAVB_MEM_TCAL_H + diff --git a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal_pub.h b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal_pub.h index b6d3b239..d1624e77 100644 --- a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal_pub.h +++ b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_mem_tcal_pub.h @@ -1,38 +1,38 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef OPENAVB_MEM_TCAL_PUB_H -#define OPENAVB_MEM_TCAL_PUB_H 1 - -#include -#include - -#endif // OPENAVB_MEM_TCAL_PUB_H - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef OPENAVB_MEM_TCAL_PUB_H +#define OPENAVB_MEM_TCAL_PUB_H 1 + +#include +#include + +#endif // OPENAVB_MEM_TCAL_PUB_H + diff --git a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_tcal_pub.h b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_tcal_pub.h index f3bb489b..2193e4b1 100644 --- a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_tcal_pub.h +++ b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_tcal_pub.h @@ -1,38 +1,38 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef OPENAVB_TCAL_PUB_H -#define OPENAVB_TCAL_PUB_H 1 - -// Logging Extra Newline. Some platforms libraries require an extra newline -static const bool OPENAVB_TCAL_LOG_EXTRA_NEWLINE = TRUE; - -#endif // OPENAVB_TCAL_PUB_H - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef OPENAVB_TCAL_PUB_H +#define OPENAVB_TCAL_PUB_H 1 + +// Logging Extra Newline. Some platforms libraries require an extra newline +static const bool OPENAVB_TCAL_LOG_EXTRA_NEWLINE = TRUE; + +#endif // OPENAVB_TCAL_PUB_H + diff --git a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_time_tcal_pub.h b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_time_tcal_pub.h index 4afe007e..216adec0 100644 --- a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_time_tcal_pub.h +++ b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_time_tcal_pub.h @@ -1,49 +1,49 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef _OPENAVB_TIME_TCAL_PUB_H -#define _OPENAVB_TIME_TCAL_PUB_H - -#if PROVIDED_BY_PLATFORM -typedef int clockid_t; -#endif - -#if PROVIDED_BY_PLATFORM -struct timespec { - long tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ -}; -struct itimerspec { - struct timespec it_interval; /* timer period */ - struct timespec it_value; /* timer expiration */ -}; -#endif - -#endif // _OPENAVB_TIME_TCAL_PUB_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef _OPENAVB_TIME_TCAL_PUB_H +#define _OPENAVB_TIME_TCAL_PUB_H + +#if PROVIDED_BY_PLATFORM +typedef int clockid_t; +#endif + +#if PROVIDED_BY_PLATFORM +struct timespec { + long tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +struct itimerspec { + struct timespec it_interval; /* timer period */ + struct timespec it_value; /* timer expiration */ +}; +#endif + +#endif // _OPENAVB_TIME_TCAL_PUB_H diff --git a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_types_base_tcal_pub.h b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_types_base_tcal_pub.h index 5f4da71e..64d7d6ba 100644 --- a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_types_base_tcal_pub.h +++ b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_types_base_tcal_pub.h @@ -1,40 +1,40 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef AVB_TYPES_BASE_TCAL_PUB_H -#define AVB_TYPES_BASE_TCAL_PUB_H 1 - -#define OPENAVB_PRAGMA(arg) _Pragma(#arg) - -#define OPENAVB_CODE_FUNCTION_PRI -#define OPENAVB_CODE_MODULE_PRI -#define OPENAVB_DATA_PRI - -#endif // AVB_TYPES_BASE_TCAL_PUB_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef AVB_TYPES_BASE_TCAL_PUB_H +#define AVB_TYPES_BASE_TCAL_PUB_H 1 + +#define OPENAVB_PRAGMA(arg) _Pragma(#arg) + +#define OPENAVB_CODE_FUNCTION_PRI +#define OPENAVB_CODE_MODULE_PRI +#define OPENAVB_DATA_PRI + +#endif // AVB_TYPES_BASE_TCAL_PUB_H diff --git a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_warnings_tcal.h b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_warnings_tcal.h index 637910a2..8da12fd1 100644 --- a/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_warnings_tcal.h +++ b/lib/avtp_pipeline/platform/platTCAL/GNU/openavb_warnings_tcal.h @@ -1,37 +1,37 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef OPENAVB_WARNINGS_TCAL_H -#define OPENAVB_WARNINGS_TCAL_H 1 - -#define OPENAVB_SUPPRESS_WARNING_UNREACHABLE_CODE() - -#endif // OPENAVB_WARNINGS_TCAL_H - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef OPENAVB_WARNINGS_TCAL_H +#define OPENAVB_WARNINGS_TCAL_H 1 + +#define OPENAVB_SUPPRESS_WARNING_UNREACHABLE_CODE() + +#endif // OPENAVB_WARNINGS_TCAL_H + diff --git a/lib/avtp_pipeline/platform/platTCAL/GNU/rawsock/openavb_rawsock_tcal.h b/lib/avtp_pipeline/platform/platTCAL/GNU/rawsock/openavb_rawsock_tcal.h index 460cf50e..72934112 100644 --- a/lib/avtp_pipeline/platform/platTCAL/GNU/rawsock/openavb_rawsock_tcal.h +++ b/lib/avtp_pipeline/platform/platTCAL/GNU/rawsock/openavb_rawsock_tcal.h @@ -1,59 +1,59 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef OPENAVB_RAWSOCK_TCAL_H -#define OPENAVB_RAWSOCK_TCAL_H 1 - - -// Ethernet header -typedef struct { - U8 dhost[ETH_ALEN]; - U8 shost[ETH_ALEN]; - uint16_t ethertype; -} -__attribute__ ((__packed__)) eth_hdr_t; - -// VLAN tag -typedef struct { - uint16_t tpip; - uint16_t bits; -} -__attribute__ ((__packed__)) vlan_tag_t; - -// Ethernet header w/VLAN tag -typedef struct { - U8 dhost[ETH_ALEN]; - U8 shost[ETH_ALEN]; - vlan_tag_t vlan; - uint16_t ethertype; -} -__attribute__ ((__packed__)) eth_vlan_hdr_t; - -#endif // OPENAVB_RAWSOCK_TCAL_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef OPENAVB_RAWSOCK_TCAL_H +#define OPENAVB_RAWSOCK_TCAL_H 1 + + +// Ethernet header +typedef struct { + U8 dhost[ETH_ALEN]; + U8 shost[ETH_ALEN]; + uint16_t ethertype; +} +__attribute__ ((__packed__)) eth_hdr_t; + +// VLAN tag +typedef struct { + uint16_t tpip; + uint16_t bits; +} +__attribute__ ((__packed__)) vlan_tag_t; + +// Ethernet header w/VLAN tag +typedef struct { + U8 dhost[ETH_ALEN]; + U8 shost[ETH_ALEN]; + vlan_tag_t vlan; + uint16_t ethertype; +} +__attribute__ ((__packed__)) eth_vlan_hdr_t; + +#endif // OPENAVB_RAWSOCK_TCAL_H diff --git a/lib/avtp_pipeline/platform/x86_i210/mcr/openavb_mcr_hal.c b/lib/avtp_pipeline/platform/x86_i210/mcr/openavb_mcr_hal.c index 5dee1f6f..6cdd873e 100644 --- a/lib/avtp_pipeline/platform/x86_i210/mcr/openavb_mcr_hal.c +++ b/lib/avtp_pipeline/platform/x86_i210/mcr/openavb_mcr_hal.c @@ -1,62 +1,62 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#define AVB_LOG_COMPONENT "MCR" -#include "openavb_pub.h" -#include "openavb_log.h" - -#include "openavb_mcr_hal.h" - - -bool halInitMCR(U32 packetRate, U32 pushInterval, U32 timestampInterval, U32 recoveryInterval) -{ - return TRUE; -} - -bool halCloseMCR(void) -{ - return TRUE; -} - -bool halPushMCR(void) -{ - return TRUE; -} - -void halAdjustMCRNSec(S32 adjNSec) -{ -} - -void halAdjustMCRGranularityNSec(U32 adjGranularityNSec) -{ -} - - - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#define AVB_LOG_COMPONENT "MCR" +#include "openavb_pub.h" +#include "openavb_log.h" + +#include "openavb_mcr_hal.h" + + +bool halInitMCR(U32 packetRate, U32 pushInterval, U32 timestampInterval, U32 recoveryInterval) +{ + return TRUE; +} + +bool halCloseMCR(void) +{ + return TRUE; +} + +bool halPushMCR(void) +{ + return TRUE; +} + +void halAdjustMCRNSec(S32 adjNSec) +{ +} + +void halAdjustMCRGranularityNSec(U32 adjGranularityNSec) +{ +} + + + diff --git a/lib/avtp_pipeline/platform/x86_i210/mcr/openavb_mcr_hal.h b/lib/avtp_pipeline/platform/x86_i210/mcr/openavb_mcr_hal.h index a458b262..85579122 100644 --- a/lib/avtp_pipeline/platform/x86_i210/mcr/openavb_mcr_hal.h +++ b/lib/avtp_pipeline/platform/x86_i210/mcr/openavb_mcr_hal.h @@ -1,37 +1,37 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef OPENAVB_MCR_HAL_H -#define OPENAVB_MCR_HAL_H - -#include "openavb_platform.h" -#include "openavb_mcr_hal_pub.h" - -#endif // OPENAVB_MCR_HAL_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef OPENAVB_MCR_HAL_H +#define OPENAVB_MCR_HAL_H + +#include "openavb_platform.h" +#include "openavb_mcr_hal_pub.h" + +#endif // OPENAVB_MCR_HAL_H diff --git a/lib/avtp_pipeline/platform/x86_i210/openavb_hal.h b/lib/avtp_pipeline/platform/x86_i210/openavb_hal.h index 58d077a0..a12e4dba 100644 --- a/lib/avtp_pipeline/platform/x86_i210/openavb_hal.h +++ b/lib/avtp_pipeline/platform/x86_i210/openavb_hal.h @@ -1,38 +1,38 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#ifndef _OPENAVB_HAL_H -#define _OPENAVB_HAL_H - -// Note this remains for backwards compatabilty with older prots. See openavb_mcr_hall_pub.h for newer APIs -// halPushMCR() API not defined -#define HAL_PUSH_MCR(mcrTimeStampPtr) FALSE - -#endif // _OPENAVB_HAL_H +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#ifndef _OPENAVB_HAL_H +#define _OPENAVB_HAL_H + +// Note this remains for backwards compatabilty with older prots. See openavb_mcr_hall_pub.h for newer APIs +// halPushMCR() API not defined +#define HAL_PUSH_MCR(mcrTimeStampPtr) FALSE + +#endif // _OPENAVB_HAL_H diff --git a/lib/avtp_pipeline/platform/x86_i210/openavb_time_hal.c b/lib/avtp_pipeline/platform/x86_i210/openavb_time_hal.c index 1a07a4bb..5b96224a 100644 --- a/lib/avtp_pipeline/platform/x86_i210/openavb_time_hal.c +++ b/lib/avtp_pipeline/platform/x86_i210/openavb_time_hal.c @@ -1,72 +1,72 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#include "openavb_platform.h" -#include "openavb_time_hal.h" -#include "openavb_ether_hal.h" - -#include "openavb_trace.h" - -#define AVB_LOG_COMPONENT "halTime" -#include "openavb_pub.h" -#include "openavb_log.h" - -static device_t *igb_dev = NULL; - -bool halTimeInitialize(void) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TIME); - igb_dev = igbAcquireDevice(); - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; -} - -bool halTimeFinalize(void) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TIME); - igbReleaseDevice(igb_dev); - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; -} - -bool halTimeGetLocaltime(U64 *localTime64) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TIME); - - if (igb_get_wallclock(igb_dev, localTime64, NULL ) > 0) { - IF_LOG_INTERVAL(1000) AVB_LOG_ERROR("Failed to get wallclock time"); - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return FALSE; - } - - AVB_TRACE_EXIT(AVB_TRACE_TIME); - return TRUE; -} - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#include "openavb_platform.h" +#include "openavb_time_hal.h" +#include "openavb_ether_hal.h" + +#include "openavb_trace.h" + +#define AVB_LOG_COMPONENT "halTime" +#include "openavb_pub.h" +#include "openavb_log.h" + +static device_t *igb_dev = NULL; + +bool halTimeInitialize(void) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TIME); + igb_dev = igbAcquireDevice(); + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; +} + +bool halTimeFinalize(void) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TIME); + igbReleaseDevice(igb_dev); + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; +} + +bool halTimeGetLocaltime(U64 *localTime64) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TIME); + + if (igb_get_wallclock(igb_dev, localTime64, NULL ) > 0) { + IF_LOG_INTERVAL(1000) AVB_LOG_ERROR("Failed to get wallclock time"); + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return FALSE; + } + + AVB_TRACE_EXIT(AVB_TRACE_TIME); + return TRUE; +} + diff --git a/lib/avtp_pipeline/platform/x86_i210/openavb_time_hal.h b/lib/avtp_pipeline/platform/x86_i210/openavb_time_hal.h index 9bd04048..a36b004e 100644 --- a/lib/avtp_pipeline/platform/x86_i210/openavb_time_hal.h +++ b/lib/avtp_pipeline/platform/x86_i210/openavb_time_hal.h @@ -1,38 +1,38 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + #ifndef _OPENAVB_TIME_HAL_H #define _OPENAVB_TIME_HAL_H - -bool halTimeInitialize(void); -bool halTimeFinalize(void); -bool halTimeGetLocaltime(U64 *localTime64); + +bool halTimeInitialize(void); +bool halTimeFinalize(void); +bool halTimeGetLocaltime(U64 *localTime64); #endif // _OPENAVB_TIME_HAL_H diff --git a/lib/avtp_pipeline/tl/openavb_listener_no_endpoint.c b/lib/avtp_pipeline/tl/openavb_listener_no_endpoint.c index 877d1c18..d60de0cb 100644 --- a/lib/avtp_pipeline/tl/openavb_listener_no_endpoint.c +++ b/lib/avtp_pipeline/tl/openavb_listener_no_endpoint.c @@ -1,80 +1,80 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE SUMMARY : Listener implementation -*/ - -#include -#include -#include -#include "openavb_platform.h" -#include "openavb_tl.h" -#include "openavb_avtp.h" -#include "openavb_listener.h" -#include "openavb_endpoint.h" - -#define AVB_LOG_COMPONENT "Listener" -#include "openavb_log.h" -#include "openavb_trace.h" - -bool openavbTLRunListenerInit(int hnd, AVBStreamID_t *streamID) -{ - tl_state_t *pTLState = TLHandleListGet(hnd); - openavb_tl_cfg_t *pCfg = &pTLState->cfg; - listener_data_t *pListenerData = pTLState->pPvtListenerData; - - strncpy(pListenerData->ifname, pCfg->ifname, IFNAMSIZ); - memcpy(&pListenerData->streamID.addr, &pCfg->stream_addr.mac->ether_addr_octet, ETH_ALEN); - pListenerData->streamID.uniqueID = pCfg->stream_uid; - memcpy(&pListenerData->destAddr, &pCfg->dest_addr.mac->ether_addr_octet, ETH_ALEN); - pListenerData->tSpec.maxIntervalFrames = pCfg->max_interval_frames; - pListenerData->tSpec.maxFrameSize = pCfg->max_frame_size; - - AVB_LOGF_INFO("Dest Addr: "ETH_FORMAT, ETH_OCTETS(pListenerData->destAddr)); - AVB_LOGF_INFO("Starting stream: "STREAMID_FORMAT, STREAMID_ARGS(streamID)); - listenerStartStream(pTLState); - - return TRUE; -} - - -void openavbEptClntNotifyLstnrOfSrpCb(int endpointHandle, - AVBStreamID_t *streamID, - char *ifname, - U8 destAddr[], - openavbSrpAttribType_t tlkrDecl, - AVBTSpec_t *tSpec, - U8 srClassID, - U32 latency, - openavbSrpFailInfo_t *failInfo) -{ -} - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : Listener implementation +*/ + +#include +#include +#include +#include "openavb_platform.h" +#include "openavb_tl.h" +#include "openavb_avtp.h" +#include "openavb_listener.h" +#include "openavb_endpoint.h" + +#define AVB_LOG_COMPONENT "Listener" +#include "openavb_log.h" +#include "openavb_trace.h" + +bool openavbTLRunListenerInit(int hnd, AVBStreamID_t *streamID) +{ + tl_state_t *pTLState = TLHandleListGet(hnd); + openavb_tl_cfg_t *pCfg = &pTLState->cfg; + listener_data_t *pListenerData = pTLState->pPvtListenerData; + + strncpy(pListenerData->ifname, pCfg->ifname, IFNAMSIZ); + memcpy(&pListenerData->streamID.addr, &pCfg->stream_addr.mac->ether_addr_octet, ETH_ALEN); + pListenerData->streamID.uniqueID = pCfg->stream_uid; + memcpy(&pListenerData->destAddr, &pCfg->dest_addr.mac->ether_addr_octet, ETH_ALEN); + pListenerData->tSpec.maxIntervalFrames = pCfg->max_interval_frames; + pListenerData->tSpec.maxFrameSize = pCfg->max_frame_size; + + AVB_LOGF_INFO("Dest Addr: "ETH_FORMAT, ETH_OCTETS(pListenerData->destAddr)); + AVB_LOGF_INFO("Starting stream: "STREAMID_FORMAT, STREAMID_ARGS(streamID)); + listenerStartStream(pTLState); + + return TRUE; +} + + +void openavbEptClntNotifyLstnrOfSrpCb(int endpointHandle, + AVBStreamID_t *streamID, + char *ifname, + U8 destAddr[], + openavbSrpAttribType_t tlkrDecl, + AVBTSpec_t *tSpec, + U8 srClassID, + U32 latency, + openavbSrpFailInfo_t *failInfo) +{ +} + diff --git a/lib/avtp_pipeline/tl/openavb_talker_no_endpoint.c b/lib/avtp_pipeline/tl/openavb_talker_no_endpoint.c index d7e08225..042801e3 100644 --- a/lib/avtp_pipeline/tl/openavb_talker_no_endpoint.c +++ b/lib/avtp_pipeline/tl/openavb_talker_no_endpoint.c @@ -1,151 +1,151 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE SUMMARY : Talker implementation for use without endpoint -*/ - -#include -#include -#include -#include "openavb_tl.h" -#include "openavb_avtp.h" -#include "openavb_talker.h" -#include "openavb_qmgr.h" -#include "openavb_endpoint.h" - -#define AVB_LOG_COMPONENT "Talker" -#include "openavb_log.h" -#include "openavb_trace.h" - -// SR Class default Priority (PCP) values per IEEE 802.1Q-2011 Table 6-6 -#define SR_CLASS_A_DEFAULT_PRIORITY 3 -#define SR_CLASS_B_DEFAULT_PRIORITY 2 - -// SR Class default VLAN Id values per IEEE 802.1Q-2011 Table 9-2 -#define SR_CLASS_A_DEFAULT_VID 2 -#define SR_CLASS_B_DEFAULT_VID 2 - -// Returns TRUE, to say we're connected and registers tspec with FQTSS tspec should be initialized -bool openavbTLRunTalkerInit(tl_state_t *pTLState) -{ - openavb_tl_cfg_t *pCfg = &pTLState->cfg; - talker_data_t *pTalkerData = pTLState->pPvtTalkerData; - //avtp_stream_t *pStream = (avtp_stream_t *)(pTalkerData->avtpHandle); - - strncpy(pTalkerData->ifname, pCfg->ifname, IFNAMSIZ); - - // CORE_TODO: It would be good to have some parts of endpoint moved into non-endpoint general code to handle some the stream - // configuration values. - // strncpy(pTalkerData->ifname, pCfg->ifname, IFNAMSIZ); - if (pCfg->stream_addr.mac) { - memcpy(pTalkerData->streamID.addr, pCfg->stream_addr.mac, ETH_ALEN); - }else { - AVB_LOG_WARNING("Stream Address Not Set"); - } - - pTalkerData->streamID.uniqueID = pCfg->stream_uid; - if (pCfg->sr_class == SR_CLASS_A) { - pTalkerData->classRate = 8000; - pTalkerData->vlanID = pCfg->vlan_id == VLAN_NULL ? - SR_CLASS_A_DEFAULT_VID : pCfg->vlan_id; - pTalkerData->vlanPCP = SR_CLASS_A_DEFAULT_PRIORITY; - } - else if (pCfg->sr_class == SR_CLASS_B) { - pTalkerData->classRate = 4000; - pTalkerData->vlanID = pCfg->vlan_id == VLAN_NULL ? - SR_CLASS_B_DEFAULT_VID : pCfg->vlan_id; - pTalkerData->vlanPCP = SR_CLASS_B_DEFAULT_PRIORITY; - } - memcpy(&pTalkerData->destAddr, &pCfg->dest_addr.mac->ether_addr_octet, ETH_ALEN); - - unsigned int maxBitrate = 0; - if (pCfg->intf_cb.intf_get_src_bitrate_cb != NULL) { - maxBitrate = pCfg->intf_cb.intf_get_src_bitrate_cb(pTLState->pMediaQ); - } - if (maxBitrate > 0) { - if (pCfg->map_cb.map_set_src_bitrate_cb != NULL) { - pCfg->map_cb.map_set_src_bitrate_cb(pTLState->pMediaQ, maxBitrate); - } - - if (pCfg->map_cb.map_get_max_interval_frames_cb != NULL) { - unsigned int map_intv_frames = pCfg->map_cb.map_get_max_interval_frames_cb(pTLState->pMediaQ, pTLState->cfg.sr_class); - pCfg->max_interval_frames = map_intv_frames > 0 ? map_intv_frames : pCfg->max_interval_frames; - } - } - pTalkerData->tSpec.maxIntervalFrames = pCfg->max_interval_frames; - pTalkerData->tSpec.maxFrameSize = pCfg->map_cb.map_max_data_size_cb(pTLState->pMediaQ); - - // TODO_COREAVB : This wakeRate should also be set in the endpoint case and removed from the tasker.c start stream - if (!pCfg->map_cb.map_transmit_interval_cb(pTLState->pMediaQ)) { - pTalkerData->wakeRate = pTalkerData->classRate / pCfg->batch_factor; - } - else { - // Override the class observation interval with the one provided by the mapping module. - pTalkerData->wakeRate = pCfg->map_cb.map_transmit_interval_cb(pTLState->pMediaQ) / pCfg->batch_factor; - } - - if_info_t ifinfo; - openavbCheckInterface(pTalkerData->ifname, &ifinfo); - - pTalkerData->fwmark = openavbQmgrAddStream((SRClassIdx_t)pCfg->sr_class, - pTalkerData->wakeRate, - pTalkerData->tSpec.maxIntervalFrames, - pTalkerData->tSpec.maxFrameSize); - - if (pTalkerData->fwmark == INVALID_FWMARK) - return FALSE; - - AVB_LOGF_INFO("Dest Addr: "ETH_FORMAT, ETH_OCTETS(pTalkerData->destAddr)); - AVB_LOGF_INFO("Starting stream: "STREAMID_FORMAT, STREAMID_ARGS(&pTalkerData->streamID)); - talkerStartStream(pTLState); - - return TRUE; -} - -void openavbTLRunTalkerFinish(tl_state_t *pTLState) -{ - talker_data_t *pTalkerData = pTLState->pPvtTalkerData; - openavbQmgrRemoveStream(pTalkerData->fwmark); -} - -void openavbEptClntNotifyTlkrOfSrpCb( -int endpointHandle, -AVBStreamID_t *streamID, -char *ifname, -U8 destAddr[], -openavbSrpLsnrDeclSubtype_t lsnrDecl, -U32 classRate, -U16 vlanID, -U8 priority, -U16 fwmark) -{ -} - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : Talker implementation for use without endpoint +*/ + +#include +#include +#include +#include "openavb_tl.h" +#include "openavb_avtp.h" +#include "openavb_talker.h" +#include "openavb_qmgr.h" +#include "openavb_endpoint.h" + +#define AVB_LOG_COMPONENT "Talker" +#include "openavb_log.h" +#include "openavb_trace.h" + +// SR Class default Priority (PCP) values per IEEE 802.1Q-2011 Table 6-6 +#define SR_CLASS_A_DEFAULT_PRIORITY 3 +#define SR_CLASS_B_DEFAULT_PRIORITY 2 + +// SR Class default VLAN Id values per IEEE 802.1Q-2011 Table 9-2 +#define SR_CLASS_A_DEFAULT_VID 2 +#define SR_CLASS_B_DEFAULT_VID 2 + +// Returns TRUE, to say we're connected and registers tspec with FQTSS tspec should be initialized +bool openavbTLRunTalkerInit(tl_state_t *pTLState) +{ + openavb_tl_cfg_t *pCfg = &pTLState->cfg; + talker_data_t *pTalkerData = pTLState->pPvtTalkerData; + //avtp_stream_t *pStream = (avtp_stream_t *)(pTalkerData->avtpHandle); + + strncpy(pTalkerData->ifname, pCfg->ifname, IFNAMSIZ); + + // CORE_TODO: It would be good to have some parts of endpoint moved into non-endpoint general code to handle some the stream + // configuration values. + // strncpy(pTalkerData->ifname, pCfg->ifname, IFNAMSIZ); + if (pCfg->stream_addr.mac) { + memcpy(pTalkerData->streamID.addr, pCfg->stream_addr.mac, ETH_ALEN); + }else { + AVB_LOG_WARNING("Stream Address Not Set"); + } + + pTalkerData->streamID.uniqueID = pCfg->stream_uid; + if (pCfg->sr_class == SR_CLASS_A) { + pTalkerData->classRate = 8000; + pTalkerData->vlanID = pCfg->vlan_id == VLAN_NULL ? + SR_CLASS_A_DEFAULT_VID : pCfg->vlan_id; + pTalkerData->vlanPCP = SR_CLASS_A_DEFAULT_PRIORITY; + } + else if (pCfg->sr_class == SR_CLASS_B) { + pTalkerData->classRate = 4000; + pTalkerData->vlanID = pCfg->vlan_id == VLAN_NULL ? + SR_CLASS_B_DEFAULT_VID : pCfg->vlan_id; + pTalkerData->vlanPCP = SR_CLASS_B_DEFAULT_PRIORITY; + } + memcpy(&pTalkerData->destAddr, &pCfg->dest_addr.mac->ether_addr_octet, ETH_ALEN); + + unsigned int maxBitrate = 0; + if (pCfg->intf_cb.intf_get_src_bitrate_cb != NULL) { + maxBitrate = pCfg->intf_cb.intf_get_src_bitrate_cb(pTLState->pMediaQ); + } + if (maxBitrate > 0) { + if (pCfg->map_cb.map_set_src_bitrate_cb != NULL) { + pCfg->map_cb.map_set_src_bitrate_cb(pTLState->pMediaQ, maxBitrate); + } + + if (pCfg->map_cb.map_get_max_interval_frames_cb != NULL) { + unsigned int map_intv_frames = pCfg->map_cb.map_get_max_interval_frames_cb(pTLState->pMediaQ, pTLState->cfg.sr_class); + pCfg->max_interval_frames = map_intv_frames > 0 ? map_intv_frames : pCfg->max_interval_frames; + } + } + pTalkerData->tSpec.maxIntervalFrames = pCfg->max_interval_frames; + pTalkerData->tSpec.maxFrameSize = pCfg->map_cb.map_max_data_size_cb(pTLState->pMediaQ); + + // TODO_COREAVB : This wakeRate should also be set in the endpoint case and removed from the tasker.c start stream + if (!pCfg->map_cb.map_transmit_interval_cb(pTLState->pMediaQ)) { + pTalkerData->wakeRate = pTalkerData->classRate / pCfg->batch_factor; + } + else { + // Override the class observation interval with the one provided by the mapping module. + pTalkerData->wakeRate = pCfg->map_cb.map_transmit_interval_cb(pTLState->pMediaQ) / pCfg->batch_factor; + } + + if_info_t ifinfo; + openavbCheckInterface(pTalkerData->ifname, &ifinfo); + + pTalkerData->fwmark = openavbQmgrAddStream((SRClassIdx_t)pCfg->sr_class, + pTalkerData->wakeRate, + pTalkerData->tSpec.maxIntervalFrames, + pTalkerData->tSpec.maxFrameSize); + + if (pTalkerData->fwmark == INVALID_FWMARK) + return FALSE; + + AVB_LOGF_INFO("Dest Addr: "ETH_FORMAT, ETH_OCTETS(pTalkerData->destAddr)); + AVB_LOGF_INFO("Starting stream: "STREAMID_FORMAT, STREAMID_ARGS(&pTalkerData->streamID)); + talkerStartStream(pTLState); + + return TRUE; +} + +void openavbTLRunTalkerFinish(tl_state_t *pTLState) +{ + talker_data_t *pTalkerData = pTLState->pPvtTalkerData; + openavbQmgrRemoveStream(pTalkerData->fwmark); +} + +void openavbEptClntNotifyTlkrOfSrpCb( +int endpointHandle, +AVBStreamID_t *streamID, +char *ifname, +U8 destAddr[], +openavbSrpLsnrDeclSubtype_t lsnrDecl, +U32 classRate, +U16 vlanID, +U8 priority, +U16 fwmark) +{ +} + diff --git a/lib/avtp_pipeline/tl/openavb_tl.c b/lib/avtp_pipeline/tl/openavb_tl.c index eb9ee145..256f7051 100755 --- a/lib/avtp_pipeline/tl/openavb_tl.c +++ b/lib/avtp_pipeline/tl/openavb_tl.c @@ -1,734 +1,734 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE SUMMARY : Common implementation for the talker and listener -*/ - -#include -#include -#include -#include "openavb_tl.h" -#include "openavb_trace.h" -#include "openavb_mediaq.h" -#include "openavb_talker.h" -#include "openavb_listener.h" -// #include "openavb_avtp.h" -#include "openavb_platform.h" - -#define AVB_LOG_COMPONENT "Talker / Listener" -#include "openavb_pub.h" -#include "openavb_log.h" - -U32 gMaxTL; -tl_handle_t *gTLHandleList; - -// We are accessed from multiple threads, so need a mutex -MUTEX_HANDLE(gTLStateMutex); - -#define MATCH(A, B)(strcasecmp((A), (B)) == 0) -//#define MATCH_LEFT(A, B, C)(strncasecmp((A), (B), (C)) == 0) -#define MATCH_LEFT(A, B, C) (memcmp((A), (B), (C)) == 0) - -THREAD_TYPE(listenerThread); -THREAD_TYPE(talkerThread); - -void* openavbTLThreadFn(void *pv); -#define THREAD_CREATE_TALKER() THREAD_CREATE(talkerThread, pTLState->TLThread, NULL, openavbTLThreadFn, pTLState) -#define THREAD_CREATE_LISTENER() THREAD_CREATE(listenerThread, pTLState->TLThread, NULL, openavbTLThreadFn, pTLState) - -void timespec_add_usec(struct timespec *t, unsigned long us) -{ - t->tv_nsec += us * NANOSECONDS_PER_USEC; - t->tv_sec += t->tv_nsec / NANOSECONDS_PER_SECOND; - t->tv_nsec = t->tv_nsec % NANOSECONDS_PER_SECOND; -} - -void timespec_sub_usec(struct timespec *t, unsigned long us) -{ - t->tv_nsec -= us * NANOSECONDS_PER_USEC; - t->tv_sec += t->tv_nsec / NANOSECONDS_PER_SECOND; - t->tv_nsec = t->tv_nsec % NANOSECONDS_PER_SECOND; - if (t->tv_nsec < 0) { - t->tv_sec--; - t->tv_nsec = NANOSECONDS_PER_SECOND + t->tv_nsec; - } -} - -unsigned long timespec_usec_diff(struct timespec *t1, struct timespec *t2) -{ - return (t1->tv_sec - t2->tv_sec) * MICROSECONDS_PER_SECOND - + (t1->tv_nsec - t2->tv_nsec) / NANOSECONDS_PER_USEC; -} - -int timespec_cmp(struct timespec *a, struct timespec *b) -{ - if (a->tv_sec > b->tv_sec) - return 1; - else if (a->tv_sec < b->tv_sec) - return -1; - else { - if (a->tv_nsec > b->tv_nsec) - return 1; - else if (a->tv_nsec < b->tv_nsec) - return -1; - } - return 0; -} - -static bool TLHandleListAdd(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - if (!handle || !gTLHandleList) { - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - TL_LOCK(); - int i1; - for (i1 = 0; i1 < gMaxTL; i1++) { - if (!gTLHandleList[i1]) { - gTLHandleList[i1] = handle; - TL_UNLOCK(); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return TRUE; - } - } - TL_UNLOCK(); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; -} - -bool TLHandleListRemove(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - if (!handle || !gTLHandleList) { - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - TL_LOCK(); - int i1; - for (i1 = 0; i1 < gMaxTL; i1++) { - if (gTLHandleList[i1] == handle) { - gTLHandleList[i1] = NULL; - TL_UNLOCK(); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return TRUE; - } - } - TL_UNLOCK(); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; -} - -static bool checkIntfCallbacks(openavb_tl_cfg_t *pCfg) -{ - bool validCfg = TRUE; - - if (!pCfg->intf_cb.intf_cfg_cb) { - AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_cfg'."); - // validCfg = FALSE; - } - if ((pCfg->role == AVB_ROLE_TALKER) && !pCfg->intf_cb.intf_tx_init_cb) { - AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_tx_init'."); - // validCfg = FALSE; - } - if ((pCfg->role == AVB_ROLE_TALKER) && !pCfg->intf_cb.intf_tx_cb) { - AVB_LOG_ERROR("INI file doesn't specify inferface callback for '_tx'."); - validCfg = FALSE; - } - if ((pCfg->role == AVB_ROLE_LISTENER) && !pCfg->intf_cb.intf_rx_init_cb) { - AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_rx_init'."); - // validCfg = FALSE; - } - if ((pCfg->role == AVB_ROLE_LISTENER) && !pCfg->intf_cb.intf_rx_cb) { - AVB_LOG_ERROR("INI file doesn't specify inferface callback for '_rx'."); - validCfg = FALSE; - } - if (!pCfg->intf_cb.intf_end_cb) { - AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_end'."); - // validCfg = FALSE; - } - if (!pCfg->intf_cb.intf_gen_init_cb) { - AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_gen_init'."); - // validCfg = FALSE; - } - if (!pCfg->intf_cb.intf_gen_end_cb) { - AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_gen_end'."); - // validCfg = FALSE; - } - if (!pCfg->intf_cb.intf_avdecc_init_cb) { - // Optional callback - // CORE_TODO: AVDECC not formally supported yet. - // AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_avdecc_init'."); - // validCfg = FALSE; - } - - return validCfg; -} - -static bool checkMapCallbacks(openavb_tl_cfg_t *pCfg) -{ - bool validCfg = TRUE; - - if (!pCfg->map_cb.map_cfg_cb) { - AVB_LOG_WARNING("INI doesn't specify mapping callback for '_cfg'."); - // validCfg = FALSE; - } - if (!pCfg->map_cb.map_subtype_cb) { - AVB_LOG_WARNING("INI doesn't specify mapping callback for '_subtype'."); - // validCfg = FALSE; - } - if (!pCfg->map_cb.map_avtp_version_cb) { - AVB_LOG_WARNING("INI doesn't specify mapping callback for '_avtp_version'."); - // validCfg = FALSE; - } - if ((pCfg->role == AVB_ROLE_TALKER) && !pCfg->map_cb.map_tx_init_cb) { - AVB_LOG_WARNING("INI doesn't specify mapping callback for '_tx_init'."); - // validCfg = FALSE; - } - if ((pCfg->role == AVB_ROLE_TALKER) && !pCfg->map_cb.map_tx_cb) { - AVB_LOG_ERROR("INI doesn't specify mapping callback for '_tx'."); - validCfg = FALSE; - } - if ((pCfg->role == AVB_ROLE_LISTENER) && !pCfg->map_cb.map_rx_init_cb) { - AVB_LOG_WARNING("INI doesn't specify mapping callback for '_rx_init'."); - // validCfg = FALSE; - } - if ((pCfg->role == AVB_ROLE_LISTENER) && !pCfg->map_cb.map_rx_cb) { - AVB_LOG_ERROR("INI doesn't specify mapping callback for '_rx'."); - validCfg = FALSE; - } - if (!pCfg->map_cb.map_end_cb) { - AVB_LOG_WARNING("INI doesn't specify mapping callback for '_end'."); - // validCfg = FALSE; - } - if (!pCfg->map_cb.map_gen_init_cb) { - AVB_LOG_WARNING("INI doesn't specify mapping callback for '_gen_init'."); - // validCfg = FALSE; - } - if (!pCfg->map_cb.map_gen_end_cb) { - AVB_LOG_WARNING("INI doesn't specify mapping callback for '_gen_end'."); - // validCfg = FALSE; - } - if (!pCfg->map_cb.map_avdecc_init_cb) { - // Optional callback - // CORE_TODO: AVDECC not formally supported yet. - // AVB_LOG_WARNING("INI doesn't specify mapping callback for '_avdecc_init'."); - // validCfg = FALSE; - } - - return validCfg; -} - -void openavbTLUnconfigure(tl_state_t *pTLState) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - // CORE_TODO: Disable this functionality until updated to properly handle distinction between values point to static const char - // and dynamically allocated strings. -#if 0 - openavb_tl_cfg_t *pCfg = &pTLState->cfg; - - int i1; - for (i1 = 0; i1 < pCfg->nLibCfgItems; i1++) { - if (pCfg->libCfgNames[i1]) - free(pCfg->libCfgNames[i1]); - if (pNVCfg->libCfgValues[i1]) - free(pNVCfg->libCfgValues[i1]); - pCfg->libCfgNames[i1] = pNVCfg->libCfgValues[i1] = NULL; - } - pCfg->nLibCfgItems = 0; -#endif - - AVB_TRACE_EXIT(AVB_TRACE_TL); -} - - -/* Public APIs - */ -// General initizlization of the talker and listener library. Must be called prior to using any other TL APIs. -EXTERN_DLL_EXPORT bool openavbTLInitialize(U32 maxTL) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - LOG_EAVB_CORE_VERSION(); - - // CORE_TODO : This can be used to AVB stack init functionality once such a thing exists in the reference implementation - AVB_TIME_INIT(); - - gMaxTL = maxTL; - - { - MUTEX_ATTR_HANDLE(mta); - MUTEX_ATTR_INIT(mta); - MUTEX_ATTR_SET_TYPE(mta, MUTEX_ATTR_TYPE_DEFAULT); - MUTEX_ATTR_SET_NAME(mta, "gTLStateMutex"); - MUTEX_CREATE_ERR(); - MUTEX_CREATE(gTLStateMutex, mta); - MUTEX_LOG_ERR("Error creating mutex"); - } - - gTLHandleList = calloc(1, sizeof(tl_handle_t) * gMaxTL); - if (gTLHandleList) { - AVB_TRACE_EXIT(AVB_TRACE_TL); - return TRUE; - } - else { - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } -} - -// General cleanup of the talker and listener library. Should be called after all Talker and Listeners are closed. -EXTERN_DLL_EXPORT bool openavbTLCleanup() -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - if (gTLHandleList) { - free(gTLHandleList); - gTLHandleList = NULL; - } - else { - return FALSE; - } - - { - MUTEX_CREATE_ERR(); - MUTEX_DESTROY(gTLStateMutex); - MUTEX_LOG_ERR("Error destroying mutex"); - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return TRUE; -} - -EXTERN_DLL_EXPORT bool openavbGetVersion(U8 *major, U8 *minor, U8 *revision) -{ - if (!major || !minor || !revision) { - return FALSE; - } - - *major = AVB_CORE_VER_MAJOR; - *minor = AVB_CORE_VER_MINOR; - *revision = AVB_CORE_VER_REVISION; - return TRUE; -} - -EXTERN_DLL_EXPORT tl_handle_t openavbTLOpen(void) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = calloc(1, sizeof(tl_state_t)); - - if (!pTLState) { - AVB_LOG_ERROR("Unable to allocate talker listener state data."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return NULL; - } - - if (!TLHandleListAdd(pTLState)) { - AVB_LOG_ERROR("To many talker listeners open."); - free(pTLState); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return NULL; - } - - return pTLState; -} - -EXTERN_DLL_EXPORT void openavbTLInitCfg(openavb_tl_cfg_t *pCfg) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - memset(pCfg, 0, sizeof(openavb_tl_cfg_t)); - - // Set default values. - pCfg->role = AVB_ROLE_UNDEFINED; - //pCfg->map_cb; - //pCfg->intf_cb; - //pCfg->dest_addr; - //pCfg->stream_addr; - pCfg->stream_uid = -1; - pCfg->max_interval_frames = 1; - pCfg->max_frame_size = 1500; - pCfg->max_transit_usec = 50000; - pCfg->max_transmit_deficit_usec = 50000; - pCfg->internal_latency = 0; - pCfg->max_stale = MICROSECONDS_PER_SECOND; - pCfg->batch_factor = 1; - pCfg->report_seconds = 0; - pCfg->start_paused = FALSE; - pCfg->sr_class = SR_CLASS_B; - pCfg->sr_rank = SR_RANK_REGULAR; - pCfg->raw_tx_buffers = 8; - pCfg->raw_rx_buffers = 100; - pCfg->tx_blocking_in_intf = 0; - pCfg->rx_signal_mode = 1; - pCfg->pMapInitFn = NULL; - pCfg->pIntfInitFn = NULL; - pCfg->vlan_id = VLAN_NULL; - - AVB_TRACE_EXIT(AVB_TRACE_TL); -} - -EXTERN_DLL_EXPORT bool openavbTLConfigure(tl_handle_t handle, openavb_tl_cfg_t *pCfgIn, openavb_tl_cfg_name_value_t *pNVCfg) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - // Create the mediaQ - pTLState->pMediaQ = openavbMediaQCreate(); - if (!pTLState->pMediaQ) { - AVB_LOG_ERROR("Unable to create media queue"); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - // CORE_TODO: It's not safe to simply copy the openavb_tl_cfg_t since there are embedded pointers in the cfg_mac_t member. - // Those pointers need to be updated after a copy. Longer term the cfg_mac_t should be changed to not contain the mac - // member to remedy this issue and avoid further bugs. - memcpy(&pTLState->cfg, pCfgIn, sizeof(openavb_tl_cfg_t)); - pTLState->cfg.dest_addr.mac = &pTLState->cfg.dest_addr.buffer; - pTLState->cfg.stream_addr.mac = &pTLState->cfg.stream_addr.buffer; - - openavb_tl_cfg_t *pCfg = &pTLState->cfg; - - if (!((pCfg->role == AVB_ROLE_TALKER) || (pCfg->role == AVB_ROLE_LISTENER))) { - AVB_LOG_ERROR("Talker - Listener Config Error: invalid role"); - return FALSE; - } - - if ((pCfg->role == AVB_ROLE_TALKER) && (pCfg->max_interval_frames == 0)) { - AVB_LOG_ERROR("Talker - Listener Config Error: talker role requires 'max_interval_frames'"); - return FALSE; - } - - openavbMediaQSetMaxStaleTail(pTLState->pMediaQ, pCfg->max_stale); - - if (!openavbTLOpenLinkLibsOsal(pTLState)) { - AVB_LOG_ERROR("Failed to open mapping / interface library"); - return FALSE; - } - - if (pCfg->pMapInitFn && pCfg->pMapInitFn(pTLState->pMediaQ, &pCfg->map_cb, pCfg->max_transit_usec)) { - checkMapCallbacks(&pTLState->cfg); - } - else { - AVB_LOG_ERROR("Mapping initialize function error."); - return FALSE; - } - - if (pCfg->pIntfInitFn && pCfg->pIntfInitFn(pTLState->pMediaQ, &pCfg->intf_cb)) { - checkIntfCallbacks(&pTLState->cfg); - } - else { - AVB_LOG_ERROR("Interface initialize function error."); - return FALSE; - } - - // Submit configuration values to mapping and interface modules - int i; - for (i = 0; i < pNVCfg->nLibCfgItems; i++) { - if (MATCH_LEFT(pNVCfg->libCfgNames[i], "intf_nv_", 8)) { - if (pCfg->intf_cb.intf_cfg_cb) { - pCfg->intf_cb.intf_cfg_cb(pTLState->pMediaQ, pNVCfg->libCfgNames[i], pNVCfg->libCfgValues[i]); - } - else { - AVB_LOGF_ERROR("No interface module cfg function; ignoring %s", pNVCfg->libCfgNames[i]); - } - } - else if (MATCH_LEFT(pNVCfg->libCfgNames[i], "map_nv_", 7)) { - if (pCfg->map_cb.map_cfg_cb) { - pCfg->map_cb.map_cfg_cb(pTLState->pMediaQ, pNVCfg->libCfgNames[i], pNVCfg->libCfgValues[i]); - } - else { - AVB_LOGF_ERROR("No mapping module cfg function; ignoring %s", pNVCfg->libCfgNames[i]); - } - } - else { - assert(0); - } - } // for loop ends - - pTLState->cfg.map_cb.map_gen_init_cb(pTLState->pMediaQ); - pTLState->cfg.intf_cb.intf_gen_init_cb(pTLState->pMediaQ); - - return TRUE; -} - -EXTERN_DLL_EXPORT bool openavbTLRun(tl_handle_t handle) -{ - bool retVal = FALSE; - - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - do { - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - break; - } - - pTLState->bRunning = TRUE; - if (pTLState->cfg.role == AVB_ROLE_TALKER) { - THREAD_CREATE_TALKER(); - } - else if (pTLState->cfg.role == AVB_ROLE_LISTENER) { - THREAD_CREATE_LISTENER(); - } - - retVal = TRUE; - - } while (0); - - - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return retVal; -} - -extern DLL_EXPORT bool openavbTLStop(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - if (pTLState->bRunning) { - // don't set bStreaming to false here, that's needed to track - // that the streaming thread is running, so we can shut it down. - //pTLState->bStreaming = FALSE; - pTLState->bRunning = FALSE; - - THREAD_JOIN(pTLState->TLThread, NULL); - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return TRUE; -} - -EXTERN_DLL_EXPORT bool openavbTLClose(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - if (pTLState->bRunning == TRUE) { - // In case openavbTLStop wasn't called stop is now. - openavbTLStop(handle); - } - - pTLState->cfg.intf_cb.intf_gen_end_cb(pTLState->pMediaQ); - pTLState->cfg.map_cb.map_gen_end_cb(pTLState->pMediaQ); - - TLHandleListRemove(handle); - - openavbTLUnconfigure(pTLState); - openavbTLCloseLinkLibsOsal(pTLState); - - if (pTLState->pMediaQ) { - openavbMediaQDelete(pTLState->pMediaQ); - pTLState->pMediaQ = NULL; - } - - // Free TLState - free(pTLState); - pTLState = NULL; - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return TRUE; -} - -EXTERN_DLL_EXPORT void* openavbTLGetIntfHostCBList(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return pTLState->cfg.intf_cb.intf_host_cb_list; -} - -EXTERN_DLL_EXPORT void* openavbTLGetIntfHandle(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return pTLState->pMediaQ; -} - -EXTERN_DLL_EXPORT bool openavbTLIsRunning(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return pTLState->bRunning; -} - -EXTERN_DLL_EXPORT bool openavbTLIsConnected(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return pTLState->bConnected; -} - -EXTERN_DLL_EXPORT bool openavbTLIsStreaming(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return FALSE; - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return pTLState->bStreaming; -} - -EXTERN_DLL_EXPORT avb_role_t openavbTLGetRole(tl_handle_t handle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle"); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return AVB_ROLE_UNDEFINED; - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return pTLState->cfg.role; -} - - -EXTERN_DLL_EXPORT U64 openavbTLStat(tl_handle_t handle, tl_stat_t stat) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - U64 val = 0; - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle"); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return 0; - } - - if (pTLState->cfg.role == AVB_ROLE_TALKER) { - val = openavbTalkerGetStat(pTLState, stat); - } - else if (pTLState->cfg.role == AVB_ROLE_LISTENER) { - val = openavbListenerGetStat(pTLState, stat); - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return val; -} - -EXTERN_DLL_EXPORT void openavbTLPauseStream(tl_handle_t handle, bool bPause) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)handle; - - if (!pTLState) { - AVB_LOG_ERROR("Invalid handle."); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return; - } - - if (pTLState->cfg.role == AVB_ROLE_TALKER) { - openavbTLPauseTalker(pTLState, bPause); - } - else if (pTLState->cfg.role == AVB_ROLE_LISTENER) { - openavbTLPauseListener(pTLState, bPause); - } - - AVB_TRACE_EXIT(AVB_TRACE_TL); -} - - - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : Common implementation for the talker and listener +*/ + +#include +#include +#include +#include "openavb_tl.h" +#include "openavb_trace.h" +#include "openavb_mediaq.h" +#include "openavb_talker.h" +#include "openavb_listener.h" +// #include "openavb_avtp.h" +#include "openavb_platform.h" + +#define AVB_LOG_COMPONENT "Talker / Listener" +#include "openavb_pub.h" +#include "openavb_log.h" + +U32 gMaxTL; +tl_handle_t *gTLHandleList; + +// We are accessed from multiple threads, so need a mutex +MUTEX_HANDLE(gTLStateMutex); + +#define MATCH(A, B)(strcasecmp((A), (B)) == 0) +//#define MATCH_LEFT(A, B, C)(strncasecmp((A), (B), (C)) == 0) +#define MATCH_LEFT(A, B, C) (memcmp((A), (B), (C)) == 0) + +THREAD_TYPE(listenerThread); +THREAD_TYPE(talkerThread); + +void* openavbTLThreadFn(void *pv); +#define THREAD_CREATE_TALKER() THREAD_CREATE(talkerThread, pTLState->TLThread, NULL, openavbTLThreadFn, pTLState) +#define THREAD_CREATE_LISTENER() THREAD_CREATE(listenerThread, pTLState->TLThread, NULL, openavbTLThreadFn, pTLState) + +void timespec_add_usec(struct timespec *t, unsigned long us) +{ + t->tv_nsec += us * NANOSECONDS_PER_USEC; + t->tv_sec += t->tv_nsec / NANOSECONDS_PER_SECOND; + t->tv_nsec = t->tv_nsec % NANOSECONDS_PER_SECOND; +} + +void timespec_sub_usec(struct timespec *t, unsigned long us) +{ + t->tv_nsec -= us * NANOSECONDS_PER_USEC; + t->tv_sec += t->tv_nsec / NANOSECONDS_PER_SECOND; + t->tv_nsec = t->tv_nsec % NANOSECONDS_PER_SECOND; + if (t->tv_nsec < 0) { + t->tv_sec--; + t->tv_nsec = NANOSECONDS_PER_SECOND + t->tv_nsec; + } +} + +unsigned long timespec_usec_diff(struct timespec *t1, struct timespec *t2) +{ + return (t1->tv_sec - t2->tv_sec) * MICROSECONDS_PER_SECOND + + (t1->tv_nsec - t2->tv_nsec) / NANOSECONDS_PER_USEC; +} + +int timespec_cmp(struct timespec *a, struct timespec *b) +{ + if (a->tv_sec > b->tv_sec) + return 1; + else if (a->tv_sec < b->tv_sec) + return -1; + else { + if (a->tv_nsec > b->tv_nsec) + return 1; + else if (a->tv_nsec < b->tv_nsec) + return -1; + } + return 0; +} + +static bool TLHandleListAdd(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + if (!handle || !gTLHandleList) { + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + TL_LOCK(); + int i1; + for (i1 = 0; i1 < gMaxTL; i1++) { + if (!gTLHandleList[i1]) { + gTLHandleList[i1] = handle; + TL_UNLOCK(); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return TRUE; + } + } + TL_UNLOCK(); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; +} + +bool TLHandleListRemove(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + if (!handle || !gTLHandleList) { + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + TL_LOCK(); + int i1; + for (i1 = 0; i1 < gMaxTL; i1++) { + if (gTLHandleList[i1] == handle) { + gTLHandleList[i1] = NULL; + TL_UNLOCK(); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return TRUE; + } + } + TL_UNLOCK(); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; +} + +static bool checkIntfCallbacks(openavb_tl_cfg_t *pCfg) +{ + bool validCfg = TRUE; + + if (!pCfg->intf_cb.intf_cfg_cb) { + AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_cfg'."); + // validCfg = FALSE; + } + if ((pCfg->role == AVB_ROLE_TALKER) && !pCfg->intf_cb.intf_tx_init_cb) { + AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_tx_init'."); + // validCfg = FALSE; + } + if ((pCfg->role == AVB_ROLE_TALKER) && !pCfg->intf_cb.intf_tx_cb) { + AVB_LOG_ERROR("INI file doesn't specify inferface callback for '_tx'."); + validCfg = FALSE; + } + if ((pCfg->role == AVB_ROLE_LISTENER) && !pCfg->intf_cb.intf_rx_init_cb) { + AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_rx_init'."); + // validCfg = FALSE; + } + if ((pCfg->role == AVB_ROLE_LISTENER) && !pCfg->intf_cb.intf_rx_cb) { + AVB_LOG_ERROR("INI file doesn't specify inferface callback for '_rx'."); + validCfg = FALSE; + } + if (!pCfg->intf_cb.intf_end_cb) { + AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_end'."); + // validCfg = FALSE; + } + if (!pCfg->intf_cb.intf_gen_init_cb) { + AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_gen_init'."); + // validCfg = FALSE; + } + if (!pCfg->intf_cb.intf_gen_end_cb) { + AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_gen_end'."); + // validCfg = FALSE; + } + if (!pCfg->intf_cb.intf_avdecc_init_cb) { + // Optional callback + // CORE_TODO: AVDECC not formally supported yet. + // AVB_LOG_WARNING("INI file doesn't specify inferface callback for '_avdecc_init'."); + // validCfg = FALSE; + } + + return validCfg; +} + +static bool checkMapCallbacks(openavb_tl_cfg_t *pCfg) +{ + bool validCfg = TRUE; + + if (!pCfg->map_cb.map_cfg_cb) { + AVB_LOG_WARNING("INI doesn't specify mapping callback for '_cfg'."); + // validCfg = FALSE; + } + if (!pCfg->map_cb.map_subtype_cb) { + AVB_LOG_WARNING("INI doesn't specify mapping callback for '_subtype'."); + // validCfg = FALSE; + } + if (!pCfg->map_cb.map_avtp_version_cb) { + AVB_LOG_WARNING("INI doesn't specify mapping callback for '_avtp_version'."); + // validCfg = FALSE; + } + if ((pCfg->role == AVB_ROLE_TALKER) && !pCfg->map_cb.map_tx_init_cb) { + AVB_LOG_WARNING("INI doesn't specify mapping callback for '_tx_init'."); + // validCfg = FALSE; + } + if ((pCfg->role == AVB_ROLE_TALKER) && !pCfg->map_cb.map_tx_cb) { + AVB_LOG_ERROR("INI doesn't specify mapping callback for '_tx'."); + validCfg = FALSE; + } + if ((pCfg->role == AVB_ROLE_LISTENER) && !pCfg->map_cb.map_rx_init_cb) { + AVB_LOG_WARNING("INI doesn't specify mapping callback for '_rx_init'."); + // validCfg = FALSE; + } + if ((pCfg->role == AVB_ROLE_LISTENER) && !pCfg->map_cb.map_rx_cb) { + AVB_LOG_ERROR("INI doesn't specify mapping callback for '_rx'."); + validCfg = FALSE; + } + if (!pCfg->map_cb.map_end_cb) { + AVB_LOG_WARNING("INI doesn't specify mapping callback for '_end'."); + // validCfg = FALSE; + } + if (!pCfg->map_cb.map_gen_init_cb) { + AVB_LOG_WARNING("INI doesn't specify mapping callback for '_gen_init'."); + // validCfg = FALSE; + } + if (!pCfg->map_cb.map_gen_end_cb) { + AVB_LOG_WARNING("INI doesn't specify mapping callback for '_gen_end'."); + // validCfg = FALSE; + } + if (!pCfg->map_cb.map_avdecc_init_cb) { + // Optional callback + // CORE_TODO: AVDECC not formally supported yet. + // AVB_LOG_WARNING("INI doesn't specify mapping callback for '_avdecc_init'."); + // validCfg = FALSE; + } + + return validCfg; +} + +void openavbTLUnconfigure(tl_state_t *pTLState) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + // CORE_TODO: Disable this functionality until updated to properly handle distinction between values point to static const char + // and dynamically allocated strings. +#if 0 + openavb_tl_cfg_t *pCfg = &pTLState->cfg; + + int i1; + for (i1 = 0; i1 < pCfg->nLibCfgItems; i1++) { + if (pCfg->libCfgNames[i1]) + free(pCfg->libCfgNames[i1]); + if (pNVCfg->libCfgValues[i1]) + free(pNVCfg->libCfgValues[i1]); + pCfg->libCfgNames[i1] = pNVCfg->libCfgValues[i1] = NULL; + } + pCfg->nLibCfgItems = 0; +#endif + + AVB_TRACE_EXIT(AVB_TRACE_TL); +} + + +/* Public APIs + */ +// General initizlization of the talker and listener library. Must be called prior to using any other TL APIs. +EXTERN_DLL_EXPORT bool openavbTLInitialize(U32 maxTL) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + LOG_EAVB_CORE_VERSION(); + + // CORE_TODO : This can be used to AVB stack init functionality once such a thing exists in the reference implementation + AVB_TIME_INIT(); + + gMaxTL = maxTL; + + { + MUTEX_ATTR_HANDLE(mta); + MUTEX_ATTR_INIT(mta); + MUTEX_ATTR_SET_TYPE(mta, MUTEX_ATTR_TYPE_DEFAULT); + MUTEX_ATTR_SET_NAME(mta, "gTLStateMutex"); + MUTEX_CREATE_ERR(); + MUTEX_CREATE(gTLStateMutex, mta); + MUTEX_LOG_ERR("Error creating mutex"); + } + + gTLHandleList = calloc(1, sizeof(tl_handle_t) * gMaxTL); + if (gTLHandleList) { + AVB_TRACE_EXIT(AVB_TRACE_TL); + return TRUE; + } + else { + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } +} + +// General cleanup of the talker and listener library. Should be called after all Talker and Listeners are closed. +EXTERN_DLL_EXPORT bool openavbTLCleanup() +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + if (gTLHandleList) { + free(gTLHandleList); + gTLHandleList = NULL; + } + else { + return FALSE; + } + + { + MUTEX_CREATE_ERR(); + MUTEX_DESTROY(gTLStateMutex); + MUTEX_LOG_ERR("Error destroying mutex"); + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return TRUE; +} + +EXTERN_DLL_EXPORT bool openavbGetVersion(U8 *major, U8 *minor, U8 *revision) +{ + if (!major || !minor || !revision) { + return FALSE; + } + + *major = AVB_CORE_VER_MAJOR; + *minor = AVB_CORE_VER_MINOR; + *revision = AVB_CORE_VER_REVISION; + return TRUE; +} + +EXTERN_DLL_EXPORT tl_handle_t openavbTLOpen(void) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = calloc(1, sizeof(tl_state_t)); + + if (!pTLState) { + AVB_LOG_ERROR("Unable to allocate talker listener state data."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return NULL; + } + + if (!TLHandleListAdd(pTLState)) { + AVB_LOG_ERROR("To many talker listeners open."); + free(pTLState); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return NULL; + } + + return pTLState; +} + +EXTERN_DLL_EXPORT void openavbTLInitCfg(openavb_tl_cfg_t *pCfg) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + memset(pCfg, 0, sizeof(openavb_tl_cfg_t)); + + // Set default values. + pCfg->role = AVB_ROLE_UNDEFINED; + //pCfg->map_cb; + //pCfg->intf_cb; + //pCfg->dest_addr; + //pCfg->stream_addr; + pCfg->stream_uid = -1; + pCfg->max_interval_frames = 1; + pCfg->max_frame_size = 1500; + pCfg->max_transit_usec = 50000; + pCfg->max_transmit_deficit_usec = 50000; + pCfg->internal_latency = 0; + pCfg->max_stale = MICROSECONDS_PER_SECOND; + pCfg->batch_factor = 1; + pCfg->report_seconds = 0; + pCfg->start_paused = FALSE; + pCfg->sr_class = SR_CLASS_B; + pCfg->sr_rank = SR_RANK_REGULAR; + pCfg->raw_tx_buffers = 8; + pCfg->raw_rx_buffers = 100; + pCfg->tx_blocking_in_intf = 0; + pCfg->rx_signal_mode = 1; + pCfg->pMapInitFn = NULL; + pCfg->pIntfInitFn = NULL; + pCfg->vlan_id = VLAN_NULL; + + AVB_TRACE_EXIT(AVB_TRACE_TL); +} + +EXTERN_DLL_EXPORT bool openavbTLConfigure(tl_handle_t handle, openavb_tl_cfg_t *pCfgIn, openavb_tl_cfg_name_value_t *pNVCfg) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + // Create the mediaQ + pTLState->pMediaQ = openavbMediaQCreate(); + if (!pTLState->pMediaQ) { + AVB_LOG_ERROR("Unable to create media queue"); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + // CORE_TODO: It's not safe to simply copy the openavb_tl_cfg_t since there are embedded pointers in the cfg_mac_t member. + // Those pointers need to be updated after a copy. Longer term the cfg_mac_t should be changed to not contain the mac + // member to remedy this issue and avoid further bugs. + memcpy(&pTLState->cfg, pCfgIn, sizeof(openavb_tl_cfg_t)); + pTLState->cfg.dest_addr.mac = &pTLState->cfg.dest_addr.buffer; + pTLState->cfg.stream_addr.mac = &pTLState->cfg.stream_addr.buffer; + + openavb_tl_cfg_t *pCfg = &pTLState->cfg; + + if (!((pCfg->role == AVB_ROLE_TALKER) || (pCfg->role == AVB_ROLE_LISTENER))) { + AVB_LOG_ERROR("Talker - Listener Config Error: invalid role"); + return FALSE; + } + + if ((pCfg->role == AVB_ROLE_TALKER) && (pCfg->max_interval_frames == 0)) { + AVB_LOG_ERROR("Talker - Listener Config Error: talker role requires 'max_interval_frames'"); + return FALSE; + } + + openavbMediaQSetMaxStaleTail(pTLState->pMediaQ, pCfg->max_stale); + + if (!openavbTLOpenLinkLibsOsal(pTLState)) { + AVB_LOG_ERROR("Failed to open mapping / interface library"); + return FALSE; + } + + if (pCfg->pMapInitFn && pCfg->pMapInitFn(pTLState->pMediaQ, &pCfg->map_cb, pCfg->max_transit_usec)) { + checkMapCallbacks(&pTLState->cfg); + } + else { + AVB_LOG_ERROR("Mapping initialize function error."); + return FALSE; + } + + if (pCfg->pIntfInitFn && pCfg->pIntfInitFn(pTLState->pMediaQ, &pCfg->intf_cb)) { + checkIntfCallbacks(&pTLState->cfg); + } + else { + AVB_LOG_ERROR("Interface initialize function error."); + return FALSE; + } + + // Submit configuration values to mapping and interface modules + int i; + for (i = 0; i < pNVCfg->nLibCfgItems; i++) { + if (MATCH_LEFT(pNVCfg->libCfgNames[i], "intf_nv_", 8)) { + if (pCfg->intf_cb.intf_cfg_cb) { + pCfg->intf_cb.intf_cfg_cb(pTLState->pMediaQ, pNVCfg->libCfgNames[i], pNVCfg->libCfgValues[i]); + } + else { + AVB_LOGF_ERROR("No interface module cfg function; ignoring %s", pNVCfg->libCfgNames[i]); + } + } + else if (MATCH_LEFT(pNVCfg->libCfgNames[i], "map_nv_", 7)) { + if (pCfg->map_cb.map_cfg_cb) { + pCfg->map_cb.map_cfg_cb(pTLState->pMediaQ, pNVCfg->libCfgNames[i], pNVCfg->libCfgValues[i]); + } + else { + AVB_LOGF_ERROR("No mapping module cfg function; ignoring %s", pNVCfg->libCfgNames[i]); + } + } + else { + assert(0); + } + } // for loop ends + + pTLState->cfg.map_cb.map_gen_init_cb(pTLState->pMediaQ); + pTLState->cfg.intf_cb.intf_gen_init_cb(pTLState->pMediaQ); + + return TRUE; +} + +EXTERN_DLL_EXPORT bool openavbTLRun(tl_handle_t handle) +{ + bool retVal = FALSE; + + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + do { + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + break; + } + + pTLState->bRunning = TRUE; + if (pTLState->cfg.role == AVB_ROLE_TALKER) { + THREAD_CREATE_TALKER(); + } + else if (pTLState->cfg.role == AVB_ROLE_LISTENER) { + THREAD_CREATE_LISTENER(); + } + + retVal = TRUE; + + } while (0); + + + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return retVal; +} + +extern DLL_EXPORT bool openavbTLStop(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + if (pTLState->bRunning) { + // don't set bStreaming to false here, that's needed to track + // that the streaming thread is running, so we can shut it down. + //pTLState->bStreaming = FALSE; + pTLState->bRunning = FALSE; + + THREAD_JOIN(pTLState->TLThread, NULL); + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return TRUE; +} + +EXTERN_DLL_EXPORT bool openavbTLClose(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + if (pTLState->bRunning == TRUE) { + // In case openavbTLStop wasn't called stop is now. + openavbTLStop(handle); + } + + pTLState->cfg.intf_cb.intf_gen_end_cb(pTLState->pMediaQ); + pTLState->cfg.map_cb.map_gen_end_cb(pTLState->pMediaQ); + + TLHandleListRemove(handle); + + openavbTLUnconfigure(pTLState); + openavbTLCloseLinkLibsOsal(pTLState); + + if (pTLState->pMediaQ) { + openavbMediaQDelete(pTLState->pMediaQ); + pTLState->pMediaQ = NULL; + } + + // Free TLState + free(pTLState); + pTLState = NULL; + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return TRUE; +} + +EXTERN_DLL_EXPORT void* openavbTLGetIntfHostCBList(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return pTLState->cfg.intf_cb.intf_host_cb_list; +} + +EXTERN_DLL_EXPORT void* openavbTLGetIntfHandle(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return pTLState->pMediaQ; +} + +EXTERN_DLL_EXPORT bool openavbTLIsRunning(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return pTLState->bRunning; +} + +EXTERN_DLL_EXPORT bool openavbTLIsConnected(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return pTLState->bConnected; +} + +EXTERN_DLL_EXPORT bool openavbTLIsStreaming(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return FALSE; + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return pTLState->bStreaming; +} + +EXTERN_DLL_EXPORT avb_role_t openavbTLGetRole(tl_handle_t handle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle"); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return AVB_ROLE_UNDEFINED; + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return pTLState->cfg.role; +} + + +EXTERN_DLL_EXPORT U64 openavbTLStat(tl_handle_t handle, tl_stat_t stat) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + U64 val = 0; + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle"); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return 0; + } + + if (pTLState->cfg.role == AVB_ROLE_TALKER) { + val = openavbTalkerGetStat(pTLState, stat); + } + else if (pTLState->cfg.role == AVB_ROLE_LISTENER) { + val = openavbListenerGetStat(pTLState, stat); + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return val; +} + +EXTERN_DLL_EXPORT void openavbTLPauseStream(tl_handle_t handle, bool bPause) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)handle; + + if (!pTLState) { + AVB_LOG_ERROR("Invalid handle."); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return; + } + + if (pTLState->cfg.role == AVB_ROLE_TALKER) { + openavbTLPauseTalker(pTLState, bPause); + } + else if (pTLState->cfg.role == AVB_ROLE_LISTENER) { + openavbTLPauseListener(pTLState, bPause); + } + + AVB_TRACE_EXIT(AVB_TRACE_TL); +} + + + diff --git a/lib/avtp_pipeline/tl/openavb_tl_no_endpoint.c b/lib/avtp_pipeline/tl/openavb_tl_no_endpoint.c index 85173d2c..c3940d87 100644 --- a/lib/avtp_pipeline/tl/openavb_tl_no_endpoint.c +++ b/lib/avtp_pipeline/tl/openavb_tl_no_endpoint.c @@ -1,134 +1,134 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -/* -* MODULE SUMMARY : Common implementation for the talker and listener -*/ - -#include -#include -#include -#include "openavb_tl.h" -#include "openavb_trace.h" -//#include "openavb_mediaq.h" -#include "openavb_talker.h" -#include "openavb_listener.h" -#include "openavb_avtp.h" -#include "openavb_endpoint.h" - -#include "openavb_platform.h" - -#define AVB_LOG_COMPONENT "Talker / Listener" -#include "openavb_pub.h" -#include "openavb_log.h" - -void openavbEptClntCheckVerMatchesSrvr(int endpointHandle, U32 AVBVersion) -{ -} - - -// Talker Listener thread function -void* openavbTLThreadFn(void *pv) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - tl_state_t *pTLState = (tl_state_t *)pv; - - openavbTLThreadFnOsal(pTLState); - - TL_LOCK(); - // Assign a unique endpoint handle - static int gEndpointHandle = 1; - pTLState->endpointHandle = gEndpointHandle++; - TL_UNLOCK(); - - while (pTLState->bRunning) { - AVB_TRACE_LINE(AVB_TRACE_TL_DETAIL); - - if (pTLState->cfg.role == AVB_ROLE_TALKER) { - openavbTLRunTalker(pTLState); - } - else { - openavbTLRunListener(pTLState); - } - - // Close the endpoint connection. unless connection already gone in which case the socket could already be reused. - if (pTLState->bConnected) { - pTLState->bConnected = FALSE; - pTLState->endpointHandle = 0; - } - - if (pTLState->bRunning) { - SLEEP(1); - } - } - - THREAD_JOINABLE(pTLState->TLThread); - - AVB_TRACE_EXIT(AVB_TRACE_TL); - return NULL; -} - -tl_handle_t TLHandleListGet(int endpointHandle) -{ - AVB_TRACE_ENTRY(AVB_TRACE_TL); - - if (!endpointHandle || !gTLHandleList) { - AVB_TRACE_EXIT(AVB_TRACE_TL); - return NULL; - } - - TL_LOCK(); - int i1; - for (i1 = 0; i1 < gMaxTL; i1++) { - if (gTLHandleList[i1]) { - tl_state_t *pTLState = (tl_state_t *)gTLHandleList[i1]; - if (pTLState->endpointHandle == endpointHandle) { - TL_UNLOCK(); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return pTLState; - } - } - } - TL_UNLOCK(); - AVB_TRACE_EXIT(AVB_TRACE_TL); - return NULL; -} - -bool openavbEptClntStopStream(int h, AVBStreamID_t *streamID) -{ - return TRUE; -} - -bool openavbEptClntService(int h, int timeout) -{ - return TRUE; -} - +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : Common implementation for the talker and listener +*/ + +#include +#include +#include +#include "openavb_tl.h" +#include "openavb_trace.h" +//#include "openavb_mediaq.h" +#include "openavb_talker.h" +#include "openavb_listener.h" +#include "openavb_avtp.h" +#include "openavb_endpoint.h" + +#include "openavb_platform.h" + +#define AVB_LOG_COMPONENT "Talker / Listener" +#include "openavb_pub.h" +#include "openavb_log.h" + +void openavbEptClntCheckVerMatchesSrvr(int endpointHandle, U32 AVBVersion) +{ +} + + +// Talker Listener thread function +void* openavbTLThreadFn(void *pv) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + tl_state_t *pTLState = (tl_state_t *)pv; + + openavbTLThreadFnOsal(pTLState); + + TL_LOCK(); + // Assign a unique endpoint handle + static int gEndpointHandle = 1; + pTLState->endpointHandle = gEndpointHandle++; + TL_UNLOCK(); + + while (pTLState->bRunning) { + AVB_TRACE_LINE(AVB_TRACE_TL_DETAIL); + + if (pTLState->cfg.role == AVB_ROLE_TALKER) { + openavbTLRunTalker(pTLState); + } + else { + openavbTLRunListener(pTLState); + } + + // Close the endpoint connection. unless connection already gone in which case the socket could already be reused. + if (pTLState->bConnected) { + pTLState->bConnected = FALSE; + pTLState->endpointHandle = 0; + } + + if (pTLState->bRunning) { + SLEEP(1); + } + } + + THREAD_JOINABLE(pTLState->TLThread); + + AVB_TRACE_EXIT(AVB_TRACE_TL); + return NULL; +} + +tl_handle_t TLHandleListGet(int endpointHandle) +{ + AVB_TRACE_ENTRY(AVB_TRACE_TL); + + if (!endpointHandle || !gTLHandleList) { + AVB_TRACE_EXIT(AVB_TRACE_TL); + return NULL; + } + + TL_LOCK(); + int i1; + for (i1 = 0; i1 < gMaxTL; i1++) { + if (gTLHandleList[i1]) { + tl_state_t *pTLState = (tl_state_t *)gTLHandleList[i1]; + if (pTLState->endpointHandle == endpointHandle) { + TL_UNLOCK(); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return pTLState; + } + } + } + TL_UNLOCK(); + AVB_TRACE_EXIT(AVB_TRACE_TL); + return NULL; +} + +bool openavbEptClntStopStream(int h, AVBStreamID_t *streamID) +{ + return TRUE; +} + +bool openavbEptClntService(int h, int timeout) +{ + return TRUE; +} + diff --git a/lib/avtp_pipeline/util/openavb_queue.c b/lib/avtp_pipeline/util/openavb_queue.c index 4dbbf366..cc7ea21d 100644 --- a/lib/avtp_pipeline/util/openavb_queue.c +++ b/lib/avtp_pipeline/util/openavb_queue.c @@ -1,196 +1,196 @@ -/************************************************************************************************************* -Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company -All rights reserved. - -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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. - -Attributions: The inih library portion of the source code is licensed from -Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. -Complete license and copyright information can be found at -https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. -*************************************************************************************************************/ - -#include -#include -#include -#include - -#include "openavb_debug.h" -#include "openavb_queue.h" - -OPENAVB_CODE_MODULE_PRI - -struct openavb_queue_elem { - bool setFlg; - void *data; -}; - -struct openavb_queue { - // Size of each element - U32 elemSize; - - // Number of queue element slots - U32 queueSize; - - // Next element to be filled - int head; - - // Next element to be pulled - int tail; - - openavb_queue_elem_t elemArray; -}; - -openavb_queue_t openavbQueueNewQueue(U32 elemSize, U32 queueSize) -{ - if (elemSize < 1 || queueSize < 1) - return NULL; - - openavb_queue_t retQueue = calloc(1, sizeof(struct openavb_queue)); - if (retQueue) { - retQueue->elemArray = calloc(queueSize, sizeof(struct openavb_queue_elem)); - if (retQueue->elemArray) { - U32 i1; - for (i1 = 0; i1 < queueSize; i1++) { - retQueue->elemArray[i1].data = calloc(1, elemSize); - if (!retQueue->elemArray[i1].data) { - openavbQueueDeleteQueue(retQueue); - return NULL; - } - } - } - else { - openavbQueueDeleteQueue(retQueue); - return NULL; - } - - retQueue->elemSize = elemSize; - retQueue->queueSize = queueSize; - retQueue->head = 0; - retQueue->tail = 0; - } - - return retQueue; -} - -void openavbQueueDeleteQueue(openavb_queue_t queue) -{ - if (queue) { - U32 i1; - for (i1 = 0; i1 < queue->queueSize; i1++) { - free(queue->elemArray[i1].data); - queue->elemArray[i1].data = NULL; - } - free(queue->elemArray); - queue->elemArray = NULL; - free(queue); - } -} - -U32 openavbQueueGetQueueSize(openavb_queue_t queue) -{ - if (queue) { - return queue->queueSize; - } - return 0; -} - -U32 openavbQueueGetElemCount(openavb_queue_t queue) -{ - U32 cnt = 0; - if (queue) { - if (queue->head > queue->tail) { - cnt += queue->head - queue->tail - 1; - } - else if (queue->head < queue->tail) { - cnt += queue->head + ((queue->queueSize - 1) - queue->tail); - } - - if (queue->elemArray[queue->tail].setFlg) { - cnt++; - } - } - return cnt; -} - -U32 openavbQueueGetElemSize(openavb_queue_t queue) -{ - if (queue) { - return queue->elemSize; - } - return 0; -} - -void *openavbQueueData(openavb_queue_elem_t elem) -{ - if (elem) { - return elem->data; - } - return NULL; -} - -openavb_queue_elem_t openavbQueueHeadLock(openavb_queue_t queue) -{ - if (queue) { - if (!queue->elemArray[queue->head].setFlg) { - return &queue->elemArray[queue->head]; - } - } - return NULL; -} - -void openavbQueueHeadUnlock(openavb_queue_t queue) -{ -} - -void openavbQueueHeadPush(openavb_queue_t queue) -{ - if (queue) { - queue->elemArray[queue->head++].setFlg = TRUE; - if (queue->head >= queue->queueSize) { - queue->head = 0; - } - } -} - -openavb_queue_elem_t openavbQueueTailLock(openavb_queue_t queue) -{ - if (queue) { - if (queue->elemArray[queue->tail].setFlg) { - return &queue->elemArray[queue->tail]; - } - } - return NULL; -} - -void openavbQueueTailUnlock(openavb_queue_t queue) -{ -} - -void openavbQueueTailPull(openavb_queue_t queue) -{ - if (queue) { - queue->elemArray[queue->tail++].setFlg = FALSE; - if (queue->tail >= queue->queueSize) { - queue->tail = 0; - } - } -} +/************************************************************************************************************* +Copyright (c) 2012-2015, Symphony Teleca Corporation, a Harman International Industries, Incorporated company +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. + +Attributions: The inih library portion of the source code is licensed from +Brush Technology and Ben Hoyt - Copyright (c) 2009, Brush Technology and Copyright (c) 2009, Ben Hoyt. +Complete license and copyright information can be found at +https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. +*************************************************************************************************************/ + +#include +#include +#include +#include + +#include "openavb_debug.h" +#include "openavb_queue.h" + +OPENAVB_CODE_MODULE_PRI + +struct openavb_queue_elem { + bool setFlg; + void *data; +}; + +struct openavb_queue { + // Size of each element + U32 elemSize; + + // Number of queue element slots + U32 queueSize; + + // Next element to be filled + int head; + + // Next element to be pulled + int tail; + + openavb_queue_elem_t elemArray; +}; + +openavb_queue_t openavbQueueNewQueue(U32 elemSize, U32 queueSize) +{ + if (elemSize < 1 || queueSize < 1) + return NULL; + + openavb_queue_t retQueue = calloc(1, sizeof(struct openavb_queue)); + if (retQueue) { + retQueue->elemArray = calloc(queueSize, sizeof(struct openavb_queue_elem)); + if (retQueue->elemArray) { + U32 i1; + for (i1 = 0; i1 < queueSize; i1++) { + retQueue->elemArray[i1].data = calloc(1, elemSize); + if (!retQueue->elemArray[i1].data) { + openavbQueueDeleteQueue(retQueue); + return NULL; + } + } + } + else { + openavbQueueDeleteQueue(retQueue); + return NULL; + } + + retQueue->elemSize = elemSize; + retQueue->queueSize = queueSize; + retQueue->head = 0; + retQueue->tail = 0; + } + + return retQueue; +} + +void openavbQueueDeleteQueue(openavb_queue_t queue) +{ + if (queue) { + U32 i1; + for (i1 = 0; i1 < queue->queueSize; i1++) { + free(queue->elemArray[i1].data); + queue->elemArray[i1].data = NULL; + } + free(queue->elemArray); + queue->elemArray = NULL; + free(queue); + } +} + +U32 openavbQueueGetQueueSize(openavb_queue_t queue) +{ + if (queue) { + return queue->queueSize; + } + return 0; +} + +U32 openavbQueueGetElemCount(openavb_queue_t queue) +{ + U32 cnt = 0; + if (queue) { + if (queue->head > queue->tail) { + cnt += queue->head - queue->tail - 1; + } + else if (queue->head < queue->tail) { + cnt += queue->head + ((queue->queueSize - 1) - queue->tail); + } + + if (queue->elemArray[queue->tail].setFlg) { + cnt++; + } + } + return cnt; +} + +U32 openavbQueueGetElemSize(openavb_queue_t queue) +{ + if (queue) { + return queue->elemSize; + } + return 0; +} + +void *openavbQueueData(openavb_queue_elem_t elem) +{ + if (elem) { + return elem->data; + } + return NULL; +} + +openavb_queue_elem_t openavbQueueHeadLock(openavb_queue_t queue) +{ + if (queue) { + if (!queue->elemArray[queue->head].setFlg) { + return &queue->elemArray[queue->head]; + } + } + return NULL; +} + +void openavbQueueHeadUnlock(openavb_queue_t queue) +{ +} + +void openavbQueueHeadPush(openavb_queue_t queue) +{ + if (queue) { + queue->elemArray[queue->head++].setFlg = TRUE; + if (queue->head >= queue->queueSize) { + queue->head = 0; + } + } +} + +openavb_queue_elem_t openavbQueueTailLock(openavb_queue_t queue) +{ + if (queue) { + if (queue->elemArray[queue->tail].setFlg) { + return &queue->elemArray[queue->tail]; + } + } + return NULL; +} + +void openavbQueueTailUnlock(openavb_queue_t queue) +{ +} + +void openavbQueueTailPull(openavb_queue_t queue) +{ + if (queue) { + queue->elemArray[queue->tail++].setFlg = FALSE; + if (queue->tail >= queue->queueSize) { + queue->tail = 0; + } + } +} -- cgit v1.2.1 From df37b79bc95cf842b375d3d393e0df8c3479b0ea Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:57:51 +0200 Subject: avtp_pipeline: Fixed SLEEP_NSEC(). --- lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h b/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h index e3833f0d..d9998357 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h +++ b/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h @@ -64,7 +64,7 @@ https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. #define SLEEP(sec) sleep(sec) #define SLEEP_MSEC(mSec) usleep(mSec * 1000) -#define SLEEP_NSEC(nSec) usleep(nSec) +#define SLEEP_NSEC(nSec) usleep(nSec / 1000) #define SLEEP_UNTIL_NSEC(nSec) xSleepUntilNSec(nSec) inline static void xSleepUntilNSec(U64 nSec) { -- cgit v1.2.1 From 7b422abf268b574e7d40a6a086243f6699904775 Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Thu, 16 Jun 2016 12:19:19 -0600 Subject: avtp_pipeline: Tone gen module updates Unlimited number of channels 16, 24, 32 bit sample depth for int samples float32 samples Volume adjustment Up to two fixed-value Int32 fixed value channels --- .../intf_tonegen/openavb_intf_tonegen.c | 196 +++++++++++++++++---- lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini | 8 + 2 files changed, 165 insertions(+), 39 deletions(-) diff --git a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c index b2a1bf23..3be1cfa6 100644 --- a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c +++ b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c @@ -48,7 +48,7 @@ https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. #include "openavb_intf_pub.h" #define AVB_LOG_COMPONENT "Tone Gen Interface" -#include "openavb_log_pub.h" +#include "openavb_log_pub.h" #define PI 3.14159265358979f @@ -58,7 +58,7 @@ typedef struct { ///////////// // intf_nv_tone_hz: The tone hz to generate U32 toneHz; - + // intf_nv_on_off_interval_msec: Interval for turning tone on and off. A value of zero will keep the tone on. U32 onOffIntervalMSec; @@ -69,17 +69,28 @@ typedef struct { avb_audio_rate_t audioRate; // intf_nv_audio_type - avb_audio_bit_depth_t audioType; + avb_audio_type_t audioType; // intf_nv_audio_bit_depth avb_audio_bit_depth_t audioBitDepth; // intf_nv_audio_endian - avb_audio_bit_depth_t audioEndian; + avb_audio_endian_t audioEndian; // intf_nv_channels avb_audio_channels_t audioChannels; + // Volume for the tone generation + float volume; + + // Fixed 32 bit value 1 + bool fv1Enabled; + U32 fv1; + + // Fixed 32 bit value 2 + bool fv2Enabled; + U32 fv2; + ///////////// // Variable data ///////////// @@ -87,9 +98,9 @@ typedef struct { // Packing interval U32 intervalCounter; - // Keeps track of if the tone is currently on or off + // Keeps track of if the tone is currently on or off U32 freq; - + // Keeps track of how long before toggling the tone on / off U32 freqCountdown; @@ -98,10 +109,12 @@ typedef struct { // Index to into the melody string U32 melodyIdx; - + // Length of the melody string U32 melodyLen; + U32 fvChannels; + } pvt_data_t; #define MSEC_PER_COUNT 250 @@ -243,6 +256,7 @@ void openavbIntfToneGenCfgCB(media_q_t *pMediaQ, const char *name, const char *v } } +#if 1 // both bit_depth and audio_type are not required, just use audio_type, always do big endian else if (strcmp(name, "intf_nv_audio_bit_depth") == 0) { val = strtol(value, &pEnd, 10); // TODO: Should check for specific values @@ -262,42 +276,72 @@ void openavbIntfToneGenCfgCB(media_q_t *pMediaQ, const char *name, const char *v else if (strcmp(name, "intf_nv_audio_type") == 0) { if (strncasecmp(value, "float", 5) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_FLOAT; + pPvtData->audioType = AVB_AUDIO_TYPE_FLOAT; else if (strncasecmp(value, "sign", 4) == 0 || strncasecmp(value, "int", 4) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_INT; + pPvtData->audioType = AVB_AUDIO_TYPE_INT; else if (strncasecmp(value, "unsign", 6) == 0 || strncasecmp(value, "uint", 4) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_UINT; + pPvtData->audioType = AVB_AUDIO_TYPE_UINT; else { AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_type."); - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_TYPE_UNSPEC; + pPvtData->audioType = AVB_AUDIO_TYPE_UNSPEC; } // Give the audio parameters to the mapping module. if (xSupportedMappingFormat(pMediaQ)) { - pPubMapUncmpAudioInfo->audioType = (avb_audio_type_t)pPvtData->audioType; + pPubMapUncmpAudioInfo->audioType = pPvtData->audioType; } } else if (strcmp(name, "intf_nv_audio_endian") == 0) { if (strncasecmp(value, "big", 3) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_BIG; + pPvtData->audioEndian = AVB_AUDIO_ENDIAN_BIG; else if (strncasecmp(value, "little", 6) == 0) - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_LITTLE; + pPvtData->audioEndian = AVB_AUDIO_ENDIAN_LITTLE; else { AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_endian."); - pPvtData->audioType = (avb_audio_bit_depth_t)AVB_AUDIO_ENDIAN_UNSPEC; + pPvtData->audioEndian = AVB_AUDIO_ENDIAN_UNSPEC; } // Give the audio parameters to the mapping module. if (xSupportedMappingFormat(pMediaQ)) { - pPubMapUncmpAudioInfo->audioEndian = (avb_audio_endian_t)pPvtData->audioEndian; + pPubMapUncmpAudioInfo->audioEndian = pPvtData->audioEndian; + } + } +#else + else if (strcmp(name, "intf_nv_audio_type") == 0) { + if (strncasecmp(value, "float", 5) == 0) { + pPvtData->audioType = AVB_AUDIO_TYPE_FLOAT; + pPvtData->audioBitDepth = 32; + } else if (strncasecmp(value, "int32", 5) == 0) { + pPvtData->audioType = AVB_AUDIO_TYPE_INT; + pPvtData->audioBitDepth = 32; + } else if (strncasecmp(value, "int24", 5) == 0) { + pPvtData->audioType = AVB_AUDIO_TYPE_INT; + pPvtData->audioBitDepth = 24; + } else if (strncasecmp(value, "int16", 5) == 0) { + pPvtData->audioType = AVB_AUDIO_TYPE_INT; + pPvtData->audioBitDepth = 16; + } else { + AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_type."); + pPvtData->audioType = AVB_AUDIO_TYPE_UNSPEC; + } + + // always big endian + pPvtData->audioEndian = AVB_AUDIO_ENDIAN_BIG; + + // Give the audio parameters to the mapping module. + if (xSupportedMappingFormat(pMediaQ)) { + pPubMapUncmpAudioInfo->audioType = pPvtData->audioType; + pPubMapUncmpAudioInfo->audioBitDepth = pPvtData->audioBitDepth; + pPubMapUncmpAudioInfo->audioEndian = pPvtData->audioEndian; } } +#endif else if (strcmp(name, "intf_nv_audio_channels") == 0) { val = strtol(value, &pEnd, 10); // TODO: Should check for specific values - if (val >= AVB_AUDIO_CHANNELS_1 && val <= AVB_AUDIO_CHANNELS_8) { + if (val >= AVB_AUDIO_CHANNELS_1) { pPvtData->audioChannels = (avb_audio_channels_t)val; } else { @@ -310,7 +354,27 @@ void openavbIntfToneGenCfgCB(media_q_t *pMediaQ, const char *name, const char *v pPubMapUncmpAudioInfo->audioChannels = pPvtData->audioChannels; } } - + + else if (strcmp(name, "intf_nv_volume") == 0) { + U32 vol = strtol(value, &pEnd, 10); + if (vol > 100) { + vol = 100; + } + pPvtData->volume = (float)vol / 100.0; + } + + else if (strcmp(name, "intf_nv_fv1") == 0) { + pPvtData->fv1 = strtol(value, &pEnd, 10); + pPvtData->fv1Enabled = true; + pPvtData->fvChannels++; + } + + else if (strcmp(name, "intf_nv_fv2") == 0) { + pPvtData->fv2 = strtol(value, &pEnd, 10); + pPvtData->fv2Enabled = true; + pPvtData->fvChannels++; + } + } AVB_TRACE_EXIT(AVB_TRACE_INTF); @@ -387,7 +451,8 @@ bool openavbIntfToneGenTxCB(media_q_t *pMediaQ) static U32 runningFrameCnt = 0; U32 frameCnt; U32 channelCnt; - U32 idx = 0; + U8 *pData = pMediaQItem->pPubData; + for (frameCnt = 0; frameCnt < pPubMapUncmpAudioInfo->framesPerItem; frameCnt++) { // Check for tone on / off toggle @@ -408,44 +473,87 @@ bool openavbIntfToneGenTxCB(media_q_t *pMediaQ) else { // Fixed tone if (pPvtData->onOffIntervalMSec > 0) { - if (pPvtData->freq == 0) + if (pPvtData->freq == 0) { pPvtData->freq = pPvtData->toneHz; - else + } else { pPvtData->freq = 0; + } pPvtData->freqCountdown = (pPubMapUncmpAudioInfo->audioRate / 1000) * pPvtData->onOffIntervalMSec; } else { pPvtData->freqCountdown = pPubMapUncmpAudioInfo->audioRate; // Just run steady for 1 sec + pPvtData->freq = pPvtData->toneHz; } } - pPvtData->ratio = pPvtData->freq / (float)pPubMapUncmpAudioInfo->audioRate; + pPvtData->ratio = (float)pPvtData->freq / (float)pPubMapUncmpAudioInfo->audioRate; } pPvtData->freqCountdown--; - - float value = SIN(2 * PI * (runningFrameCnt++ % pPubMapUncmpAudioInfo->audioRate) * pPvtData->ratio); - - if (pPubMapUncmpAudioInfo->itemSampleSizeBytes == 2) { - // 16 bit audio - S16 sample = (S16)(value * 15000); - for (channelCnt = 0; channelCnt < pPubMapUncmpAudioInfo->audioChannels; channelCnt++) { - unsigned char c; - U8 *pData = pMediaQItem->pPubData; - c = (unsigned)sample % 256; - pData[idx++] = c; - c = (unsigned)sample / 256 % 256; - pData[idx++] = c; + float value = SIN(2 * PI * (runningFrameCnt++ % pPubMapUncmpAudioInfo->audioRate) * pPvtData->ratio) * pPvtData->volume; + + +#if 0 // for debug + printf("value(%f), runningFrameCnt(%ul), audioRate(%d), ratio(%f)\n", value, runningFrameCnt, (int)pPubMapUncmpAudioInfo->audioRate, pPvtData->ratio); +#endif + for (channelCnt = 0; channelCnt < pPubMapUncmpAudioInfo->audioChannels - pPvtData->fvChannels; channelCnt++) { + if (pPvtData->audioType == AVB_AUDIO_TYPE_INT) { + if (pPvtData->audioBitDepth == 32) { + S32 sample32 = (S32)(value * (32000 << 16)); + S32 tmp32 = htonl(sample32); + memcpy(pData, (U8 *)&tmp32, 4); + pData += 4; + } else if (pPvtData->audioBitDepth == 24) { + S32 sample24 = (S32)(value * (32000 << 16)); + S32 tmp24 = htonl(sample24); + memcpy(pData, (U8 *)&tmp24, 3); + pData += 3; + } else if (pPvtData->audioBitDepth == 16) { + S16 sample16 = (S32)(value * 32000); + S16 tmp16 = htons(sample16); + memcpy(pData, (U8 *)&tmp16, 2); + pData += 2; + } + } else if (pPvtData->audioType == AVB_AUDIO_TYPE_FLOAT) { + U32 tmp32f; + // value *= .75; // attenuate value + memcpy((U8 *)&tmp32f, (U8 *)&value, 4); // done so no warning with -Wstrict-aliasing + tmp32f = htonl(tmp32f); + memcpy(pData, (U8 *)&tmp32f, 4); +#if 0 // for debug + if (runningFrameCnt == 20) { + printf("sin(%f), tmp32f_0(%08X), tmp32f_1(%08X)\n", value, tmp32f_0, tmp32f_1); + } +#endif + pData += 4; + } else { + // CORE_TODO + AVB_LOG_ERROR("Audio sample size format not implemented yet for tone generator interface module"); } } - else { - // CORE_TODO - AVB_LOG_ERROR("Audio sample size format not implemented yet for tone generator interface module"); + + if (pPvtData->fvChannels > 0) { + if (pPvtData->audioType == AVB_AUDIO_TYPE_INT) { + if (pPvtData->audioBitDepth == 32) { + if (pPvtData->fv1Enabled) { + S32 tmp32 = htonl(pPvtData->fv1); + memcpy(pData, (U8 *)&tmp32, 4); + pData += 4; + } + + if (pPvtData->fv2Enabled) { + S32 tmp32 = htonl(pPvtData->fv2); + memcpy(pData, (U8 *)&tmp32, 4); + pData += 4; + } + } + } } } pMediaQItem->dataLen = pPubMapUncmpAudioInfo->itemSize; openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); + openavbMediaQHeadPush(pMediaQ); AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); @@ -492,7 +600,8 @@ void openavbIntfToneGenGenEndCB(media_q_t *pMediaQ) } // Main initialization entry point into the interface module -extern DLL_EXPORT bool openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) +//extern DLL_EXPORT bool openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) +extern bool DLL_EXPORT openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) { AVB_TRACE_ENTRY(AVB_TRACE_INTF); @@ -517,6 +626,15 @@ extern DLL_EXPORT bool openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_ pPvtData->intervalCounter = 0; pPvtData->melodyIdx = 0; + pPvtData->audioType = AVB_AUDIO_TYPE_INT; + pPvtData->audioEndian = AVB_AUDIO_ENDIAN_BIG; + + pPvtData->volume = 50; + pPvtData->fv1Enabled = false; + pPvtData->fv1 = 0; + pPvtData->fv2Enabled = false; + pPvtData->fv2 = 0; + pPvtData->fvChannels = 0; } AVB_TRACE_EXIT(AVB_TRACE_INTF); diff --git a/lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini b/lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini index 24a207c9..6112dd4f 100644 --- a/lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini +++ b/lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini @@ -143,7 +143,15 @@ intf_nv_audio_bit_depth = 16 # intf_nv_audio_channels: The number of channels of the generated audio intf_nv_audio_channels = 2 +# intf_nv_volume: The volume of the tone generation PCM in percentage from 0 - 100 +intf_nv_volume = 100 +# Optionally replace the last one or two channels with fixed sample values +# intf_nv_fv1: First fixed 32-bit value +#intf_nv_fv1 = 1234 + +# intf_nv_fv2: Second fixed 32-bit value +#intf_nv_fv2 = 5678 -- cgit v1.2.1 From b77be74f98c8097f59926b06078d12a6938ad88f Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Thu, 16 Jun 2016 16:26:53 -0600 Subject: avtp_pipeline: Fix CMake and init for intf_tonegen --- lib/avtp_pipeline/platform/Linux/CMakeLists.txt | 2 +- lib/avtp_pipeline/platform/Linux/avb_host/openavb_host.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/avtp_pipeline/platform/Linux/CMakeLists.txt b/lib/avtp_pipeline/platform/Linux/CMakeLists.txt index 585ed769..047b6a76 100644 --- a/lib/avtp_pipeline/platform/Linux/CMakeLists.txt +++ b/lib/avtp_pipeline/platform/Linux/CMakeLists.txt @@ -247,7 +247,7 @@ if ( AVB_FEATURE_PCAP ) endif () add_library ( avbTl ${SRC_FILES} ) -target_link_libraries ( avbTl dl ) +target_link_libraries ( avbTl dl m ) install ( TARGETS avbTl ARCHIVE DESTINATION ${AVB_INSTALL_LIB_DIR} ) diff --git a/lib/avtp_pipeline/platform/Linux/avb_host/openavb_host.c b/lib/avtp_pipeline/platform/Linux/avb_host/openavb_host.c index e1eec996..54995b7a 100644 --- a/lib/avtp_pipeline/platform/Linux/avb_host/openavb_host.c +++ b/lib/avtp_pipeline/platform/Linux/avb_host/openavb_host.c @@ -204,7 +204,7 @@ int main(int argc, char *argv[]) registerStaticIntfModule(openavbIntfCtrlInitialize); registerStaticIntfModule(openavbIntfLoggerInitialize); registerStaticIntfModule(openavbIntfNullInitialize); - //registerStaticIntfModule(openavbIntfToneGenInitialize); + registerStaticIntfModule(openavbIntfToneGenInitialize); registerStaticIntfModule(openavbIntfViewerInitialize); registerStaticIntfModule(openavbIntfAlsaInitialize); registerStaticIntfModule(openavbIntfMjpegGstInitialize); -- cgit v1.2.1 From b52196cd6f60d14b00aff15e84f40ee9c23f6572 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:57:42 +0200 Subject: avtp_pipeline: Openavb_harness should also know about tonegen. Add missing registration of tonegen interface. --- lib/avtp_pipeline/platform/Linux/avb_host/openavb_harness.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/avtp_pipeline/platform/Linux/avb_host/openavb_harness.c b/lib/avtp_pipeline/platform/Linux/avb_host/openavb_harness.c index c999e628..f9342ff5 100644 --- a/lib/avtp_pipeline/platform/Linux/avb_host/openavb_harness.c +++ b/lib/avtp_pipeline/platform/Linux/avb_host/openavb_harness.c @@ -196,7 +196,7 @@ int main(int argc, char *argv[]) registerStaticIntfModule(openavbIntfCtrlInitialize); registerStaticIntfModule(openavbIntfLoggerInitialize); registerStaticIntfModule(openavbIntfNullInitialize); - //registerStaticIntfModule(openavbIntfToneGenInitialize); + registerStaticIntfModule(openavbIntfToneGenInitialize); registerStaticIntfModule(openavbIntfViewerInitialize); registerStaticIntfModule(openavbIntfAlsaInitialize); registerStaticIntfModule(openavbIntfMjpegGstInitialize); -- cgit v1.2.1 From 9836be9cf94bb14a7f64900a6144450e0f16c6b5 Mon Sep 17 00:00:00 2001 From: Carolyn Wyborny Date: Tue, 11 Mar 2014 06:15:37 +0000 Subject: igb: Add register defines needed for time sync functions This patch adds defines needed for implementing the auxiliary time sync functions and also changes code to call the updated defines instead of the old. Reported-by: Richard Cochran Signed-off-by: Carolyn Wyborny Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/e1000_defines.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- kmod/igb/e1000_regs.h | 11 ++++++-- kmod/igb/igb_ptp.c | 4 +-- 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/kmod/igb/e1000_defines.h b/kmod/igb/e1000_defines.h index 4dce56b9..4022e22b 100644 --- a/kmod/igb/e1000_defines.h +++ b/kmod/igb/e1000_defines.h @@ -58,8 +58,10 @@ #define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */ #define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* SW Definable Pin 4 data */ #define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* SW Definable Pin 6 data */ +#define E1000_CTRL_EXT_SDP2_DATA 0x00000040 /* SW Definable Pin 2 data */ #define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* SW Definable Pin 3 data */ #define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ +#define E1000_CTRL_EXT_SDP2_DIR 0x00000400 /* Direction of SDP2 0=in 1=out */ #define E1000_CTRL_EXT_SDP3_DIR 0x00000800 /* Direction of SDP3 0=in 1=out */ #define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */ #define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ @@ -258,6 +260,8 @@ #define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ #define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ #define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ +#define E1000_CTRL_SDP0_DIR 0x00400000 /* SDP0 Data direction */ +#define E1000_CTRL_SDP1_DIR 0x00800000 /* SDP1 Data direction */ #define E1000_CTRL_RST 0x04000000 /* Global reset */ #define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ #define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ @@ -719,8 +723,67 @@ #define E1000_TIMINCA_INCPERIOD_SHIFT 24 #define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF -#define E1000_TSICR_TXTS 0x00000002 -#define E1000_TSIM_TXTS 0x00000002 +/* Time Sync Interrupt Cause/Mask Register Bits */ + +#define TSINTR_SYS_WRAP (1 << 0) /* SYSTIM Wrap around. */ +#define TSINTR_TXTS (1 << 1) /* Transmit Timestamp. */ +#define TSINTR_RXTS (1 << 2) /* Receive Timestamp. */ +#define TSINTR_TT0 (1 << 3) /* Target Time 0 Trigger. */ +#define TSINTR_TT1 (1 << 4) /* Target Time 1 Trigger. */ +#define TSINTR_AUTT0 (1 << 5) /* Auxiliary Timestamp 0 Taken. */ +#define TSINTR_AUTT1 (1 << 6) /* Auxiliary Timestamp 1 Taken. */ +#define TSINTR_TADJ (1 << 7) /* Time Adjust Done. */ + +#define TSYNC_INTERRUPTS TSINTR_TXTS +#define E1000_TSICR_TXTS TSINTR_TXTS + +/* TSAUXC Configuration Bits */ +#define TSAUXC_EN_TT0 (1 << 0) /* Enable target time 0. */ +#define TSAUXC_EN_TT1 (1 << 1) /* Enable target time 1. */ +#define TSAUXC_EN_CLK0 (1 << 2) /* Enable Configurable Frequency Clock 0. */ +#define TSAUXC_SAMP_AUT0 (1 << 3) /* Latch SYSTIML/H into AUXSTMPL/0. */ +#define TSAUXC_ST0 (1 << 4) /* Start Clock 0 Toggle on Target Time 0. */ +#define TSAUXC_EN_CLK1 (1 << 5) /* Enable Configurable Frequency Clock 1. */ +#define TSAUXC_SAMP_AUT1 (1 << 6) /* Latch SYSTIML/H into AUXSTMPL/1. */ +#define TSAUXC_ST1 (1 << 7) /* Start Clock 1 Toggle on Target Time 1. */ +#define TSAUXC_EN_TS0 (1 << 8) /* Enable hardware timestamp 0. */ +#define TSAUXC_AUTT0 (1 << 9) /* Auxiliary Timestamp Taken. */ +#define TSAUXC_EN_TS1 (1 << 10) /* Enable hardware timestamp 0. */ +#define TSAUXC_AUTT1 (1 << 11) /* Auxiliary Timestamp Taken. */ +#define TSAUXC_PLSG (1 << 17) /* Generate a pulse. */ +#define TSAUXC_DISABLE (1 << 31) /* Disable SYSTIM Count Operation. */ + +/* SDP Configuration Bits */ +#define AUX0_SEL_SDP0 (0 << 0) /* Assign SDP0 to auxiliary time stamp 0. */ +#define AUX0_SEL_SDP1 (1 << 0) /* Assign SDP1 to auxiliary time stamp 0. */ +#define AUX0_SEL_SDP2 (2 << 0) /* Assign SDP2 to auxiliary time stamp 0. */ +#define AUX0_SEL_SDP3 (3 << 0) /* Assign SDP3 to auxiliary time stamp 0. */ +#define AUX0_TS_SDP_EN (1 << 2) /* Enable auxiliary time stamp trigger 0. */ +#define AUX1_SEL_SDP0 (0 << 3) /* Assign SDP0 to auxiliary time stamp 1. */ +#define AUX1_SEL_SDP1 (1 << 3) /* Assign SDP1 to auxiliary time stamp 1. */ +#define AUX1_SEL_SDP2 (2 << 3) /* Assign SDP2 to auxiliary time stamp 1. */ +#define AUX1_SEL_SDP3 (3 << 3) /* Assign SDP3 to auxiliary time stamp 1. */ +#define AUX1_TS_SDP_EN (1 << 5) /* Enable auxiliary time stamp trigger 1. */ +#define TS_SDP0_SEL_TT0 (0 << 6) /* Target time 0 is output on SDP0. */ +#define TS_SDP0_SEL_TT1 (1 << 6) /* Target time 1 is output on SDP0. */ +#define TS_SDP0_SEL_FC0 (2 << 6) /* Freq clock 0 is output on SDP0. */ +#define TS_SDP0_SEL_FC1 (3 << 6) /* Freq clock 1 is output on SDP0. */ +#define TS_SDP0_EN (1 << 8) /* SDP0 is assigned to Tsync. */ +#define TS_SDP1_SEL_TT0 (0 << 9) /* Target time 0 is output on SDP1. */ +#define TS_SDP1_SEL_TT1 (1 << 9) /* Target time 1 is output on SDP1. */ +#define TS_SDP1_SEL_FC0 (2 << 9) /* Freq clock 0 is output on SDP1. */ +#define TS_SDP1_SEL_FC1 (3 << 9) /* Freq clock 1 is output on SDP1. */ +#define TS_SDP1_EN (1 << 11) /* SDP1 is assigned to Tsync. */ +#define TS_SDP2_SEL_TT0 (0 << 12) /* Target time 0 is output on SDP2. */ +#define TS_SDP2_SEL_TT1 (1 << 12) /* Target time 1 is output on SDP2. */ +#define TS_SDP2_SEL_FC0 (2 << 12) /* Freq clock 0 is output on SDP2. */ +#define TS_SDP2_SEL_FC1 (3 << 12) /* Freq clock 1 is output on SDP2. */ +#define TS_SDP2_EN (1 << 14) /* SDP2 is assigned to Tsync. */ +#define TS_SDP3_SEL_TT0 (0 << 15) /* Target time 0 is output on SDP3. */ +#define TS_SDP3_SEL_TT1 (1 << 15) /* Target time 1 is output on SDP3. */ +#define TS_SDP3_SEL_FC0 (2 << 15) /* Freq clock 0 is output on SDP3. */ +#define TS_SDP3_SEL_FC1 (3 << 15) /* Freq clock 1 is output on SDP3. */ +#define TS_SDP3_EN (1 << 17) /* SDP3 is assigned to Tsync. */ /* TUPLE Filtering Configuration */ #define E1000_TTQF_DISABLE_MASK 0xF0008000 /* TTQF Disable Mask */ #define E1000_TTQF_QUEUE_ENABLE 0x100 /* TTQF Queue Enable Bit */ diff --git a/kmod/igb/e1000_regs.h b/kmod/igb/e1000_regs.h index da373a97..dbc106eb 100644 --- a/kmod/igb/e1000_regs.h +++ b/kmod/igb/e1000_regs.h @@ -51,6 +51,7 @@ #define E1000_FCT 0x00030 /* Flow Control Type - RW */ #define E1000_CONNSW 0x00034 /* Copper/Fiber switch control - RW */ #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ +#define E1000_TSSDP 0x0003C /* Time Sync SDP Configuration Register - RW */ #define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ #define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ #define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ @@ -529,11 +530,17 @@ #define E1000_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */ #define E1000_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */ #define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */ +#define E1000_TRGTTIML0 0x0B644 /* Target Time Register 0 Low - RW */ +#define E1000_TRGTTIMH0 0x0B648 /* Target Time Register 0 High - RW */ +#define E1000_TRGTTIML1 0x0B64C /* Target Time Register 1 Low - RW */ +#define E1000_TRGTTIMH1 0x0B650 /* Target Time Register 1 High - RW */ +#define E1000_AUXSTMPL0 0x0B65C /* Auxiliary Time Stamp 0 Register Low - RO */ +#define E1000_AUXSTMPH0 0x0B660 /* Auxiliary Time Stamp 0 Register High - RO */ +#define E1000_AUXSTMPL1 0x0B664 /* Auxiliary Time Stamp 1 Register Low - RO */ +#define E1000_AUXSTMPH1 0x0B668 /* Auxiliary Time Stamp 1 Register High - RO */ #define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */ #define E1000_TSICR 0x0B66C /* Interrupt Cause Register */ #define E1000_TSIM 0x0B674 /* Interrupt Mask Register */ -#define E1000_AUXSTMPL0 0x0B65C /* Auxiliary Time Stamp 0 Reg - Low */ -#define E1000_AUXSTMPH0 0x0B660 /* Auxiliary Time Stamp 0 Reg - Low */ /* Filtering Registers */ #define E1000_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */ diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 744fa654..2157541c 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -972,7 +972,7 @@ void igb_ptp_init(struct igb_adapter *adapter) /* Initialize the time sync interrupts for devices that support it. */ if (hw->mac.type >= e1000_82580) { - E1000_WRITE_REG(hw, E1000_TSIM, E1000_TSIM_TXTS); + E1000_WRITE_REG(hw, E1000_TSIM, TSYNC_INTERRUPTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); } @@ -1058,7 +1058,7 @@ void igb_ptp_reset(struct igb_adapter *adapter) case e1000_i211: /* Enable the timer functions and interrupts. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); - E1000_WRITE_REG(hw, E1000_TSIM, E1000_TSIM_TXTS); + E1000_WRITE_REG(hw, E1000_TSIM, TSYNC_INTERRUPTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); break; default: -- cgit v1.2.1 From 2d60f12d06d642aad70a5c47f03e02de5f060430 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 16 May 2014 07:21:13 +0000 Subject: igb: rename igb_ptp_enable to igb_ptp_feature_enable The name igb_ptp_enable is not synonymous with the purpose of this function, so rename it to better explain its purpose. Signed-off-by: Jacob Keller Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/igb_ptp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 2157541c..ba14b6ff 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -471,8 +471,8 @@ static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, } #endif -static int igb_ptp_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, int on) +static int igb_ptp_feature_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) { return -EOPNOTSUPP; } @@ -890,7 +890,7 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.gettime = igb_ptp_gettime_82576; adapter->ptp_caps.settime = igb_ptp_settime_82576; #endif - adapter->ptp_caps.enable = igb_ptp_enable; + adapter->ptp_caps.enable = igb_ptp_feature_enable; adapter->cc.read = igb_ptp_read_82576; adapter->cc.mask = CLOCKSOURCE_MASK(64); adapter->cc.mult = 1; @@ -916,7 +916,7 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.gettime = igb_ptp_gettime_82576; adapter->ptp_caps.settime = igb_ptp_settime_82576; #endif - adapter->ptp_caps.enable = igb_ptp_enable; + adapter->ptp_caps.enable = igb_ptp_feature_enable; adapter->cc.read = igb_ptp_read_82580; adapter->cc.mask = CLOCKSOURCE_MASK(IGB_NBITS_82580); adapter->cc.mult = 1; @@ -940,7 +940,7 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.gettime = igb_ptp_gettime_i210; adapter->ptp_caps.settime = igb_ptp_settime_i210; #endif - adapter->ptp_caps.enable = igb_ptp_enable; + adapter->ptp_caps.enable = igb_ptp_feature_enable; /* Enable the timer functions by clearing bit 31. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); break; -- cgit v1.2.1 From ea8e7c99dbe9236ac418712da66e8b9f0a43f569 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Fri, 21 Nov 2014 20:51:10 +0000 Subject: igb: refactor time sync interrupt handling The code that handles the time sync interrupt is repeated in three different places. This patch refactors the identical code blocks into a single helper function. Signed-off-by: Richard Cochran Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/igb_main.c | 49 +++++++++++++++++++------------------------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index 7b13c1d6..78a0b009 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -6049,6 +6049,19 @@ void igb_update_stats(struct igb_adapter *adapter) } } +static void igb_tsync_interrupt(struct igb_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + u32 tsicr = rd32(E1000_TSICR); + + if (tsicr & E1000_TSICR_TXTS) { + /* acknowledge the interrupt */ + wr32(E1000_TSICR, E1000_TSICR_TXTS); + /* retrieve hardware timestamp */ + schedule_work(&adapter->ptp_tx_work); + } +} + static irqreturn_t igb_msix_other(int irq, void *data) { struct igb_adapter *adapter = data; @@ -6081,16 +6094,8 @@ static irqreturn_t igb_msix_other(int irq, void *data) } #ifdef HAVE_PTP_1588_CLOCK - if (icr & E1000_ICR_TS) { - u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); - - if (tsicr & E1000_TSICR_TXTS) { - /* acknowledge the interrupt */ - E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); - /* retrieve hardware timestamp */ - schedule_work(&adapter->ptp_tx_work); - } - } + if (icr & E1000_ICR_TS) + igb_tsync_interrupt(adapter); #endif /* HAVE_PTP_1588_CLOCK */ /* Check for MDD event */ @@ -6999,16 +7004,8 @@ static irqreturn_t igb_intr_msi(int irq, void *data) } #ifdef HAVE_PTP_1588_CLOCK - if (icr & E1000_ICR_TS) { - u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); - - if (tsicr & E1000_TSICR_TXTS) { - /* acknowledge the interrupt */ - E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); - /* retrieve hardware timestamp */ - schedule_work(&adapter->ptp_tx_work); - } - } + if (icr & E1000_ICR_TS) + igb_tsync_interrupt(adapter); #endif /* HAVE_PTP_1588_CLOCK */ napi_schedule(&q_vector->napi); @@ -7055,16 +7052,8 @@ static irqreturn_t igb_intr(int irq, void *data) } #ifdef HAVE_PTP_1588_CLOCK - if (icr & E1000_ICR_TS) { - u32 tsicr = E1000_READ_REG(hw, E1000_TSICR); - - if (tsicr & E1000_TSICR_TXTS) { - /* acknowledge the interrupt */ - E1000_WRITE_REG(hw, E1000_TSICR, E1000_TSICR_TXTS); - /* retrieve hardware timestamp */ - schedule_work(&adapter->ptp_tx_work); - } - } + if (icr & E1000_ICR_TS) + igb_tsync_interrupt(adapter); #endif /* HAVE_PTP_1588_CLOCK */ napi_schedule(&q_vector->napi); -- cgit v1.2.1 From 7b0686381dd35d90991313e51c382a69ccfe512d Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Fri, 21 Nov 2014 20:51:15 +0000 Subject: igb: serialize access to the time sync interrupt registers The time sync related interrupt registers may be manipulated from different contexts. This patch protects the registers from being asynchronously changed by the reset function. Also, the patch removes a misleading comment. The reset function is disabling a bunch of functions, not enabling them. Signed-off-by: Richard Cochran Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/igb_ptp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index ba14b6ff..7f63e92a 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -1038,6 +1038,7 @@ void igb_ptp_stop(struct igb_adapter *adapter) void igb_ptp_reset(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; + unsigned long flags; if (!(adapter->flags & IGB_FLAG_PTP)) return; @@ -1045,6 +1046,8 @@ void igb_ptp_reset(struct igb_adapter *adapter) /* reset the tstamp_config */ igb_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config); + spin_lock_irqsave(&adapter->tmreg_lock, flags); + switch (adapter->hw.mac.type) { case e1000_82576: /* Dial the nominal frequency. */ @@ -1056,24 +1059,25 @@ void igb_ptp_reset(struct igb_adapter *adapter) case e1000_i354: case e1000_i210: case e1000_i211: - /* Enable the timer functions and interrupts. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); E1000_WRITE_REG(hw, E1000_TSIM, TSYNC_INTERRUPTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); break; default: /* No work to do. */ - return; + goto out; } /* Re-initialize the timer. */ if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) { struct timespec64 ts64 = ktime_to_timespec64(ktime_get_real()); - igb_ptp_settime64_i210(&adapter->ptp_caps, &ts64); + igb_ptp_write_i210(adapter, &ts64); } else { timecounter_init(&adapter->tc, &adapter->cc, ktime_to_ns(ktime_get_real())); } +out: + spin_unlock_irqrestore(&adapter->tmreg_lock, flags); } #endif /* HAVE_PTP_1588_CLOCK */ -- cgit v1.2.1 From cb421d371d830a95d717ebd727fc1e841288f5cc Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Fri, 21 Nov 2014 20:51:20 +0000 Subject: igb: enable internal PPS for the i210 The i210 device can produce an interrupt on the full second. This patch allows using this interrupt to generate an internal PPS event for adjusting the kernel system time. Signed-off-by: Richard Cochran Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/igb_main.c | 18 +++++++++++++++--- kmod/igb/igb_ptp.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index 78a0b009..0122c5a5 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -6052,14 +6052,26 @@ void igb_update_stats(struct igb_adapter *adapter) static void igb_tsync_interrupt(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; - u32 tsicr = rd32(E1000_TSICR); + struct ptp_clock_event event; + u32 ack = 0, tsicr = rd32(E1000_TSICR); + + if (tsicr & TSINTR_SYS_WRAP) { + event.type = PTP_CLOCK_PPS; + if (adapter->ptp_caps.pps) + ptp_clock_event(adapter->ptp_clock, &event); + else + dev_err(&adapter->pdev->dev, "unexpected SYS WRAP"); + ack |= TSINTR_SYS_WRAP; + } if (tsicr & E1000_TSICR_TXTS) { - /* acknowledge the interrupt */ - wr32(E1000_TSICR, E1000_TSICR_TXTS); /* retrieve hardware timestamp */ schedule_work(&adapter->ptp_tx_work); + ack |= E1000_TSICR_TXTS; } + + /* acknowledge the interrupts */ + wr32(E1000_TSICR, ack); } static irqreturn_t igb_msix_other(int irq, void *data) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 7f63e92a..bfd66833 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -471,6 +471,34 @@ static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, } #endif +static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct igb_adapter *igb = + container_of(ptp, struct igb_adapter, ptp_caps); + struct e1000_hw *hw = &igb->hw; + unsigned long flags; + u32 tsim; + + switch (rq->type) { + case PTP_CLK_REQ_PPS: + spin_lock_irqsave(&igb->tmreg_lock, flags); + tsim = rd32(E1000_TSIM); + if (on) + tsim |= TSINTR_SYS_WRAP; + else + tsim &= ~TSINTR_SYS_WRAP; + wr32(E1000_TSIM, tsim); + spin_unlock_irqrestore(&igb->tmreg_lock, flags); + return 0; + + default: + break; + } + + return -EOPNOTSUPP; +} + static int igb_ptp_feature_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) { @@ -930,7 +958,7 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 62499999; adapter->ptp_caps.n_ext_ts = 0; - adapter->ptp_caps.pps = 0; + adapter->ptp_caps.pps = 1; adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210; #ifdef HAVE_PTP_CLOCK_INFO_GETTIME64 @@ -940,7 +968,7 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.gettime = igb_ptp_gettime_i210; adapter->ptp_caps.settime = igb_ptp_settime_i210; #endif - adapter->ptp_caps.enable = igb_ptp_feature_enable; + adapter->ptp_caps.enable = igb_ptp_feature_enable_i210; /* Enable the timer functions by clearing bit 31. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); break; -- cgit v1.2.1 From 2f0dffbd2035cbb28f92e72829551717993af8e2 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Fri, 21 Nov 2014 20:51:26 +0000 Subject: igb: enable auxiliary PHC functions for the i210 The i210 device offers a number of special PTP Hardware Clock features on the Software Defined Pins (SDPs). This patch adds support for two of the possible functions, namely time stamping external events, and periodic output signals. The assignment of PHC functions to the four SDP can be freely chosen by the user. Signed-off-by: Richard Cochran Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/igb.h | 9 +++ kmod/igb/igb_main.c | 51 +++++++++++- kmod/igb/igb_ptp.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 276 insertions(+), 6 deletions(-) diff --git a/kmod/igb/igb.h b/kmod/igb/igb.h index 1da12050..3e2a801a 100644 --- a/kmod/igb/igb.h +++ b/kmod/igb/igb.h @@ -514,6 +514,9 @@ struct hwmon_buff { unsigned int n_hwmon; }; #endif /* IGB_HWMON */ +#define IGB_N_EXTTS 2 +#define IGB_N_PEROUT 2 +#define IGB_N_SDP 4 #ifdef ETHTOOL_GRXFHINDIR #define IGB_RETA_SIZE 128 #endif /* ETHTOOL_GRXFHINDIR */ @@ -659,6 +662,12 @@ struct igb_adapter { struct timecounter tc; u32 tx_hwtstamp_timeouts; u32 rx_hwtstamp_cleared; + + struct ptp_pin_desc sdp_config[IGB_N_SDP]; + struct { + struct timespec start; + struct timespec period; + } perout[IGB_N_PEROUT]; #endif /* HAVE_PTP_1588_CLOCK */ #ifdef HAVE_I2C_SUPPORT diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index 0122c5a5..c5d88b0f 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -6053,7 +6053,8 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct ptp_clock_event event; - u32 ack = 0, tsicr = rd32(E1000_TSICR); + struct timespec ts; + u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR); if (tsicr & TSINTR_SYS_WRAP) { event.type = PTP_CLOCK_PPS; @@ -6070,6 +6071,54 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) ack |= E1000_TSICR_TXTS; } + if (tsicr & TSINTR_TT0) { + spin_lock(&adapter->tmreg_lock); + ts = timespec_add(adapter->perout[0].start, + adapter->perout[0].period); + wr32(E1000_TRGTTIML0, ts.tv_nsec); + wr32(E1000_TRGTTIMH0, ts.tv_sec); + tsauxc = rd32(E1000_TSAUXC); + tsauxc |= TSAUXC_EN_TT0; + wr32(E1000_TSAUXC, tsauxc); + adapter->perout[0].start = ts; + spin_unlock(&adapter->tmreg_lock); + ack |= TSINTR_TT0; + } + + if (tsicr & TSINTR_TT1) { + spin_lock(&adapter->tmreg_lock); + ts = timespec_add(adapter->perout[1].start, + adapter->perout[1].period); + wr32(E1000_TRGTTIML1, ts.tv_nsec); + wr32(E1000_TRGTTIMH1, ts.tv_sec); + tsauxc = rd32(E1000_TSAUXC); + tsauxc |= TSAUXC_EN_TT1; + wr32(E1000_TSAUXC, tsauxc); + adapter->perout[1].start = ts; + spin_unlock(&adapter->tmreg_lock); + ack |= TSINTR_TT1; + } + + if (tsicr & TSINTR_AUTT0) { + nsec = rd32(E1000_AUXSTMPL0); + sec = rd32(E1000_AUXSTMPH0); + event.type = PTP_CLOCK_EXTTS; + event.index = 0; + event.timestamp = sec * 1000000000ULL + nsec; + ptp_clock_event(adapter->ptp_clock, &event); + ack |= TSINTR_AUTT0; + } + + if (tsicr & TSINTR_AUTT1) { + nsec = rd32(E1000_AUXSTMPL1); + sec = rd32(E1000_AUXSTMPH1); + event.type = PTP_CLOCK_EXTTS; + event.index = 1; + event.timestamp = sec * 1000000000ULL + nsec; + ptp_clock_event(adapter->ptp_clock, &event); + ack |= TSINTR_AUTT1; + } + /* acknowledge the interrupts */ wr32(E1000_TSICR, ack); } diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index bfd66833..6be17bfc 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -471,16 +471,204 @@ static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, } #endif +static void igb_pin_direction(int pin, int input, u32 *ctrl, u32 *ctrl_ext) +{ + u32 *ptr = pin < 2 ? ctrl : ctrl_ext; + u32 mask[IGB_N_SDP] = { + E1000_CTRL_SDP0_DIR, + E1000_CTRL_SDP1_DIR, + E1000_CTRL_EXT_SDP2_DIR, + E1000_CTRL_EXT_SDP3_DIR, + }; + + if (input) + *ptr &= ~mask[pin]; + else + *ptr |= mask[pin]; +} + +static void igb_pin_extts(struct igb_adapter *igb, int chan, int pin) +{ + struct e1000_hw *hw = &igb->hw; + u32 aux0_sel_sdp[IGB_N_SDP] = { + AUX0_SEL_SDP0, AUX0_SEL_SDP1, AUX0_SEL_SDP2, AUX0_SEL_SDP3, + }; + u32 aux1_sel_sdp[IGB_N_SDP] = { + AUX1_SEL_SDP0, AUX1_SEL_SDP1, AUX1_SEL_SDP2, AUX1_SEL_SDP3, + }; + u32 ts_sdp_en[IGB_N_SDP] = { + TS_SDP0_EN, TS_SDP1_EN, TS_SDP2_EN, TS_SDP3_EN, + }; + u32 ctrl, ctrl_ext, tssdp = 0; + + ctrl = rd32(E1000_CTRL); + ctrl_ext = rd32(E1000_CTRL_EXT); + tssdp = rd32(E1000_TSSDP); + + igb_pin_direction(pin, 1, &ctrl, &ctrl_ext); + + /* Make sure this pin is not enabled as an output. */ + tssdp &= ~ts_sdp_en[pin]; + + if (chan == 1) { + tssdp &= ~AUX1_SEL_SDP3; + tssdp |= aux1_sel_sdp[pin] | AUX1_TS_SDP_EN; + } else { + tssdp &= ~AUX0_SEL_SDP3; + tssdp |= aux0_sel_sdp[pin] | AUX0_TS_SDP_EN; + } + + wr32(E1000_TSSDP, tssdp); + wr32(E1000_CTRL, ctrl); + wr32(E1000_CTRL_EXT, ctrl_ext); +} + +static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin) +{ + struct e1000_hw *hw = &igb->hw; + u32 aux0_sel_sdp[IGB_N_SDP] = { + AUX0_SEL_SDP0, AUX0_SEL_SDP1, AUX0_SEL_SDP2, AUX0_SEL_SDP3, + }; + u32 aux1_sel_sdp[IGB_N_SDP] = { + AUX1_SEL_SDP0, AUX1_SEL_SDP1, AUX1_SEL_SDP2, AUX1_SEL_SDP3, + }; + u32 ts_sdp_en[IGB_N_SDP] = { + TS_SDP0_EN, TS_SDP1_EN, TS_SDP2_EN, TS_SDP3_EN, + }; + u32 ts_sdp_sel_tt0[IGB_N_SDP] = { + TS_SDP0_SEL_TT0, TS_SDP1_SEL_TT0, + TS_SDP2_SEL_TT0, TS_SDP3_SEL_TT0, + }; + u32 ts_sdp_sel_tt1[IGB_N_SDP] = { + TS_SDP0_SEL_TT1, TS_SDP1_SEL_TT1, + TS_SDP2_SEL_TT1, TS_SDP3_SEL_TT1, + }; + u32 ts_sdp_sel_clr[IGB_N_SDP] = { + TS_SDP0_SEL_FC1, TS_SDP1_SEL_FC1, + TS_SDP2_SEL_FC1, TS_SDP3_SEL_FC1, + }; + u32 ctrl, ctrl_ext, tssdp = 0; + + ctrl = rd32(E1000_CTRL); + ctrl_ext = rd32(E1000_CTRL_EXT); + tssdp = rd32(E1000_TSSDP); + + igb_pin_direction(pin, 0, &ctrl, &ctrl_ext); + + /* Make sure this pin is not enabled as an input. */ + if ((tssdp & AUX0_SEL_SDP3) == aux0_sel_sdp[pin]) + tssdp &= ~AUX0_TS_SDP_EN; + + if ((tssdp & AUX1_SEL_SDP3) == aux1_sel_sdp[pin]) + tssdp &= ~AUX1_TS_SDP_EN; + + tssdp &= ~ts_sdp_sel_clr[pin]; + if (chan == 1) + tssdp |= ts_sdp_sel_tt1[pin]; + else + tssdp |= ts_sdp_sel_tt0[pin]; + + tssdp |= ts_sdp_en[pin]; + + wr32(E1000_TSSDP, tssdp); + wr32(E1000_CTRL, ctrl); + wr32(E1000_CTRL_EXT, ctrl_ext); +} + static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); struct e1000_hw *hw = &igb->hw; + u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh; unsigned long flags; - u32 tsim; + struct timespec ts; + int pin; + s64 ns; switch (rq->type) { + case PTP_CLK_REQ_EXTTS: + if (on) { + pin = ptp_find_pin(igb->ptp_clock, PTP_PF_EXTTS, + rq->extts.index); + if (pin < 0) + return -EBUSY; + } + if (rq->extts.index == 1) { + tsauxc_mask = TSAUXC_EN_TS1; + tsim_mask = TSINTR_AUTT1; + } else { + tsauxc_mask = TSAUXC_EN_TS0; + tsim_mask = TSINTR_AUTT0; + } + spin_lock_irqsave(&igb->tmreg_lock, flags); + tsauxc = rd32(E1000_TSAUXC); + tsim = rd32(E1000_TSIM); + if (on) { + igb_pin_extts(igb, rq->extts.index, pin); + tsauxc |= tsauxc_mask; + tsim |= tsim_mask; + } else { + tsauxc &= ~tsauxc_mask; + tsim &= ~tsim_mask; + } + wr32(E1000_TSAUXC, tsauxc); + wr32(E1000_TSIM, tsim); + spin_unlock_irqrestore(&igb->tmreg_lock, flags); + return 0; + + case PTP_CLK_REQ_PEROUT: + if (on) { + pin = ptp_find_pin(igb->ptp_clock, PTP_PF_PEROUT, + rq->perout.index); + if (pin < 0) + return -EBUSY; + } + ts.tv_sec = rq->perout.period.sec; + ts.tv_nsec = rq->perout.period.nsec; + ns = timespec_to_ns(&ts); + ns = ns >> 1; + if (on && ns < 500000LL) { + /* 2k interrupts per second is an awful lot. */ + return -EINVAL; + } + ts = ns_to_timespec(ns); + if (rq->perout.index == 1) { + tsauxc_mask = TSAUXC_EN_TT1; + tsim_mask = TSINTR_TT1; + trgttiml = E1000_TRGTTIML1; + trgttimh = E1000_TRGTTIMH1; + } else { + tsauxc_mask = TSAUXC_EN_TT0; + tsim_mask = TSINTR_TT0; + trgttiml = E1000_TRGTTIML0; + trgttimh = E1000_TRGTTIMH0; + } + spin_lock_irqsave(&igb->tmreg_lock, flags); + tsauxc = rd32(E1000_TSAUXC); + tsim = rd32(E1000_TSIM); + if (on) { + int i = rq->perout.index; + + igb_pin_perout(igb, i, pin); + igb->perout[i].start.tv_sec = rq->perout.start.sec; + igb->perout[i].start.tv_nsec = rq->perout.start.nsec; + igb->perout[i].period.tv_sec = ts.tv_sec; + igb->perout[i].period.tv_nsec = ts.tv_nsec; + wr32(trgttiml, rq->perout.start.sec); + wr32(trgttimh, rq->perout.start.nsec); + tsauxc |= tsauxc_mask; + tsim |= tsim_mask; + } else { + tsauxc &= ~tsauxc_mask; + tsim &= ~tsim_mask; + } + wr32(E1000_TSAUXC, tsauxc); + wr32(E1000_TSIM, tsim); + spin_unlock_irqrestore(&igb->tmreg_lock, flags); + return 0; + case PTP_CLK_REQ_PPS: spin_lock_irqsave(&igb->tmreg_lock, flags); tsim = rd32(E1000_TSIM); @@ -491,9 +679,6 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, wr32(E1000_TSIM, tsim); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; - - default: - break; } return -EOPNOTSUPP; @@ -505,6 +690,20 @@ static int igb_ptp_feature_enable(struct ptp_clock_info *ptp, return -EOPNOTSUPP; } +static int igb_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, + enum ptp_pin_function func, unsigned int chan) +{ + switch (func) { + case PTP_PF_NONE: + case PTP_PF_EXTTS: + case PTP_PF_PEROUT: + break; + case PTP_PF_PHYSYNC: + return -1; + } + return 0; +} + /** * igb_ptp_tx_work * @work: pointer to work struct @@ -901,6 +1100,7 @@ void igb_ptp_init(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; + int i; switch (hw->mac.type) { case e1000_82576: @@ -954,11 +1154,21 @@ void igb_ptp_init(struct igb_adapter *adapter) break; case e1000_i210: case e1000_i211: + for (i = 0; i < IGB_N_SDP; i++) { + struct ptp_pin_desc *ppd = &adapter->sdp_config[i]; + + snprintf(ppd->name, sizeof(ppd->name), "SDP%d", i); + ppd->index = i; + ppd->func = PTP_PF_NONE; + } snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 62499999; - adapter->ptp_caps.n_ext_ts = 0; + adapter->ptp_caps.n_ext_ts = IGB_N_EXTTS; + adapter->ptp_caps.n_per_out = IGB_N_PEROUT; + adapter->ptp_caps.n_pins = IGB_N_SDP; adapter->ptp_caps.pps = 1; + adapter->ptp_caps.pin_config = adapter->sdp_config; adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210; #ifdef HAVE_PTP_CLOCK_INFO_GETTIME64 @@ -969,6 +1179,7 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.settime = igb_ptp_settime_i210; #endif adapter->ptp_caps.enable = igb_ptp_feature_enable_i210; + adapter->ptp_caps.verify = igb_ptp_verify_pin; /* Enable the timer functions by clearing bit 31. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); break; @@ -1088,6 +1299,7 @@ void igb_ptp_reset(struct igb_adapter *adapter) case e1000_i210: case e1000_i211: E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); + wr32(E1000_TSSDP, 0x0); E1000_WRITE_REG(hw, E1000_TSIM, TSYNC_INTERRUPTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); break; -- cgit v1.2.1 From 2f401c8fc9132db9747b46dce32ed47da2a7af69 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Mar 2015 03:34:09 +0000 Subject: igb: Fix warning pin may be used uninitialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building the kernel using the gcc 4.8.3 compiler included in Fedora 20 I was repeatedly seeing the warning: drivers/net/ethernet/intel/igb/igb_ptp.c: In function ‘igb_ptp_feature_enable_i210’: drivers/net/ethernet/intel/igb/igb_ptp.c:395:21: warning: ‘pin’ may be used uninitialized in this function [-Wmaybe-uninitialized] tssdp &= ~ts_sdp_en[pin]; ^ drivers/net/ethernet/intel/igb/igb_ptp.c:471:6: note: ‘pin’ was declared here int pin; ^ To resolve it I am assigning the pin a value of -1 when it is instantiated. Signed-off-by: Alexander Duyck Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/igb_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 6be17bfc..f42e9ebc 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -584,7 +584,7 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh; unsigned long flags; struct timespec ts; - int pin; + int pin = -1; s64 ns; switch (rq->type) { -- cgit v1.2.1 From 7716aea81db8d7488c3a904974efcfb787e83d80 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 6 Mar 2015 03:34:14 +0000 Subject: igb: Make arrays on stack static const to avoid reallocation While addressing the pin problem I noticed that all of the pin register values where having to be pushed onto the stack each time the function was called. To avoid that I am making them static const so that they should only need to be allocated once and we can avoid all the instructions to get them onto the stack.. size before: text data bss dec hex filename 161477 10512 8 171997 29fdd drivers/net/ethernet/intel/igb/igb.ko size after: text data bss dec hex filename 161205 10512 8 171725 29ecd drivers/net/ethernet/intel/igb/igb.ko Signed-off-by: Alexander Duyck Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/igb_ptp.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index f42e9ebc..a82e0165 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -474,7 +474,7 @@ static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, static void igb_pin_direction(int pin, int input, u32 *ctrl, u32 *ctrl_ext) { u32 *ptr = pin < 2 ? ctrl : ctrl_ext; - u32 mask[IGB_N_SDP] = { + static const u32 mask[IGB_N_SDP] = { E1000_CTRL_SDP0_DIR, E1000_CTRL_SDP1_DIR, E1000_CTRL_EXT_SDP2_DIR, @@ -489,16 +489,16 @@ static void igb_pin_direction(int pin, int input, u32 *ctrl, u32 *ctrl_ext) static void igb_pin_extts(struct igb_adapter *igb, int chan, int pin) { - struct e1000_hw *hw = &igb->hw; - u32 aux0_sel_sdp[IGB_N_SDP] = { + static const u32 aux0_sel_sdp[IGB_N_SDP] = { AUX0_SEL_SDP0, AUX0_SEL_SDP1, AUX0_SEL_SDP2, AUX0_SEL_SDP3, }; - u32 aux1_sel_sdp[IGB_N_SDP] = { + static const u32 aux1_sel_sdp[IGB_N_SDP] = { AUX1_SEL_SDP0, AUX1_SEL_SDP1, AUX1_SEL_SDP2, AUX1_SEL_SDP3, }; - u32 ts_sdp_en[IGB_N_SDP] = { + static const u32 ts_sdp_en[IGB_N_SDP] = { TS_SDP0_EN, TS_SDP1_EN, TS_SDP2_EN, TS_SDP3_EN, }; + struct e1000_hw *hw = &igb->hw; u32 ctrl, ctrl_ext, tssdp = 0; ctrl = rd32(E1000_CTRL); @@ -525,28 +525,28 @@ static void igb_pin_extts(struct igb_adapter *igb, int chan, int pin) static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin) { - struct e1000_hw *hw = &igb->hw; - u32 aux0_sel_sdp[IGB_N_SDP] = { + static const u32 aux0_sel_sdp[IGB_N_SDP] = { AUX0_SEL_SDP0, AUX0_SEL_SDP1, AUX0_SEL_SDP2, AUX0_SEL_SDP3, }; - u32 aux1_sel_sdp[IGB_N_SDP] = { + static const u32 aux1_sel_sdp[IGB_N_SDP] = { AUX1_SEL_SDP0, AUX1_SEL_SDP1, AUX1_SEL_SDP2, AUX1_SEL_SDP3, }; - u32 ts_sdp_en[IGB_N_SDP] = { + static const u32 ts_sdp_en[IGB_N_SDP] = { TS_SDP0_EN, TS_SDP1_EN, TS_SDP2_EN, TS_SDP3_EN, }; - u32 ts_sdp_sel_tt0[IGB_N_SDP] = { + static const u32 ts_sdp_sel_tt0[IGB_N_SDP] = { TS_SDP0_SEL_TT0, TS_SDP1_SEL_TT0, TS_SDP2_SEL_TT0, TS_SDP3_SEL_TT0, }; - u32 ts_sdp_sel_tt1[IGB_N_SDP] = { + static const u32 ts_sdp_sel_tt1[IGB_N_SDP] = { TS_SDP0_SEL_TT1, TS_SDP1_SEL_TT1, TS_SDP2_SEL_TT1, TS_SDP3_SEL_TT1, }; - u32 ts_sdp_sel_clr[IGB_N_SDP] = { + static const u32 ts_sdp_sel_clr[IGB_N_SDP] = { TS_SDP0_SEL_FC1, TS_SDP1_SEL_FC1, TS_SDP2_SEL_FC1, TS_SDP3_SEL_FC1, }; + struct e1000_hw *hw = &igb->hw; u32 ctrl, ctrl_ext, tssdp = 0; ctrl = rd32(E1000_CTRL); -- cgit v1.2.1 From 6bf0336bde6bfa53f73e5ff8b36749ac317880a5 Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Sun, 29 Mar 2015 23:12:03 +0200 Subject: ptp: igb: convert to the 64 bit get/set time methods. For the 82576, the driver's clock is implemented using a timecounter, and so with this patch that device is ready for the year 2038. However, in the case of the i210, the device stores the number of seconds in a 32 bit register. Therefore, more work is needed on this driver before the year 2038 comes around. Compile tested only. Signed-off-by: Richard Cochran Acked-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Roland Hii --- kmod/igb/igb_ptp.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index a82e0165..6c31319e 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -138,7 +138,8 @@ static cycle_t igb_ptp_read_82580(const struct cyclecounter *cc) * SYSTIM read access for I210/I211 */ -static void igb_ptp_read_i210(struct igb_adapter *adapter, struct timespec *ts) +static void igb_ptp_read_i210(struct igb_adapter *adapter, + struct timespec64 *ts) { struct e1000_hw *hw = &adapter->hw; u32 sec, nsec; @@ -156,7 +157,7 @@ static void igb_ptp_read_i210(struct igb_adapter *adapter, struct timespec *ts) } static void igb_ptp_write_i210(struct igb_adapter *adapter, - const struct timespec *ts) + const struct timespec64 *ts) { struct e1000_hw *hw = &adapter->hw; @@ -314,13 +315,13 @@ static int igb_ptp_adjtime_i210(struct ptp_clock_info *ptp, s64 delta) struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); unsigned long flags; - struct timespec now, then = ns_to_timespec(delta); + struct timespec64 now, then = ns_to_timespec64(delta); spin_lock_irqsave(&igb->tmreg_lock, flags); igb_ptp_read_i210(igb, &now); - now = timespec_add(now, then); - igb_ptp_write_i210(igb, (const struct timespec *)&now); + now = timespec64_add(now, then); + igb_ptp_write_i210(igb, (const struct timespec64 *)&now); spin_unlock_irqrestore(&igb->tmreg_lock, flags); @@ -351,13 +352,11 @@ static int igb_ptp_gettime64_i210(struct ptp_clock_info *ptp, { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); - struct timespec ts; unsigned long flags; spin_lock_irqsave(&igb->tmreg_lock, flags); - igb_ptp_read_i210(igb, &ts); - *ts64 = timespec_to_timespec64(ts); + igb_ptp_read_i210(igb, ts64); spin_unlock_irqrestore(&igb->tmreg_lock, flags); @@ -390,13 +389,11 @@ static int igb_ptp_settime64_i210(struct ptp_clock_info *ptp, { struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); - struct timespec ts; unsigned long flags; - ts = timespec64_to_timespec(*ts64); spin_lock_irqsave(&igb->tmreg_lock, flags); - igb_ptp_write_i210(igb, &ts); + igb_ptp_write_i210(igb, ts64); spin_unlock_irqrestore(&igb->tmreg_lock, flags); @@ -457,17 +454,11 @@ static int igb_ptp_settime_82576(struct ptp_clock_info *ptp, static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, const struct timespec *ts) { - struct igb_adapter *igb = container_of(ptp, struct igb_adapter, - ptp_caps); - unsigned long flags; - - spin_lock_irqsave(&igb->tmreg_lock, flags); + struct timespec64 ts64; - igb_ptp_write_i210(igb, ts); + ts64 = timespec_to_timespec64(*ts); - spin_unlock_irqrestore(&igb->tmreg_lock, flags); - - return 0; + return igb_ptp_settime64_i210(ptp, &ts64); } #endif -- cgit v1.2.1 From b54bcbdd4d0b57b1bd9c2fb5c2520a2bd6072d4e Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Thu, 11 Jun 2015 14:51:30 +0200 Subject: net: igb: fix the start time for periodic output signals When programming the start of a periodic output, the code wrongly places the seconds value into the "low" register and the nanoseconds into the "high" register. Even though this is backwards, it slipped through my testing, because the re-arming code in the interrupt service routine is correct, and the signal does appear starting with the second edge. This patch fixes the issue by programming the registers correctly. Signed-off-by: Richard Cochran Reviewed-by: Jacob Keller Acked-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Roland Hii --- kmod/igb/igb_ptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 6c31319e..5fc3616b 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -647,8 +647,8 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, igb->perout[i].start.tv_nsec = rq->perout.start.nsec; igb->perout[i].period.tv_sec = ts.tv_sec; igb->perout[i].period.tv_nsec = ts.tv_nsec; - wr32(trgttiml, rq->perout.start.sec); - wr32(trgttimh, rq->perout.start.nsec); + wr32(trgttimh, rq->perout.start.sec); + wr32(trgttiml, rq->perout.start.nsec); tsauxc |= tsauxc_mask; tsim |= tsim_mask; } else { -- cgit v1.2.1 From 6aaa8f75d3db8e3301dab62555957060a925122a Mon Sep 17 00:00:00 2001 From: Richard Cochran Date: Thu, 23 Jul 2015 14:59:30 -0700 Subject: igb: implement high frequency periodic output signals In addition to interrupt driven target time output events, the i210 also has two programmable clock outputs. These clocks support periods between 16 nanoseconds and 140 milliseconds. This patch implements the periodic output function using the clock outputs when possible, falling back to the target time for longer periods. Signed-off-by: Richard Cochran Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/e1000_regs.h | 2 ++ kmod/igb/igb_ptp.c | 72 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/kmod/igb/e1000_regs.h b/kmod/igb/e1000_regs.h index dbc106eb..caf1d04d 100644 --- a/kmod/igb/e1000_regs.h +++ b/kmod/igb/e1000_regs.h @@ -534,6 +534,8 @@ #define E1000_TRGTTIMH0 0x0B648 /* Target Time Register 0 High - RW */ #define E1000_TRGTTIML1 0x0B64C /* Target Time Register 1 Low - RW */ #define E1000_TRGTTIMH1 0x0B650 /* Target Time Register 1 High - RW */ +#define E1000_FREQOUT0 0x0B654 /* Frequency Out 0 Control Register - RW */ +#define E1000_FREQOUT1 0x0B658 /* Frequency Out 1 Control Register - RW */ #define E1000_AUXSTMPL0 0x0B65C /* Auxiliary Time Stamp 0 Register Low - RO */ #define E1000_AUXSTMPH0 0x0B660 /* Auxiliary Time Stamp 0 Register High - RO */ #define E1000_AUXSTMPL1 0x0B664 /* Auxiliary Time Stamp 1 Register Low - RO */ diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 5fc3616b..bb9e8ce8 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -514,7 +514,7 @@ static void igb_pin_extts(struct igb_adapter *igb, int chan, int pin) wr32(E1000_CTRL_EXT, ctrl_ext); } -static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin) +static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin, int freq) { static const u32 aux0_sel_sdp[IGB_N_SDP] = { AUX0_SEL_SDP0, AUX0_SEL_SDP1, AUX0_SEL_SDP2, AUX0_SEL_SDP3, @@ -533,6 +533,14 @@ static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin) TS_SDP0_SEL_TT1, TS_SDP1_SEL_TT1, TS_SDP2_SEL_TT1, TS_SDP3_SEL_TT1, }; + static const u32 ts_sdp_sel_fc0[IGB_N_SDP] = { + TS_SDP0_SEL_FC0, TS_SDP1_SEL_FC0, + TS_SDP2_SEL_FC0, TS_SDP3_SEL_FC0, + }; + static const u32 ts_sdp_sel_fc1[IGB_N_SDP] = { + TS_SDP0_SEL_FC1, TS_SDP1_SEL_FC1, + TS_SDP2_SEL_FC1, TS_SDP3_SEL_FC1, + }; static const u32 ts_sdp_sel_clr[IGB_N_SDP] = { TS_SDP0_SEL_FC1, TS_SDP1_SEL_FC1, TS_SDP2_SEL_FC1, TS_SDP3_SEL_FC1, @@ -554,11 +562,17 @@ static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin) tssdp &= ~AUX1_TS_SDP_EN; tssdp &= ~ts_sdp_sel_clr[pin]; - if (chan == 1) - tssdp |= ts_sdp_sel_tt1[pin]; - else - tssdp |= ts_sdp_sel_tt0[pin]; - + if (freq) { + if (chan == 1) + tssdp |= ts_sdp_sel_fc1[pin]; + else + tssdp |= ts_sdp_sel_fc0[pin]; + } else { + if (chan == 1) + tssdp |= ts_sdp_sel_tt1[pin]; + else + tssdp |= ts_sdp_sel_tt0[pin]; + } tssdp |= ts_sdp_en[pin]; wr32(E1000_TSSDP, tssdp); @@ -572,10 +586,10 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); struct e1000_hw *hw = &igb->hw; - u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh; + u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh, freqout; unsigned long flags; struct timespec ts; - int pin = -1; + int use_freq = 0, pin = -1; s64 ns; switch (rq->type) { @@ -620,40 +634,58 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, ts.tv_nsec = rq->perout.period.nsec; ns = timespec_to_ns(&ts); ns = ns >> 1; - if (on && ns < 500000LL) { - /* 2k interrupts per second is an awful lot. */ - return -EINVAL; + if (on && ns <= 70000000LL) { + if (ns < 8LL) + return -EINVAL; + use_freq = 1; } ts = ns_to_timespec(ns); if (rq->perout.index == 1) { - tsauxc_mask = TSAUXC_EN_TT1; - tsim_mask = TSINTR_TT1; + if (use_freq) { + tsauxc_mask = TSAUXC_EN_CLK1 | TSAUXC_ST1; + tsim_mask = 0; + } else { + tsauxc_mask = TSAUXC_EN_TT1; + tsim_mask = TSINTR_TT1; + } trgttiml = E1000_TRGTTIML1; trgttimh = E1000_TRGTTIMH1; + freqout = E1000_FREQOUT1; } else { - tsauxc_mask = TSAUXC_EN_TT0; - tsim_mask = TSINTR_TT0; + if (use_freq) { + tsauxc_mask = TSAUXC_EN_CLK0 | TSAUXC_ST0; + tsim_mask = 0; + } else { + tsauxc_mask = TSAUXC_EN_TT0; + tsim_mask = TSINTR_TT0; + } trgttiml = E1000_TRGTTIML0; trgttimh = E1000_TRGTTIMH0; + freqout = E1000_FREQOUT0; } spin_lock_irqsave(&igb->tmreg_lock, flags); tsauxc = rd32(E1000_TSAUXC); tsim = rd32(E1000_TSIM); + if (rq->perout.index == 1) { + tsauxc &= ~(TSAUXC_EN_TT1 | TSAUXC_EN_CLK1 | TSAUXC_ST1); + tsim &= ~TSINTR_TT1; + } else { + tsauxc &= ~(TSAUXC_EN_TT0 | TSAUXC_EN_CLK0 | TSAUXC_ST0); + tsim &= ~TSINTR_TT0; + } if (on) { int i = rq->perout.index; - - igb_pin_perout(igb, i, pin); + igb_pin_perout(igb, i, pin, use_freq); igb->perout[i].start.tv_sec = rq->perout.start.sec; igb->perout[i].start.tv_nsec = rq->perout.start.nsec; igb->perout[i].period.tv_sec = ts.tv_sec; igb->perout[i].period.tv_nsec = ts.tv_nsec; wr32(trgttimh, rq->perout.start.sec); wr32(trgttiml, rq->perout.start.nsec); + if (use_freq) + wr32(freqout, ns); tsauxc |= tsauxc_mask; tsim |= tsim_mask; - } else { - tsauxc &= ~tsauxc_mask; - tsim &= ~tsim_mask; } wr32(E1000_TSAUXC, tsauxc); wr32(E1000_TSIM, tsim); -- cgit v1.2.1 From 6039b3f3f5cd3f34ec88712ac8b5f35cd6c2df98 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 30 Sep 2015 13:26:33 +0200 Subject: net: igb: avoid using timespec We want to deprecate the use of 'struct timespec' on 32-bit architectures, as it is will overflow in 2038. The igb driver uses it to read the current time, and can simply be changed to use ktime_get_real_ts64() instead. Because of hardware limitations, there is still an overflow in year 2106, which we cannot really avoid, but this documents the overflow. Signed-off-by: Arnd Bergmann Cc: Jeff Kirsher Cc: intel-wired-lan@lists.osuosl.org Reviewed-by: Richard Cochran Signed-off-by: David S. Miller Signed-off-by: Roland Hii --- kmod/igb/igb.h | 4 ++-- kmod/igb/igb_main.c | 15 ++++++++------- kmod/igb/igb_ptp.c | 8 ++++---- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/kmod/igb/igb.h b/kmod/igb/igb.h index 3e2a801a..f60cd814 100644 --- a/kmod/igb/igb.h +++ b/kmod/igb/igb.h @@ -665,8 +665,8 @@ struct igb_adapter { struct ptp_pin_desc sdp_config[IGB_N_SDP]; struct { - struct timespec start; - struct timespec period; + struct timespec64 start; + struct timespec64 period; } perout[IGB_N_PEROUT]; #endif /* HAVE_PTP_1588_CLOCK */ diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index c5d88b0f..c18ec935 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -6053,7 +6053,7 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct ptp_clock_event event; - struct timespec ts; + struct timespec64 ts; u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR); if (tsicr & TSINTR_SYS_WRAP) { @@ -6073,10 +6073,11 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) if (tsicr & TSINTR_TT0) { spin_lock(&adapter->tmreg_lock); - ts = timespec_add(adapter->perout[0].start, - adapter->perout[0].period); + ts = timespec64_add(adapter->perout[0].start, + adapter->perout[0].period); + /* u32 conversion of tv_sec is safe until y2106 */ wr32(E1000_TRGTTIML0, ts.tv_nsec); - wr32(E1000_TRGTTIMH0, ts.tv_sec); + wr32(E1000_TRGTTIMH0, (u32)ts.tv_sec); tsauxc = rd32(E1000_TSAUXC); tsauxc |= TSAUXC_EN_TT0; wr32(E1000_TSAUXC, tsauxc); @@ -6087,10 +6088,10 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) if (tsicr & TSINTR_TT1) { spin_lock(&adapter->tmreg_lock); - ts = timespec_add(adapter->perout[1].start, - adapter->perout[1].period); + ts = timespec64_add(adapter->perout[1].start, + adapter->perout[1].period); wr32(E1000_TRGTTIML1, ts.tv_nsec); - wr32(E1000_TRGTTIMH1, ts.tv_sec); + wr32(E1000_TRGTTIMH1, (u32)ts.tv_sec); tsauxc = rd32(E1000_TSAUXC); tsauxc |= TSAUXC_EN_TT1; wr32(E1000_TSAUXC, tsauxc); diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index bb9e8ce8..c173fb6a 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -166,7 +166,7 @@ static void igb_ptp_write_i210(struct igb_adapter *adapter, * sub-nanosecond resolution. */ E1000_WRITE_REG(hw, E1000_SYSTIML, ts->tv_nsec); - E1000_WRITE_REG(hw, E1000_SYSTIMH, ts->tv_sec); + E1000_WRITE_REG(hw, E1000_SYSTIMH, (u32)ts->tv_sec); } /** @@ -588,7 +588,7 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, struct e1000_hw *hw = &igb->hw; u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh, freqout; unsigned long flags; - struct timespec ts; + struct timespec64 ts; int use_freq = 0, pin = -1; s64 ns; @@ -632,14 +632,14 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, } ts.tv_sec = rq->perout.period.sec; ts.tv_nsec = rq->perout.period.nsec; - ns = timespec_to_ns(&ts); + ns = timespec64_to_ns(&ts); ns = ns >> 1; if (on && ns <= 70000000LL) { if (ns < 8LL) return -EINVAL; use_freq = 1; } - ts = ns_to_timespec(ns); + ts = ns_to_timespec64(ns); if (rq->perout.index == 1) { if (use_freq) { tsauxc_mask = TSAUXC_EN_CLK1 | TSAUXC_ST1; -- cgit v1.2.1 From 90bb6ae2988734875f66898bca7e10f4a572e1ce Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Mon, 11 Jan 2016 15:34:18 +0800 Subject: igb: add conditions for I210 to generate periodic clock output In general case the maximum supported half cycle time of the synchronized output clock is 70msec. Slower half cycle time than 70msec can be programmed also as long as the output clock is synchronized to whole seconds, useful specifically for generating a 1Hz clock. Permitted values for the clock half cycle time are: 125,000,000 decimal, 250,000,000 decimal and 500,000,000 decimal (equals to 125msec, 250msec and 500msec respectively). Before this patch, only the half cycle time of less than or equal to 70msec uses the I210 clock output function. This patch adds additional conditions when half cycle time is equal to 125msec or 250msec or 500msec to use clock output function. Under other conditions, interrupt driven target time output events method is still used to generate the desired clock output. Signed-off-by: Roland Hii Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: Roland Hii --- kmod/igb/igb_ptp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index c173fb6a..e8fa8f8c 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -634,7 +634,8 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, ts.tv_nsec = rq->perout.period.nsec; ns = timespec64_to_ns(&ts); ns = ns >> 1; - if (on && ns <= 70000000LL) { + if (on && ((ns <= 70000000LL) || (ns == 125000000LL) || + (ns == 250000000LL) || (ns == 500000000LL))) { if (ns < 8LL) return -EINVAL; use_freq = 1; -- cgit v1.2.1 From fbbec598c035f74ec90d72224d16a4bed9f4c4f2 Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Tue, 5 Apr 2016 13:07:48 +0800 Subject: igb: replace undefined functions after backport. Replace rd32(...) with E1000_READ_REG(hw, ...) and wr32(...) with E1000_WRITE_REG(hw, ...). Signed-off-by: Roland Hii --- kmod/igb/igb_main.c | 28 ++++++++++++++-------------- kmod/igb/igb_ptp.c | 52 ++++++++++++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/kmod/igb/igb_main.c b/kmod/igb/igb_main.c index c18ec935..11b1a00a 100644 --- a/kmod/igb/igb_main.c +++ b/kmod/igb/igb_main.c @@ -6054,7 +6054,7 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) struct e1000_hw *hw = &adapter->hw; struct ptp_clock_event event; struct timespec64 ts; - u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR); + u32 ack = 0, tsauxc, sec, nsec, tsicr = E1000_READ_REG(hw, E1000_TSICR); if (tsicr & TSINTR_SYS_WRAP) { event.type = PTP_CLOCK_PPS; @@ -6076,11 +6076,11 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) ts = timespec64_add(adapter->perout[0].start, adapter->perout[0].period); /* u32 conversion of tv_sec is safe until y2106 */ - wr32(E1000_TRGTTIML0, ts.tv_nsec); - wr32(E1000_TRGTTIMH0, (u32)ts.tv_sec); - tsauxc = rd32(E1000_TSAUXC); + E1000_WRITE_REG(hw, E1000_TRGTTIML0, ts.tv_nsec); + E1000_WRITE_REG(hw, E1000_TRGTTIMH0, (u32)ts.tv_sec); + tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); tsauxc |= TSAUXC_EN_TT0; - wr32(E1000_TSAUXC, tsauxc); + E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc); adapter->perout[0].start = ts; spin_unlock(&adapter->tmreg_lock); ack |= TSINTR_TT0; @@ -6090,19 +6090,19 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) spin_lock(&adapter->tmreg_lock); ts = timespec64_add(adapter->perout[1].start, adapter->perout[1].period); - wr32(E1000_TRGTTIML1, ts.tv_nsec); - wr32(E1000_TRGTTIMH1, (u32)ts.tv_sec); - tsauxc = rd32(E1000_TSAUXC); + E1000_WRITE_REG(hw, E1000_TRGTTIML1, ts.tv_nsec); + E1000_WRITE_REG(hw, E1000_TRGTTIMH1, (u32)ts.tv_sec); + tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); tsauxc |= TSAUXC_EN_TT1; - wr32(E1000_TSAUXC, tsauxc); + E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc); adapter->perout[1].start = ts; spin_unlock(&adapter->tmreg_lock); ack |= TSINTR_TT1; } if (tsicr & TSINTR_AUTT0) { - nsec = rd32(E1000_AUXSTMPL0); - sec = rd32(E1000_AUXSTMPH0); + nsec = E1000_READ_REG(hw, E1000_AUXSTMPL0); + sec = E1000_READ_REG(hw, E1000_AUXSTMPH0); event.type = PTP_CLOCK_EXTTS; event.index = 0; event.timestamp = sec * 1000000000ULL + nsec; @@ -6111,8 +6111,8 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) } if (tsicr & TSINTR_AUTT1) { - nsec = rd32(E1000_AUXSTMPL1); - sec = rd32(E1000_AUXSTMPH1); + nsec = E1000_READ_REG(hw, E1000_AUXSTMPL1); + sec = E1000_READ_REG(hw, E1000_AUXSTMPH1); event.type = PTP_CLOCK_EXTTS; event.index = 1; event.timestamp = sec * 1000000000ULL + nsec; @@ -6121,7 +6121,7 @@ static void igb_tsync_interrupt(struct igb_adapter *adapter) } /* acknowledge the interrupts */ - wr32(E1000_TSICR, ack); + E1000_WRITE_REG(hw, E1000_TSICR, ack); } static irqreturn_t igb_msix_other(int irq, void *data) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index e8fa8f8c..6179528b 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -492,9 +492,9 @@ static void igb_pin_extts(struct igb_adapter *igb, int chan, int pin) struct e1000_hw *hw = &igb->hw; u32 ctrl, ctrl_ext, tssdp = 0; - ctrl = rd32(E1000_CTRL); - ctrl_ext = rd32(E1000_CTRL_EXT); - tssdp = rd32(E1000_TSSDP); + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + tssdp = E1000_READ_REG(hw, E1000_TSSDP); igb_pin_direction(pin, 1, &ctrl, &ctrl_ext); @@ -509,9 +509,9 @@ static void igb_pin_extts(struct igb_adapter *igb, int chan, int pin) tssdp |= aux0_sel_sdp[pin] | AUX0_TS_SDP_EN; } - wr32(E1000_TSSDP, tssdp); - wr32(E1000_CTRL, ctrl); - wr32(E1000_CTRL_EXT, ctrl_ext); + E1000_WRITE_REG(hw, E1000_TSSDP, tssdp); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); } static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin, int freq) @@ -548,9 +548,9 @@ static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin, int freq) struct e1000_hw *hw = &igb->hw; u32 ctrl, ctrl_ext, tssdp = 0; - ctrl = rd32(E1000_CTRL); - ctrl_ext = rd32(E1000_CTRL_EXT); - tssdp = rd32(E1000_TSSDP); + ctrl = E1000_READ_REG(hw, E1000_CTRL); + ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); + tssdp = E1000_READ_REG(hw, E1000_TSSDP); igb_pin_direction(pin, 0, &ctrl, &ctrl_ext); @@ -575,9 +575,9 @@ static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin, int freq) } tssdp |= ts_sdp_en[pin]; - wr32(E1000_TSSDP, tssdp); - wr32(E1000_CTRL, ctrl); - wr32(E1000_CTRL_EXT, ctrl_ext); + E1000_WRITE_REG(hw, E1000_TSSDP, tssdp); + E1000_WRITE_REG(hw, E1000_CTRL, ctrl); + E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); } static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, @@ -608,8 +608,8 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, tsim_mask = TSINTR_AUTT0; } spin_lock_irqsave(&igb->tmreg_lock, flags); - tsauxc = rd32(E1000_TSAUXC); - tsim = rd32(E1000_TSIM); + tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); + tsim = E1000_READ_REG(hw, E1000_TSIM); if (on) { igb_pin_extts(igb, rq->extts.index, pin); tsauxc |= tsauxc_mask; @@ -618,8 +618,8 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, tsauxc &= ~tsauxc_mask; tsim &= ~tsim_mask; } - wr32(E1000_TSAUXC, tsauxc); - wr32(E1000_TSIM, tsim); + E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc); + E1000_WRITE_REG(hw, E1000_TSIM, tsim); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; @@ -665,8 +665,8 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, freqout = E1000_FREQOUT0; } spin_lock_irqsave(&igb->tmreg_lock, flags); - tsauxc = rd32(E1000_TSAUXC); - tsim = rd32(E1000_TSIM); + tsauxc = E1000_READ_REG(hw, E1000_TSAUXC); + tsim = E1000_READ_REG(hw, E1000_TSIM); if (rq->perout.index == 1) { tsauxc &= ~(TSAUXC_EN_TT1 | TSAUXC_EN_CLK1 | TSAUXC_ST1); tsim &= ~TSINTR_TT1; @@ -681,26 +681,26 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, igb->perout[i].start.tv_nsec = rq->perout.start.nsec; igb->perout[i].period.tv_sec = ts.tv_sec; igb->perout[i].period.tv_nsec = ts.tv_nsec; - wr32(trgttimh, rq->perout.start.sec); - wr32(trgttiml, rq->perout.start.nsec); + E1000_WRITE_REG(hw, trgttimh, rq->perout.start.sec); + E1000_WRITE_REG(hw, trgttiml, rq->perout.start.nsec); if (use_freq) - wr32(freqout, ns); + E1000_WRITE_REG(hw, freqout, ns); tsauxc |= tsauxc_mask; tsim |= tsim_mask; } - wr32(E1000_TSAUXC, tsauxc); - wr32(E1000_TSIM, tsim); + E1000_WRITE_REG(hw, E1000_TSAUXC, tsauxc); + E1000_WRITE_REG(hw, E1000_TSIM, tsim); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; case PTP_CLK_REQ_PPS: spin_lock_irqsave(&igb->tmreg_lock, flags); - tsim = rd32(E1000_TSIM); + tsim = E1000_READ_REG(hw, E1000_TSIM); if (on) tsim |= TSINTR_SYS_WRAP; else tsim &= ~TSINTR_SYS_WRAP; - wr32(E1000_TSIM, tsim); + E1000_WRITE_REG(hw, E1000_TSIM, tsim); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; } @@ -1323,7 +1323,7 @@ void igb_ptp_reset(struct igb_adapter *adapter) case e1000_i210: case e1000_i211: E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); - wr32(E1000_TSSDP, 0x0); + E1000_WRITE_REG(hw, E1000_TSSDP, 0x0); E1000_WRITE_REG(hw, E1000_TSIM, TSYNC_INTERRUPTS); E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_TS); break; -- cgit v1.2.1 From 67bd406d2f8f92b116c54db571194efd4b8ba6fd Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Thu, 28 Apr 2016 18:56:58 +0800 Subject: igb: fix ptp_pin_desc symbol not found error when kernel ver < 3.15 The added auxiliary PTP Hardware Clock (PHC) functions for the I210 has dependency in PTP code, e.g. struct ptp_pin_desc. The dependency in PTP code is added to mainline kernel since kernel version 3.15. #ifdef HAVE_PTP_1588_CLOCK_PINS pairs are added around the new code that gives compilation errors and warnings when compiling against kernel version < 3.15. HAVE_PTP_1588_CLOCK_PINS has been defined in kcompat.h. Signed-off-by: Roland Hii --- kmod/igb/igb.h | 2 ++ kmod/igb/igb_ptp.c | 26 +++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/kmod/igb/igb.h b/kmod/igb/igb.h index f60cd814..7fb3e53a 100644 --- a/kmod/igb/igb.h +++ b/kmod/igb/igb.h @@ -663,7 +663,9 @@ struct igb_adapter { u32 tx_hwtstamp_timeouts; u32 rx_hwtstamp_cleared; +#ifdef HAVE_PTP_1588_CLOCK_PINS struct ptp_pin_desc sdp_config[IGB_N_SDP]; +#endif /* HAVE_PTP_1588_CLOCK_PINS */ struct { struct timespec64 start; struct timespec64 period; diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index 6179528b..c1b0a44d 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -462,6 +462,7 @@ static int igb_ptp_settime_i210(struct ptp_clock_info *ptp, } #endif +#ifdef HAVE_PTP_1588_CLOCK_PINS static void igb_pin_direction(int pin, int input, u32 *ctrl, u32 *ctrl_ext) { u32 *ptr = pin < 2 ? ctrl : ctrl_ext; @@ -579,6 +580,7 @@ static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin, int freq) E1000_WRITE_REG(hw, E1000_CTRL, ctrl); E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); } +#endif /* HAVE_PTP_1588_CLOCK_PINS */ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) @@ -586,13 +588,17 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, struct igb_adapter *igb = container_of(ptp, struct igb_adapter, ptp_caps); struct e1000_hw *hw = &igb->hw; - u32 tsauxc, tsim, tsauxc_mask, tsim_mask, trgttiml, trgttimh, freqout; unsigned long flags; + u32 tsim; +#ifdef HAVE_PTP_1588_CLOCK_PINS + u32 tsauxc, tsauxc_mask, tsim_mask, trgttiml, trgttimh, freqout; struct timespec64 ts; int use_freq = 0, pin = -1; s64 ns; +#endif /* HAVE_PTP_1588_CLOCK_PINS */ switch (rq->type) { +#ifdef HAVE_PTP_1588_CLOCK_PINS case PTP_CLK_REQ_EXTTS: if (on) { pin = ptp_find_pin(igb->ptp_clock, PTP_PF_EXTTS, @@ -692,6 +698,7 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, E1000_WRITE_REG(hw, E1000_TSIM, tsim); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; +#endif /* HAVE_PTP_1588_CLOCK_PINS */ case PTP_CLK_REQ_PPS: spin_lock_irqsave(&igb->tmreg_lock, flags); @@ -703,6 +710,11 @@ static int igb_ptp_feature_enable_i210(struct ptp_clock_info *ptp, E1000_WRITE_REG(hw, E1000_TSIM, tsim); spin_unlock_irqrestore(&igb->tmreg_lock, flags); return 0; + +#ifndef HAVE_PTP_1588_CLOCK_PINS + default: + break; +#endif /* HAVE_PTP_1588_CLOCK_PINS */ } return -EOPNOTSUPP; @@ -714,6 +726,7 @@ static int igb_ptp_feature_enable(struct ptp_clock_info *ptp, return -EOPNOTSUPP; } +#ifdef HAVE_PTP_1588_CLOCK_PINS static int igb_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, enum ptp_pin_function func, unsigned int chan) { @@ -727,6 +740,7 @@ static int igb_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, } return 0; } +#endif /* HAVE_PTP_1588_CLOCK_PINS */ /** * igb_ptp_tx_work @@ -1124,7 +1138,9 @@ void igb_ptp_init(struct igb_adapter *adapter) { struct e1000_hw *hw = &adapter->hw; struct net_device *netdev = adapter->netdev; +#ifdef HAVE_PTP_1588_CLOCK_PINS int i; +#endif /* HAVE_PTP_1588_CLOCK_PINS */ switch (hw->mac.type) { case e1000_82576: @@ -1178,6 +1194,7 @@ void igb_ptp_init(struct igb_adapter *adapter) break; case e1000_i210: case e1000_i211: +#ifdef HAVE_PTP_1588_CLOCK_PINS for (i = 0; i < IGB_N_SDP; i++) { struct ptp_pin_desc *ppd = &adapter->sdp_config[i]; @@ -1185,14 +1202,19 @@ void igb_ptp_init(struct igb_adapter *adapter) ppd->index = i; ppd->func = PTP_PF_NONE; } +#endif /* HAVE_PTP_1588_CLOCK_PINS */ snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); adapter->ptp_caps.owner = THIS_MODULE; adapter->ptp_caps.max_adj = 62499999; adapter->ptp_caps.n_ext_ts = IGB_N_EXTTS; adapter->ptp_caps.n_per_out = IGB_N_PEROUT; +#ifdef HAVE_PTP_1588_CLOCK_PINS adapter->ptp_caps.n_pins = IGB_N_SDP; +#endif /* HAVE_PTP_1588_CLOCK_PINS */ adapter->ptp_caps.pps = 1; +#ifdef HAVE_PTP_1588_CLOCK_PINS adapter->ptp_caps.pin_config = adapter->sdp_config; +#endif /* HAVE_PTP_1588_CLOCK_PINS */ adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580; adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210; #ifdef HAVE_PTP_CLOCK_INFO_GETTIME64 @@ -1203,7 +1225,9 @@ void igb_ptp_init(struct igb_adapter *adapter) adapter->ptp_caps.settime = igb_ptp_settime_i210; #endif adapter->ptp_caps.enable = igb_ptp_feature_enable_i210; +#ifdef HAVE_PTP_1588_CLOCK_PINS adapter->ptp_caps.verify = igb_ptp_verify_pin; +#endif /* HAVE_PTP_1588_CLOCK_PINS */ /* Enable the timer functions by clearing bit 31. */ E1000_WRITE_REG(hw, E1000_TSAUXC, 0x0); break; -- cgit v1.2.1 From 128ff4a21b9a7c6abae48da827e69c549b61f25b Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Thu, 8 Sep 2016 15:59:25 +0800 Subject: simple_rx: Fixed typos in Makefiles to properly clean targets There were two typos in Makefiles which cause the commands "make simple_listener_clean" and "make simple_rx_clean" do not clean simple_listener.o object file and also simple_rx executable file. This patch fixed the typos to properly clean the generated files. Signed-off-by: Roland Hii --- Makefile | 2 +- examples/simple_rx/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2cfe159b..32308b6f 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ simple_listener: $(call descend,examples/$@) simple_listener_clean: - $(call descend,examples/simple_rx/,clean) + $(call descend,examples/simple_listener/,clean) simple_rx: $(MAKE) lib diff --git a/examples/simple_rx/Makefile b/examples/simple_rx/Makefile index 7ca14365..bf83a484 100644 --- a/examples/simple_rx/Makefile +++ b/examples/simple_rx/Makefile @@ -23,5 +23,5 @@ $(IGBDIR)/igb.o: $(IGBDIR)/igb.c $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ clean: - $(RM) simple_listener + $(RM) simple_rx $(RM) `find . -name "*~" -o -name "*.[oa]" -o -name "\#*\#" -o -name TAGS -o -name core -o -name "*.orig"` -- cgit v1.2.1 From b4fdc7b76b5558923db3e3c79a117c5c154aaf1e Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Thu, 8 Sep 2016 16:21:27 +0800 Subject: Fixed Makefile to clean all generated files There were some object files left in examples/common/ and lib/common/ folders when "make clean" command was issued. This patch will also remove those object files when the clean command is issued. Signed-off-by: Roland Hii --- Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 32308b6f..7e326ef0 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,7 @@ lib: FORCE lib_clean: $(call descend,lib/igb/,clean) + $(call descend,lib/common/,clean) mrpd: $(call descend,daemons/$@) @@ -67,6 +68,12 @@ daemons_all: mrpd maap gptp daemons_all_clean: mrpd_clean gptp_clean maap_clean +examples_common: + $(call descend,examples/common) + +examples_common_clean: + $(call descend,examples/common/,clean) + simple_talker: $(MAKE) lib $(call descend,examples/$@) @@ -124,10 +131,10 @@ avtp_pipeline_clean: avtp_pipeline_doc: lib $(MAKE) -s -C lib/avtp_pipeline -f avtp_pipeline.mk doc -examples_all: simple_talker simple_listener mrp_client live_stream jackd-talker \ +examples_all: examples_common simple_talker simple_listener mrp_client live_stream jackd-talker \ jackd-listener simple_rx -examples_all_clean: simple_talker_clean simple_listener_clean mrp_client_clean \ +examples_all_clean: examples_common_clean simple_talker_clean simple_listener_clean mrp_client_clean \ jackd-talker_clean jackd-listener_clean live_stream_clean simple_rx_clean all: igb lib daemons_all examples_all avtp_pipeline -- cgit v1.2.1 From 46662db0ac474fb022dc1bd597767ee5cb1b0c23 Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Tue, 13 Sep 2016 14:30:21 +0800 Subject: Fix compile warnings and errors after added -O2 compile option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit warning: comparison between signed and unsigned integer expressions [-Wsign-compare] -- daemons/mrpd/msrp.c -- daemons/mrpd/msrp.h warning: always overflow destination buffer [enabled by default] -- daemons/gptp/linux/src/linux_hal_common.cpp warning: ignoring return value [-Wunused-result] -- daemons/gptp/linux/src/linux_hal_persist_file.cpp -- examples/live_stream/listener.c warning: may be used uninitialized in this function [-Wmaybe-uninitialized] -- daemons/gptp/linux/src/linux_hal_generic.cpp -- daemons/gptp/linux/src/daemon_cl.cpp -- daemons/maap/common/maap_protocol.c warning: array subscript is above array bounds [-Warray-bounds] -- daemons/maap/linux/maap_linux.c error: obj/ini.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC -- lib/igb/Makefile warning: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C [enabled by default] error: obj/ini.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC fatal error: igb.h: No such file or directory -- daemons/gptp/linux/build/Makefile Signed-off-by: Roland Hii --- daemons/gptp/linux/build/Makefile | 4 ++-- daemons/gptp/linux/src/daemon_cl.cpp | 2 +- daemons/gptp/linux/src/linux_hal_common.cpp | 2 +- daemons/gptp/linux/src/linux_hal_generic.cpp | 8 +++++--- daemons/gptp/linux/src/linux_hal_persist_file.cpp | 4 +++- daemons/maap/common/maap_protocol.c | 2 +- daemons/maap/linux/maap_linux.c | 2 +- daemons/mrpd/msrp.c | 2 +- daemons/mrpd/msrp.h | 2 +- examples/live_stream/listener.c | 4 +++- lib/igb/Makefile | 1 + 11 files changed, 20 insertions(+), 13 deletions(-) diff --git a/daemons/gptp/linux/build/Makefile b/daemons/gptp/linux/build/Makefile index 21048c06..b02a4507 100644 --- a/daemons/gptp/linux/build/Makefile +++ b/daemons/gptp/linux/build/Makefile @@ -30,7 +30,7 @@ ALTERNATE_LINUX_INCPATH=$(HOME)/header/include/ -CFLAGS_G = -Wall -std=c++0x -g -I. -I../../common -I../src \ +CFLAGS_G = -Wall -fPIC -g -I. -I../../common -I../src \ -I$(ALTERNATE_LINUX_INCPATH) # Check to see if PTP cross-timestamping is supported in hardware/driver @@ -46,7 +46,7 @@ ifeq ($(HAS_PRECISE_TIME),0) CFLAGS_G += -DPTP_HW_CROSSTSTAMP endif -CPPFLAGS_G = $(CFLAGS_G) -Wnon-virtual-dtor +CPPFLAGS_G = $(CFLAGS_G) -std=c++0x -Wnon-virtual-dtor LDFLAGS_G = -lpthread -lrt diff --git a/daemons/gptp/linux/src/daemon_cl.cpp b/daemons/gptp/linux/src/daemon_cl.cpp index b5b46a10..50f422aa 100644 --- a/daemons/gptp/linux/src/daemon_cl.cpp +++ b/daemons/gptp/linux/src/daemon_cl.cpp @@ -112,7 +112,7 @@ int main(int argc, char **argv) bool pps = false; uint8_t priority1 = 248; bool override_portstate = false; - PortState port_state; + PortState port_state = PTP_SLAVE; char *restoredata = NULL; char *restoredataptr = NULL; diff --git a/daemons/gptp/linux/src/linux_hal_common.cpp b/daemons/gptp/linux/src/linux_hal_common.cpp index ed986b07..3c67e457 100644 --- a/daemons/gptp/linux/src/linux_hal_common.cpp +++ b/daemons/gptp/linux/src/linux_hal_common.cpp @@ -847,7 +847,7 @@ bool LinuxNetworkInterfaceFactory::createInterface } memset( &device, 0, sizeof(device)); - ifname->toString( device.ifr_name, IFNAMSIZ ); + ifname->toString( device.ifr_name, IFNAMSIZ - 1 ); err = ioctl( net_iface_l->sd_event, SIOCGIFHWADDR, &device ); if( err == -1 ) { GPTP_LOG_ERROR diff --git a/daemons/gptp/linux/src/linux_hal_generic.cpp b/daemons/gptp/linux/src/linux_hal_generic.cpp index 041e733f..fd599f26 100644 --- a/daemons/gptp/linux/src/linux_hal_generic.cpp +++ b/daemons/gptp/linux/src/linux_hal_generic.cpp @@ -455,7 +455,7 @@ bool LinuxTimestamperGeneric::HWTimestamper_gettime { unsigned i; struct ptp_clock_time *pct; - struct ptp_clock_time *system_time_l, *device_time_l; + struct ptp_clock_time *system_time_l = NULL, *device_time_l = NULL; int64_t interval = LLONG_MAX; struct ptp_sys_offset offset; @@ -475,8 +475,10 @@ bool LinuxTimestamperGeneric::HWTimestamper_gettime } } - *device_time = pctTimestamp( device_time_l ); - *system_time = pctTimestamp( system_time_l ); + if (device_time_l) + *device_time = pctTimestamp( device_time_l ); + if (system_time_l) + *system_time = pctTimestamp( system_time_l ); } return true; diff --git a/daemons/gptp/linux/src/linux_hal_persist_file.cpp b/daemons/gptp/linux/src/linux_hal_persist_file.cpp index e3539473..8655c6cd 100644 --- a/daemons/gptp/linux/src/linux_hal_persist_file.cpp +++ b/daemons/gptp/linux/src/linux_hal_persist_file.cpp @@ -123,7 +123,9 @@ public: bool result = false; if (memoryDataLength > storedDataLength) { - ftruncate(persistFD, memoryDataLength); + int ret = ftruncate(persistFD, memoryDataLength); + if (ret != 0) { + } if (restoredata != ((void *)-1)) { restoredata = mremap(restoredata, storedDataLength, memoryDataLength, MREMAP_MAYMOVE); } diff --git a/daemons/maap/common/maap_protocol.c b/daemons/maap/common/maap_protocol.c index eb09b72e..b9530adb 100644 --- a/daemons/maap/common/maap_protocol.c +++ b/daemons/maap/common/maap_protocol.c @@ -57,7 +57,7 @@ int state_transit(maap_info_t *maap_info) uint8_t *s = NULL; int i= 0; int num_bytes = 0; - int maap_probe_count; + int maap_probe_count = 0; switch (current_state) { case INITIAL: diff --git a/daemons/maap/linux/maap_linux.c b/daemons/maap/linux/maap_linux.c index a0e19969..c0634c69 100644 --- a/daemons/maap/linux/maap_linux.c +++ b/daemons/maap/linux/maap_linux.c @@ -195,7 +195,7 @@ int main(int argc, char *argv[]) } pthread_mutex_init(&(lock), NULL); - seed = src_mac[6] + time(NULL); + seed = src_mac[5] + time(NULL); srand(seed); maap_Info = (maap_info_t *)calloc(1,sizeof(maap_info_t)); diff --git a/daemons/mrpd/msrp.c b/daemons/mrpd/msrp.c index 8dd127e4..2e8c3713 100644 --- a/daemons/mrpd/msrp.c +++ b/daemons/mrpd/msrp.c @@ -124,7 +124,7 @@ void msrp_print_debug_info(int evt, const struct msrp_attribute *attrib) } #endif -int msrp_count_type(int attrib_type) +int msrp_count_type(uint32_t attrib_type) { int count = 0; struct msrp_attribute *attrib; diff --git a/daemons/mrpd/msrp.h b/daemons/mrpd/msrp.h index 7228e2e2..96d0eb5d 100644 --- a/daemons/mrpd/msrp.h +++ b/daemons/mrpd/msrp.h @@ -187,7 +187,7 @@ int msrp_recv_msg(void); * \param attrib_type The attribute type to count. * \return The number of attributes of type attrib_type in the MSRP database. */ -int msrp_count_type(int attrib_type); +int msrp_count_type(uint32_t attrib_type); /** * Return the number of interesting talker stream ids recorded in the diff --git a/examples/live_stream/listener.c b/examples/live_stream/listener.c index 7ce12000..5109a3c8 100644 --- a/examples/live_stream/listener.c +++ b/examples/live_stream/listener.c @@ -198,8 +198,10 @@ int main(int argc, char *argv[ ]) fprintf(stderr,"frame sequence = %lld\n", frame_sequence++); h1722 = (seventeen22_header *)((uint8_t*)frame + sizeof(eth_header)); length = ntohs(h1722->length) - sizeof(six1883_header); - write(1, (uint8_t *)((uint8_t*)frame + sizeof(eth_header) + sizeof(seventeen22_header) + + rc = write(1, (uint8_t *)((uint8_t*)frame + sizeof(eth_header) + sizeof(seventeen22_header) + sizeof(six1883_header)), length); + if (rc != length) { + } } else { fprintf(stderr,"recvfrom() error for frame sequence = %lld\n", frame_sequence++); } diff --git a/lib/igb/Makefile b/lib/igb/Makefile index 8a0c4151..68cb1872 100644 --- a/lib/igb/Makefile +++ b/lib/igb/Makefile @@ -2,6 +2,7 @@ OBJS=igb INCL=e1000_82575.h e1000_defines.h e1000_hw.h e1000_osdep.h e1000_regs.h igb.h AVBLIB=libigb.a #CFLAGS=-ggdb +CFLAGS=-fPIC CC?=gcc RANLIB?=ranlib -- cgit v1.2.1 From d3b3764e017037527fa3cce288ac70155f3f4afe Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Tue, 28 Jun 2016 17:47:10 -0600 Subject: avtp_pipeline: Added clock synthesis module. --- lib/avtp_pipeline/mcs/CMakeLists.txt | 5 +++ lib/avtp_pipeline/mcs/openavb_mcs.c | 59 +++++++++++++++++++++++++ lib/avtp_pipeline/mcs/openavb_mcs.h | 42 ++++++++++++++++++ lib/avtp_pipeline/platform/Linux/CMakeLists.txt | 2 + 4 files changed, 108 insertions(+) create mode 100644 lib/avtp_pipeline/mcs/CMakeLists.txt create mode 100644 lib/avtp_pipeline/mcs/openavb_mcs.c create mode 100644 lib/avtp_pipeline/mcs/openavb_mcs.h diff --git a/lib/avtp_pipeline/mcs/CMakeLists.txt b/lib/avtp_pipeline/mcs/CMakeLists.txt new file mode 100644 index 00000000..0f942140 --- /dev/null +++ b/lib/avtp_pipeline/mcs/CMakeLists.txt @@ -0,0 +1,5 @@ +SET (SRC_FILES ${SRC_FILES} + ${AVB_SRC_DIR}/mcs/openavb_mcs.c + PARENT_SCOPE +) + diff --git a/lib/avtp_pipeline/mcs/openavb_mcs.c b/lib/avtp_pipeline/mcs/openavb_mcs.c new file mode 100644 index 00000000..ba3b12fe --- /dev/null +++ b/lib/avtp_pipeline/mcs/openavb_mcs.c @@ -0,0 +1,59 @@ +/************************************************************************************************************* +Copyright (c) 2016, Harman International Industries, Incorporated +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : Media clock timestamp synthesis for stored or generated media +*/ + +#include "openavb_platform_pub.h" +#include "openavb_types_pub.h" +#include "openavb_log_pub.h" +#include "openavb_mcs.h" + +void openavbMcsInit(mcs_t *mediaClockSynth, U64 nsPerAdvance) +{ + mediaClockSynth->firstTimeSet = FALSE; + mediaClockSynth->nsPerAdvance = nsPerAdvance; + mediaClockSynth->edgeTime = 0; +} + +void openavbMcsAdvance(mcs_t *mediaClockSynth) +{ + if (mediaClockSynth->firstTimeSet == FALSE) { + CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &mediaClockSynth->edgeTime); + if (mediaClockSynth->edgeTime) { + mediaClockSynth->firstTimeSet = TRUE; + } + } + else { + mediaClockSynth->edgeTime += mediaClockSynth->nsPerAdvance; + IF_LOG_INTERVAL(8000) { + U64 nowNS; + CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &nowNS); + S64 fixedRealDelta = mediaClockSynth->edgeTime - nowNS; + AVB_LOGF_INFO("Fixed/Real TS Delta: %llu", fixedRealDelta); + } + } +} diff --git a/lib/avtp_pipeline/mcs/openavb_mcs.h b/lib/avtp_pipeline/mcs/openavb_mcs.h new file mode 100644 index 00000000..1d448961 --- /dev/null +++ b/lib/avtp_pipeline/mcs/openavb_mcs.h @@ -0,0 +1,42 @@ +/************************************************************************************************************* +Copyright (c) 2016, Harman International Industries, Incorporated +All rights reserved. + +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 COPYRIGHT HOLDERS AND CONTRIBUTORS LISTED "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 COPYRIGHT OWNER OR CONTRIBUTORS LISTED 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. +*************************************************************************************************************/ + +/* +* MODULE SUMMARY : Media clock timestamp synthesis for stored or generated media +*/ + +#ifndef OPENAVB_MCS_H +#define OPENAVB_MCS_H + +typedef struct { + bool firstTimeSet; + U64 nsPerAdvance; + U64 edgeTime; +} mcs_t; + +void openavbMcsInit(mcs_t *mediaClockSynth, U64 nsPerAdvance); +void openavbMcsAdvance(mcs_t *mediaClockSynth); + +#endif diff --git a/lib/avtp_pipeline/platform/Linux/CMakeLists.txt b/lib/avtp_pipeline/platform/Linux/CMakeLists.txt index 047b6a76..7a098293 100644 --- a/lib/avtp_pipeline/platform/Linux/CMakeLists.txt +++ b/lib/avtp_pipeline/platform/Linux/CMakeLists.txt @@ -205,6 +205,7 @@ include_directories( ${AVB_OSAL_DIR}/endpoint ${AVB_OSAL_DIR}/fqtss/qmgr ${AVB_SRC_DIR}/../common + ${AVB_SRC_DIR}/mcs ) # Need include and link directories for GLIB @@ -220,6 +221,7 @@ add_subdirectory ( mediaq ) add_subdirectory ( inih ) add_subdirectory ( rawsock ) add_subdirectory ( qmgr ) +add_subdirectory ( mcs ) if (AVB_FEATURE_ENDPOINT) add_subdirectory ( endpoint ) SET ( SRC_FILES ${SRC_FILES} ${AVB_OSAL_DIR}/openavb_osal_endpoint.c ) -- cgit v1.2.1 From 49ccb517b1c18f2c9d3598423dc3903a5b3c4e0f Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Thu, 16 Jun 2016 18:22:17 -0600 Subject: avtp_pipeline: Low-latency changes. Talker thread CPU pinning. Talker thread uses real time scheduler. Spin waits on wallclock instead of sleeps. Media clock synthesis (instead of PTP wallclock) used in tonegen. Cleaned up version of patch from Ken Carlino. --- lib/avtp_pipeline/avtp/openavb_avtp_time_pub.h | 10 +++++++ .../intf_tonegen/openavb_intf_tonegen.c | 11 ++++++++ .../platform/Linux/openavb_os_services_osal.h | 32 +++++++++++++++++++++- lib/avtp_pipeline/tl/openavb_talker.c | 15 ++++++++-- lib/avtp_pipeline/tl/openavb_tl.c | 4 +++ 5 files changed, 68 insertions(+), 4 deletions(-) diff --git a/lib/avtp_pipeline/avtp/openavb_avtp_time_pub.h b/lib/avtp_pipeline/avtp/openavb_avtp_time_pub.h index e2ab0c2e..f2e24213 100644 --- a/lib/avtp_pipeline/avtp/openavb_avtp_time_pub.h +++ b/lib/avtp_pipeline/avtp/openavb_avtp_time_pub.h @@ -123,6 +123,16 @@ void openavbAvtpTimeSetToTimestamp(avtp_time_t *pAvtpTime, U32 timestamp); */ void openavbAvtpTimeSetToTimespec(avtp_time_t *pAvtpTime, timespec_t* timestamp); +/** Set to nanosecond timestamp. + * + * Set the time in the avtp_time_t structure to the value of U64 + * timeNS. + * + * \param pAvtpTime A pointer to the avtp_time_t structure. + * \param timeNS A U64 timestamp in nanoseconds. + */ +void openavbAvtpTimeSetToTimestampNS(avtp_time_t *pAvtpTime, U64 timeNS); + /** Push a timestamp, for use in Media Clock Recovery (MCR). * \note Not available in all platforms. * diff --git a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c index 3be1cfa6..fd85e206 100644 --- a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c +++ b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c @@ -46,6 +46,7 @@ https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. #include "openavb_map_uncmp_audio_pub.h" #include "openavb_map_aaf_audio_pub.h" #include "openavb_intf_pub.h" +#include "openavb_mcs.h" #define AVB_LOG_COMPONENT "Tone Gen Interface" #include "openavb_log_pub.h" @@ -115,6 +116,9 @@ typedef struct { U32 fvChannels; + // Media clock synthesis for precise timestamps + mcs_t mcs; + } pvt_data_t; #define MSEC_PER_COUNT 250 @@ -552,7 +556,12 @@ bool openavbIntfToneGenTxCB(media_q_t *pMediaQ) pMediaQItem->dataLen = pPubMapUncmpAudioInfo->itemSize; +#if 0 openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); +#else + openavbMcsAdvance(&pPvtData->mcs); + openavbAvtpTimeSetToTimestampNS(pMediaQItem->pAvtpTime, pPvtData->mcs.edgeTime); +#endif openavbMediaQHeadPush(pMediaQ); @@ -635,6 +644,8 @@ extern bool DLL_EXPORT openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_ pPvtData->fv2Enabled = false; pPvtData->fv2 = 0; pPvtData->fvChannels = 0; + + openavbMcsInit(&pPvtData->mcs, 125000UL); } AVB_TRACE_EXIT(AVB_TRACE_INTF); diff --git a/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h b/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h index d9998357..3ea5be9a 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h +++ b/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h @@ -74,7 +74,17 @@ inline static void xSleepUntilNSec(U64 nSec) clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &tmpTime, NULL); } - +#define SPIN_UNTIL_NSEC(nsec) xSpinUntilNSec(nsec) +inline static void xSpinUntilNSec(U64 nSec) +{ + do { + U64 spinNowNS; + CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &spinNowNS); + if (spinNowNS > nSec) + break; + } + while (1); +} #define RAND() random() #define SRAND(seed) srandom(seed) @@ -119,6 +129,26 @@ thread##_type thread##_ThreadData pthread_attr_destroy(&thread_attr); \ } +// KENTEST +#define THREAD_SET_RT_PRIORITY(threadhandle, priority) \ + { \ + struct sched_param param; \ + param.__sched_priority = priority; \ + pthread_setschedparam(threadhandle##_ThreadData.pthread, SCHED_RR, ¶m); \ + } + +// KENTEST - quick hard code pinning to core 2 and 3. +#define THREAD_PIN(threadhandle) \ + { \ + cpu_set_t cpuset; \ + int i1; \ + CPU_ZERO(&cpuset); \ + for (i1 = 2; i1 < 4; i1++) { \ + CPU_SET(i1, &cpuset); \ + } \ + pthread_setaffinity_np(threadhandle##_ThreadData.pthread, sizeof(cpu_set_t), &cpuset); \ + } + #define THREAD_CHECK_ERROR(threadhandle, message, error) \ do { \ error=FALSE; \ diff --git a/lib/avtp_pipeline/tl/openavb_talker.c b/lib/avtp_pipeline/tl/openavb_talker.c index ed623a26..eb80ba50 100644 --- a/lib/avtp_pipeline/tl/openavb_talker.c +++ b/lib/avtp_pipeline/tl/openavb_talker.c @@ -118,8 +118,10 @@ bool talkerStartStream(tl_state_t *pTLState) // setup the initial times U64 nowNS; - CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); - + // KENTEST + //CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); + CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &nowNS); + // Align clock : allows for some performance gain nowNS = ((nowNS + (pTalkerData->intervalNS)) / pTalkerData->intervalNS) * pTalkerData->intervalNS; @@ -200,8 +202,13 @@ static inline bool talkerDoStream(tl_state_t *pTLState) if (!pCfg->tx_blocking_in_intf) { + +#if 0 // sleep until the next interval SLEEP_UNTIL_NSEC(pTalkerData->nextCycleNS); +#else + SPIN_UNTIL_NSEC(pTalkerData->nextCycleNS); +#endif //AVB_DBG_INTERVAL(8000, TRUE); @@ -224,7 +231,9 @@ static inline bool talkerDoStream(tl_state_t *pTLState) bRet = TRUE; } - CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); + // KENTEST + //CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); + CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &nowNS); if (pCfg->report_seconds > 0) { if (nowNS > pTalkerData->nextReportNS) { diff --git a/lib/avtp_pipeline/tl/openavb_tl.c b/lib/avtp_pipeline/tl/openavb_tl.c index 256f7051..b9d8fac0 100755 --- a/lib/avtp_pipeline/tl/openavb_tl.c +++ b/lib/avtp_pipeline/tl/openavb_tl.c @@ -509,6 +509,10 @@ EXTERN_DLL_EXPORT bool openavbTLRun(tl_handle_t handle) pTLState->bRunning = TRUE; if (pTLState->cfg.role == AVB_ROLE_TALKER) { THREAD_CREATE_TALKER(); + + // KENTEST + THREAD_SET_RT_PRIORITY(pTLState->TLThread, 10); + THREAD_PIN(pTLState->TLThread); } else if (pTLState->cfg.role == AVB_ROLE_LISTENER) { THREAD_CREATE_LISTENER(); -- cgit v1.2.1 From fe066f23f00c27f9d9ef2182e48d914a1458b65f Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:57:54 +0200 Subject: avtp_pipeline: Tonegen volume changed to dB. dB is more natural way to specify volume. --- lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c | 9 +++------ lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c index fd85e206..05d6c678 100644 --- a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c +++ b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c @@ -360,11 +360,8 @@ void openavbIntfToneGenCfgCB(media_q_t *pMediaQ, const char *name, const char *v } else if (strcmp(name, "intf_nv_volume") == 0) { - U32 vol = strtol(value, &pEnd, 10); - if (vol > 100) { - vol = 100; - } - pPvtData->volume = (float)vol / 100.0; + S32 vol = strtol(value, &pEnd, 10); + pPvtData->volume = pow(10.0, vol/10.0); } else if (strcmp(name, "intf_nv_fv1") == 0) { @@ -638,7 +635,7 @@ extern bool DLL_EXPORT openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_ pPvtData->audioType = AVB_AUDIO_TYPE_INT; pPvtData->audioEndian = AVB_AUDIO_ENDIAN_BIG; - pPvtData->volume = 50; + pPvtData->volume = 1.0f; pPvtData->fv1Enabled = false; pPvtData->fv1 = 0; pPvtData->fv2Enabled = false; diff --git a/lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini b/lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini index 6112dd4f..0efe3aca 100644 --- a/lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini +++ b/lib/avtp_pipeline/intf_tonegen/tonegen_talker.ini @@ -143,8 +143,8 @@ intf_nv_audio_bit_depth = 16 # intf_nv_audio_channels: The number of channels of the generated audio intf_nv_audio_channels = 2 -# intf_nv_volume: The volume of the tone generation PCM in percentage from 0 - 100 -intf_nv_volume = 100 +# intf_nv_volume: The volune of the tone generation PCM in dB +intf_nv_volume = 0 # Optionally replace the last one or two channels with fixed sample values # intf_nv_fv1: First fixed 32-bit value -- cgit v1.2.1 From 00be3e3a4ffa1d98b4ec373a9758c8ed239fe914 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:57:56 +0200 Subject: avtp_pipeline: Fixed indentation. --- lib/avtp_pipeline/avtp/openavb_avtp.c | 12 ++++++------ lib/avtp_pipeline/tl/openavb_talker.c | 7 ++++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/avtp_pipeline/avtp/openavb_avtp.c b/lib/avtp_pipeline/avtp/openavb_avtp.c index 6cf3ea8b..df03cec1 100644 --- a/lib/avtp_pipeline/avtp/openavb_avtp.c +++ b/lib/avtp_pipeline/avtp/openavb_avtp.c @@ -325,12 +325,12 @@ openavbRC openavbAvtpTx(void *pv, bool bSend, bool txBlockingInIntf) } if (!txBlockingInIntf) { - // Call interface module to read data - pStream->pIntfCB->intf_tx_cb(pStream->pMediaQ); - // Call mapping module to move data into AVTP frame - txCBResult = pStream->pMapCB->map_tx_cb(pStream->pMediaQ, pAvtpFrame, &avtpFrameLen); - - pStream->bytes += avtpFrameLen; + // Call interface module to read data + pStream->pIntfCB->intf_tx_cb(pStream->pMediaQ); + // Call mapping module to move data into AVTP frame + txCBResult = pStream->pMapCB->map_tx_cb(pStream->pMediaQ, pAvtpFrame, &avtpFrameLen); + + pStream->bytes += avtpFrameLen; } else { // Blocking in interface mode. Pull from media queue for tx first diff --git a/lib/avtp_pipeline/tl/openavb_talker.c b/lib/avtp_pipeline/tl/openavb_talker.c index eb80ba50..938d4171 100644 --- a/lib/avtp_pipeline/tl/openavb_talker.c +++ b/lib/avtp_pipeline/tl/openavb_talker.c @@ -215,11 +215,12 @@ static inline bool talkerDoStream(tl_state_t *pTLState) // send the frames for this interval int i; for (i = pTalkerData->wakeFrames; i > 0; i--) { - if (IS_OPENAVB_SUCCESS(openavbAvtpTx(pTalkerData->avtpHandle, i == 1, pCfg->tx_blocking_in_intf))) + if (IS_OPENAVB_SUCCESS(openavbAvtpTx(pTalkerData->avtpHandle, i == 1, pCfg->tx_blocking_in_intf))) pTalkerData->cntFrames++; - else break; - } + else + break; } + } else { // Interface module block option if (IS_OPENAVB_SUCCESS(openavbAvtpTx(pTalkerData->avtpHandle, TRUE, pCfg->tx_blocking_in_intf))) -- cgit v1.2.1 From b2bce0ce424c6c1562aaa615f3dc96c02e861278 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:57:58 +0200 Subject: avtp_pipeline: Added grandmaster2local conversion function. --- lib/common/avb.c | 15 +++++++++++++++ lib/common/avb.h | 1 + 2 files changed, 16 insertions(+) diff --git a/lib/common/avb.c b/lib/common/avb.c index 4cdf56de..3f5dbfce 100644 --- a/lib/common/avb.c +++ b/lib/common/avb.c @@ -217,6 +217,21 @@ bool gptplocaltime(const gPtpTimeData * td, uint64_t* now_local) return true; } +bool gptpmaster2local(const gPtpTimeData *td, const uint64_t master, uint64_t *local) +{ + int64_t delta_8021as; + int64_t delta_local; + + if (!td || !local) + return false; + + delta_8021as = master - td->local_time + td->ml_phoffset; + delta_local = delta_8021as / td->ml_freqoffset; + *local = td->local_time + delta_local; + + return true; +} + /* setters & getters for seventeen22_header */ void avb_set_1722_cd_indicator(seventeen22_header *h1722, uint64_t cd_indicator) { diff --git a/lib/common/avb.h b/lib/common/avb.h index 55ffc195..e5b9f8b6 100644 --- a/lib/common/avb.h +++ b/lib/common/avb.h @@ -120,6 +120,7 @@ int gptpdeinit(int *shm_fd, char **shm_map); int gptpgetdata(char *shm_mmap, gPtpTimeData *td); int gptpscaling(char *shm_mmap, gPtpTimeData *td); bool gptplocaltime(const gPtpTimeData * td, uint64_t* now_local); +bool gptpmaster2local(const gPtpTimeData *td, const uint64_t master, uint64_t *local); void avb_set_1722_cd_indicator(seventeen22_header *h1722, uint64_t cd_indicator); uint64_t avb_get_1722_cd_indicator(seventeen22_header *h1722); -- cgit v1.2.1 From abb13ee08bdd6a72d9bdec838dce1da1ad52ad04 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:58:00 +0200 Subject: avtp_pipeline: Launchtime added to openavbRawsockTxFrameReady. --- lib/avtp_pipeline/avtp/openavb_avtp.c | 2 +- lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.c | 4 ++-- lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.h | 2 +- lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.c | 6 +++++- lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.h | 2 +- lib/avtp_pipeline/platform/Linux/rawsock/rawsock_tx.c | 2 +- lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.c | 7 ++++++- lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.h | 2 +- lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.c | 6 +++++- lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.h | 2 +- lib/avtp_pipeline/rawsock/openavb_rawsock.h | 3 ++- lib/avtp_pipeline/rawsock/rawsock_impl.c | 6 +++--- lib/avtp_pipeline/rawsock/rawsock_impl.h | 2 +- 13 files changed, 30 insertions(+), 16 deletions(-) diff --git a/lib/avtp_pipeline/avtp/openavb_avtp.c b/lib/avtp_pipeline/avtp/openavb_avtp.c index df03cec1..6a3fbe02 100644 --- a/lib/avtp_pipeline/avtp/openavb_avtp.c +++ b/lib/avtp_pipeline/avtp/openavb_avtp.c @@ -353,7 +353,7 @@ openavbRC openavbAvtpTx(void *pv, bool bSend, bool txBlockingInIntf) // Increment the sequence number now that we are sure this is a good packet. pStream->avtp_sequence_num++; // Mark the frame "ready to send". - openavbRawsockTxFrameReady(pStream->rawsock, pStream->pBuf, avtpFrameLen + pStream->ethHdrLen); + openavbRawsockTxFrameReady(pStream->rawsock, pStream->pBuf, avtpFrameLen + pStream->ethHdrLen, 0); // Send if requested if (bSend) openavbRawsockSend(pStream->rawsock); diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.c b/lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.c index cbb6ce80..162b2e07 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.c +++ b/lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.c @@ -192,7 +192,7 @@ bool igbRawsockRelTxFrame(void *pvRawsock, U8 *pBuffer) } // Release a TX frame, and mark it as ready to send -bool igbRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len) +bool igbRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec) { AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL); igb_rawsock_t *rawsock = (igb_rawsock_t*)pvRawsock; @@ -207,7 +207,7 @@ bool igbRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len) rawsock->tx_packet->len = len; #if IGB_LAUNCHTIME_ENABLED - gptplocaltime(&gPtpTD, &rawsock->tx_packet->attime); + gptpmaster2local(&gPtpTD, timeNsec, &rawsock->tx_packet->attime); #endif err = igb_xmit(rawsock->igb_dev, rawsock->queue, rawsock->tx_packet); diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.h b/lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.h index efea97a9..e542e1c1 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.h +++ b/lib/avtp_pipeline/platform/Linux/rawsock/igb_rawsock.h @@ -54,7 +54,7 @@ U8 *igbRawsockGetTxFrame(void *pvRawsock, bool blocking, unsigned int *len); bool igbRawsockRelTxFrame(void *pvRawsock, U8 *pBuffer); -bool igbRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len); +bool igbRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec); int igbRawsockSend(void *pvRawsock); diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.c b/lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.c index 3a4a1046..1f87c043 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.c +++ b/lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.c @@ -117,11 +117,15 @@ U8 *pcapRawsockGetTxFrame(void *pvRawsock, bool blocking, unsigned int *len) return false; } -bool pcapRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len) +bool pcapRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec) { pcap_rawsock_t *rawsock = (pcap_rawsock_t*)pvRawsock; int ret = -1; + if (timeNsec) { + IF_LOG_INTERVAL(1000) AVB_LOG_WARNING("launch time is unsupported in pcap_rawsock"); + } + if (rawsock) { ret = pcap_sendpacket(rawsock->handle, pBuffer, len); if (ret == -1) { diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.h b/lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.h index ed8e7943..9e5fe12e 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.h +++ b/lib/avtp_pipeline/platform/Linux/rawsock/pcap_rawsock.h @@ -46,7 +46,7 @@ void pcapRawsockClose(void *pvRawsock); U8 *pcapRawsockGetTxFrame(void *pvRawsock, bool blocking, unsigned int *len); -bool pcapRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len); +bool pcapRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec); U8 *pcapRawsockGetRxFrame(void *pvRawsock, U32 timeout, unsigned int *offset, unsigned int *len); diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/rawsock_tx.c b/lib/avtp_pipeline/platform/Linux/rawsock/rawsock_tx.c index e01b5998..4db5b6e3 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/rawsock_tx.c +++ b/lib/avtp_pipeline/platform/Linux/rawsock/rawsock_tx.c @@ -191,7 +191,7 @@ int main(int argc, char* argv[]) txlen = hdrlen + 3; } - openavbRawsockTxFrameReady(rs, pBuf, txlen); + openavbRawsockTxFrameReady(rs, pBuf, txlen, 0); packetCnt++; diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.c b/lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.c index 71c7a3af..de03d4a6 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.c +++ b/lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.c @@ -324,7 +324,7 @@ bool ringRawsockRelTxFrame(void *pvRawsock, U8 *pBuffer) } // Release a TX frame, and mark it as ready to send -bool ringRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len) +bool ringRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec) { AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL); ring_rawsock_t *rawsock = (ring_rawsock_t*)pvRawsock; @@ -335,6 +335,11 @@ bool ringRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len) return FALSE; } + if (timeNsec) { + IF_LOG_INTERVAL(1000) AVB_LOG_WARNING("launch time is unsupported in ring_rawsock"); + } + + volatile struct tpacket2_hdr *pHdr = (struct tpacket2_hdr*)(pBuffer - rawsock->bufHdrSize); AVB_LOGF_VERBOSE("pBuffer=%p, pHdr=%p szFrame=%d, len=%d", pBuffer, pHdr, rawsock->base.frameSize, len); diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.h b/lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.h index 92117f84..d95e94e9 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.h +++ b/lib/avtp_pipeline/platform/Linux/rawsock/ring_rawsock.h @@ -88,7 +88,7 @@ U8* ringRawsockGetTxFrame(void *pvRawsock, bool blocking, unsigned int *len); bool ringRawsockRelTxFrame(void *pvRawsock, U8 *pBuffer); // Release a TX frame, and mark it as ready to send -bool ringRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len); +bool ringRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec); // Send all packets that are ready (i.e. tell kernel to send them) int ringRawsockSend(void *pvRawsock); diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.c b/lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.c index 385d57e6..644a6011 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.c +++ b/lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.c @@ -305,7 +305,7 @@ bool simpleRawsockTxSetHdr(void *pvRawsock, hdr_info_t *pHdr) } // Release a TX frame, and send it -bool simpleRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len) +bool simpleRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec) { AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL); simple_rawsock_t *rawsock = (simple_rawsock_t*)pvRawsock; @@ -316,6 +316,10 @@ bool simpleRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len) return FALSE; } + if (timeNsec) { + IF_LOG_INTERVAL(1000) AVB_LOG_WARNING("launch time is unsupported in simple_rawsock"); + } + int flags = MSG_DONTWAIT; send(rawsock->sock, pBuffer, len, flags); diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.h b/lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.h index db0ef1f3..48b9003b 100644 --- a/lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.h +++ b/lib/avtp_pipeline/platform/Linux/rawsock/simple_rawsock.h @@ -68,7 +68,7 @@ bool simpleRawsockTxSetMark(void *pvRawsock, int mark); bool simpleRawsockTxSetHdr(void *pvRawsock, hdr_info_t *pHdr); // Release a TX frame, and mark it as ready to send -bool simpleRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len); +bool simpleRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec); // Get a RX frame U8* simpleRawsockGetRxFrame(void *pvRawsock, U32 timeout, unsigned int *offset, unsigned int *len); diff --git a/lib/avtp_pipeline/rawsock/openavb_rawsock.h b/lib/avtp_pipeline/rawsock/openavb_rawsock.h index 04671450..156e3711 100644 --- a/lib/avtp_pipeline/rawsock/openavb_rawsock.h +++ b/lib/avtp_pipeline/rawsock/openavb_rawsock.h @@ -143,7 +143,8 @@ bool openavbRawsockRelTxFrame(void *rawsock, U8 *pBuffer); // Submit a frame and mark it "ready to send" bool openavbRawsockTxFrameReady(void *rawsock, // rawsock handle U8 *pFrame, // pointer to frame buffer - U32 len); // length of frame to send + U32 len, // length of frame to send + U64 timeNsec); // launch time (in gPTP wall clock) // Send all packets that are marked "ready to send". // Returns count of bytes in sent frames - or < 0 for error. diff --git a/lib/avtp_pipeline/rawsock/rawsock_impl.c b/lib/avtp_pipeline/rawsock/rawsock_impl.c index c351f47c..c9a4df53 100644 --- a/lib/avtp_pipeline/rawsock/rawsock_impl.c +++ b/lib/avtp_pipeline/rawsock/rawsock_impl.c @@ -43,7 +43,7 @@ bool baseRawsockRxAVTPSubtype(void *rawsock, U8 subtype) { return false; } bool baseRawsockTxSetMark(void *rawsock, int prio) { return false; } U8 *baseRawsockGetTxFrame(void *rawsock, bool blocking, U32 *size) { return NULL; } bool baseRawsockRelTxFrame(void *rawsock, U8 *pBuffer) { return false; } -bool baseRawsockTxFrameReady(void *rawsock, U8 *pFrame, U32 len) { return false; } +bool baseRawsockTxFrameReady(void *rawsock, U8 *pFrame, U32 len, U64 timeNsec) { return false; } int baseRawsockSend(void *rawsock) { return -1; } int baseRawsockTxBufLevel(void *rawsock) { return -1; } int baseRawsockRxBufLevel(void *rawsock) { return -1; } @@ -273,11 +273,11 @@ bool openavbRawsockRelTxFrame(void *pvRawsock, U8 *pBuffer) return ret; } -bool openavbRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len) +bool openavbRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec) { AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL); - bool ret = ((base_rawsock_t*)pvRawsock)->cb.txFrameReady(pvRawsock, pBuffer, len); + bool ret = ((base_rawsock_t*)pvRawsock)->cb.txFrameReady(pvRawsock, pBuffer, len, timeNsec); AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL); return ret; diff --git a/lib/avtp_pipeline/rawsock/rawsock_impl.h b/lib/avtp_pipeline/rawsock/rawsock_impl.h index b1d6cf7b..7269b9f0 100644 --- a/lib/avtp_pipeline/rawsock/rawsock_impl.h +++ b/lib/avtp_pipeline/rawsock/rawsock_impl.h @@ -75,7 +75,7 @@ typedef struct { bool (*txSetMark)(void* rawsock, int prio); U8* (*getTxFrame)(void* rawsock, bool blocking, U32* size); bool (*relTxFrame)(void* rawsock, U8* pBuffer); - bool (*txFrameReady)(void* rawsock, U8* pFrame, U32 len); + bool (*txFrameReady)(void* rawsock, U8* pFrame, U32 len, U64 timeNsec); int (*send)(void* rawsock); int (*txBufLevel)(void* rawsock); int (*rxBufLevel)(void* rawsock); -- cgit v1.2.1 From 05b488c77391b75ff1581b31c352fb6ac166de57 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:58:05 +0200 Subject: avtp_pipeline: Makefiles modifications for launchtime feature. Necessary build environment changes added. --- lib/avtp_pipeline/avtp_pipeline.mk | 2 ++ lib/avtp_pipeline/platform/Linux/CMakeLists.txt | 8 ++++++++ lib/avtp_pipeline/platform/x86_i210/openavb_ether_hal.h | 2 -- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/avtp_pipeline/avtp_pipeline.mk b/lib/avtp_pipeline/avtp_pipeline.mk index b0f4ede0..a4d1c8d5 100644 --- a/lib/avtp_pipeline/avtp_pipeline.mk +++ b/lib/avtp_pipeline/avtp_pipeline.mk @@ -1,4 +1,5 @@ AVB_FEATURE_ENDPOINT ?= 1 +IGB_LAUNCHTIME_ENABLED ?= 0 .PHONY: all clean @@ -18,4 +19,5 @@ build/Makefile: cd build && \ cmake -DCMAKE_TOOLCHAIN_FILE=../platform/Linux/x86_i210_linux.cmake \ -DAVB_FEATURE_ENDPOINT=$(AVB_FEATURE_ENDPOINT) \ + -DIGB_LAUNCHTIME_ENABLED=$(IGB_LAUNCHTIME_ENABLED) \ .. diff --git a/lib/avtp_pipeline/platform/Linux/CMakeLists.txt b/lib/avtp_pipeline/platform/Linux/CMakeLists.txt index 7a098293..5a9c2f82 100644 --- a/lib/avtp_pipeline/platform/Linux/CMakeLists.txt +++ b/lib/avtp_pipeline/platform/Linux/CMakeLists.txt @@ -93,6 +93,14 @@ if (NOT DEFINED AVB_FEATURE_ENDPOINT) set ( AVB_FEATURE_ENDPOINT 0 ) endif () +# Default launchtime feature +if (NOT DEFINED IGB_LAUNCHTIME_ENABLED) + set ( IGB_LAUNCHTIME_ENABLED 0 ) +else () + MESSAGE ( "-- IGB launch time enabled" ) +endif () +set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DIGB_LAUNCHTIME_ENABLED=${IGB_LAUNCHTIME_ENABLED}" ) + # Export feature flags for sub-builds if (AVB_FEATURE_FQTSS) diff --git a/lib/avtp_pipeline/platform/x86_i210/openavb_ether_hal.h b/lib/avtp_pipeline/platform/x86_i210/openavb_ether_hal.h index 2ccc9db8..b152a37b 100644 --- a/lib/avtp_pipeline/platform/x86_i210/openavb_ether_hal.h +++ b/lib/avtp_pipeline/platform/x86_i210/openavb_ether_hal.h @@ -41,8 +41,6 @@ https://github.com/benhoyt/inih/commit/74d2ca064fb293bc60a77b0bd068075b293cf175. // how many pages to alloc for tx buffers (2 frames fit in one page) #define IGB_PAGES 20 -#define IGB_LAUNCHTIME_ENABLED 0 - device_t *igbAcquireDevice(); void igbReleaseDevice(device_t *igb_dev); -- cgit v1.2.1 From 8d30e1e277e415c86d1460914b2b2733d8f661e9 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:58:08 +0200 Subject: avtp_pipeline: Talker and avtp make use of launchtime. --- lib/avtp_pipeline/avtp/openavb_avtp.c | 24 +++++++++++++++++++++++- lib/avtp_pipeline/tl/openavb_talker.c | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/avtp_pipeline/avtp/openavb_avtp.c b/lib/avtp_pipeline/avtp/openavb_avtp.c index 6a3fbe02..055ed726 100644 --- a/lib/avtp_pipeline/avtp/openavb_avtp.c +++ b/lib/avtp_pipeline/avtp/openavb_avtp.c @@ -324,15 +324,37 @@ openavbRC openavbAvtpTx(void *pv, bool bSend, bool txBlockingInIntf) AVB_RC_LOG_TRACE_RET(rc, AVB_TRACE_AVTP_DETAIL); } + U64 timeNsec = 0; + if (!txBlockingInIntf) { // Call interface module to read data pStream->pIntfCB->intf_tx_cb(pStream->pMediaQ); + +#if IGB_LAUNCHTIME_ENABLED + // lets get unmodified timestamp from mediaq item about to be sent by mapping + media_q_item_t* item = openavbMediaQTailLock(pStream->pMediaQ, true); + if (item) { + timeNsec = item->pAvtpTime->timeNsec; + openavbMediaQTailUnlock(pStream->pMediaQ); + } +#endif + // Call mapping module to move data into AVTP frame txCBResult = pStream->pMapCB->map_tx_cb(pStream->pMediaQ, pAvtpFrame, &avtpFrameLen); pStream->bytes += avtpFrameLen; } else { + +#if IGB_LAUNCHTIME_ENABLED + // lets get unmodified timestamp from mediaq item about to be sent by mapping + media_q_item_t* item = openavbMediaQTailLock(pStream->pMediaQ, true); + if (item) { + timeNsec = item->pAvtpTime->timeNsec; + openavbMediaQTailUnlock(pStream->pMediaQ); + } +#endif + // Blocking in interface mode. Pull from media queue for tx first if ((txCBResult = pStream->pMapCB->map_tx_cb(pStream->pMediaQ, pAvtpFrame, &avtpFrameLen)) == TX_CB_RET_PACKET_NOT_READY) { // Call interface module to read data @@ -353,7 +375,7 @@ openavbRC openavbAvtpTx(void *pv, bool bSend, bool txBlockingInIntf) // Increment the sequence number now that we are sure this is a good packet. pStream->avtp_sequence_num++; // Mark the frame "ready to send". - openavbRawsockTxFrameReady(pStream->rawsock, pStream->pBuf, avtpFrameLen + pStream->ethHdrLen, 0); + openavbRawsockTxFrameReady(pStream->rawsock, pStream->pBuf, avtpFrameLen + pStream->ethHdrLen, timeNsec); // Send if requested if (bSend) openavbRawsockSend(pStream->rawsock); diff --git a/lib/avtp_pipeline/tl/openavb_talker.c b/lib/avtp_pipeline/tl/openavb_talker.c index 938d4171..dad0ebf0 100644 --- a/lib/avtp_pipeline/tl/openavb_talker.c +++ b/lib/avtp_pipeline/tl/openavb_talker.c @@ -203,11 +203,13 @@ static inline bool talkerDoStream(tl_state_t *pTLState) if (!pCfg->tx_blocking_in_intf) { +#if !IGB_LAUNCHTIME_ENABLED #if 0 // sleep until the next interval SLEEP_UNTIL_NSEC(pTalkerData->nextCycleNS); #else SPIN_UNTIL_NSEC(pTalkerData->nextCycleNS); +#endif #endif //AVB_DBG_INTERVAL(8000, TRUE); -- cgit v1.2.1 From 6c52083027b89c27cb5823fce1f0c1c69aa58c6c Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 11 Jul 2016 15:58:10 +0200 Subject: avtp_pipeline: Launchtime in echo talker used. --- lib/avtp_pipeline/intf_echo/openavb_intf_echo.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/avtp_pipeline/intf_echo/openavb_intf_echo.c b/lib/avtp_pipeline/intf_echo/openavb_intf_echo.c index 4bc2f6ae..34870f9f 100755 --- a/lib/avtp_pipeline/intf_echo/openavb_intf_echo.c +++ b/lib/avtp_pipeline/intf_echo/openavb_intf_echo.c @@ -77,6 +77,9 @@ typedef struct { ///////////// // When increment is enable this is the counter U32 Counter; +#if IGB_LAUNCHTIME_ENABLED + avtp_time_t walltime; +#endif } pvt_data_t; @@ -168,6 +171,10 @@ void openavbIntfEchoTxInitCB(media_q_t *pMediaQ) } pPvtData->Counter = 0; +#if IGB_LAUNCHTIME_ENABLED + openavbAvtpTimeSetToWallTime(&pPvtData->walltime); + AVB_LOG_INFO(__func__); +#endif } AVB_TRACE_EXIT(AVB_TRACE_INTF); @@ -209,7 +216,12 @@ bool openavbIntfEchoTxCB(media_q_t *pMediaQ) printf("%s\n\r", (char *)pMediaQItem->pPubData); } +#if IGB_LAUNCHTIME_ENABLED + openavbAvtpTimeAddUSec(&pPvtData->walltime, 125); + *pMediaQItem->pAvtpTime = pPvtData->walltime; +#else openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); +#endif openavbMediaQHeadPush(pMediaQ); AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); return TRUE; -- cgit v1.2.1 From e763fae0603e2fc5d097fc9d568676ba47087fda Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Tue, 13 Sep 2016 10:23:04 +0200 Subject: avtp_pipeline: Do not print Fixed/Real TS Delta in launchtime mode. --- lib/avtp_pipeline/mcs/openavb_mcs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/avtp_pipeline/mcs/openavb_mcs.c b/lib/avtp_pipeline/mcs/openavb_mcs.c index ba3b12fe..d58d46d8 100644 --- a/lib/avtp_pipeline/mcs/openavb_mcs.c +++ b/lib/avtp_pipeline/mcs/openavb_mcs.c @@ -49,11 +49,13 @@ void openavbMcsAdvance(mcs_t *mediaClockSynth) } else { mediaClockSynth->edgeTime += mediaClockSynth->nsPerAdvance; +#if !IGB_LAUNCHTIME_ENABLED IF_LOG_INTERVAL(8000) { U64 nowNS; CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &nowNS); S64 fixedRealDelta = mediaClockSynth->edgeTime - nowNS; AVB_LOGF_INFO("Fixed/Real TS Delta: %llu", fixedRealDelta); } +#endif } } -- cgit v1.2.1 From fd04d96ac0e8003f566fa50f9ad52dbd208d4503 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Thu, 14 Jul 2016 12:24:59 +0200 Subject: avtp_pipeline: Fixed timestamping mode added. Details: To enable it set fixed_timestamp = 1 in ini file. Interface that wish to support fixed timestamping must implement intf_fixed_timestamp_enable callback. Change-Id: Iba3455957fcd8bdbe522a9831989a162b45aaedb --- lib/avtp_pipeline/include/openavb_intf_pub.h | 24 ++++++++++ .../platform/Linux/tl/openavb_tl_osal.c | 9 ++++ lib/avtp_pipeline/tl/openavb_talker.c | 51 +++++++++++++--------- lib/avtp_pipeline/tl/openavb_tl.c | 1 + lib/avtp_pipeline/tl/openavb_tl_pub.h | 2 + 5 files changed, 67 insertions(+), 20 deletions(-) diff --git a/lib/avtp_pipeline/include/openavb_intf_pub.h b/lib/avtp_pipeline/include/openavb_intf_pub.h index fdd00a11..5b57c033 100755 --- a/lib/avtp_pipeline/include/openavb_intf_pub.h +++ b/lib/avtp_pipeline/include/openavb_intf_pub.h @@ -170,6 +170,28 @@ typedef void (*openavb_intf_gen_end_cb_t)(media_q_t *pMediaQ); */ typedef unsigned int (*openavb_intf_get_src_bitrate_t)(media_q_t *pMediaQ); +/** Enable fixed timestamping in interface. + * + * Everytime interface needs to set media_q_item_t.pAvtpTime it calls openavbAvtpTimeSetToWallTime() to set. + * + * When fixed timestamping is enabled, interface only calls openavbAvtpTimeSetToWallTime() once + * for first media_q_item, then for next items it just adds fixed delay calculated + * from transmitInterval and batchFactor. + * + * If transmitInterval = 8000 and batchFactor = 1 then 125 us will be added. + * If batchFactor is 4, 4 items will have the same AVTP time set and + * then 125 * 4 = 500 us will be added to timestamp. + * + * \param pMediaQ A pointer to media queue for this stream + * \param enable true to enable, false to disable + * \param transmitInterval The transmit interval (in frames per second) + * \param batchFactor Number of intervals to handle at once + * + * \note This callback is optional, does not need to be implemented in the + * interface module. + */ +typedef void (*openavb_intf_enable_fixed_timestamp)(media_q_t *pMediaQ, bool enable, U32 transmitInterval, U32 batchFactor); + /** Interface callbacks structure. */ typedef struct { @@ -197,6 +219,8 @@ typedef struct { void * intf_host_cb_list; /// Source bit rate callback. openavb_intf_get_src_bitrate_t intf_get_src_bitrate_cb; + /// Enable fixed timestamp callback + openavb_intf_enable_fixed_timestamp intf_enable_fixed_timestamp; } openavb_intf_cb_t; /** Main initialization entry point into the interface module. diff --git a/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c b/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c index d10ab6b8..eeccb8f0 100644 --- a/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c +++ b/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c @@ -312,6 +312,15 @@ static int openavbTLCfgCallback(void *user, const char *tlSection, const char *n valOK = TRUE; } } + else if (MATCH(name, "fixed_timestamp")) { + errno = 0; + long tmp; + tmp = strtol(value, &pEnd, 0); + if (*pEnd == '\0' && errno == 0) { + pCfg->fixed_timestamp = tmp; + valOK = TRUE; + } + } else if (MATCH(name, "map_lib")) { if (pTLState->mapLib.libName) diff --git a/lib/avtp_pipeline/tl/openavb_talker.c b/lib/avtp_pipeline/tl/openavb_talker.c index dad0ebf0..81b69d4c 100644 --- a/lib/avtp_pipeline/tl/openavb_talker.c +++ b/lib/avtp_pipeline/tl/openavb_talker.c @@ -71,6 +71,18 @@ bool talkerStartStream(tl_state_t *pTLState) if (pCfg->max_transmit_deficit_usec == 0) pCfg->max_transmit_deficit_usec = 50000; + U32 transmitInterval = pTalkerData->classRate; + if (pCfg->map_cb.map_transmit_interval_cb(pTLState->pMediaQ)) { + // Override the class observation interval with the one provided by the mapping module. + transmitInterval = pCfg->map_cb.map_transmit_interval_cb(pTLState->pMediaQ); + } + + if (pCfg->intf_cb.intf_enable_fixed_timestamp) { + pCfg->intf_cb.intf_enable_fixed_timestamp(pTLState->pMediaQ, pCfg->fixed_timestamp, transmitInterval, pCfg->batch_factor); + } else if (pCfg->fixed_timestamp) { + AVB_LOG_ERROR("Fixed timestamp enabled but interface doesn't support it"); + } + openavbRC rc = openavbAvtpTxInit(pTLState->pMediaQ, &pCfg->map_cb, &pCfg->intf_cb, @@ -91,13 +103,8 @@ bool talkerStartStream(tl_state_t *pTLState) avtp_stream_t *pStream = (avtp_stream_t *)(pTalkerData->avtpHandle); - if (!pStream->pMapCB->map_transmit_interval_cb(pTLState->pMediaQ)) { - pTalkerData->wakeRate = pTalkerData->classRate / pCfg->batch_factor; - } - else { - // Override the class observation interval with the one provided by the mapping module. - pTalkerData->wakeRate = pStream->pMapCB->map_transmit_interval_cb(pTLState->pMediaQ) / pCfg->batch_factor; - } + pTalkerData->wakeRate = transmitInterval / pCfg->batch_factor; + pTalkerData->sleepUsec = MICROSECONDS_PER_SECOND / pTalkerData->wakeRate; pTalkerData->intervalNS = NANOSECONDS_PER_SECOND / pTalkerData->wakeRate; @@ -118,9 +125,12 @@ bool talkerStartStream(tl_state_t *pTLState) // setup the initial times U64 nowNS; - // KENTEST - //CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); - CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &nowNS); + + if (!pCfg->fixed_timestamp) { + CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); + } else { + CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &nowNS); + } // Align clock : allows for some performance gain nowNS = ((nowNS + (pTalkerData->intervalNS)) / pTalkerData->intervalNS) * pTalkerData->intervalNS; @@ -202,15 +212,14 @@ static inline bool talkerDoStream(tl_state_t *pTLState) if (!pCfg->tx_blocking_in_intf) { - + if (!pCfg->fixed_timestamp) { + // sleep until the next interval + SLEEP_UNTIL_NSEC(pTalkerData->nextCycleNS); + } else { #if !IGB_LAUNCHTIME_ENABLED -#if 0 - // sleep until the next interval - SLEEP_UNTIL_NSEC(pTalkerData->nextCycleNS); -#else - SPIN_UNTIL_NSEC(pTalkerData->nextCycleNS); -#endif + SPIN_UNTIL_NSEC(pTalkerData->nextCycleNS); #endif + } //AVB_DBG_INTERVAL(8000, TRUE); @@ -234,9 +243,11 @@ static inline bool talkerDoStream(tl_state_t *pTLState) bRet = TRUE; } - // KENTEST - //CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); - CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &nowNS); + if (!pCfg->fixed_timestamp) { + CLOCK_GETTIME64(OPENAVB_TIMER_CLOCK, &nowNS); + } else { + CLOCK_GETTIME64(OPENAVB_CLOCK_WALLTIME, &nowNS); + } if (pCfg->report_seconds > 0) { if (nowNS > pTalkerData->nextReportNS) { diff --git a/lib/avtp_pipeline/tl/openavb_tl.c b/lib/avtp_pipeline/tl/openavb_tl.c index b9d8fac0..d266fb88 100755 --- a/lib/avtp_pipeline/tl/openavb_tl.c +++ b/lib/avtp_pipeline/tl/openavb_tl.c @@ -396,6 +396,7 @@ EXTERN_DLL_EXPORT void openavbTLInitCfg(openavb_tl_cfg_t *pCfg) pCfg->pMapInitFn = NULL; pCfg->pIntfInitFn = NULL; pCfg->vlan_id = VLAN_NULL; + pCfg->fixed_timestamp = 0; AVB_TRACE_EXIT(AVB_TRACE_TL); } diff --git a/lib/avtp_pipeline/tl/openavb_tl_pub.h b/lib/avtp_pipeline/tl/openavb_tl_pub.h index 6e46494b..54185b09 100755 --- a/lib/avtp_pipeline/tl/openavb_tl_pub.h +++ b/lib/avtp_pipeline/tl/openavb_tl_pub.h @@ -129,6 +129,8 @@ typedef struct { U16 vlan_id; /// When set incoming packets will trigger a signal to the stream task to wakeup. bool rx_signal_mode; + /// + U32 fixed_timestamp; /// Initialization function in mapper openavb_map_initialize_fn_t pMapInitFn; -- cgit v1.2.1 From 4dd0dc3f40ac3bc2e47e699f4a85adcd09e88396 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Tue, 13 Sep 2016 10:23:15 +0200 Subject: avtp_pipeline: echo intf using fixed timestamp settings. --- lib/avtp_pipeline/intf_echo/openavb_intf_echo.c | 43 ++++++++++++++++++------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/lib/avtp_pipeline/intf_echo/openavb_intf_echo.c b/lib/avtp_pipeline/intf_echo/openavb_intf_echo.c index 34870f9f..bee8aef3 100755 --- a/lib/avtp_pipeline/intf_echo/openavb_intf_echo.c +++ b/lib/avtp_pipeline/intf_echo/openavb_intf_echo.c @@ -77,9 +77,10 @@ typedef struct { ///////////// // When increment is enable this is the counter U32 Counter; -#if IGB_LAUNCHTIME_ENABLED + + bool fixedTimestampEnabled; + U32 tsIncrement; avtp_time_t walltime; -#endif } pvt_data_t; @@ -171,10 +172,9 @@ void openavbIntfEchoTxInitCB(media_q_t *pMediaQ) } pPvtData->Counter = 0; -#if IGB_LAUNCHTIME_ENABLED - openavbAvtpTimeSetToWallTime(&pPvtData->walltime); - AVB_LOG_INFO(__func__); -#endif + + if (pPvtData->fixedTimestampEnabled) + openavbAvtpTimeSetToWallTime(&pPvtData->walltime); } AVB_TRACE_EXIT(AVB_TRACE_INTF); @@ -216,12 +216,12 @@ bool openavbIntfEchoTxCB(media_q_t *pMediaQ) printf("%s\n\r", (char *)pMediaQItem->pPubData); } -#if IGB_LAUNCHTIME_ENABLED - openavbAvtpTimeAddUSec(&pPvtData->walltime, 125); + if (pPvtData->fixedTimestampEnabled) { + openavbAvtpTimeAddUSec(&pPvtData->walltime, pPvtData->tsIncrement); *pMediaQItem->pAvtpTime = pPvtData->walltime; -#else - openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); -#endif + } else { + openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); + } openavbMediaQHeadPush(pMediaQ); AVB_TRACE_EXIT(AVB_TRACE_INTF_DETAIL); return TRUE; @@ -323,6 +323,25 @@ void openavbIntfEchoGenEndCB(media_q_t *pMediaQ) AVB_TRACE_EXIT(AVB_TRACE_INTF); } +void openavbIntfEchoEnableFixedTimestamp(media_q_t *pMediaQ, bool enabled, U32 transmitInterval, U32 batchFactor) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + if (pMediaQ && pMediaQ->pPvtIntfInfo) { + pvt_data_t *pPvtData = (pvt_data_t *)pMediaQ->pPvtIntfInfo; + + pPvtData->fixedTimestampEnabled = enabled; + if (pPvtData->fixedTimestampEnabled) { + pPvtData->tsIncrement = NANOSECONDS_PER_SECOND/transmitInterval; + } + + if (batchFactor != 1) { + AVB_LOGF_WARNING("batchFactor of %d ignored (must be 1)", batchFactor); + } + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + // Main initialization entry point into the interface module extern bool DLL_EXPORT openavbIntfEchoInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) { @@ -346,6 +365,7 @@ extern bool DLL_EXPORT openavbIntfEchoInitialize(media_q_t *pMediaQ, openavb_int pIntfCB->intf_rx_cb = openavbIntfEchoRxCB; pIntfCB->intf_end_cb = openavbIntfEchoEndCB; pIntfCB->intf_gen_end_cb = openavbIntfEchoGenEndCB; + pIntfCB->intf_enable_fixed_timestamp = openavbIntfEchoEnableFixedTimestamp; pPvtData->pEchoString = NULL; pPvtData->echoStringRepeat = 1; @@ -354,6 +374,7 @@ extern bool DLL_EXPORT openavbIntfEchoInitialize(media_q_t *pMediaQ, openavb_int pPvtData->txLocalEcho = FALSE; pPvtData->noNewline = FALSE; pPvtData->ignoreTimestamp = FALSE; + pPvtData->fixedTimestampEnabled = FALSE; } AVB_TRACE_EXIT(AVB_TRACE_INTF); -- cgit v1.2.1 From fdd6c69f4e8fef8cd9941c591605570c50a99e6a Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Tue, 13 Sep 2016 10:23:25 +0200 Subject: avtp_pipeline: tonegen uses fixed timestamp settings. --- .../intf_tonegen/openavb_intf_tonegen.c | 37 ++++- .../intf_tonegen/tonegen_talker_lowlatency.ini | 162 +++++++++++++++++++++ 2 files changed, 192 insertions(+), 7 deletions(-) create mode 100644 lib/avtp_pipeline/intf_tonegen/tonegen_talker_lowlatency.ini diff --git a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c index 05d6c678..29aa8be3 100644 --- a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c +++ b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c @@ -119,6 +119,8 @@ typedef struct { // Media clock synthesis for precise timestamps mcs_t mcs; + bool fixedTimestampEnabled; + } pvt_data_t; #define MSEC_PER_COUNT 250 @@ -553,12 +555,12 @@ bool openavbIntfToneGenTxCB(media_q_t *pMediaQ) pMediaQItem->dataLen = pPubMapUncmpAudioInfo->itemSize; -#if 0 - openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); -#else - openavbMcsAdvance(&pPvtData->mcs); - openavbAvtpTimeSetToTimestampNS(pMediaQItem->pAvtpTime, pPvtData->mcs.edgeTime); -#endif + if (!pPvtData->fixedTimestampEnabled) { + openavbAvtpTimeSetToWallTime(pMediaQItem->pAvtpTime); + } else { + openavbMcsAdvance(&pPvtData->mcs); + openavbAvtpTimeSetToTimestampNS(pMediaQItem->pAvtpTime, pPvtData->mcs.edgeTime); + } openavbMediaQHeadPush(pMediaQ); @@ -605,6 +607,26 @@ void openavbIntfToneGenGenEndCB(media_q_t *pMediaQ) AVB_TRACE_EXIT(AVB_TRACE_INTF); } +void openavbIntfToneGenEnableFixedTimestamp(media_q_t *pMediaQ, bool enabled, U32 transmitInterval, U32 batchFactor) +{ + AVB_TRACE_ENTRY(AVB_TRACE_INTF); + if (pMediaQ && pMediaQ->pPvtIntfInfo) { + pvt_data_t *pPvtData = (pvt_data_t *)pMediaQ->pPvtIntfInfo; + + pPvtData->fixedTimestampEnabled = enabled; + if (pPvtData->fixedTimestampEnabled) { + openavbMcsInit(&pPvtData->mcs, NANOSECONDS_PER_SECOND/transmitInterval); + AVB_LOG_INFO("Fixed timestamping enabled"); + } + + if (batchFactor != 1) { + AVB_LOGF_WARNING("batchFactor of %d ignored (must be 1)", batchFactor); + } + } + + AVB_TRACE_EXIT(AVB_TRACE_INTF); +} + // Main initialization entry point into the interface module //extern DLL_EXPORT bool openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) extern bool DLL_EXPORT openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_intf_cb_t *pIntfCB) @@ -629,6 +651,7 @@ extern bool DLL_EXPORT openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_ pIntfCB->intf_rx_cb = openavbIntfToneGenRxCB; pIntfCB->intf_end_cb = openavbIntfToneGenEndCB; pIntfCB->intf_gen_end_cb = openavbIntfToneGenGenEndCB; + pIntfCB->intf_enable_fixed_timestamp = openavbIntfToneGenEnableFixedTimestamp; pPvtData->intervalCounter = 0; pPvtData->melodyIdx = 0; @@ -642,7 +665,7 @@ extern bool DLL_EXPORT openavbIntfToneGenInitialize(media_q_t *pMediaQ, openavb_ pPvtData->fv2 = 0; pPvtData->fvChannels = 0; - openavbMcsInit(&pPvtData->mcs, 125000UL); + pPvtData->fixedTimestampEnabled = false; } AVB_TRACE_EXIT(AVB_TRACE_INTF); diff --git a/lib/avtp_pipeline/intf_tonegen/tonegen_talker_lowlatency.ini b/lib/avtp_pipeline/intf_tonegen/tonegen_talker_lowlatency.ini new file mode 100644 index 00000000..a97861ca --- /dev/null +++ b/lib/avtp_pipeline/intf_tonegen/tonegen_talker_lowlatency.ini @@ -0,0 +1,162 @@ +##################################################################### +# General Talker configuration +##################################################################### +# role: Sets the process as a talker or listener. Valid values are +# talker or listener +role = talker + +# stream_addr: Used on the listener and should be set to the +# mac address of the talker. +#stream_addr = 00:25:64:48:ca:a8 + +# stream_uid: The unique stream ID. The talker and listener must +# both have this set the same. +stream_uid = 1 + +# dest_addr: destination multicast address for the stream. +# +# If using SRP and MAAP, dynamic destination addresses are generated +# automatically by the talker and passed to the listner, and don't +# need to be configured. +# +# Without MAAP, locally administered (static) addresses must be +# configured. Thouse addresses are in the range of: +# 91:E0:F0:00:FE:00 - 91:E0:F0:00:FE:FF. +# Typically use :00 for the first stream, :01 for the second, etc. +# +# When SRP is being used the static destination address only needs to +# be set in the talker. If SRP is not being used the destination address +# needs to be set (to the same value) in both the talker and listener. +# +# The destination is a multicast address, not a real MAC address, so it +# does not match the talker or listener's interface MAC. There are +# several pools of those addresses for use by AVTP defined in 1722. +# +#dest_addr = 91:e0:f0:00:fe:00 + +# max_interval_frames: The maximum number of packets that will be sent during +# an observation interval. This is only used on the talker. +max_interval_frames = 1 + +# sr_class: A talker only setting. Values are either A or B. If not set an internal +# default is used. +sr_class = A + +# sr_rank: A talker only setting. If not set an internal default is used. +#sr_rank = 1 + +# max_transit_usec: Allows manually specifying a maximum transit time. +# On the talker this value is added to the PTP walltime to create the AVTP Timestamp. +# On the listener this value is used to validate an expected valid timestamp range. +# Note: For the listener the map_nv_item_count value must be set large enough to +# allow buffering at least as many AVTP packets that can be transmitted during this +# max transit time. +max_transit_usec = 2000 + +# internal_latency: Allows mannually specifying an internal latency time. This is used +# only on the talker. +#internal_latency = 0 + +# max_stale: The number of microseconds beyond the presentation time that media queue items will be purged +# because they are too old (past the presentation time). This is only used on listener end stations. +# Note: needing to purge old media queue items is often a sign of some other problem. For example: a delay at +# stream startup before incoming packets are ready to be processed by the media sink. If this deficit +# in processing or purging the old (stale) packets is not handled, syncing multiple listeners will be problematic. +#max_stale = 1000 + +# raw_tx_buffers: The number of raw socket transmit buffers. Typically 4 - 8 are good values. +# This is only used by the talker. If not set internal defaults are used. +#raw_tx_buffers = 1 + +# raw_rx_buffers: The number of raw socket receive buffers. Typically 50 - 100 are good values. +# This is only used by the listener. If not set internal defaults are used. +#raw_rx_buffers = 100 + +# report_seconds: How often to output stats. Defaults to 10 seconds. 0 turns off the stats. +# report_seconds = 0 + +# Ethernet Interface Name. Only needed on some platforms when stack is built with no endpoint functionality +# ifname = eth0 + +# vlan_id: VLAN Identifier (1-4094). Used in "no endpoint" builds. Defaults to 2. +# vlan_id = 2 + +# Enable fixed timestamping in interface. Defaults to disable (0). +fixed_timestamp = 1 + +##################################################################### +# Mapping module configuration +##################################################################### +# map_lib: The name of the library file (commonly a .so file) that +# implements the Initialize function. Comment out the map_lib name +# and link in the .c file to the openavb_tl executable to embed the mapper +# directly into the executable unit. There is no need to change anything +# else. The Initialize function will still be dynamically linked in. +map_lib = ./libopenavb_map_aaf_audio.so + +# map_fn: The name of the initialize function in the mapper. +map_fn = openavbMapAVTPAudioInitialize + +# map_nv_item_count: The number of media queue elements to hold. +map_nv_item_count = 20 + +# map_nv_tx_rate: Transmit rate. +# This must be set for the uncompressed audio mapping module. +map_nv_tx_rate = 8000 + +# map_nv_packing_factor: Multiple of how many packets of audio frames to place in a media queue item. +# Note: Typically when decreasing the map_nv_tx_rate the packing factor will also be decreased since +# the number of frames per packet will be increasing. +map_nv_packing_factor = 1 + +##################################################################### +# Interface module configuration +##################################################################### +# intf_lib: The name of the library file (commonly a .so file) that +# implements the Initialize function. Comment out the intf_lib name +# and link in the .c file to the openavb_tl executable to embed the interface +# directly into the executable unit. There is no need to change anything +# else. The Initialize function will still be dynamically linked in. +# intf_fn: The name of the initialize function in the interface. +intf_lib = ./libopenavb_intf_tonegen.so + +# intf_fn: The name of the initialize function in the interface. +intf_fn = openavbIntfTonegenInitialize + +# intf_nv_tone_hz: The frequence of the tone +intf_nv_tone_hz = 261 + +# intf_nv_on_off_interval_msec: How many millisecs to turn on and off the tone +intf_nv_on_off_interval_msec = 1000 + +# intf_nv_melody_string: A simple melody to play. When a melody string is set the on/off tone hz is not used. +# Full range of supported notes +# intf_nv_melody_string = A4B4C4D4E4F4G4a4b4c4d4e4f4g4 +# DoRaMi... +# intf_nv_melody_string = A4B4C4D4E4F4G4a4 +# Twinkle Twinkle little star +# intf_nv_melody_string = C2C2G2G2a2a2G2 2F2F2E2E2D2D2C2 2C2C2G2G2a2a2G2 2F2F2E2E2D2D2C2 2G2G2F2F2E2E2D2 2G2G2F2F2E2E2D2 2C2C2G2G2a2a2G2 2F2F2E2E2D2D2C2 2 + +# intf_nv_audio_rate: Sampling rate of the generated audio +intf_nv_audio_rate = 48000 + +# intf_nv_audio_bit_depth: Bit depth of the generated audio +intf_nv_audio_bit_depth = 16 + +# intf_nv_audio_channels: The number of channels of the generated audio +intf_nv_audio_channels = 2 + +# intf_nv_volume: The volune of the tone generation PCM in dB +intf_nv_volume = 0 + +# Optionally replace the last one or two channels with fixed sample values +# intf_nv_fv1: First fixed 32-bit value +#intf_nv_fv1 = 1234 + +# intf_nv_fv2: Second fixed 32-bit value +#intf_nv_fv2 = 5678 + + + + + -- cgit v1.2.1 From 3ba04a9146ba5b58de101fb170c42dffa7efa055 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Tue, 13 Sep 2016 10:23:32 +0200 Subject: avtp_pipeline: tonegen remove debug code. --- .../intf_tonegen/openavb_intf_tonegen.c | 40 ---------------------- 1 file changed, 40 deletions(-) diff --git a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c index 29aa8be3..66ff499b 100644 --- a/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c +++ b/lib/avtp_pipeline/intf_tonegen/openavb_intf_tonegen.c @@ -262,7 +262,6 @@ void openavbIntfToneGenCfgCB(media_q_t *pMediaQ, const char *name, const char *v } } -#if 1 // both bit_depth and audio_type are not required, just use audio_type, always do big endian else if (strcmp(name, "intf_nv_audio_bit_depth") == 0) { val = strtol(value, &pEnd, 10); // TODO: Should check for specific values @@ -313,36 +312,6 @@ void openavbIntfToneGenCfgCB(media_q_t *pMediaQ, const char *name, const char *v pPubMapUncmpAudioInfo->audioEndian = pPvtData->audioEndian; } } -#else - else if (strcmp(name, "intf_nv_audio_type") == 0) { - if (strncasecmp(value, "float", 5) == 0) { - pPvtData->audioType = AVB_AUDIO_TYPE_FLOAT; - pPvtData->audioBitDepth = 32; - } else if (strncasecmp(value, "int32", 5) == 0) { - pPvtData->audioType = AVB_AUDIO_TYPE_INT; - pPvtData->audioBitDepth = 32; - } else if (strncasecmp(value, "int24", 5) == 0) { - pPvtData->audioType = AVB_AUDIO_TYPE_INT; - pPvtData->audioBitDepth = 24; - } else if (strncasecmp(value, "int16", 5) == 0) { - pPvtData->audioType = AVB_AUDIO_TYPE_INT; - pPvtData->audioBitDepth = 16; - } else { - AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_type."); - pPvtData->audioType = AVB_AUDIO_TYPE_UNSPEC; - } - - // always big endian - pPvtData->audioEndian = AVB_AUDIO_ENDIAN_BIG; - - // Give the audio parameters to the mapping module. - if (xSupportedMappingFormat(pMediaQ)) { - pPubMapUncmpAudioInfo->audioType = pPvtData->audioType; - pPubMapUncmpAudioInfo->audioBitDepth = pPvtData->audioBitDepth; - pPubMapUncmpAudioInfo->audioEndian = pPvtData->audioEndian; - } - } -#endif else if (strcmp(name, "intf_nv_audio_channels") == 0) { val = strtol(value, &pEnd, 10); @@ -494,10 +463,6 @@ bool openavbIntfToneGenTxCB(media_q_t *pMediaQ) float value = SIN(2 * PI * (runningFrameCnt++ % pPubMapUncmpAudioInfo->audioRate) * pPvtData->ratio) * pPvtData->volume; - -#if 0 // for debug - printf("value(%f), runningFrameCnt(%ul), audioRate(%d), ratio(%f)\n", value, runningFrameCnt, (int)pPubMapUncmpAudioInfo->audioRate, pPvtData->ratio); -#endif for (channelCnt = 0; channelCnt < pPubMapUncmpAudioInfo->audioChannels - pPvtData->fvChannels; channelCnt++) { if (pPvtData->audioType == AVB_AUDIO_TYPE_INT) { if (pPvtData->audioBitDepth == 32) { @@ -522,11 +487,6 @@ bool openavbIntfToneGenTxCB(media_q_t *pMediaQ) memcpy((U8 *)&tmp32f, (U8 *)&value, 4); // done so no warning with -Wstrict-aliasing tmp32f = htonl(tmp32f); memcpy(pData, (U8 *)&tmp32f, 4); -#if 0 // for debug - if (runningFrameCnt == 20) { - printf("sin(%f), tmp32f_0(%08X), tmp32f_1(%08X)\n", value, tmp32f_0, tmp32f_1); - } -#endif pData += 4; } else { // CORE_TODO -- cgit v1.2.1 From aab02a481bc89d3a5dac745e0c17d11110b3b4c0 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Mon, 5 Sep 2016 14:50:36 +0200 Subject: avtp_pipeline: Added parsing of tx_blocking_in_intf. --- lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c b/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c index eeccb8f0..390a5175 100644 --- a/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c +++ b/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c @@ -321,6 +321,15 @@ static int openavbTLCfgCallback(void *user, const char *tlSection, const char *n valOK = TRUE; } } + else if (MATCH(name, "tx_blocking_in_intf")) { + errno = 0; + long tmp; + tmp = strtol(value, &pEnd, 0); + if (*pEnd == '\0' && errno == 0) { + pCfg->tx_blocking_in_intf = tmp; + valOK = TRUE; + } + } else if (MATCH(name, "map_lib")) { if (pTLState->mapLib.libName) -- cgit v1.2.1 From 9231acc4317a1effc384afc9d8445f384e06a000 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Fri, 9 Sep 2016 11:43:39 +0200 Subject: avtp_pipeline: Affinity and priority can be specified in ini file. --- .../intf_tonegen/tonegen_talker_lowlatency.ini | 6 ++++++ .../platform/Linux/openavb_os_services_osal.h | 8 +++----- lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c | 18 ++++++++++++++++++ lib/avtp_pipeline/tl/openavb_tl.c | 7 ++++--- lib/avtp_pipeline/tl/openavb_tl_pub.h | 6 +++++- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/lib/avtp_pipeline/intf_tonegen/tonegen_talker_lowlatency.ini b/lib/avtp_pipeline/intf_tonegen/tonegen_talker_lowlatency.ini index a97861ca..2c4846c4 100644 --- a/lib/avtp_pipeline/intf_tonegen/tonegen_talker_lowlatency.ini +++ b/lib/avtp_pipeline/intf_tonegen/tonegen_talker_lowlatency.ini @@ -84,6 +84,12 @@ max_transit_usec = 2000 # Enable fixed timestamping in interface. Defaults to disable (0). fixed_timestamp = 1 +# Bit mask used for CPU pinning. Defaults to all cpus can be used (0xffffffff). +thread_affinity = 12 + +# Enable real time scheduling with this priority. Defaults to not use RT sched (0). +thread_rt_priority = 10 + ##################################################################### # Mapping module configuration ##################################################################### diff --git a/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h b/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h index 3ea5be9a..5619e946 100644 --- a/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h +++ b/lib/avtp_pipeline/platform/Linux/openavb_os_services_osal.h @@ -129,7 +129,6 @@ thread##_type thread##_ThreadData pthread_attr_destroy(&thread_attr); \ } -// KENTEST #define THREAD_SET_RT_PRIORITY(threadhandle, priority) \ { \ struct sched_param param; \ @@ -137,14 +136,13 @@ thread##_type thread##_ThreadData pthread_setschedparam(threadhandle##_ThreadData.pthread, SCHED_RR, ¶m); \ } -// KENTEST - quick hard code pinning to core 2 and 3. -#define THREAD_PIN(threadhandle) \ +#define THREAD_PIN(threadhandle, affinity) \ { \ cpu_set_t cpuset; \ int i1; \ CPU_ZERO(&cpuset); \ - for (i1 = 2; i1 < 4; i1++) { \ - CPU_SET(i1, &cpuset); \ + for (i1 = 0; i1 < 32; i1++) { \ + if (affinity & (1 << i1)) CPU_SET(i1, &cpuset); \ } \ pthread_setaffinity_np(threadhandle##_ThreadData.pthread, sizeof(cpu_set_t), &cpuset); \ } diff --git a/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c b/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c index 390a5175..287b0a3d 100644 --- a/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c +++ b/lib/avtp_pipeline/platform/Linux/tl/openavb_tl_osal.c @@ -330,6 +330,24 @@ static int openavbTLCfgCallback(void *user, const char *tlSection, const char *n valOK = TRUE; } } + else if (MATCH(name, "thread_rt_priority")) { + errno = 0; + long tmp; + tmp = strtol(value, &pEnd, 0); + if (*pEnd == '\0' && errno == 0) { + pCfg->thread_rt_priority = tmp; + valOK = TRUE; + } + } + else if (MATCH(name, "thread_affinity")) { + errno = 0; + unsigned long tmp; + tmp = strtoul(value, &pEnd, 0); + if (*pEnd == '\0' && errno == 0) { + pCfg->thread_affinity = tmp; + valOK = TRUE; + } + } else if (MATCH(name, "map_lib")) { if (pTLState->mapLib.libName) diff --git a/lib/avtp_pipeline/tl/openavb_tl.c b/lib/avtp_pipeline/tl/openavb_tl.c index d266fb88..0a534d44 100755 --- a/lib/avtp_pipeline/tl/openavb_tl.c +++ b/lib/avtp_pipeline/tl/openavb_tl.c @@ -397,6 +397,8 @@ EXTERN_DLL_EXPORT void openavbTLInitCfg(openavb_tl_cfg_t *pCfg) pCfg->pIntfInitFn = NULL; pCfg->vlan_id = VLAN_NULL; pCfg->fixed_timestamp = 0; + pCfg->thread_rt_priority = 0; + pCfg->thread_affinity = 0xFFFFFFFF; AVB_TRACE_EXIT(AVB_TRACE_TL); } @@ -511,9 +513,8 @@ EXTERN_DLL_EXPORT bool openavbTLRun(tl_handle_t handle) if (pTLState->cfg.role == AVB_ROLE_TALKER) { THREAD_CREATE_TALKER(); - // KENTEST - THREAD_SET_RT_PRIORITY(pTLState->TLThread, 10); - THREAD_PIN(pTLState->TLThread); + THREAD_SET_RT_PRIORITY(pTLState->TLThread, pTLState->cfg.thread_rt_priority); + THREAD_PIN(pTLState->TLThread, pTLState->cfg.thread_affinity); } else if (pTLState->cfg.role == AVB_ROLE_LISTENER) { THREAD_CREATE_LISTENER(); diff --git a/lib/avtp_pipeline/tl/openavb_tl_pub.h b/lib/avtp_pipeline/tl/openavb_tl_pub.h index 54185b09..39a43b24 100755 --- a/lib/avtp_pipeline/tl/openavb_tl_pub.h +++ b/lib/avtp_pipeline/tl/openavb_tl_pub.h @@ -129,8 +129,12 @@ typedef struct { U16 vlan_id; /// When set incoming packets will trigger a signal to the stream task to wakeup. bool rx_signal_mode; - /// + /// Enable fixed timestamping in interface U32 fixed_timestamp; + /// Bit mask used for CPU pinning + U32 thread_affinity; + /// Real time priority of thread. + U32 thread_rt_priority; /// Initialization function in mapper openavb_map_initialize_fn_t pMapInitFn; -- cgit v1.2.1 From 26e563fe22aea2d2482cc1383d7a0f570ca7696c Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Tue, 30 Aug 2016 16:19:03 -0400 Subject: gPTP: fix MSVC compiler warnings --- daemons/gptp/common/ieee1588port.cpp | 2 +- daemons/gptp/common/ptp_message.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 0e0a021b..ce21ea35 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -1154,7 +1154,7 @@ void IEEE1588Port::processEvent(Event e) annc->sendPort(this, NULL); delete annc; } - startAnnounceIntervalTimer(pow((double)2, getAnnounceInterval()) * 1000000000.0); + startAnnounceIntervalTimer((uint64_t)(pow((double)2, getAnnounceInterval()) * 1000000000.0)); break; case FAULT_DETECTED: GPTP_LOG_ERROR("Received FAULT_DETECTED event"); diff --git a/daemons/gptp/common/ptp_message.cpp b/daemons/gptp/common/ptp_message.cpp index 694f284c..bd05597a 100644 --- a/daemons/gptp/common/ptp_message.cpp +++ b/daemons/gptp/common/ptp_message.cpp @@ -1728,7 +1728,7 @@ void PTPMessagePathDelayRespFollowUp::setRequestingPortIdentity messageType = SIGNALLING_MESSAGE; sequenceId = port->getNextSignalSequenceId(); - targetPortIdentify = 0xff; + targetPortIdentify = (int8_t)0xff; control = MESSAGE_OTHER; -- cgit v1.2.1 From 15c97ba4409d7f923dbc5ac8fd6c6a6e5349ba2e Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Wed, 14 Sep 2016 08:22:39 +0800 Subject: Print log message when non-success code is returned Signed-off-by: Roland Hii --- daemons/gptp/linux/src/linux_hal_persist_file.cpp | 1 + examples/live_stream/listener.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/daemons/gptp/linux/src/linux_hal_persist_file.cpp b/daemons/gptp/linux/src/linux_hal_persist_file.cpp index 8655c6cd..545ad1b0 100644 --- a/daemons/gptp/linux/src/linux_hal_persist_file.cpp +++ b/daemons/gptp/linux/src/linux_hal_persist_file.cpp @@ -125,6 +125,7 @@ public: if (memoryDataLength > storedDataLength) { int ret = ftruncate(persistFD, memoryDataLength); if (ret != 0) { + printf("Failed to extend stored data length from %ld to %ld, %s\n", storedDataLength, memoryDataLength, strerror(errno)); } if (restoredata != ((void *)-1)) { restoredata = mremap(restoredata, storedDataLength, memoryDataLength, MREMAP_MAYMOVE); diff --git a/examples/live_stream/listener.c b/examples/live_stream/listener.c index 5109a3c8..8f469e2f 100644 --- a/examples/live_stream/listener.c +++ b/examples/live_stream/listener.c @@ -200,7 +200,8 @@ int main(int argc, char *argv[ ]) length = ntohs(h1722->length) - sizeof(six1883_header); rc = write(1, (uint8_t *)((uint8_t*)frame + sizeof(eth_header) + sizeof(seventeen22_header) + sizeof(six1883_header)), length); - if (rc != length) { + if (rc == -1) { + fprintf(stderr, "Failed to write %d bytes: %s (%d)\n", length, strerror(errno), errno); } } else { fprintf(stderr,"recvfrom() error for frame sequence = %lld\n", frame_sequence++); -- cgit v1.2.1 From 95af5f56d137e9512969cf2226b4f8491337f4b2 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Tue, 6 Sep 2016 09:19:35 -0400 Subject: gPTP: small change in doxygen comments related to event timers --- daemons/gptp/common/avbts_clock.hpp | 2 +- daemons/gptp/common/avbts_port.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/daemons/gptp/common/avbts_clock.hpp b/daemons/gptp/common/avbts_clock.hpp index 3e6d686a..0f7e60cf 100644 --- a/daemons/gptp/common/avbts_clock.hpp +++ b/daemons/gptp/common/avbts_clock.hpp @@ -496,7 +496,7 @@ public: * @brief Adds an event to the timer queue using a lock * @param target IEEE1588Port target * @param e Event to be added - * @param time_ns current time in nanoseconds + * @param time_ns event time in nanoseconds * @return void */ void addEventTimerLocked diff --git a/daemons/gptp/common/avbts_port.hpp b/daemons/gptp/common/avbts_port.hpp index 5e37120b..ddbd667b 100644 --- a/daemons/gptp/common/avbts_port.hpp +++ b/daemons/gptp/common/avbts_port.hpp @@ -794,7 +794,7 @@ class IEEE1588Port { /** * @brief Start sync interval timer - * @param waitTime time interval + * @param waitTime time interval in nanoseconds * @return none */ void startSyncIntervalTimer(long long unsigned int waitTime); -- cgit v1.2.1 From 2eb1f6f730f0a0ff26a45e769e8e95f3c52a8008 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Tue, 6 Sep 2016 13:16:56 -0400 Subject: gPTP: debug log output updates --- daemons/gptp/common/ieee1588port.cpp | 5 ++++- daemons/gptp/common/ptp_message.cpp | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index ce21ea35..11728616 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -907,7 +907,7 @@ void IEEE1588Port::processEvent(Event e) getTxLock(); pdelay_req->sendPort(this, NULL); - GPTP_LOG_DEBUG("Sent PDelay Request"); + GPTP_LOG_DEBUG("*** Sent PDelay Request message"); OSTimer *timer = timer_factory->createTimer(); @@ -969,6 +969,9 @@ void IEEE1588Port::processEvent(Event e) timeout : EVENT_TIMER_GRANULARITY; clock->addEventTimerLocked (this, PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES, timeout ); + GPTP_LOG_DEBUG("Schedule PDELAY_RESP_RECEIPT_TIMEOUT_EXPIRES, " + "PDelay interval %d, wait_time %lld, timeout %lld", + getPDelayInterval(), wait_time, timeout); interval = ((long long) diff --git a/daemons/gptp/common/ptp_message.cpp b/daemons/gptp/common/ptp_message.cpp index bd05597a..e0f79276 100644 --- a/daemons/gptp/common/ptp_message.cpp +++ b/daemons/gptp/common/ptp_message.cpp @@ -157,7 +157,7 @@ PTPMessageCommon *buildPTPMessage switch (messageType) { case SYNC_MESSAGE: - GPTP_LOG_DEBUG("*** Received Sync message\n" ); + GPTP_LOG_DEBUG("*** Received Sync message" ); GPTP_LOG_VERBOSE("Sync RX timestamp = %hu,%u,%u", timestamp.seconds_ms, timestamp.seconds_ls, timestamp.nanoseconds ); // Be sure buffer is the correction size @@ -1150,7 +1150,7 @@ void PTPMessagePathDelayReq::processMessage(IEEE1588Port * port) port->getTxLock(); resp->sendPort(port, sourcePortIdentity); - GPTP_LOG_DEBUG("Sent path delay response"); + GPTP_LOG_DEBUG("*** Sent PDelay Response message"); GPTP_LOG_VERBOSE("Start TS Read"); ts_good = port->getTxTimestamp @@ -1213,7 +1213,7 @@ void PTPMessagePathDelayReq::processMessage(IEEE1588Port * port) resp_fwup->setCorrectionField(0); resp_fwup->sendPort(port, sourcePortIdentity); - GPTP_LOG_DEBUG("Sent path delay response fwup"); + GPTP_LOG_DEBUG("*** Sent PDelay Response FollowUp message"); delete resp; delete resp_fwup; -- cgit v1.2.1 From 160ec7fced2c57d4555ad13c082bd97f24671877 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Wed, 7 Sep 2016 09:49:16 -0400 Subject: gPTP: doxygen comment update for HAL send() parameter list --- daemons/gptp/linux/src/linux_hal_common.hpp | 2 +- daemons/gptp/windows/daemon_cl/windows_hal.hpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/daemons/gptp/linux/src/linux_hal_common.hpp b/daemons/gptp/linux/src/linux_hal_common.hpp index fb77be19..732dfc13 100644 --- a/daemons/gptp/linux/src/linux_hal_common.hpp +++ b/daemons/gptp/linux/src/linux_hal_common.hpp @@ -157,7 +157,7 @@ public: /** * @brief Sends a packet to a remote address * @param addr [in] Remote link layer address - * @param etherType [in] The EtherType of the message + * @param etherType [in] The EtherType of the message in host order * @param payload [in] Data buffer * @param length Size of data buffer * @param timestamp TRUE if to use the event socket with the PTP multicast address. FALSE if to use diff --git a/daemons/gptp/windows/daemon_cl/windows_hal.hpp b/daemons/gptp/windows/daemon_cl/windows_hal.hpp index 8c12c807..abbe5fa9 100644 --- a/daemons/gptp/windows/daemon_cl/windows_hal.hpp +++ b/daemons/gptp/windows/daemon_cl/windows_hal.hpp @@ -70,6 +70,7 @@ public: /** * @brief Sends a packet to a remote address * @param addr [in] Destination link Layer address + * @param etherType [in] The EtherType of the message in host order * @param payload [in] Data buffer * @param length Size of buffer * @param timestamp TRUE: Use timestamp, FALSE otherwise -- cgit v1.2.1 From 6374ee7584be5e9ae537295cd2b70058099f5899 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Fri, 9 Sep 2016 12:21:17 -0400 Subject: gPTP: add labels to PATH_DELAY_RESP_MESSAGE debug output --- daemons/gptp/common/ptp_message.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemons/gptp/common/ptp_message.cpp b/daemons/gptp/common/ptp_message.cpp index e0f79276..82518e8f 100644 --- a/daemons/gptp/common/ptp_message.cpp +++ b/daemons/gptp/common/ptp_message.cpp @@ -279,7 +279,7 @@ PTPMessageCommon *buildPTPMessage break; case PATH_DELAY_RESP_MESSAGE: - GPTP_LOG_DEBUG("*** Received PDelay Response message, %u, %u, %u", + GPTP_LOG_DEBUG("*** Received PDelay Response message, Timestamp %u (sec) %u (ns), seqID %u", timestamp.seconds_ls, timestamp.nanoseconds, sequenceId); -- cgit v1.2.1 From cf4baaccd136690efc6e7373ac0c88342be397c8 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Fri, 9 Sep 2016 12:26:36 -0400 Subject: gPTP: debug log output update to IEEE1588Port::processEvent() --- daemons/gptp/common/ieee1588port.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 11728616..56896980 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -931,6 +931,10 @@ void IEEE1588Port::processEvent(Event e) if (ts_good == GPTP_EC_SUCCESS) { pdelay_req->setTimestamp(req_timestamp); + GPTP_LOG_DEBUG( + "PDelay Request message, Timestamp %u (sec) %u (ns), seqID %u", + req_timestamp.seconds_ls, req_timestamp.nanoseconds, + pdelay_req->getSequenceId()); } else { Timestamp failed = INVALID_TIMESTAMP; pdelay_req->setTimestamp(failed); @@ -945,17 +949,6 @@ void IEEE1588Port::processEvent(Event e) "Error (TX) timestamping PDelay request, error=%d\t%s", ts_good, msg); } -#ifdef DEBUG - if (ts_good == GPTP_EC_SUCCESS) { - GPTP_LOG_DEBUG - ("Successful PDelay Req timestamp, %u,%u", - req_timestamp.seconds_ls, - req_timestamp.nanoseconds); - } else { - GPTP_LOG_DEBUG - ("*** Unsuccessful PDelay Req timestamp"); - } -#endif { long long timeout; @@ -1145,6 +1138,7 @@ void IEEE1588Port::processEvent(Event e) } break; case ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES: + GPTP_LOG_DEBUG("ANNOUNCE_INTERVAL_TIMEOUT_EXPIRES occured"); if (asCapable) { // Send an announce message PTPMessageAnnounce *annc = new PTPMessageAnnounce(this); @@ -1166,6 +1160,7 @@ void IEEE1588Port::processEvent(Event e) } break; case PDELAY_DEFERRED_PROCESSING: + GPTP_LOG_DEBUG("PDELAY_DEFERRED_PROCESSING occured"); pdelay_rx_lock->lock(); if (last_pdelay_resp_fwup == NULL) { GPTP_LOG_ERROR("PDelay Response Followup is NULL!"); -- cgit v1.2.1 From 75b7b06e13a2d65d04ed636d5e540b6a797f147a Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Wed, 21 Sep 2016 09:54:58 +0800 Subject: Remove -fPIC flag from makefiles Signed-off-by: Roland Hii --- daemons/gptp/linux/build/Makefile | 2 +- lib/igb/Makefile | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/daemons/gptp/linux/build/Makefile b/daemons/gptp/linux/build/Makefile index b02a4507..633ed0ec 100644 --- a/daemons/gptp/linux/build/Makefile +++ b/daemons/gptp/linux/build/Makefile @@ -30,7 +30,7 @@ ALTERNATE_LINUX_INCPATH=$(HOME)/header/include/ -CFLAGS_G = -Wall -fPIC -g -I. -I../../common -I../src \ +CFLAGS_G = -Wall -g -I. -I../../common -I../src \ -I$(ALTERNATE_LINUX_INCPATH) # Check to see if PTP cross-timestamping is supported in hardware/driver diff --git a/lib/igb/Makefile b/lib/igb/Makefile index 68cb1872..8a0c4151 100644 --- a/lib/igb/Makefile +++ b/lib/igb/Makefile @@ -2,7 +2,6 @@ OBJS=igb INCL=e1000_82575.h e1000_defines.h e1000_hw.h e1000_osdep.h e1000_regs.h igb.h AVBLIB=libigb.a #CFLAGS=-ggdb -CFLAGS=-fPIC CC?=gcc RANLIB?=ranlib -- cgit v1.2.1 From 76850a08783fb5c2d88bd0fd7928cfecc2fb6bce Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Wed, 14 Sep 2016 11:16:28 -0600 Subject: Use C++11 support for CPPUTest build This adjusts the top-level cmake config to tell CPPUTest to build with C++11 support enabled. This will hopefully fix some reported build fails although the reported failures don't occur for me. Could be a compiler version thing. --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index cba5d830..f6cc0776 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required (VERSION 2.8) project (open-avb) enable_testing() + +set(C++11 ON CACHE BOOL "Compile with C++11 support" FORCE) add_subdirectory("thirdparty/cpputest") add_subdirectory("daemons/common/tests") add_subdirectory("daemons/mrpd") -- cgit v1.2.1 From f0509e81bf5f367f43f4f1624695d046e1e419e9 Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Wed, 14 Sep 2016 11:18:18 -0600 Subject: Fix compiler warnings in mrpd tests When switching CPPUTest to C++11, some warnings appeared regarding implicit casting of string literals to (char *). This is deprecated in C++ now. --- .travis.yml | 11 ++++++++++- daemons/mrpd/tests/simple/parse_tests.cpp | 16 ++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index f06e4416..c57acc44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,17 @@ git: before_install: - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules - git submodule update --init --recursive + - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update -qq - - sudo apt-get install doxygen graphviz + - sudo apt-get install doxygen graphviz gcc-4.8 g++-4.8 + - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 10 + - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 20 + - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.6 10 + - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 20 + - sudo update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 30 + - sudo update-alternatives --set cc /usr/bin/gcc + - sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 30 + - sudo update-alternatives --set c++ /usr/bin/g++ compiler: - gcc env: BUILD_KERNEL=3.13.0-36-generic diff --git a/daemons/mrpd/tests/simple/parse_tests.cpp b/daemons/mrpd/tests/simple/parse_tests.cpp index b7bdfe7d..f66b2f27 100644 --- a/daemons/mrpd/tests/simple/parse_tests.cpp +++ b/daemons/mrpd/tests/simple/parse_tests.cpp @@ -70,7 +70,7 @@ TEST(ParseTestGroup, TestParse_null) int err_index; int status; struct parse_param specs[] = { - { "C" PARSE_ASSIGN, parse_null, &value }, + { (char*)"C" PARSE_ASSIGN, parse_null, &value }, { 0, parse_null, 0 }}; const char strz[] = "C=1234"; @@ -96,7 +96,7 @@ TEST(ParseTestGroup, TestParse_u8) int err_index; int status; struct parse_param specs[] = { - { "C" PARSE_ASSIGN, parse_u8, &value }, + { (char*)"C" PARSE_ASSIGN, parse_u8, &value }, { 0, parse_null, 0 } }; char strz[64]; int i; @@ -147,7 +147,7 @@ TEST(ParseTestGroup, TestParse_u16) int err_index; int status; struct parse_param specs[] = { - { "C" PARSE_ASSIGN, parse_u16, &value }, + { (char*)"C" PARSE_ASSIGN, parse_u16, &value }, { 0, parse_null, 0 } }; char strz[64]; int i; @@ -197,7 +197,7 @@ TEST(ParseTestGroup, TestParse_u16_04x) int err_index; int status; struct parse_param specs[] = { - { "C" PARSE_ASSIGN, parse_u16_04x, &value }, + { (char*)"C" PARSE_ASSIGN, parse_u16_04x, &value }, { 0, parse_null, 0 } }; char strz[64]; int i; @@ -247,7 +247,7 @@ TEST(ParseTestGroup, TestParse_u32) int err_index; int status; struct parse_param specs[] = { - { "C" PARSE_ASSIGN, parse_u32, &value }, + { (char*)"C" PARSE_ASSIGN, parse_u32, &value }, { 0, parse_null, 0 } }; char strz[64]; int i; @@ -298,13 +298,13 @@ TEST(ParseTestGroup, TestParse_u64) int err_index; int status; struct parse_param specsu[] = { - { "C" PARSE_ASSIGN, parse_u64, &value }, + { (char*)"C" PARSE_ASSIGN, parse_u64, &value }, { 0, parse_null, 0 } }; struct parse_param specsx[] = { - { "C" PARSE_ASSIGN, parse_h64, &value }, + { (char*)"C" PARSE_ASSIGN, parse_h64, &value }, { 0, parse_null, 0 } }; struct parse_param specsc[] = { - { "C" PARSE_ASSIGN, parse_c64, &stream_id }, + { (char*)"C" PARSE_ASSIGN, parse_c64, &stream_id }, { 0, parse_null, 0 } }; char strz[64]; int i, j; -- cgit v1.2.1 From 83a35bb31a7b82d9137c3e034bb21440b5e8ac14 Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Fri, 9 Sep 2016 08:22:05 -0400 Subject: gPTP: remove accelerated SYNC send on startup. See discussion in #465. --- daemons/gptp/common/avbts_port.hpp | 7 +---- daemons/gptp/common/ieee1588port.cpp | 38 +++------------------------- daemons/gptp/linux/src/daemon_cl.cpp | 14 +--------- daemons/gptp/windows/daemon_cl/daemon_cl.cpp | 1 - 4 files changed, 6 insertions(+), 54 deletions(-) diff --git a/daemons/gptp/common/avbts_port.hpp b/daemons/gptp/common/avbts_port.hpp index ddbd667b..cb4f2761 100644 --- a/daemons/gptp/common/avbts_port.hpp +++ b/daemons/gptp/common/avbts_port.hpp @@ -219,9 +219,6 @@ typedef struct { /* forceSlave Forces port to be slave */ bool forceSlave; - /* accelerated_sync_count If non-zero, then start 16ms sync timer */ - int accelerated_sync_count; - /* timestamper Hardware timestamper instance */ HWTimestamper * timestamper; @@ -319,7 +316,6 @@ class IEEE1588Port { char log_min_mean_delay_req_interval; char log_min_mean_pdelay_req_interval; bool burst_enabled; - int _accelerated_sync_count; static const int64_t ONE_WAY_DELAY_DEFAULT = 3600000000000; static const int64_t INVALID_LINKDELAY = 3600000000000; static const int64_t NEIGHBOR_PROP_DELAY_THRESH = 800; @@ -620,7 +616,6 @@ class IEEE1588Port { * @param clock IEEE1588Clock instance * @param index Interface index * @param forceSlave Forces port to be slave - * @param accelerated_sync_count If non-zero, then start 16ms sync timer * @param timestamper Hardware timestamper instance * @param offset Initial clock offset * @param net_label Network label @@ -631,7 +626,7 @@ class IEEE1588Port { */ IEEE1588Port (IEEE1588Clock * clock, uint16_t index, - bool forceSlave, int accelerated_sync_count, + bool forceSlave, HWTimestamper * timestamper, int32_t offset, InterfaceLabel * net_label, OSConditionFactory * condition_factory, diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 56896980..71fde4ae 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -140,7 +140,6 @@ IEEE1588Port::IEEE1588Port(IEEE1588PortInit_t *portInit) /*TODO: Add intervals below to a config interface*/ log_mean_sync_interval = initialLogSyncInterval; - _accelerated_sync_count = portInit->accelerated_sync_count; log_mean_announce_interval = 0; log_min_mean_pdelay_req_interval = initialLogPdelayReqInterval; @@ -523,10 +522,6 @@ void IEEE1588Port::processEvent(Event e) Event e3 = NULL_EVENT; Event e4 = NULL_EVENT; - if( port_state != PTP_MASTER ) { - _accelerated_sync_count = -1; - } - if (!automotive_profile) { if (port_state != PTP_SLAVE && port_state != PTP_MASTER) { GPTP_LOG_STATUS("Starting PDelay"); @@ -1104,36 +1099,11 @@ void IEEE1588Port::processEvent(Event e) system_time, local_system_freq_offset, sync_count, pdelay_count, port_state, asCapable ); - if (!automotive_profile) { - /* If accelerated_sync is non-zero then start 16 ms sync - timer, subtract 1, for last one start PDelay also */ - if( _accelerated_sync_count > 0 ) { - clock->addEventTimerLocked - ( this, SYNC_INTERVAL_TIMEOUT_EXPIRES, 8000000 ); - --_accelerated_sync_count; - } else { - syncDone(); - if( _accelerated_sync_count == 0 ) { - --_accelerated_sync_count; - } - wait_time *= 1000; // to ns - wait_time = - ((long long) - (pow((double)2,getSyncInterval())*1000000000.0)) - - wait_time; - wait_time = wait_time > EVENT_TIMER_GRANULARITY ? wait_time : - EVENT_TIMER_GRANULARITY; - startSyncIntervalTimer(wait_time); - } - } - else { - // Automotive Profile - syncDone(); + syncDone(); - wait_time = ((long long) (pow((double)2, getSyncInterval()) * 1000000000.0)); - wait_time = wait_time > EVENT_TIMER_GRANULARITY ? wait_time : EVENT_TIMER_GRANULARITY; - startSyncIntervalTimer(wait_time); - } + wait_time = ((long long) (pow((double)2, getSyncInterval()) * 1000000000.0)); + wait_time = wait_time > EVENT_TIMER_GRANULARITY ? wait_time : EVENT_TIMER_GRANULARITY; + startSyncIntervalTimer(wait_time); } break; diff --git a/daemons/gptp/linux/src/daemon_cl.cpp b/daemons/gptp/linux/src/daemon_cl.cpp index 50f422aa..c1cdf5b5 100644 --- a/daemons/gptp/linux/src/daemon_cl.cpp +++ b/daemons/gptp/linux/src/daemon_cl.cpp @@ -65,7 +65,7 @@ void gPTPPersistWriteCB(char *bufPtr, uint32_t bufSize); void print_usage( char *arg0 ) { fprintf( stderr, "%s [-S] [-P] [-M ] " - "[-A ] [-G ] [-R ] " + "[-G ] [-R ] " "[-D ] " "[-T] [-L] [-E] [-GM] [-INITSYNC ] [-OPERSYNC ] " "[-INITPDELAY ] [-OPERPDELAY ] " @@ -77,7 +77,6 @@ void print_usage( char *arg0 ) { "\t-S start syntonization\n" "\t-P pulse per second\n" "\t-M save/restore state\n" - "\t-A initial accelerated sync count\n" "\t-G group id for shared memory\n" "\t-R priority 1 value\n" "\t-D Phy Delay \n" @@ -120,7 +119,6 @@ int main(int argc, char **argv) off_t restoredatacount = 0; bool restorefailed = false; LinuxIPCArg *ipc_arg = NULL; - int accelerated_sync_count = 0; bool use_config_file = false; char config_file_path[512]; memset(config_file_path, 0, 512); @@ -130,7 +128,6 @@ int main(int argc, char **argv) portInit.clock = NULL; portInit.index = 0; portInit.forceSlave = false; - portInit.accelerated_sync_count = 0; portInit.timestamper = NULL; portInit.offset = 0; portInit.net_label = NULL; @@ -207,14 +204,6 @@ int main(int argc, char **argv) "command line\n" ); } } - else if( strcmp(argv[i] + 1, "A" ) == 0 ) { - if( i+1 < argc ) { - accelerated_sync_count = atoi( argv[++i] ); - } else { - printf( "Accelerated sync count must be specified on the " - "command line with A option\n" ); - } - } else if( strcmp(argv[i] + 1, "G") == 0 ) { if( i+1 < argc ) { ipc_arg = new LinuxIPCArg(argv[++i]); @@ -353,7 +342,6 @@ int main(int argc, char **argv) portInit.clock = pClock; portInit.index = 1; portInit.forceSlave = false; - portInit.accelerated_sync_count = accelerated_sync_count; portInit.timestamper = timestamper; portInit.offset = 0; portInit.net_label = ifname; diff --git a/daemons/gptp/windows/daemon_cl/daemon_cl.cpp b/daemons/gptp/windows/daemon_cl/daemon_cl.cpp index 4c879103..ccea00eb 100644 --- a/daemons/gptp/windows/daemon_cl/daemon_cl.cpp +++ b/daemons/gptp/windows/daemon_cl/daemon_cl.cpp @@ -84,7 +84,6 @@ int _tmain(int argc, _TCHAR* argv[]) portInit.clock = NULL; portInit.index = 1; portInit.forceSlave = false; - portInit.accelerated_sync_count = 0; portInit.timestamper = NULL; portInit.offset = 0; portInit.net_label = NULL; -- cgit v1.2.1 From b12caadb45f9d24427201a480c60c9139200803f Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Fri, 23 Sep 2016 14:53:01 -0600 Subject: Initial Linux support. "Old" test cases build and run successfully. Full code version compiles, but has no main loop support. Makefile needs help. --- daemons/maap/common/intervals.c | 206 ++++++++++ daemons/maap/common/intervals.h | 165 ++++++++ daemons/maap/common/maap.c | 444 +++++++++++++++++++++ daemons/maap/common/maap.h | 73 ++++ daemons/maap/common/maap_iface.h | 42 ++ daemons/maap/common/maap_net.h | 14 + daemons/maap/common/maap_packet.c | 141 +++++++ daemons/maap/common/maap_packet.h | 35 ++ daemons/maap/common/maap_timer.h | 30 ++ daemons/maap/common/platform.h | 48 +++ daemons/maap/linux/Makefile | 36 +- daemons/maap/linux/src/maap_linux.c | 26 ++ daemons/maap/linux/src/maap_linux_legacy.c | 279 +++++++++++++ daemons/maap/linux/src/maap_net_linux.c | 36 ++ daemons/maap/linux/src/maap_timer_linux.c | 86 +++++ daemons/maap/test/endian.h | 96 +++++ daemons/maap/test/maap_net_dummy.c | 39 ++ daemons/maap/test/maap_test.c | 559 +++++++++++++++++++++++++++ daemons/maap/test/maap_timer_dummy.c | 81 ++++ daemons/maap/test/test_intervals.c | 103 +++++ daemons/maap/test/test_maap_packet_packing.c | 115 ++++++ 21 files changed, 2649 insertions(+), 5 deletions(-) create mode 100644 daemons/maap/common/intervals.c create mode 100644 daemons/maap/common/intervals.h create mode 100644 daemons/maap/common/maap.c create mode 100644 daemons/maap/common/maap.h create mode 100644 daemons/maap/common/maap_iface.h create mode 100644 daemons/maap/common/maap_net.h create mode 100644 daemons/maap/common/maap_packet.c create mode 100644 daemons/maap/common/maap_packet.h create mode 100644 daemons/maap/common/maap_timer.h create mode 100644 daemons/maap/common/platform.h create mode 100644 daemons/maap/linux/src/maap_linux.c create mode 100644 daemons/maap/linux/src/maap_linux_legacy.c create mode 100644 daemons/maap/linux/src/maap_net_linux.c create mode 100644 daemons/maap/linux/src/maap_timer_linux.c create mode 100755 daemons/maap/test/endian.h create mode 100644 daemons/maap/test/maap_net_dummy.c create mode 100644 daemons/maap/test/maap_test.c create mode 100644 daemons/maap/test/maap_timer_dummy.c create mode 100644 daemons/maap/test/test_intervals.c create mode 100644 daemons/maap/test/test_maap_packet_packing.c diff --git a/daemons/maap/common/intervals.c b/daemons/maap/common/intervals.c new file mode 100644 index 00000000..5be06a1b --- /dev/null +++ b/daemons/maap/common/intervals.c @@ -0,0 +1,206 @@ +#include +#include "intervals.h" + +static inline int check_overlap(Interval *a, Interval *b) { + return (a->low <= b->high && b->low <= a->high); +} + +Interval *alloc_interval(uint32_t start, uint32_t count) { + Interval *i; + i = calloc(1, sizeof (Interval)); + if (i) { + i->low = start; + i->high = i->max = start + count - 1; + } + return i; +} + +void free_interval(Interval *node) { + return free(node); +} + +int insert_interval(Interval **root, Interval *node) { + Interval *current; + + if (*root == NULL) { + *root = node; + return INTERVAL_SUCCESS; + } + current = *root; + while (1) { + if (check_overlap(current, node)) { + return INTERVAL_OVERLAP; + } + if (node->low < current->low) { + if (current->left_child == NULL) { + current->left_child = node; + node->parent = current; + break; + } else { + current = current->left_child; + } + } else { + if (current->right_child == NULL) { + current->right_child = node; + node->parent = current; + break; + } else { + current = current->right_child; + } + } + } + current = node; + while (current->parent) { + if (current->max > current->parent->max) { + current->parent->max = current->max; + } + current = current->parent; + } + return INTERVAL_SUCCESS; +} + +Interval *remove_interval(Interval **root, Interval *node) { + Interval *snip, *child, *current; + + /* If the node to remove does not have two children, we will snip it, + otherwise we will swap it with its successor and snip that one */ + if (!node->left_child || !node->right_child) { + snip = node; + } else { + snip = next_interval(node); + } + + /* If the node to snip has a child, make its parent link point to the snipped + node's parent */ + if (snip->left_child) { + child = snip->left_child; + } else { + child = snip->right_child; + } + if (child) { + child->parent = snip->parent; + } + + /* If the snipped node has no parent, it is the root node and we use the + provided root pointer to point to the child. Otherwise, we find if the + snipped node was a left or right child and set the appropriate link in the + parent node */ + if (!snip->parent) { + *root = child; + } else if (snip == snip->parent->left_child) { + snip->parent->left_child = child; + } else { + snip->parent->right_child = child; + } + + /* Swap the contents of the node passed in to remove with the one chosen to be + snipped */ + if (snip != node) { + node->low = snip->low; + node->high = snip->high; + node->max = snip->max; + node->data = snip->data; + } + + /* If the snipped node was not the root, propagate the max value back up the + tree */ + if (snip->parent) { + current = snip->parent; + if (current->left_child && current->left_child->max > current->max) { + current->max = current->left_child->max; + } + if (current->right_child && current->right_child->max > current->max) { + current->max = current->right_child->max; + } + while (current->parent) { + if (current->max > current->parent->max) { + current->parent->max = current->max; + } + current = current->parent; + } + } + return snip; +} + +Interval *minimum_interval(Interval *root) { + Interval *current = root; + + while (1) { + if (current && current->left_child) { + current = current->left_child; + } else { + return current; + } + } +} + +Interval *maximum_interval(Interval *root) { + Interval *current = root; + + while (1) { + if (current && current->right_child) { + current = current->right_child; + } else { + return current; + } + } +} + +Interval *next_interval(Interval *node) { + Interval *parent, *child; + + if (node->right_child) { + return minimum_interval(node->right_child); + } + + child = node; + parent = node->parent; + while (parent && child == parent->right_child) { + child = parent; + parent = parent->parent; + } + return parent; +} + +Interval *prev_interval(Interval *node) { + Interval *parent, *child; + + if (node->left_child) { + return maximum_interval(node->left_child); + } + + child = node; + parent = node->parent; + while (parent && child == parent->left_child) { + child = parent; + parent = parent->parent; + } + return parent; +} + +Interval *search_interval(Interval *root, uint32_t start, uint32_t count) { + Interval *current; + Interval i; + + i.low = start; + i.high = start + count - 1; + current = root; + + while (current && !check_overlap(current, &i)) { + if (current->left_child && current->left_child->max >= i.low) { + current = current->left_child; + } else { + current = current->right_child; + } + } + + return current; +} + +void traverse_interval(Interval *root, Visitor action) { + if (root) { + traverse_interval(root->left_child, action); + action(root); + traverse_interval(root->right_child, action); + } +} diff --git a/daemons/maap/common/intervals.h b/daemons/maap/common/intervals.h new file mode 100644 index 00000000..c8aa1fee --- /dev/null +++ b/daemons/maap/common/intervals.h @@ -0,0 +1,165 @@ +#ifndef INTERVALS_H +#define INTERVALS_H + +#include + +/** + * Augmented Binary Search Tree for Intervals + * + * This library will keep track of non-overlapping intervals in the uint32 range + * + * It supports insert, remove, minimum, maximum, next, previous, search, and + * traverse operations. All updates occur in-place. + * + * All memory allocation must be handled by the user through the alloc_interval + * and free_interval functions. These are not called by any library functions. + * + * To create an empty set of intervals, simply store an Interval pointer. The + * address of this pointer will be passed to the insert and remove operations, + * which will update the pointer if the root node of the tree changes. + */ + +/* Return values for insert_interval */ + +/** + * The interval was inserted + */ +#define INTERVAL_SUCCESS 0 + +/** + * The interval overlapped and wasn't inserted + */ +#define INTERVAL_OVERLAP -1 + +/** + * A range of integers with an upper and lower bound. + */ +typedef struct interval_node Interval; + +/** + * Signature for function pointer parameter to traverse_interval() + */ +typedef void (*Visitor)(Interval *); + +struct interval_node { + uint32_t low; + uint32_t high; + uint32_t max; + void *data; + Interval *parent; + Interval *left_child; + Interval *right_child; +}; + +/** + * Allocates, initializes, and returns a pointer to an Interval. + * + * @param start The first integer in the interval + * + * @param count The number of integers in the interval + * + * @return An initialized Interval, or NULL if the allocator fails. + */ +Interval *alloc_interval(uint32_t start, uint32_t count); + +/** + * Deallocates an Interval. + * + * @note Be sure to call this after removing an interval from a set + * + * @param node The Interval to deallocate. + */ +void free_interval(Interval *node); + +/** + * Insert an Interval into the set of tracked Intervals. + * + * @param root The address of the Interval pointer that is the root of the set + * + * @param node The Interval to attempt to insert in the set + * + * @return INTERVAL_SUCCESS if the node inserted to the set without overlap, + * INTERVAL_OVERLAP if the node was not inserted due to overlap with an existing + * Interval. + */ +int insert_interval(Interval **root, Interval *node); + +/** + * Remove an Interval from the set of tracked Intervals. + * + * @WARNING: Because the actual node removed from the tree might not be the same + * as the one passed in, the return value MUST be stored and used to free the + * Interval that was removed from the set. + * + * @param root The address of the pointer to the root of the set of Intervals + * + * @param node The address of the Interval to remove from the set + * + * @return The address of the Interval storage that should be freed + */ +Interval *remove_interval(Interval **root, Interval *node); + +/** + * Find the minimum Interval from a set of Intervals. + * + * @param root The address of the root of the set of Intervals + * + * @return The address of the Interval with the smallest 'low' value in the set, + * or NULL if the set is empty. + */ +Interval *minimum_interval(Interval *root); + +/** + * Find the maximum Interval from a set of Intervals. + * + * @param root The address of the root of the set of Intervals + * + * @return The address of the Interval with the largest 'low' value in the set, + * or NULL if the set is empty. + */ +Interval *maximum_interval(Interval *root); + +/** + * Get the next Interval in the set assuming an ordering based on the 'low' value. + * + * @param node The Interval to find the successor of. + * + * @return The successor of the passed-in Interval, or NULL if there is none. + */ +Interval *next_interval(Interval *node); + +/** + * Get the previous Interval in the set assuming an ordering based on the 'low' + * value. + * + * @param node The Interval to find the predecessor of. + * + * @return The predecessor of the passed-in Interval, or NULL if there is none. + */ +Interval *prev_interval(Interval *node); + +/** + * Find the first Interval in a set that overlaps with the given interval. + * + * @param root The root Interval of the set to search. + * + * @param start The first integer in the interval to search for. + * + * @param count The number of integers in the interval to search for. + * + * @return The first overlapping Interval, or NULL if there is none. + */ +Interval *search_interval(Interval *root, uint32_t start, uint32_t count); + +/** + * Traverse the Interval set, performing an action on each Interval. + * + * @note Intervals will be visited in increasing order of their 'low' values. + * + * @param root The root Interval of the set to traverse. + * + * @param action The action to invoke on each Interval. + */ +void traverse_interval(Interval *root, Visitor action); + +#endif diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c new file mode 100644 index 00000000..f685a7b8 --- /dev/null +++ b/daemons/maap/common/maap.c @@ -0,0 +1,444 @@ +#include "maap.h" +#include "maap_packet.h" + +#include +#include +#include +#include +#include +#include + +/* Linux-specific header files */ +#include +#include + +static int get_count(Client *mc, Range *range) { + (void)mc; + return range->interval->high - range->interval->low + 1; +} + +static uint64_t get_start_address(Client *mc, Range *range) { + return mc->address_base + range->interval->high; +} + +static int send_packet(Client *mc, MAAP_Packet *p) { + uint8_t *pbuf = NULL; + int ret = 0; + (void)mc; + + pbuf = Net_getPacketBuffer(mc->net); + + pack_maap(p, pbuf); + + ret = Net_sendPacket(mc->net, pbuf); + return ret; +} + +static int send_probe(Client *mc, Range *range) { + MAAP_Packet p; + + init_packet(&p); + + p.message_type = MAAP_PROBE; + p.requested_start_address = get_start_address(mc, range); + p.requested_count = get_count(mc, range); + + return send_packet(mc, &p); +} + +static int send_announce(Client *mc, Range *range) { + MAAP_Packet p; + + init_packet(&p); + + p.message_type = MAAP_ANNOUNCE; + p.requested_start_address = get_start_address(mc, range); + p.requested_count = get_count(mc, range); + + return send_packet(mc, &p); +} + +static int send_defend(Client *mc, Range *range, uint64_t start, + uint16_t count, uint64_t destination) { + MAAP_Packet p; + + init_packet(&p); + + p.DA = destination; + p.message_type = MAAP_DEFEND; + p.requested_start_address = start; + p.requested_count = count; + p.start_address = get_start_address(mc, range); + p.count = get_count(mc, range); + + return send_packet(mc, &p); +} + +static int inform_acquired(Client *mc, Range *range) { + Notify note; + printf("Address range acquired: %" PRIx64 " %d\n", + get_start_address(mc, range), + get_count(mc, range)); + + note.kind = MAAP_ACQUIRED; + note.id = range->id; + note.start = get_start_address(mc, range); + note.count = get_count(mc, range); + + add_notify(mc, ¬e); + return 0; +} + +static int inform_yielded(Client *mc, Range *range) { + Notify note; + printf("Address range yielded\n"); + + note.kind = MAAP_YIELDED; + note.id = range->id; + note.start = get_start_address(mc, range); + note.count = get_count(mc, range); + + add_notify(mc, ¬e); + return 0; +} + +static void start_timer(Client *mc) { + + if (mc->timer_queue) { + Time_setTimer(mc->timer, &mc->timer_queue->next_act_time); + } + + mc->timer_running = 1; +} + +void add_notify(Client *mc, Notify *mn) { + Notify_List *tmp, *li = calloc(1, sizeof (Notify_List)); + memcpy(&li->notify, mn, sizeof (Notify)); + + if (mc->notifies == NULL) { + mc->notifies = li; + } else { + tmp = mc->notifies; + while (tmp->next) { + tmp = tmp->next; + } + tmp->next = li; + } +} + +int get_notify(Client *mc, Notify *mn) { + Notify_List *tmp; + + if (mc->notifies) { + tmp = mc->notifies; + memcpy(mn, tmp, sizeof (Notify)); + mc->notifies = tmp->next; + free(tmp); + return 1; + } + return 0; +} + +int maap_init_client(Client *mc, uint64_t range_info) { + if (mc->initialized) { + printf("MAAP already initialized\n"); + return -1; + } + + mc->timer = Time_newTimer(); + if (!mc->timer) { + printf("Failed to create Timer\n"); + return -1; + } + + mc->net = Net_newNet(); + if (!mc->net) { + printf("Failed to create Net\n"); + Time_delTimer(mc->timer); + return -1; + } + + mc->address_base = range_info & MAAP_BASE_MASK; + /* Consider 0 to be 0x10000, since 0 doesn't make sense and 0x10000 is + the maximum number of values that can be stored in 16 bits */ + mc->range_len = (range_info & MAAP_RANGE_MASK) >> (ETH_ALEN * 8); + if (mc->range_len == 0) { mc->range_len = 0x10000; } + mc->ranges = NULL; + mc->timer_queue = NULL; + mc->maxid = 0; + mc->timer_running = 0; + mc->notifies = NULL; + + mc->initialized = 1; + + printf("MAAP initialized, start: %012llx, max: %08x", + (unsigned long long)range_info & MAAP_BASE_MASK, + (unsigned int)((range_info & MAAP_RANGE_MASK) >> (ETH_ALEN * 8)) - 1); + return 0; +} + +void maap_deinit_client(Client *mc) { + assert(!mc->initialized); + assert(!mc->timer_queue); + + Time_delTimer(mc->timer); + Net_delNet(mc->net); + + mc->timer = NULL; + mc->net = NULL; + mc->initialized = 0; +} + +int rand_ms(int variation) { + return random() % variation; +} + +int schedule_timer(Client *mc, Range *range) { + Range *rp; + uint64_t ns; + Time ts; + + if (range->state == MAAP_STATE_PROBING) { + ns = MAAP_PROBE_INTERVAL_BASE + rand_ms(MAAP_PROBE_INTERVAL_VARIATION); + ns = ns * 1000000; + printf("Scheduling probe timer for %" PRIu64 " ns from now", ns); + Time_setFromNanos(&ts, ns); + printf("Which is a timespec of:"); + Time_dump(&ts); + Time_setFromMonotonicTimer(&range->next_act_time); + printf("Current time is:"); + Time_dump(&range->next_act_time); + Time_add(&range->next_act_time, &ts); + printf("Expiration time is:"); + Time_dump(&range->next_act_time); + printf("\n\n"); + } else if (range->state == MAAP_STATE_DEFENDING) { + ns = MAAP_ANNOUNCE_INTERVAL_BASE + rand_ms(MAAP_ANNOUNCE_INTERVAL_VARIATION); + ns = ns * 1000000; + printf("Scheduling defend timer for %" PRIx64 " ns from now", ns); + Time_setFromNanos(&ts, (uint64_t)ns); + Time_setFromMonotonicTimer(&range->next_act_time); + Time_add(&range->next_act_time, &ts); + Time_dump(&range->next_act_time); + } + + if (mc->timer_queue == NULL || + Time_cmp(&range->next_act_time, &mc->timer_queue->next_act_time) < 0) { + range->next_timer = mc->timer_queue; + mc->timer_queue = range; + } else { + rp = mc->timer_queue; + while (rp->next_timer && + Time_cmp(&rp->next_timer->next_act_time, &range->next_act_time) <= 0) { + rp = rp->next_timer; + } + range->next_timer = rp->next_timer; + rp->next_timer = range; + } + + return 0; +} + +int assign_interval(Client *mc, Range *range, uint16_t len) { + Interval *iv; + int rv = INTERVAL_OVERLAP; + uint32_t range_max; + + range_max = mc->range_len - 1; + + while (rv == INTERVAL_OVERLAP) { + iv = alloc_interval(random() % mc->range_len, len); + if (iv->high > range_max) { + rv = INTERVAL_OVERLAP; + } else { + rv = insert_interval(&mc->ranges, iv); + } + if (rv == INTERVAL_OVERLAP) { + free_interval(iv); + } + } + + iv->data = range; + range->interval = iv; + + return 0; +} + +int maap_reserve_range(Client *mc, uint16_t length) { + int id; + Range *range; + + range = malloc(sizeof (Range)); + if (range == NULL) { + return -1; + } + + id = mc->maxid++; + range->id = id; + range->state = MAAP_STATE_PROBING; + range->counter = MAAP_PROBE_RETRANSMITS; + Time_setFromMonotonicTimer(&range->next_act_time); + range->interval = NULL; + range->next_timer = NULL; + + assign_interval(mc, range, length); + send_probe(mc, range); + range->counter--; + schedule_timer(mc, range); + start_timer(mc); + + printf("Requested address range, id %d", id); + + return id; +} + +int maap_release_range(Client *mc, int id) { + Interval *iv; + Range *range; + int rv = -1; + + range = mc->timer_queue; + while (range) { + if (range->id == id) { + iv = range->interval; + iv = remove_interval(&mc->ranges, iv); + free_interval(iv); + /* memory for range will be freed the next time its timer elapses */ + range->state = MAAP_STATE_RELEASED; + printf("Released range id %d", id); + rv = 0; + } + range = range->next_timer; + } + + return rv; +} + +int maap_handle_packet(Client *mc, uint8_t *stream, int len) { + MAAP_Packet p; + Interval *iv; + uint32_t start; + Range *range; + int rv; + unsigned long long int a, b, c, d; + + printf("RECEIVED MAAP PACKET LEN %d", len); + if (len < 42) { + printf("Truncated MAAP packet recieved, discarding"); + return 0; + } + rv = unpack_maap(&p, stream); + if (rv != 0) { + return rv; + } + + printf("Unpacked packet"); + + a = p.requested_start_address + p.requested_count - 1; + b = mc->address_base; + c = mc->address_base + mc->range_len - 1; + d = p.requested_start_address; + if (a < b || c < d) { + printf("Packet refers to a range outside of our concern"); + printf("%016llx < %016llx || %016llx < %016llx", a, b, c, d); + return 0; + } + + start = (uint64_t)p.requested_start_address - mc->address_base; + iv = search_interval(mc->ranges, start, p.requested_count); + if (iv != NULL) { + range = iv->data; + if (range->state == MAAP_STATE_PROBING) { + printf("Found a conflicting preexisting range, look for a new one"); + /* Find an alternate interval, remove old interval, + and restart probe counter */ + assign_interval(mc, range, iv->high - iv->low + 1); + iv = remove_interval(&mc->ranges, iv); + free_interval(iv); + range->counter = MAAP_PROBE_RETRANSMITS; + } else if (range->state == MAAP_STATE_DEFENDING) { + printf("Someone is messing with our range!"); + if (p.message_type == MAAP_PROBE) { + printf("DEFEND!"); + send_defend(mc, range, p.requested_start_address, p.requested_count, + p.SA); + } else if (p.message_type == MAAP_ANNOUNCE) { + /* We may only defend vs. an ANNOUNCE once */ + if (range->counter == 0) { + printf("Defend vs. ANNOUNCE"); + send_defend(mc, range, p.requested_start_address, p.requested_count, + p.SA); + range->counter = 1; + } else { + printf("Yield vs. ANNOUNCE"); + inform_yielded(mc, range); + iv = remove_interval(&mc->ranges, iv); + free_interval(iv); + /* memory will be freed the next time its timer elapses */ + range->state = MAAP_STATE_RELEASED; + } + } else { + printf("Got a DEFEND vs. a range we own"); + /* Don't know what to do with a DEFEND, so ignore it. They'll + send another ANNOUNCE anyway. We could yield here if we wanted + to be nice */ + ; + } + } + } + + return 0; +} + +int handle_probe_timer(Client *mc, Range *range) { + if (range->counter == 0) { + inform_acquired(mc, range); + range->state = MAAP_STATE_DEFENDING; + send_announce(mc, range); + schedule_timer(mc, range); + } else { + send_probe(mc, range); + range->counter--; + schedule_timer(mc, range); + } + + return 0; +} + +int handle_defend_timer(Client *mc, Range *range) { + send_announce(mc, range); + schedule_timer(mc, range); + + return 0; +} + +int maap_handle_timer(Client *mc, Time *time) { + Range *range; + + mc->timer_running = 0; + + while ((range = mc->timer_queue) && Time_passed(time, &range->next_act_time)) { + printf("Current time:"); + Time_dump(time); + printf("Due timer:"); + Time_dump(&range->next_act_time); + mc->timer_queue = range->next_timer; + range->next_timer = NULL; + + if (range->state == MAAP_STATE_PROBING) { + printf("Handling probe timer"); + handle_probe_timer(mc, range); + } else if (range->state == MAAP_STATE_DEFENDING) { + printf("Handling defend timer"); + handle_defend_timer(mc, range); + } else if (range->state == MAAP_STATE_RELEASED) { + printf("Freeing released timer"); + free(range); + } + + } + + start_timer(mc); + + return 0; +} diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h new file mode 100644 index 00000000..8e3aa10f --- /dev/null +++ b/daemons/maap/common/maap.h @@ -0,0 +1,73 @@ +#ifndef MAAP_H +#define MAAP_H + +#include +#include +#include +#include "intervals.h" +#include "maap_iface.h" +#include "maap_timer.h" +#include "maap_net.h" + +#define MAAP_PROBE_RETRANSMITS 3 + +/* Times are in milliseconds */ +#define MAAP_PROBE_INTERVAL_BASE 500 +#define MAAP_PROBE_INTERVAL_VARIATION 100 +#define MAAP_ANNOUNCE_INTERVAL_BASE 30000 +#define MAAP_ANNOUNCE_INTERVAL_VARIATION 1000 + +#define MAAP_STATE_PROBING 0 +#define MAAP_STATE_DEFENDING 1 +#define MAAP_STATE_RELEASED 2 + +#define MAAP_CB_ACQUIRED 0 +#define MAAP_CB_YIELDED 1 + +#define MAAP_DEST_MAC {0x91, 0xE0, 0xF0, 0x00, 0xFF, 0x00} +#define MAAP_DEST_64 0x000091E0F000FF00LL +#define MAAP_TYPE 0x22F0 +#define MAAP_SUBTYPE 0xFE +#define MAAP_PKT_SIZE 42 +#define MAAP_RANGE_MASK 0xFFFF000000000000LL +#define MAAP_BASE_MASK 0x0000FFFFFFFFFFFFLL + +typedef struct notify_list Notify_List; +struct notify_list { + Notify notify; + Notify_List *next; +}; + +typedef struct range Range; +struct range { + int id; + int state; + int counter; + Time next_act_time; + Interval *interval; + Range *next_timer; +}; + +typedef struct { + uint64_t address_base; + uint32_t range_len; + Interval *ranges; + Range *timer_queue; + Timer *timer; + Net *net; + int timer_running; + int maxid; + Notify_List *notifies; + int initialized; +} Client; + +int maap_init_client(Client *mc, uint64_t range_info); +int maap_reserve_range(Client *mc, uint16_t length); +int maap_release_range(Client *mc, int id); + +int maap_handle_packet(Client *mc, uint8_t *stream, int len); +int maap_handle_timer(Client *mc, Time *time); +void add_notify(Client *mc, Notify *mn); +int get_notify(Client *mc, Notify *mn); + +#endif diff --git a/daemons/maap/common/maap_iface.h b/daemons/maap/common/maap_iface.h new file mode 100644 index 00000000..ccf0cd64 --- /dev/null +++ b/daemons/maap/common/maap_iface.h @@ -0,0 +1,42 @@ +#ifndef MAAP_IFACE_H +#define MAAP_IFACE_H + +#include + +#define MAAP_SOCKET_NAME "/var/tmp/maap.socket" +#define MAAP_CMD_BUF_SZ 500 + +/* MAAP Reqeust Format + * + * This is the format of the request the driver expects to receive from the + * Host application via a write(). + */ + +typedef enum { + MAAP_INIT, + MAAP_RESERVE, + MAAP_RELEASE, +} Cmd_Tag; + +typedef struct { + Cmd_Tag kind; + union { + uint64_t range_info; + uint16_t length; + int id; + } param; +} Cmd; + +typedef enum { + MAAP_ACQUIRED, + MAAP_YIELDED, +} Notify_Tag; + +typedef struct { + Notify_Tag kind; + int id; + uint64_t start; + uint16_t count; +} Notify; + +#endif diff --git a/daemons/maap/common/maap_net.h b/daemons/maap/common/maap_net.h new file mode 100644 index 00000000..25208f9c --- /dev/null +++ b/daemons/maap/common/maap_net.h @@ -0,0 +1,14 @@ +#ifndef MAAP_NET_H +#define MAAP_NET_H + +typedef struct maap_net Net; + +Net *Net_newNet(void); + +void Net_delNet(Net *net); + +void *Net_getPacketBuffer(Net *net); + +int Net_sendPacket(Net *net, void *buffer); + +#endif diff --git a/daemons/maap/common/maap_packet.c b/daemons/maap/common/maap_packet.c new file mode 100644 index 00000000..a3f41fc4 --- /dev/null +++ b/daemons/maap/common/maap_packet.c @@ -0,0 +1,141 @@ +#include +#include +#include "maap.h" +#include "maap_packet.h" + +int unpack_maap(MAAP_Packet *packet, uint8_t *stream) { + uint64_t tmp64; + uint16_t tmp16; + uint8_t tmp8; + + assert(packet); + assert(stream); + + memcpy(&tmp64, stream, 6); + packet->DA = BE64TOH(tmp64) >> 16; + stream += 6; + + memcpy(&tmp64, stream, 6); + packet->SA = BE64TOH(tmp64) >> 16; + stream += 6; + + memcpy(&tmp16, stream, 2); + packet->Ethertype = BE16TOH(tmp16); + stream += 2; + + memcpy(&tmp8, stream, 1); + packet->CD = (tmp8 & 0x80) >> 7; + packet->subtype = tmp8 & 0x7f; + stream++; + + memcpy(&tmp8, stream, 1); + packet->SV = (tmp8 & 0x80) >> 7; + packet->version = (tmp8 & 0x70) >> 4; + packet->message_type = tmp8 & 0x0f; + stream++; + + memcpy(&tmp8, stream, 1); + packet->status = (tmp8 & 0xf8) >> 3; + + memcpy(&tmp16, stream, 2); + packet->MAAP_data_length = BE16TOH(tmp16) & 0x07ff; + stream += 2; + + memcpy(&tmp64, stream, 8); + packet->stream_id = BE64TOH(tmp64); + stream += 8; + + memcpy(&tmp64, stream, 6); + packet->requested_start_address = BE64TOH(tmp64) >> 16; + stream += 6; + + memcpy(&tmp16, stream, 2); + packet->requested_count = BE16TOH(tmp16); + stream += 2; + + memcpy(&tmp64, stream, 6); + packet->start_address = BE64TOH(tmp64) >> 16; + stream += 6; + + memcpy(&tmp16, stream, 2); + packet->count = BE16TOH(tmp16); + + return 0; +} + +int pack_maap(MAAP_Packet *packet, uint8_t *stream) { + uint64_t tmp64; + uint16_t tmp16; + uint8_t tmp8; + + assert(packet); + assert(stream); + + tmp64 = HTOBE64(packet->DA << 16); + memcpy(stream, &tmp64, 6); + stream += 6; + + tmp64 = HTOBE64(packet->SA << 16); + memcpy(stream, &tmp64, 6); + stream += 6; + + tmp16 = HTOBE16(packet->Ethertype); + memcpy(stream, &tmp16, 2); + stream += 2; + + tmp8 = (packet->CD << 7) | (packet->subtype & 0x7f); + memcpy(stream, &tmp8, 1); + stream++; + + tmp8 = (packet->SV << 7) | ((packet->version & 0x07) << 4) | + (packet->message_type & 0x0f); + memcpy(stream, &tmp8, 1); + stream++; + + tmp16 = HTOBE16(((packet->status & 0x001f) << 11) | + (packet->MAAP_data_length & 0x07ff)); + memcpy(stream, &tmp16, 2); + stream += 2; + + tmp64 = HTOBE64(packet->stream_id); + memcpy(stream, &tmp64, 8); + stream += 8; + + tmp64 = HTOBE64(packet->requested_start_address << 16); + memcpy(stream, &tmp64, 6); + stream += 6; + + tmp16 = HTOBE16(packet->requested_count); + memcpy(stream, &tmp16, 2); + stream += 2; + + tmp64 = HTOBE64(packet->start_address << 16); + memcpy(stream, &tmp64, 6); + stream += 6; + + tmp16 = HTOBE16(packet->count); + memcpy(stream, &tmp16, 2); + + return 0; +} + +void init_packet(MAAP_Packet *packet) { + assert(packet); + + packet->DA = MAAP_DEST_64; + // packet->DA = 0xFFFFFFFFFFFF; + packet->SA = 0x0; + packet->Ethertype = MAAP_TYPE; + packet->CD = 1; + packet->subtype = 0x7e; + packet->SV = 0; + packet->version = 1; + packet->message_type = 0; + packet->status = 0; + packet->MAAP_data_length = 16; + packet->stream_id = 0; + packet->requested_start_address = 0; + packet->requested_count = 0; + packet->start_address = 0; + packet->count = 0; +} diff --git a/daemons/maap/common/maap_packet.h b/daemons/maap/common/maap_packet.h new file mode 100644 index 00000000..231456bb --- /dev/null +++ b/daemons/maap/common/maap_packet.h @@ -0,0 +1,35 @@ +#ifndef MAAP_PACKET_H +#define MAAP_PACKET_H + +#include + +#include "platform.h" + +#define MAAP_RESERVED 0 +#define MAAP_PROBE 1 +#define MAAP_DEFEND 2 +#define MAAP_ANNOUNCE 3 + +typedef struct maap_packet { + uint64_t DA; + uint64_t SA; + uint16_t Ethertype; + uint8_t CD; + uint16_t subtype; + uint8_t SV; + uint8_t version; + uint8_t message_type; + uint8_t status; + uint16_t MAAP_data_length; + uint64_t stream_id; + uint64_t requested_start_address; + uint16_t requested_count; + uint64_t start_address; + uint16_t count; +} MAAP_Packet; + +void init_packet(MAAP_Packet *packet); +int pack_maap(MAAP_Packet *packet, uint8_t *stream); +int unpack_maap(MAAP_Packet *packet, uint8_t *stream); + +#endif diff --git a/daemons/maap/common/maap_timer.h b/daemons/maap/common/maap_timer.h new file mode 100644 index 00000000..1bdd2f81 --- /dev/null +++ b/daemons/maap/common/maap_timer.h @@ -0,0 +1,30 @@ +#ifndef MAAP_TIMER_H +#define MAAP_TIMER_H + +#include + +#include "platform.h" + +typedef struct maap_timer Timer; +typedef OS_TIME_TYPE Time; + +Timer *Time_newTimer(); + +void Time_delTimer(Timer *timer); + +void Time_setTimer(Timer *timer, Time *t); + + +void Time_add(Time *a, Time *b); + +int Time_cmp(Time *a, Time *b); + +int Time_passed(Time *current, Time *target); + +void Time_setFromNanos(Time *t, uint64_t nsec); + +void Time_setFromMonotonicTimer(Time *t); + +void Time_dump(Time *t); + +#endif diff --git a/daemons/maap/common/platform.h b/daemons/maap/common/platform.h new file mode 100644 index 00000000..7bdc33af --- /dev/null +++ b/daemons/maap/common/platform.h @@ -0,0 +1,48 @@ +#ifndef MAAP_PLATFORM_H +#define MAAP_PLATFORM_H + +#if defined(__linux__) + +#include + +#define OS_TIME_TYPE struct timespec + +#elif defined(__APPLE__) + +#include +#include + +#define htobe16(x) OSSwapHostToBigInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define htobe64(x) OSSwapHostToBigInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) + +#define ETH_ALEN 6 + +#define OS_TIME_TYPE struct timeval + +#elif defined(_WIN32) + +#include + +#define htobe16(x) htons(x) +#define be16toh(x) ntohs(x) +#define htobe64(x) ((htonl(1) == 1) ? x : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) +#define be64toh(x) ((ntohl(1) == 1) ? x : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) + +#define OS_TIME_TYPE struct timeval + +#else + +#error Please create the platform support definitions for this platform + +#endif + + +#define HTOBE16(x) htobe16(x) +#define BE16TOH(x) be16toh(x) +#define HTOBE64(x) htobe64(x) +#define BE64TOH(x) be64toh(x) + + +#endif diff --git a/daemons/maap/linux/Makefile b/daemons/maap/linux/Makefile index 520939cb..0cdbe5e7 100644 --- a/daemons/maap/linux/Makefile +++ b/daemons/maap/linux/Makefile @@ -1,15 +1,41 @@ BUILD_DIR=. COMMON_DIR=../common -INCFLAGS=$(COMMON_DIR)/maap_protocol.c +LINUX_DIR=src +TEST_DIR=../test CFLAGS=$(OPT) -Wall EXTRA_FLAGS=-I$(COMMON_DIR) -FLAGS=-lpthread -lpcap +FLAGS=-lpthread -lpcap -lrt CC?=gcc -all: maap_daemon +all: maap_daemon maap_test test_intervals test_maap_packet_packing + +# common/maap_protocol.c, common/maap_protocol.h, and src/maap_linux.c are current OpenAVB files. +# test/endian.h is licensed using the GNU Lesser General Public License version 2.1 + +maap_daemon_legacy: $(LINUX_DIR)/maap_linux_legacy.c + $(CC) -o $(BUILD_DIR)/maap_daemon_legacy $(COMMON_DIR)/maap_protocol.c src/maap_linux_legacy.c $(CFLAGS) $(FLAGS) $(EXTRA_FLAGS) + +maap_daemon: $(LINUX_DIR)/maap_linux.c $(LINUX_DIR)/maap_net_linux.c $(LINUX_DIR)/maap_timer_linux.c \ + $(COMMON_DIR)/intervals.c $(COMMON_DIR)/maap.c $(COMMON_DIR)/maap_packet.c + $(CC) -o $(BUILD_DIR)/maap_daemon \ + $(LINUX_DIR)/maap_linux.c $(LINUX_DIR)/maap_net_linux.c $(LINUX_DIR)/maap_timer_linux.c \ + $(COMMON_DIR)/intervals.c $(COMMON_DIR)/maap.c $(COMMON_DIR)/maap_packet.c \ + $(CFLAGS) $(FLAGS) $(EXTRA_FLAGS) + + +maap_test: $(TEST_DIR)/maap_test.c + $(CC) -o $(BUILD_DIR)/maap_test $(TEST_DIR)/maap_test.c $(CFLAGS) $(FLAGS) $(EXTRA_FLAGS) + +test_intervals: $(TEST_DIR)/test_intervals.c + $(CC) -o $(BUILD_DIR)/test_intervals $(TEST_DIR)/test_intervals.c $(COMMON_DIR)/intervals.c $(CFLAGS) $(FLAGS) $(EXTRA_FLAGS) + +test_maap_packet_packing: $(TEST_DIR)/test_maap_packet_packing.c + $(CC) -o $(BUILD_DIR)/test_maap_packet_packing $(TEST_DIR)/test_maap_packet_packing.c $(COMMON_DIR)/maap_packet.c $(CFLAGS) $(FLAGS) $(EXTRA_FLAGS) -maap_daemon: maap_linux.c - $(CC) -o $(BUILD_DIR)/maap_daemon $(INCFLAGS) maap_linux.c $(CFLAGS) $(FLAGS) $(EXTRA_FLAGS) clean: + rm -rf $(BUILD_DIR)/maap_daemon_legacy rm -rf $(BUILD_DIR)/maap_daemon + rm -rf $(BUILD_DIR)/maap_test + rm -rf $(BUILD_DIR)/test_intervals + rm -rf $(BUILD_DIR)/test_maap_packet_packing diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c new file mode 100644 index 00000000..10ea0c17 --- /dev/null +++ b/daemons/maap/linux/src/maap_linux.c @@ -0,0 +1,26 @@ +#include "maap.h" + +#include +#include +#include +#include + +Client mc; + +/* + + 1. Initialize raw socket networking, register to receive MAAP frames + + 2. Create unix domain socket for clients to talk to us on + + 3. Start an event loop: Events are received packets, received client messages, + and timers elapsing + + */ + +int main(int argc, char *argv[]) +{ + + + return 0; +} diff --git a/daemons/maap/linux/src/maap_linux_legacy.c b/daemons/maap/linux/src/maap_linux_legacy.c new file mode 100644 index 00000000..c0634c69 --- /dev/null +++ b/daemons/maap/linux/src/maap_linux_legacy.c @@ -0,0 +1,279 @@ +/************************************************************************* + Copyright (c) 2015 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ + All rights reserved. + + 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. + + 3. Neither the name of the Vayavya labs nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. + +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "maap_protocol.h" + +uint8_t *maap_shm_mem; +struct sockaddr_ll saddrll; +pthread_t thread; +pthread_mutex_t lock; +int socketfd; + +#define VERSION_STR "0.0" + +static const char *version_str = + "maap_daemon v" VERSION_STR "\n" "Copyright (c) 2014, VAYAVYA LABS PVT LTD\n"; + +void usage(void) +{ + fprintf(stderr, + "\n" + "usage: maap_daemon [-d] -i interface-name" + "\n" + "options:\n" + " -d run daemon in the background\n" + " -i specify interface to monitor\n" + "\n" "%s" "\n", version_str); + exit(1); +} + +int main(int argc, char *argv[]) +{ + char *iface = NULL; + struct ifreq buffer; + int ifindex; + struct packet_mreq mreq; + maap_info_t *maap_Info; + uint32_t seed; + uint8_t dest_mac[6]; + uint8_t src_mac[6]; + int daemonize = 0; + int shmid; + key_t key; + int ret; + int c; + + for (;;) { + c = getopt(argc, argv, "hdi:"); + + if (c < 0) + break; + + switch (c) { + case 'd': + daemonize = 1; + break; + case 'i': + if (iface) { + printf + ("only one interface per daemon is supported\n"); + usage(); + } + iface = strdup(optarg); + break; + case 'h': + default: + usage(); + break; + } + } + if (optind < argc) + usage(); + + if (iface == NULL) + usage(); + + if (daemonize) { + ret = daemon(1, 0); + if (ret) { + printf("Error: Failed to daemonize\n"); + return -1; + } + } + + if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_TYPE))) < 0 ) + { + printf("Error: could not open socket %d\n",socketfd); + return -1; + } + + memset(&buffer, 0x00, sizeof(buffer)); + strncpy(buffer.ifr_name, (char *)iface, IFNAMSIZ); + if (ioctl(socketfd, SIOCGIFINDEX, &buffer) < 0) + { + printf("Error: could not get interface index\n"); + close(socketfd); + return -1; + } + + key = 1234; + if ((shmid = shmget(key, MAC_ADDR_LEN, IPC_CREAT | 0666)) < 0) { + printf("Error : Failed to allocate the Shared Memory\n"); + close(socketfd); + return -1; + } + + if ((maap_shm_mem = shmat(shmid, NULL, 0)) == (uint8_t *) -1) { + printf("Error : Failed to attach the created segment id by function \ + shmget()"); + close(socketfd); + return -1; + } + + ifindex = buffer.ifr_ifindex; + if (ioctl(socketfd, SIOCGIFHWADDR, &buffer) < 0) { + printf("Error: could not get interface address\n"); + close(socketfd); + return -1; + } + memcpy(src_mac, buffer.ifr_hwaddr.sa_data, MAC_ADDR_LEN); + + get_multicast_mac_adr(dest_mac); + + memset((void*)&saddrll, 0, sizeof(saddrll)); + saddrll.sll_family = AF_PACKET; + saddrll.sll_ifindex = ifindex; + saddrll.sll_halen = MAC_ADDR_LEN; + memcpy((void*)(saddrll.sll_addr), (void*)dest_mac, MAC_ADDR_LEN); + + if (bind(socketfd, (struct sockaddr*)&saddrll, sizeof(saddrll))) { + printf("Error: could not bind datagram socket\n"); + return -1; + } + + /* filter multicast address */ + memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = ifindex; + mreq.mr_type = PACKET_MR_MULTICAST; + mreq.mr_alen = 6; + memcpy(mreq.mr_address, dest_mac, mreq.mr_alen); + + if (setsockopt(socketfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, + sizeof(mreq)) < 0) { + printf("setsockopt PACKET_ADD_MEMBERSHIP failed\n"); + return -1; + } + + pthread_mutex_init(&(lock), NULL); + seed = src_mac[5] + time(NULL); + srand(seed); + + maap_Info = (maap_info_t *)calloc(1,sizeof(maap_info_t)); + + /* Initialize packet header and data */ + Init(maap_Info, src_mac); + + while (1) { + state_transit(maap_Info); + } + + close(socketfd); + + free(maap_Info); + + return 0; +} + +void delay(int seconds, int millisecond) +{ + sleep(seconds); + usleep(millisecond * 1000); +} + +void create_thread(maap_info_t *maap_info, void *announce) +{ + pthread_create(&thread, NULL, announce, (void *)(maap_info)); +} + +void destroy_thread() +{ + pthread_cancel(thread); +} + +double rand_frange(double min_n, double max_n) +{ + return (double)rand()/RAND_MAX * (max_n - min_n) + min_n; +} + +int rand_range(int min_n, int max_n) +{ + return rand() % (max_n - min_n + 1) + min_n; +} + +void send_packet(ethpkt_t *pkt_tx) +{ + int result; + if ((result = (sendto(socketfd, pkt_tx, ETH_PKT_LEN, 0, + (struct sockaddr*)&saddrll, sizeof(saddrll)) > 0))) + DBG("send successful %d\n", result); + else + DBG("Error: sending of packet failed\n"); +} + +int recv_packet(ethpkt_t *pkt_rx, int flag) +{ + int result; + socklen_t fmlen = sizeof(saddrll); + + if (flag == NON_BLOCK) + flag = MSG_DONTWAIT; + + result = recvfrom(socketfd, pkt_rx, ETH_PKT_LEN, flag, + (struct sockaddr*)&saddrll, &fmlen); + return result; +} + +void Lock() +{ + pthread_mutex_lock(&lock); +} + +void UnLock() +{ + pthread_mutex_unlock(&lock); +} + +uint16_t hton_s(uint16_t val) +{ + return htons(val); +} diff --git a/daemons/maap/linux/src/maap_net_linux.c b/daemons/maap/linux/src/maap_net_linux.c new file mode 100644 index 00000000..48a066b9 --- /dev/null +++ b/daemons/maap/linux/src/maap_net_linux.c @@ -0,0 +1,36 @@ +#include +#include + +#include "maap_net.h" + +struct maap_net { + char net_buffer[64]; +}; + +Net *Net_newNet(void) +{ + return malloc(sizeof (Net)); +} + +void Net_delNet(Net *net) +{ + assert(net); + free(net); +} + +void *Net_getPacketBuffer(Net *net) +{ + assert(net); + return (void*)net->net_buffer; +} + +int Net_sendPacket(Net *net, void *buffer) +{ + assert(net); + assert(buffer == (void*)net->net_buffer); + /* @TODO Send Packet Here */ + + return 1; +} + + diff --git a/daemons/maap/linux/src/maap_timer_linux.c b/daemons/maap/linux/src/maap_timer_linux.c new file mode 100644 index 00000000..91dfb39b --- /dev/null +++ b/daemons/maap/linux/src/maap_timer_linux.c @@ -0,0 +1,86 @@ +#include +#include +#include + +#include "maap_timer.h" + +struct maap_timer { + timer_t timer_id; +}; + +#include + +Timer *Time_newTimer(void) +{ + return malloc(sizeof (Timer)); +} + +void Time_delTimer(Timer *timer) +{ + assert(timer); + free(timer); +} + +void Time_setTimer(Timer *timer, Time *t) +{ + struct itimerspec tspec; + tspec.it_value.tv_sec = t->tv_sec; + tspec.it_value.tv_nsec = t->tv_nsec; + tspec.it_interval.tv_sec = 0; + tspec.it_interval.tv_nsec = 0; + timer_settime(timer->timer_id, TIMER_ABSTIME, &tspec, NULL); +} + +void Time_add(Time *a, Time *b) +{ + a->tv_sec = a->tv_sec + b->tv_sec; + a->tv_nsec = a->tv_nsec + b->tv_nsec; + if (a->tv_nsec > 1000000000L) { + a->tv_sec++; + a->tv_nsec = a->tv_nsec - 1000000000L; + } +} + +int Time_cmp(Time *a, Time *b) +{ + if (a->tv_sec < b->tv_sec) { + return -1; + } + if (a->tv_sec > b->tv_sec) { + return 1; + } + if (a->tv_nsec < b->tv_nsec) { + return -1; + } + if (a->tv_nsec > b->tv_nsec) { + return 1; + } + return 0; +} + +int Time_passed(Time *current, Time *target) +{ + if (current->tv_sec < target->tv_sec) { + return 0; + } + if (current->tv_sec == target->tv_sec && current->tv_nsec < target->tv_nsec) { + return 0; + } + return 1; +} + +void Time_setFromNanos(Time *t, uint64_t nsec) +{ + t->tv_sec = nsec / 1000000000LL; + t->tv_nsec = nsec - t->tv_sec * 1000000000LL; +} + +void Time_setFromMonotonicTimer(Time *t) +{ + clock_gettime(CLOCK_MONOTONIC, t); +} + +void Time_dump(Time *t) +{ + printf("tv_sec: %lu tv_nsec: %lu", (unsigned long)t->tv_sec, (unsigned long)t->tv_nsec); +} diff --git a/daemons/maap/test/endian.h b/daemons/maap/test/endian.h new file mode 100755 index 00000000..37d030a2 --- /dev/null +++ b/daemons/maap/test/endian.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1992, 1996, 1997, 2000, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ENDIAN_H +#define _ENDIAN_H 1 + +#include + +/* Definitions for byte order, according to significance of bytes, + from low addresses to high addresses. The value is what you get by + putting '4' in the most significant byte, '3' in the second most + significant byte, '2' in the second least significant byte, and '1' + in the least significant byte, and then writing down one digit for + each byte, starting with the byte at the lowest address at the left, + and proceeding to the byte with the highest address at the right. */ + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __PDP_ENDIAN 3412 + +/* This file defines `__BYTE_ORDER' for the particular machine. */ +#include + +/* Some machines may need to use a different endianness for floating point + values. */ +#ifndef __FLOAT_WORD_ORDER +# define __FLOAT_WORD_ORDER __BYTE_ORDER +#endif + +#ifdef __USE_BSD +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# define BIG_ENDIAN __BIG_ENDIAN +# define PDP_ENDIAN __PDP_ENDIAN +# define BYTE_ORDER __BYTE_ORDER +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define __LONG_LONG_PAIR(HI, LO) LO, HI +#elif __BYTE_ORDER == __BIG_ENDIAN +# define __LONG_LONG_PAIR(HI, LO) HI, LO +#endif + + +#ifdef __USE_BSD +/* Conversion interfaces. */ +# include + +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define htobe16(x) __bswap_16 (x) +# define htole16(x) (x) +# define be16toh(x) __bswap_16 (x) +# define le16toh(x) (x) + +# define htobe32(x) __bswap_32 (x) +# define htole32(x) (x) +# define be32toh(x) __bswap_32 (x) +# define le32toh(x) (x) + +# define htobe64(x) __bswap_64 (x) +# define htole64(x) (x) +# define be64toh(x) __bswap_64 (x) +# define le64toh(x) (x) +# else +# define htobe16(x) (x) +# define htole16(x) __bswap_16 (x) +# define be16toh(x) (x) +# define le16toh(x) __bswap_16 (x) + +# define htobe32(x) (x) +# define htole32(x) __bswap_32 (x) +# define be32toh(x) (x) +# define le32toh(x) __bswap_32 (x) + +# define htobe64(x) (x) +# define htole64(x) __bswap_64 (x) +# define be64toh(x) (x) +# define le64toh(x) __bswap_64 (x) +# endif +#endif + +#endif /* endian.h */ diff --git a/daemons/maap/test/maap_net_dummy.c b/daemons/maap/test/maap_net_dummy.c new file mode 100644 index 00000000..1a495215 --- /dev/null +++ b/daemons/maap/test/maap_net_dummy.c @@ -0,0 +1,39 @@ +#include +#include + +#include + +#include "maap_net.h" + +struct maap_net { + char net_buffer[64]; +}; + +Net *Net_newNet(void) +{ + return malloc(sizeof (Net)); +} + +void Net_delNet(Net *net) +{ + assert(net); + free(net); +} + +void *Net_getPacketBuffer(Net *net) +{ + assert(net); + return (void*)net->net_buffer; +} + +int Net_sendPacket(Net *net, void *buffer) +{ + assert(net); + assert(buffer == (void*)net->net_buffer); + + printf("Sending packet!\n"); + + return 1; +} + + diff --git a/daemons/maap/test/maap_test.c b/daemons/maap/test/maap_test.c new file mode 100644 index 00000000..4c775f63 --- /dev/null +++ b/daemons/maap/test/maap_test.c @@ -0,0 +1,559 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "endian.h" + +/* Test function forward declarations */ +void test1_setup(void); +void test2_setup(void); +void test3_setup(void); + +/* MAAP packet encoding/decoding */ +#define MAAP_RESERVED 0 +#define MAAP_PROBE 1 +#define MAAP_DEFEND 2 +#define MAAP_ANNOUNCE 3 + +typedef struct maap_packet { + uint64_t DA; + uint64_t SA; + uint16_t Ethertype; + uint8_t CD; + uint16_t subtype; + uint8_t SV; + uint8_t version; + uint8_t message_type; + uint8_t status; + uint16_t MAAP_data_length; + uint64_t stream_id; + uint64_t requested_start_address; + uint16_t requested_count; + uint64_t start_address; + uint16_t count; +} maap_packet_t; + +void dump_raw_stream(uint8_t *stream) { + int i; + for (i = 0; i < 42; i++) { + printf("%02x ", stream[i]); + if ((i+1) % 16 == 0) { + printf("\n"); + } + } +} + +void dump_packed_packet(maap_packet_t *packet) { + printf("\n\n"); + printf("DA: %012llx\n", (unsigned long long)packet->DA); + printf("SA: %012llx\n", (unsigned long long)packet->SA); + printf("Ethertype: 0x%04x\n", packet->Ethertype); + printf("CD: %d\n", packet->CD); + printf("subtype: 0x%02x\n", packet->subtype); + printf("SV: %d\n", packet->SV); + printf("version: %d\n", packet->version); + printf("message_type: %d\n", packet->message_type); + printf("status: %d\n", packet->status); + printf("MAAP_data_length: %d\n", packet->MAAP_data_length); + printf("stream_id: %016llx\n", (unsigned long long)packet->stream_id); + printf("requested_start_address: %012llx\n", (unsigned long long)packet->requested_start_address); + printf("requested_count: %d\n", packet->requested_count); + printf("start_address: %012llx\n", (unsigned long long)packet->start_address); + printf("count: %d\n", packet->count); +} + +int unpack_maap(maap_packet_t *packet, uint8_t *stream) { + + packet->DA = be64toh(*(uint64_t *)stream) >> 16; + stream += 6; + packet->SA = be64toh(*(uint64_t *)stream) >> 16; + stream += 6; + packet->Ethertype = be16toh(*(uint16_t *)stream); + stream += 2; + packet->CD = (*stream & 0x80) >> 7; + packet->subtype = *stream & 0x7f; + stream++; + packet->SV = (*stream & 0x80) >> 7; + packet->version = (*stream & 0x70) >> 4; + packet->message_type = *stream & 0x0f; + stream++; + packet->status = (*stream & 0xf8) >> 3; + packet->MAAP_data_length = be16toh(*(uint16_t *)stream) & 0x07ff; + stream += 2; + packet->stream_id = be64toh(*(uint64_t *)stream); + stream += 8; + packet->requested_start_address = be64toh(*(uint64_t *)stream) >> 16; + stream += 6; + packet->requested_count = be16toh(*(uint16_t *)stream); + stream += 2; + packet->start_address = be64toh(*(uint64_t *)stream) >> 16; + stream += 6; + packet->count = be16toh(*(uint16_t *)stream); + return 0; +} + +int pack_maap(maap_packet_t *packet, uint8_t *stream) { + *(uint64_t *)stream = htobe64(packet->DA << 16); + stream += 6; + *(uint64_t *)stream = htobe64(packet->SA << 16); + stream += 6; + *(uint16_t *)stream = htobe16(packet->Ethertype); + stream += 2; + *stream = (packet->CD << 7) | (packet->subtype & 0x7f); + stream++; + *stream = (packet->SV << 7) | ((packet->version & 0x07) << 4) | + (packet->message_type & 0x0f); + stream++; + *(uint16_t *)stream = htobe16(((packet->status & 0x001f) << 11) | + (packet->MAAP_data_length & 0x07ff)); + stream += 2; + *(uint64_t *)stream = htobe64(packet->stream_id); + stream += 8; + *(uint64_t *)stream = htobe64(packet->requested_start_address << 16); + stream += 6; + *(uint16_t *)stream = htobe16(packet->requested_count); + stream += 2; + *(uint64_t *)stream = htobe64(packet->start_address << 16); + stream += 6; + *(uint16_t *)stream = htobe16(packet->count); + return 0; +} + +/* callback for pcap when packets arrive */ +void parse_packet(u_char *args, const struct pcap_pkthdr *header, + const u_char *packet); + +struct maap_test_state { + int (*pkt_handler)(maap_packet_t *); + int state; + int rawsock; + uint64_t hwaddr; +}; + +struct maap_test_state test_state = {NULL, 0, 0}; + +int get_raw_sock(int ethertype) { + int rawsock; + + if((rawsock = socket(PF_PACKET, SOCK_RAW, htons(ethertype))) == -1) { + perror("Error creating raw sock: "); + exit(-1); + } + + return rawsock; +} + +int bind_sock(char *device, int rawsock, int protocol) { + struct sockaddr_ll sll; + struct ifreq ifr; + + bzero(&sll, sizeof(sll)); + bzero(&ifr, sizeof(ifr)); + + /* First, get the interface index */ + strncpy((char *)ifr.ifr_name, device, IFNAMSIZ); + if((ioctl(rawsock, SIOCGIFINDEX, &ifr)) == -1) { + printf("Error getting Interface index !\n"); + printf("Problem interface: %s\n", device); + exit(-1); + } + + /* Bind our raw socket to this interface */ + sll.sll_family = AF_PACKET; + sll.sll_ifindex = ifr.ifr_ifindex; + sll.sll_protocol = htons(protocol); + + /* Get the mac address */ + if ((ioctl(rawsock, SIOCGIFHWADDR, &ifr)) == -1) { + printf("Error getting HW address\n"); + exit(-1); + } + bcopy(ifr.ifr_hwaddr.sa_data, &test_state.hwaddr, 6); + test_state.hwaddr = be64toh(test_state.hwaddr) >> 16; + printf("Our MAC is %012llx\n", (unsigned long long int)test_state.hwaddr); + + if((bind(rawsock, (struct sockaddr*)&sll, sizeof(sll))) == -1) { + perror("Error binding raw socket to interface\n"); + exit(-1); + } + + return 1; +} + +int send_packet(int rawsock, maap_packet_t *mp) { + int sent = 0; + unsigned char pkt[60]; + + mp->SA = test_state.hwaddr; + + pack_maap(mp, pkt); + if((sent = write(rawsock, pkt, 60)) != 60) { + return 0; + } + return 1; +} + +int main(int argc, char *argv[]) { + char *dev, errbuf[PCAP_ERRBUF_SIZE]; + pcap_t *handle; + struct bpf_program fp; + char filter_exp[] = "ether proto 0x22F0"; + bpf_u_int32 mask; + bpf_u_int32 net; + + dev = pcap_lookupdev(errbuf); + if (dev == NULL) { + fprintf(stderr, "Couldn't find default device: %s\n", errbuf); + return 2; + } + + if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { + fprintf(stderr, "Couldn't get netmask for device: %s\n", dev); + net = 0; + mask = 0; + } + + handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf); + if (handle == NULL) { + fprintf(stderr, "Couldn't open device: %s\n", dev); + return 2; + } + + printf("Listening on device: %s\n", dev); + + if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) { + fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, + pcap_geterr(handle)); + return 2; + } + + if (pcap_setfilter(handle, &fp) == -1) { + fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, + pcap_geterr(handle)); + return 2; + } + + test_state.rawsock = get_raw_sock(0x22F0); + bind_sock(dev, test_state.rawsock, 0x22F0); + + test3_setup(); + + pcap_loop(handle, -1, parse_packet, NULL); +} + +void parse_packet(u_char *args, const struct pcap_pkthdr *header, + const u_char *packet) { + maap_packet_t mp; + + unpack_maap(&mp, (uint8_t *)packet); + + dump_packed_packet(&mp); + + /* Ignore messages from us */ + if (mp.SA == test_state.hwaddr) { + return; + } + + if (test_state.pkt_handler) { + test_state.pkt_handler(&mp); + } + + return; +} + +/************************************************************************* + * Test functions + *************************************************************************/ + +/* Wait for a probe, send a defense response, see if next probe is for a + different range */ + +#define WAITING_FOR_1ST_PROBE 0 +#define WAITING_FOR_2ND_PROBE 1 + +int test1_handler(maap_packet_t *mp) { + static uint64_t start; + static uint16_t count; + + switch (test_state.state) { + + case WAITING_FOR_1ST_PROBE: + + /* Make sure we're getting PROBE packets */ + if (mp->message_type != MAAP_PROBE) { + fprintf(stderr, "Test 1: Error: Received a non-probe MAAP packet. Please start the test suite before starting the MAAP client to be tested.\n"); + exit(2); + } + printf("Received a probe from %012llx for %d addresses starting at %012llx\n", + (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->requested_start_address); + + /* Store the range from the PROBE so we can conflict with it and compare + later */ + start = mp->requested_start_address; + count = mp->requested_count; + + /* Send a defense of this range */ + mp->DA = mp->SA; + mp->SA = 0; + mp->message_type = MAAP_DEFEND; + mp->start_address = start; + mp->count = count; + send_packet(test_state.rawsock, mp); + printf("Sent defend packet\n"); + + /* Update testing state */ + test_state.state = WAITING_FOR_2ND_PROBE; + + break; + + case WAITING_FOR_2ND_PROBE: + + /* Make sure we got a probe in response */ + if (mp->message_type != MAAP_PROBE) { + fprintf(stderr, "Test 1: FAIL - Got a non-probe packet, type %d.\n", + mp->message_type); + exit(2); + } + + printf("Received a probe from %012llx for %d addresses starting at %012llx\n", + (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->requested_start_address); + + /* Make sure the address range has changed */ + if (mp->requested_start_address == start) { + fprintf(stderr, "Test 1: FAIL - Got a probe for the same range.\n"); + exit(2); + } + + /* Success! */ + printf("Test 1: PASS\n"); + + test2_setup(); + + break; + } +} + +void test1_setup(void) { + test_state.state = WAITING_FOR_1ST_PROBE; + test_state.pkt_handler = test1_handler; + printf("Starting test 1: responding to a defend packet while probing\n"); +} + +/* + * Test 2 + */ + +/* Wait for an announce, send a probe for the same range, ensure we get a + * defend for the range */ + +#define WAITING_FOR_ANNOUNCE 0 +#define WAITING_FOR_DEFEND 1 + +int test2_handler(maap_packet_t *mp) { + static uint64_t start; + static uint16_t count; + + switch (test_state.state) { + + case WAITING_FOR_ANNOUNCE: + if (mp->message_type != MAAP_ANNOUNCE) { + /* Ignore non-announce packets */ + break; + } + printf("Received an announce from %012llx for %d addresses starting at %012llx\n", + (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->requested_start_address); + + /* Store the range from the ANNOUNCE so we can check the defense of this + range */ + start = mp->requested_start_address; + count = mp->requested_count; + + /* Send a probe for this range */ + mp->message_type = MAAP_PROBE; + send_packet(test_state.rawsock, mp); + printf("Sent probe packet\n"); + + /* Update testing state */ + test_state.state = WAITING_FOR_DEFEND; + + break; + + case WAITING_FOR_DEFEND: + if (mp->message_type != MAAP_DEFEND) { + fprintf(stderr, "Test 2: FAIL - Got a non-defend packet, type %d.\n", + mp->message_type); + exit(2); + } + if (mp->requested_start_address != start) { + fprintf(stderr, "Test 2: FAIL - Requested start address wasn't filled out with the value from the probe.\n"); + fprintf(stderr, "Req start address: %012llx Probe address: %012llx\n", + (unsigned long long)mp->requested_start_address, + (unsigned long long)start); + exit(2); + } + if (mp->requested_count != count) { + fprintf(stderr, "Test 2: FAIL - Requested count wasn't filled out with the value from the probe.\n"); + fprintf(stderr, "Requested count: %d Probe count: %d\n", + mp->requested_count, count); + exit(2); + } + if (mp->start_address != start) { + fprintf(stderr, "Test 2: FAIL - Start address wasn't filled out with the first conflicting address from the probe.\n"); + fprintf(stderr, "Start address: %012llx Conflicting address: %012llx\n", + (unsigned long long)mp->start_address, + (unsigned long long)start); + exit(2); + } + if (mp->count != count) { + fprintf(stderr, "Test 2: FAIL - Count wasn't filled out with the number of addresses conflicting with the probe.\n"); + fprintf(stderr, "Defend count: %d Conflicting count: %d\n", mp->count, count); + exit(2); + } + + /* Success! */ + printf("Test 2: PASS\n"); + + test3_setup(); + + break; + + } +} + +void test2_setup(void) { + test_state.state = WAITING_FOR_ANNOUNCE; + test_state.pkt_handler = test2_handler; + printf("Starting test 2: defending a reservation from a probe\n"); + printf("Waiting for an announce packet..."); +} + +/* + * Test 3 + */ + +#define WAITING_FOR_PROBE 2 + +int test3_handler(maap_packet_t *mp) { + static uint64_t start; + static uint16_t count; + static maap_packet_t saved_announce; + + switch (test_state.state) { + + case WAITING_FOR_ANNOUNCE: + if (mp->message_type != MAAP_ANNOUNCE) { + /* Ignore non-announce packets */ + break; + } + printf("Received an announce from %012llx for %d addresses starting at %012llx\n", + (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->requested_start_address); + + /* Store the range from the ANNOUNCE so we can check the defense of this + range */ + start = mp->requested_start_address; + count = mp->requested_count; + + /* Send an announce for this range (send the same packet right back) */ + send_packet(test_state.rawsock, mp); + printf("Sent announce packet\n"); + + /* Save a copy so we can send it again */ + memcpy(&saved_announce, mp, sizeof (maap_packet_t)); + + /* Update testing state */ + test_state.state = WAITING_FOR_DEFEND; + + break; + + case WAITING_FOR_DEFEND: + if (mp->message_type != MAAP_DEFEND) { + fprintf(stderr, "test 3: FAIL - Got a non-defend packet, type %d.\n", + mp->message_type); + return; + } + if (mp->requested_start_address != start) { + fprintf(stderr, "test 3: FAIL - Requested start address wasn't filled out with the value from the probe.\n"); + fprintf(stderr, "Req start address: %012llx Probe address: %012llx\n", + (unsigned long long)mp->requested_start_address, + (unsigned long long)start); + return; + } + if (mp->requested_count != count) { + fprintf(stderr, "test 3: FAIL - Requested count wasn't filled out with the value from the probe.\n"); + fprintf(stderr, "Requested count: %d Probe count: %d\n", + mp->requested_count, count); + return; + } + if (mp->start_address != start) { + fprintf(stderr, "test 3: FAIL - Start address wasn't filled out with the first conflicting address from the probe.\n"); + fprintf(stderr, "Start address: %012llx Conflicting address: %012llx\n", + (unsigned long long)mp->start_address, + (unsigned long long)start); + return; + } + if (mp->count != count) { + fprintf(stderr, "test 3: FAIL - Count wasn't filled out with the number of addresses conflicting with the probe.\n"); + fprintf(stderr, "Defend count: %d Conflicting count: %d\n", mp->count, count); + return; + } + + /* Send out the same announce again */ + send_packet(test_state.rawsock, &saved_announce); + printf("Sent second announce\n"); + + /* Update testing state */ + test_state.state = WAITING_FOR_PROBE; + + break; + + case WAITING_FOR_PROBE: + /* Make sure we got a probe in response */ + if (mp->message_type != MAAP_PROBE) { + fprintf(stderr, "Test 3: FAIL - Got a non-probe packet, type %d.\n", + mp->message_type); + return; + } + + printf("Received a probe from %012llx for %d addresses starting at %012llx\n", + (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->requested_start_address); + + /* Make sure the address range has changed */ + if (mp->requested_start_address == start) { + fprintf(stderr, "Test 3: FAIL - Got a probe for the same range.\n"); + exit(2); + } + + /* Success! */ + printf("Test 3: PASS\n"); + + printf("Waiting 5 min for next test...."); + sleep(300); + + test3_setup(); + + break; + + } +} + +void test3_setup(void) { + test_state.state = WAITING_FOR_ANNOUNCE; + test_state.pkt_handler = test3_handler; + printf("Starting test 3: yielding a reservation after 2 announces\n"); + printf("Waiting for an announce packet...\n"); +} + diff --git a/daemons/maap/test/maap_timer_dummy.c b/daemons/maap/test/maap_timer_dummy.c new file mode 100644 index 00000000..fd0071db --- /dev/null +++ b/daemons/maap/test/maap_timer_dummy.c @@ -0,0 +1,81 @@ +#include +#include +#include + +#include "maap_timer.h" + +struct maap_timer { + int timer_id; +}; + +#include + +Timer *Time_newTimer(void) +{ + return malloc(sizeof (Timer)); +} + +void Time_delTimer(Timer *timer) +{ + assert(timer); + free(timer); +} + +void Time_setTimer(Timer *timer, Time *t) +{ + (void)timer; (void)t; +} + +void Time_add(Time *a, Time *b) +{ + a->tv_sec = a->tv_sec + b->tv_sec; + a->tv_usec = a->tv_usec + b->tv_usec; + if (a->tv_usec > 1000000) { + a->tv_sec++; + a->tv_usec = a->tv_usec - 1000000; + } +} + +int Time_cmp(Time *a, Time *b) +{ + if (a->tv_sec < b->tv_sec) { + return -1; + } + if (a->tv_sec > b->tv_sec) { + return 1; + } + if (a->tv_usec < b->tv_usec) { + return -1; + } + if (a->tv_usec > b->tv_usec) { + return 1; + } + return 0; +} + +int Time_passed(Time *current, Time *target) +{ + if (current->tv_sec < target->tv_sec) { + return 0; + } + if (current->tv_sec == target->tv_sec && current->tv_usec < target->tv_usec) { + return 0; + } + return 1; +} + +void Time_setFromNanos(Time *t, uint64_t nsec) +{ + t->tv_sec = nsec / 1000000000LL; + t->tv_usec = (nsec - t->tv_sec * 1000000000LL) / 1000; +} + +void Time_setFromMonotonicTimer(Time *t) +{ + gettimeofday(t, NULL); +} + +void Time_dump(Time *t) +{ + printf("tv_sec: %lu tv_usec: %lu", (unsigned long)t->tv_sec, (unsigned long)t->tv_usec); +} diff --git a/daemons/maap/test/test_intervals.c b/daemons/maap/test/test_intervals.c new file mode 100644 index 00000000..f0bbdacf --- /dev/null +++ b/daemons/maap/test/test_intervals.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include "intervals.h" + +int last_high = 0; +int total = 0; + +void print_node(Interval *node) { + fprintf(stdout, "[%d,%d] ", node->low, node->high); + if (node->low <= last_high || + node->high < node->low) { + fprintf(stderr, "\nERROR: <%d,%d>\n", node->low, node->high); + } + last_high = node->high; + total++; +} + +int main(void) { + Interval *set = NULL, *inter, *over; + int i, rv, count; + + time((time_t *)&i); + srandom(i); + + printf("Testing duplicate values\n"); + inter = alloc_interval(1, 10); + rv = insert_interval(&set, inter); + if (rv != INTERVAL_SUCCESS) { + printf("Insert of [%d,%d] failed unexpectedly\n", inter->low, inter->high); + } else { + printf("Inserted [%d,%d]\n", inter->low, inter->high); + } + inter = alloc_interval(1, 10); + rv = insert_interval(&set, inter); + if (rv != INTERVAL_OVERLAP) { + printf("Insert of [%d,%d] should have failed, but didn't\n", inter->low, inter->high); + } else { + printf("Repeat insert of [%d,%d] failed, so the test passed\n", inter->low, inter->high); + } + + while (set) { + inter = remove_interval(&set, set); + free_interval(inter); + } + + count = 1000; + printf("\nInserting %d random intervals into a set\n", count); + + for (i = 0; i < count;) { + inter = alloc_interval(random() % 0xfffff, random() % 128 + 1); + rv = insert_interval(&set, inter); + if (rv == INTERVAL_OVERLAP) { + over = search_interval(set, inter->low, inter->high - inter->low + 1); + printf("[%d,%d] overlapped existing entry [%d,%d]\n", + inter->low, inter->high, over->low, over->high); + free_interval(inter); + } else { + printf("Inserted [%d,%d]:\n", inter->low, inter->high); + i++; + } + } + + count = 100000; + printf("\nReplacing %d random intervals\n", count); + + for (i = 0, over = NULL; i < count;) { + if (over) { + inter = alloc_interval(random() % 0xfffff, random() % 128 + 1); + rv = insert_interval(&set, inter); + if (rv == INTERVAL_SUCCESS) { + printf("Replaced [%d,%d] with [%d,%d]\n", + over->low, over->high, inter->low, inter->high); + free_interval(over); + over = NULL; + i++; + } else { + printf("Overlapping replacement interval\n"); + free_interval(inter); + } + } else { + over = search_interval(set, random() % 0xfffff, random() % 128 + 1); + if (over) over = remove_interval(&set, over); + } + } + + inter = minimum_interval(set); + printf("\nMinimum Interval: [%d,%d]\n", inter->low, inter->high); + inter = maximum_interval(set); + printf("Maximum Interval: [%d,%d]\n", inter->low, inter->high); + + printf("\nFinal set:\n"); + traverse_interval(set, print_node); + printf("\n"); + fprintf(stderr, "\nTotal members: %d\n", total); + + while (set) { + inter = remove_interval(&set, set); + free_interval(inter); + } + + return 0; +} diff --git a/daemons/maap/test/test_maap_packet_packing.c b/daemons/maap/test/test_maap_packet_packing.c new file mode 100644 index 00000000..7d228cca --- /dev/null +++ b/daemons/maap/test/test_maap_packet_packing.c @@ -0,0 +1,115 @@ +#include "maap_packet.h" +#include +#include +#include + +static uint8_t test_stream[] = { + 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, + 0x12, 0x34, + 0xfe, 0x11, 0x00, 0x10, + 0x01, 0x23, 0x45, 0x67, + 0x89, 0xab, 0xcd, 0xef, + 0xcb, 0xfe, 0x12, 0x34, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +static MAAP_Packet test_packet = { + 0x010203040506, + 0x060504030201, + 0x1234, + 1, + 0x7e, + 0, + 1, + 1, + 0, + 16, + 0x0123456789abcdef, + 0xcbfe12340000, + 255, + 0x000000000000, + 0 +}; + +void dump_stream(uint8_t *stream) { + int i; + for (i = 0; i < 42; i++) { + if (i % 4 == 0) { + printf("\n"); + } + printf("%02x ", stream[i]); + } + printf("\n"); +} + +void dump_maap_packet(MAAP_Packet *packet) { + printf("DA: %012llx\n", (unsigned long long int)packet->DA); + printf("SA: %012llx\n", (unsigned long long int)packet->SA); + printf("Ethertype: %04x\n", packet->Ethertype); + printf("CD: %d\n", packet->CD); + printf("subtype: %d\n", packet->subtype); + printf("SV: %d\n", packet->SV); + printf("version: %d\n", packet->version); + printf("message_type: %d\n", packet->message_type); + printf("status: %d\n", packet->status); + printf("MAAP_data_length: %d\n", packet->MAAP_data_length); + printf("stream_id: 0x%016llx\n", + (unsigned long long int)packet->stream_id); + printf("requested_start_address: 0x%012llx\n", + (unsigned long long int)packet->requested_start_address); + printf("requested_count: %d\n", packet->requested_count); + printf("start_address: 0x%012llx\n", + (unsigned long long int)packet->start_address); + printf("count: %d\n", packet->count); +} + +int cmp_maap_packets(MAAP_Packet *a, MAAP_Packet *b) { + return (a->DA == b->DA && + a->SA == b->SA && + a->Ethertype == b->Ethertype && + a->CD == b->CD && + a->subtype == b->subtype && + a->SV == b->SV && + a->version == b->version && + a->message_type == b->message_type && + a->status == b->status && + a->MAAP_data_length && b->MAAP_data_length && + a->stream_id == b->stream_id && + a->requested_start_address == b->requested_start_address && + a->requested_count == b->requested_count && + a->start_address == b->start_address && + a->count == b->count); +} + +int main(void) { + uint8_t buffer[42] = {0}; + MAAP_Packet result; + + unpack_maap(&result, test_stream); + if (cmp_maap_packets(&result, &test_packet)) { + printf("pack_maap success\n"); + } else { + printf("pack_maap failure\n"); + printf("Expected:\n"); + dump_maap_packet(&test_packet); + printf("Got:\n"); + dump_maap_packet(&result); + printf("\n\n"); + } + + pack_maap(&test_packet, buffer); + if (memcmp(test_stream, buffer, 42) == 0) { + printf("unpack_maap success\n"); + } else { + printf("unpack_maap failure\n"); + printf("Expected:\n"); + dump_stream(test_stream); + printf("Got:\n"); + dump_stream(buffer); + } + return 0; +} -- cgit v1.2.1 From 3bca9d3bb5c4df89cf9336c58dc32086d7407b84 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Wed, 28 Sep 2016 16:52:45 -0600 Subject: Added more unique names to structures and enums. Added newlines to the end of several printf lines. --- daemons/maap/common/maap.c | 102 +++++++++++++------------ daemons/maap/common/maap.h | 29 +++---- daemons/maap/common/maap_iface.h | 19 ++--- daemons/maap/common/maap_parse.c | 121 ++++++++++++++++++++++++++++++ daemons/maap/common/maap_parse.h | 17 +++++ daemons/maap/linux/Makefile | 4 +- daemons/maap/linux/src/maap_linux.c | 26 ------- daemons/maap/linux/src/maap_timer_linux.c | 6 +- 8 files changed, 221 insertions(+), 103 deletions(-) create mode 100644 daemons/maap/common/maap_parse.c create mode 100644 daemons/maap/common/maap_parse.h delete mode 100644 daemons/maap/linux/src/maap_linux.c diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index f685a7b8..fe74add1 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -12,16 +12,16 @@ #include #include -static int get_count(Client *mc, Range *range) { +static int get_count(Maap_Client *mc, Range *range) { (void)mc; return range->interval->high - range->interval->low + 1; } -static uint64_t get_start_address(Client *mc, Range *range) { +static uint64_t get_start_address(Maap_Client *mc, Range *range) { return mc->address_base + range->interval->high; } -static int send_packet(Client *mc, MAAP_Packet *p) { +static int send_packet(Maap_Client *mc, MAAP_Packet *p) { uint8_t *pbuf = NULL; int ret = 0; (void)mc; @@ -34,7 +34,7 @@ static int send_packet(Client *mc, MAAP_Packet *p) { return ret; } -static int send_probe(Client *mc, Range *range) { +static int send_probe(Maap_Client *mc, Range *range) { MAAP_Packet p; init_packet(&p); @@ -46,7 +46,7 @@ static int send_probe(Client *mc, Range *range) { return send_packet(mc, &p); } -static int send_announce(Client *mc, Range *range) { +static int send_announce(Maap_Client *mc, Range *range) { MAAP_Packet p; init_packet(&p); @@ -58,7 +58,7 @@ static int send_announce(Client *mc, Range *range) { return send_packet(mc, &p); } -static int send_defend(Client *mc, Range *range, uint64_t start, +static int send_defend(Maap_Client *mc, Range *range, uint64_t start, uint16_t count, uint64_t destination) { MAAP_Packet p; @@ -74,8 +74,8 @@ static int send_defend(Client *mc, Range *range, uint64_t start, return send_packet(mc, &p); } -static int inform_acquired(Client *mc, Range *range) { - Notify note; +static int inform_acquired(Maap_Client *mc, Range *range) { + Maap_Notify note; printf("Address range acquired: %" PRIx64 " %d\n", get_start_address(mc, range), get_count(mc, range)); @@ -89,8 +89,8 @@ static int inform_acquired(Client *mc, Range *range) { return 0; } -static int inform_yielded(Client *mc, Range *range) { - Notify note; +static int inform_yielded(Maap_Client *mc, Range *range) { + Maap_Notify note; printf("Address range yielded\n"); note.kind = MAAP_YIELDED; @@ -102,7 +102,7 @@ static int inform_yielded(Client *mc, Range *range) { return 0; } -static void start_timer(Client *mc) { +static void start_timer(Maap_Client *mc) { if (mc->timer_queue) { Time_setTimer(mc->timer, &mc->timer_queue->next_act_time); @@ -111,9 +111,9 @@ static void start_timer(Client *mc) { mc->timer_running = 1; } -void add_notify(Client *mc, Notify *mn) { - Notify_List *tmp, *li = calloc(1, sizeof (Notify_List)); - memcpy(&li->notify, mn, sizeof (Notify)); +void add_notify(Maap_Client *mc, Maap_Notify *mn) { + Maap_Notify_List *tmp, *li = calloc(1, sizeof (Maap_Notify_List)); + memcpy(&li->notify, mn, sizeof (Maap_Notify)); if (mc->notifies == NULL) { mc->notifies = li; @@ -126,12 +126,12 @@ void add_notify(Client *mc, Notify *mn) { } } -int get_notify(Client *mc, Notify *mn) { - Notify_List *tmp; +int get_notify(Maap_Client *mc, Maap_Notify *mn) { + Maap_Notify_List *tmp; if (mc->notifies) { tmp = mc->notifies; - memcpy(mn, tmp, sizeof (Notify)); + memcpy(mn, tmp, sizeof (Maap_Notify)); mc->notifies = tmp->next; free(tmp); return 1; @@ -139,7 +139,7 @@ int get_notify(Client *mc, Notify *mn) { return 0; } -int maap_init_client(Client *mc, uint64_t range_info) { +int maap_init_client(Maap_Client *mc, uint64_t range_info) { if (mc->initialized) { printf("MAAP already initialized\n"); return -1; @@ -171,13 +171,13 @@ int maap_init_client(Client *mc, uint64_t range_info) { mc->initialized = 1; - printf("MAAP initialized, start: %012llx, max: %08x", + printf("MAAP initialized, start: %012llx, max: %08x\n", (unsigned long long)range_info & MAAP_BASE_MASK, (unsigned int)((range_info & MAAP_RANGE_MASK) >> (ETH_ALEN * 8)) - 1); return 0; } -void maap_deinit_client(Client *mc) { +void maap_deinit_client(Maap_Client *mc) { assert(!mc->initialized); assert(!mc->timer_queue); @@ -193,7 +193,7 @@ int rand_ms(int variation) { return random() % variation; } -int schedule_timer(Client *mc, Range *range) { +int schedule_timer(Maap_Client *mc, Range *range) { Range *rp; uint64_t ns; Time ts; @@ -201,25 +201,26 @@ int schedule_timer(Client *mc, Range *range) { if (range->state == MAAP_STATE_PROBING) { ns = MAAP_PROBE_INTERVAL_BASE + rand_ms(MAAP_PROBE_INTERVAL_VARIATION); ns = ns * 1000000; - printf("Scheduling probe timer for %" PRIu64 " ns from now", ns); + printf("Scheduling probe timer for %" PRIu64 " ns from now\n", ns); Time_setFromNanos(&ts, ns); - printf("Which is a timespec of:"); + printf("Which is a timespec of: "); Time_dump(&ts); Time_setFromMonotonicTimer(&range->next_act_time); - printf("Current time is:"); + printf("\nCurrent time is: "); Time_dump(&range->next_act_time); Time_add(&range->next_act_time, &ts); - printf("Expiration time is:"); + printf("\nExpiration time is: "); Time_dump(&range->next_act_time); printf("\n\n"); } else if (range->state == MAAP_STATE_DEFENDING) { ns = MAAP_ANNOUNCE_INTERVAL_BASE + rand_ms(MAAP_ANNOUNCE_INTERVAL_VARIATION); ns = ns * 1000000; - printf("Scheduling defend timer for %" PRIx64 " ns from now", ns); + printf("Scheduling defend timer for %" PRIx64 " ns from now\n", ns); Time_setFromNanos(&ts, (uint64_t)ns); Time_setFromMonotonicTimer(&range->next_act_time); Time_add(&range->next_act_time, &ts); Time_dump(&range->next_act_time); + printf("\n\n"); } if (mc->timer_queue == NULL || @@ -239,7 +240,7 @@ int schedule_timer(Client *mc, Range *range) { return 0; } -int assign_interval(Client *mc, Range *range, uint16_t len) { +int assign_interval(Maap_Client *mc, Range *range, uint16_t len) { Interval *iv; int rv = INTERVAL_OVERLAP; uint32_t range_max; @@ -264,7 +265,7 @@ int assign_interval(Client *mc, Range *range, uint16_t len) { return 0; } -int maap_reserve_range(Client *mc, uint16_t length) { +int maap_reserve_range(Maap_Client *mc, uint16_t length) { int id; Range *range; @@ -287,12 +288,12 @@ int maap_reserve_range(Client *mc, uint16_t length) { schedule_timer(mc, range); start_timer(mc); - printf("Requested address range, id %d", id); + printf("Requested address range, id %d\n", id); return id; } -int maap_release_range(Client *mc, int id) { +int maap_release_range(Maap_Client *mc, int id) { Interval *iv; Range *range; int rv = -1; @@ -305,7 +306,7 @@ int maap_release_range(Client *mc, int id) { free_interval(iv); /* memory for range will be freed the next time its timer elapses */ range->state = MAAP_STATE_RELEASED; - printf("Released range id %d", id); + printf("Released range id %d\n", id); rv = 0; } range = range->next_timer; @@ -314,7 +315,7 @@ int maap_release_range(Client *mc, int id) { return rv; } -int maap_handle_packet(Client *mc, uint8_t *stream, int len) { +int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { MAAP_Packet p; Interval *iv; uint32_t start; @@ -322,9 +323,9 @@ int maap_handle_packet(Client *mc, uint8_t *stream, int len) { int rv; unsigned long long int a, b, c, d; - printf("RECEIVED MAAP PACKET LEN %d", len); + printf("RECEIVED MAAP PACKET LEN %d\n", len); if (len < 42) { - printf("Truncated MAAP packet recieved, discarding"); + printf("Truncated MAAP packet received, discarding\n"); return 0; } rv = unpack_maap(&p, stream); @@ -332,15 +333,15 @@ int maap_handle_packet(Client *mc, uint8_t *stream, int len) { return rv; } - printf("Unpacked packet"); + printf("Unpacked packet\n"); a = p.requested_start_address + p.requested_count - 1; b = mc->address_base; c = mc->address_base + mc->range_len - 1; d = p.requested_start_address; if (a < b || c < d) { - printf("Packet refers to a range outside of our concern"); - printf("%016llx < %016llx || %016llx < %016llx", a, b, c, d); + printf("Packet refers to a range outside of our concern\n"); + printf("%016llx < %016llx || %016llx < %016llx\n", a, b, c, d); return 0; } @@ -349,7 +350,7 @@ int maap_handle_packet(Client *mc, uint8_t *stream, int len) { if (iv != NULL) { range = iv->data; if (range->state == MAAP_STATE_PROBING) { - printf("Found a conflicting preexisting range, look for a new one"); + printf("Found a conflicting preexisting range, look for a new one\n"); /* Find an alternate interval, remove old interval, and restart probe counter */ assign_interval(mc, range, iv->high - iv->low + 1); @@ -357,20 +358,20 @@ int maap_handle_packet(Client *mc, uint8_t *stream, int len) { free_interval(iv); range->counter = MAAP_PROBE_RETRANSMITS; } else if (range->state == MAAP_STATE_DEFENDING) { - printf("Someone is messing with our range!"); + printf("Someone is messing with our range!\n"); if (p.message_type == MAAP_PROBE) { - printf("DEFEND!"); + printf("DEFEND!\n"); send_defend(mc, range, p.requested_start_address, p.requested_count, p.SA); } else if (p.message_type == MAAP_ANNOUNCE) { /* We may only defend vs. an ANNOUNCE once */ if (range->counter == 0) { - printf("Defend vs. ANNOUNCE"); + printf("Defend vs. ANNOUNCE\n"); send_defend(mc, range, p.requested_start_address, p.requested_count, p.SA); range->counter = 1; } else { - printf("Yield vs. ANNOUNCE"); + printf("Yield vs. ANNOUNCE\n"); inform_yielded(mc, range); iv = remove_interval(&mc->ranges, iv); free_interval(iv); @@ -378,7 +379,7 @@ int maap_handle_packet(Client *mc, uint8_t *stream, int len) { range->state = MAAP_STATE_RELEASED; } } else { - printf("Got a DEFEND vs. a range we own"); + printf("Got a DEFEND vs. a range we own\n"); /* Don't know what to do with a DEFEND, so ignore it. They'll send another ANNOUNCE anyway. We could yield here if we wanted to be nice */ @@ -390,7 +391,7 @@ int maap_handle_packet(Client *mc, uint8_t *stream, int len) { return 0; } -int handle_probe_timer(Client *mc, Range *range) { +int handle_probe_timer(Maap_Client *mc, Range *range) { if (range->counter == 0) { inform_acquired(mc, range); range->state = MAAP_STATE_DEFENDING; @@ -405,14 +406,14 @@ int handle_probe_timer(Client *mc, Range *range) { return 0; } -int handle_defend_timer(Client *mc, Range *range) { +int handle_defend_timer(Maap_Client *mc, Range *range) { send_announce(mc, range); schedule_timer(mc, range); return 0; } -int maap_handle_timer(Client *mc, Time *time) { +int maap_handle_timer(Maap_Client *mc, Time *time) { Range *range; mc->timer_running = 0; @@ -420,19 +421,20 @@ int maap_handle_timer(Client *mc, Time *time) { while ((range = mc->timer_queue) && Time_passed(time, &range->next_act_time)) { printf("Current time:"); Time_dump(time); - printf("Due timer:"); + printf("\nDue timer:"); Time_dump(&range->next_act_time); mc->timer_queue = range->next_timer; range->next_timer = NULL; + printf("\n"); if (range->state == MAAP_STATE_PROBING) { - printf("Handling probe timer"); + printf("Handling probe timer\n"); handle_probe_timer(mc, range); } else if (range->state == MAAP_STATE_DEFENDING) { - printf("Handling defend timer"); + printf("Handling defend timer\n"); handle_defend_timer(mc, range); } else if (range->state == MAAP_STATE_RELEASED) { - printf("Freeing released timer"); + printf("Freeing released timer\n"); free(range); } diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index 8e3aa10f..4cfdafa8 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -26,16 +26,18 @@ #define MAAP_DEST_MAC {0x91, 0xE0, 0xF0, 0x00, 0xFF, 0x00} #define MAAP_DEST_64 0x000091E0F000FF00LL +#define MAAP_RANGE_SIZE 0xFFDF +#define MAAP_RANGE_SIZE_64 (((uint64_t)MAAP_RANGE_SIZE) << 48) #define MAAP_TYPE 0x22F0 #define MAAP_SUBTYPE 0xFE #define MAAP_PKT_SIZE 42 #define MAAP_RANGE_MASK 0xFFFF000000000000LL #define MAAP_BASE_MASK 0x0000FFFFFFFFFFFFLL -typedef struct notify_list Notify_List; -struct notify_list { - Notify notify; - Notify_List *next; +typedef struct maap_notify_list Maap_Notify_List; +struct maap_notify_list { + Maap_Notify notify; + Maap_Notify_List *next; }; typedef struct range Range; @@ -57,17 +59,18 @@ typedef struct { Net *net; int timer_running; int maxid; - Notify_List *notifies; + Maap_Notify_List *notifies; int initialized; -} Client; +} Maap_Client; -int maap_init_client(Client *mc, uint64_t range_info); -int maap_reserve_range(Client *mc, uint16_t length); -int maap_release_range(Client *mc, int id); +int maap_init_client(Maap_Client *mc, uint64_t range_info); +void maap_deinit_client(Maap_Client *mc); +int maap_reserve_range(Maap_Client *mc, uint16_t length); +int maap_release_range(Maap_Client *mc, int id); -int maap_handle_packet(Client *mc, uint8_t *stream, int len); -int maap_handle_timer(Client *mc, Time *time); -void add_notify(Client *mc, Notify *mn); -int get_notify(Client *mc, Notify *mn); +int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len); +int maap_handle_timer(Maap_Client *mc, Time *time); +void add_notify(Maap_Client *mc, Maap_Notify *mn); +int get_notify(Maap_Client *mc, Maap_Notify *mn); #endif diff --git a/daemons/maap/common/maap_iface.h b/daemons/maap/common/maap_iface.h index ccf0cd64..3c4a7d68 100644 --- a/daemons/maap/common/maap_iface.h +++ b/daemons/maap/common/maap_iface.h @@ -3,40 +3,41 @@ #include -#define MAAP_SOCKET_NAME "/var/tmp/maap.socket" -#define MAAP_CMD_BUF_SZ 500 +//#define MAAP_SOCKET_NAME "/var/tmp/maap.socket" +//#define MAAP_CMD_BUF_SZ 500 -/* MAAP Reqeust Format +/* MAAP Request Format * * This is the format of the request the driver expects to receive from the * Host application via a write(). */ typedef enum { + MAAP_INVALID = 0, MAAP_INIT, MAAP_RESERVE, MAAP_RELEASE, -} Cmd_Tag; +} Maap_Cmd_Tag; typedef struct { - Cmd_Tag kind; + Maap_Cmd_Tag kind; union { uint64_t range_info; uint16_t length; int id; } param; -} Cmd; +} Maap_Cmd; typedef enum { MAAP_ACQUIRED, MAAP_YIELDED, -} Notify_Tag; +} Maap_Notify_Tag; typedef struct { - Notify_Tag kind; + Maap_Notify_Tag kind; int id; uint64_t start; uint16_t count; -} Notify; +} Maap_Notify; #endif diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c new file mode 100644 index 00000000..2977c452 --- /dev/null +++ b/daemons/maap/common/maap_parse.c @@ -0,0 +1,121 @@ +/* + * maap_parse.c + * + * Created on: Sep 27, 2016 + * Author: bthomsen + */ + +#include +#include +#include +#include + +#include "maap.h" +#include "maap_parse.h" + +int parse_text_cmd(char *buf, Maap_Cmd *cmd) { + char *argv[40]; + int argc = 0; + char *p, opt; + int set_cmd = 0, set_data = 0; + + argv[argc++] = "maap-app"; + p = strtok(buf, " \r\n"); + while ((p != NULL) && (argc < 40)) { + argv[argc++] = p; + p = strtok(NULL, " \r\n"); + } + + optind = 1; + + while (!set_cmd || !set_data) { + opt = getopt(argc, argv, "c:m:l:i:"); + switch (opt) { + case 'c': + if (set_cmd) { + printf("Only one command type at a time\n"); + return 0; + } + if (strncmp(optarg, "init", 4) == 0) { + cmd->kind = MAAP_INIT; + set_cmd = 1; + } else if (strncmp(optarg, "reserve", 7) == 0) { + cmd->kind = MAAP_RESERVE; + set_cmd = 1; + } else if (strncmp(optarg, "release", 7) == 0) { + cmd->kind = MAAP_RELEASE; + set_cmd = 1; + } else { + printf("Invalid command type\n"); + return 0; + } + break; + case 'm': + if (set_data) { + printf("Only one data argument can be used at a time\n"); + return 0; + } + cmd->param.range_info = strtoull(optarg, NULL, 16); + set_data = 1; + break; + case 'l': + if (set_data) { + printf("Only one data argument can be used at a time\n"); + return 0; + } + cmd->param.length = (uint16_t)strtoul(optarg, NULL, 0); + set_data = 1; + break; + case 'i': + if (set_data) { + printf("Only one data argument can be used at a time\n"); + return 0; + } + cmd->param.id = (int)strtoul(optarg, NULL, 0); + set_data = 1; + break; + } + } + return 1; +} + +void parse_write(Maap_Client *mc, char *buf) { + Maap_Cmd *bufcmd, cmd; + int rv = 0; + + bufcmd = (Maap_Cmd *)buf; + + switch (bufcmd->kind) { + case MAAP_INIT: + case MAAP_RESERVE: + case MAAP_RELEASE: + memcpy(&cmd, bufcmd, sizeof (Maap_Cmd)); + rv = 1; + break; + default: + bzero(&cmd, sizeof (Maap_Cmd)); + rv = parse_text_cmd(buf, &cmd); + break; + } + + if (rv) { + switch(cmd.kind) { + case MAAP_INIT: + printf("Got cmd maap_init_client, range_info: %016llx\n", (unsigned long long)cmd.param.range_info); + rv = maap_init_client(mc, cmd.param.range_info); + break; + case MAAP_RESERVE: + printf("Got cmd maap_reserve_range, length: %u\n", (unsigned)cmd.param.length); + rv = maap_reserve_range(mc, cmd.param.length); + break; + case MAAP_RELEASE: + printf("Got cmd maap_release_range, id: %d\n", cmd.param.id); + rv = maap_release_range(mc, cmd.param.id); + break; + default: + printf("Error parsing in parse_write\n"); + rv = 0; + break; + } + } +} diff --git a/daemons/maap/common/maap_parse.h b/daemons/maap/common/maap_parse.h new file mode 100644 index 00000000..1718c2a1 --- /dev/null +++ b/daemons/maap/common/maap_parse.h @@ -0,0 +1,17 @@ +/* + * maap_parse.h + * + * Created on: Sep 27, 2016 + * Author: bthomsen + */ + +#ifndef COMMON_MAAP_PARSE_H_ +#define COMMON_MAAP_PARSE_H_ + +#include "maap_iface.h" + +int parse_text_cmd(char *buf, Maap_Cmd *cmd); + +void parse_write(Maap_Client *mc, char *buf); + +#endif /* COMMON_MAAP_PARSE_H_ */ diff --git a/daemons/maap/linux/Makefile b/daemons/maap/linux/Makefile index 0cdbe5e7..c81f3d15 100644 --- a/daemons/maap/linux/Makefile +++ b/daemons/maap/linux/Makefile @@ -16,10 +16,10 @@ maap_daemon_legacy: $(LINUX_DIR)/maap_linux_legacy.c $(CC) -o $(BUILD_DIR)/maap_daemon_legacy $(COMMON_DIR)/maap_protocol.c src/maap_linux_legacy.c $(CFLAGS) $(FLAGS) $(EXTRA_FLAGS) maap_daemon: $(LINUX_DIR)/maap_linux.c $(LINUX_DIR)/maap_net_linux.c $(LINUX_DIR)/maap_timer_linux.c \ - $(COMMON_DIR)/intervals.c $(COMMON_DIR)/maap.c $(COMMON_DIR)/maap_packet.c + $(COMMON_DIR)/intervals.c $(COMMON_DIR)/maap.c $(COMMON_DIR)/maap_packet.c $(COMMON_DIR)/maap_parse.c $(CC) -o $(BUILD_DIR)/maap_daemon \ $(LINUX_DIR)/maap_linux.c $(LINUX_DIR)/maap_net_linux.c $(LINUX_DIR)/maap_timer_linux.c \ - $(COMMON_DIR)/intervals.c $(COMMON_DIR)/maap.c $(COMMON_DIR)/maap_packet.c \ + $(COMMON_DIR)/intervals.c $(COMMON_DIR)/maap.c $(COMMON_DIR)/maap_packet.c $(COMMON_DIR)/maap_parse.c \ $(CFLAGS) $(FLAGS) $(EXTRA_FLAGS) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c deleted file mode 100644 index 10ea0c17..00000000 --- a/daemons/maap/linux/src/maap_linux.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "maap.h" - -#include -#include -#include -#include - -Client mc; - -/* - - 1. Initialize raw socket networking, register to receive MAAP frames - - 2. Create unix domain socket for clients to talk to us on - - 3. Start an event loop: Events are received packets, received client messages, - and timers elapsing - - */ - -int main(int argc, char *argv[]) -{ - - - return 0; -} diff --git a/daemons/maap/linux/src/maap_timer_linux.c b/daemons/maap/linux/src/maap_timer_linux.c index 91dfb39b..eda243ba 100644 --- a/daemons/maap/linux/src/maap_timer_linux.c +++ b/daemons/maap/linux/src/maap_timer_linux.c @@ -1,14 +1,14 @@ +#include #include #include #include -#include "maap_timer.h" - struct maap_timer { timer_t timer_id; }; -#include +#include "maap_timer.h" + Timer *Time_newTimer(void) { -- cgit v1.2.1 From 3ea1cdccf8d4fedd442790d9b5484c30e51ca736 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Wed, 28 Sep 2016 16:53:39 -0600 Subject: Include changes in previous file. --- daemons/maap/linux/maap_linux.c | 279 -------------------------------- daemons/maap/linux/src/maap_linux.c | 312 ++++++++++++++++++++++++++++++++++++ 2 files changed, 312 insertions(+), 279 deletions(-) delete mode 100644 daemons/maap/linux/maap_linux.c create mode 100644 daemons/maap/linux/src/maap_linux.c diff --git a/daemons/maap/linux/maap_linux.c b/daemons/maap/linux/maap_linux.c deleted file mode 100644 index c0634c69..00000000 --- a/daemons/maap/linux/maap_linux.c +++ /dev/null @@ -1,279 +0,0 @@ -/************************************************************************* - Copyright (c) 2015 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ - All rights reserved. - - 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. - - 3. Neither the name of the Vayavya labs nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. - -****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "maap_protocol.h" - -uint8_t *maap_shm_mem; -struct sockaddr_ll saddrll; -pthread_t thread; -pthread_mutex_t lock; -int socketfd; - -#define VERSION_STR "0.0" - -static const char *version_str = - "maap_daemon v" VERSION_STR "\n" "Copyright (c) 2014, VAYAVYA LABS PVT LTD\n"; - -void usage(void) -{ - fprintf(stderr, - "\n" - "usage: maap_daemon [-d] -i interface-name" - "\n" - "options:\n" - " -d run daemon in the background\n" - " -i specify interface to monitor\n" - "\n" "%s" "\n", version_str); - exit(1); -} - -int main(int argc, char *argv[]) -{ - char *iface = NULL; - struct ifreq buffer; - int ifindex; - struct packet_mreq mreq; - maap_info_t *maap_Info; - uint32_t seed; - uint8_t dest_mac[6]; - uint8_t src_mac[6]; - int daemonize = 0; - int shmid; - key_t key; - int ret; - int c; - - for (;;) { - c = getopt(argc, argv, "hdi:"); - - if (c < 0) - break; - - switch (c) { - case 'd': - daemonize = 1; - break; - case 'i': - if (iface) { - printf - ("only one interface per daemon is supported\n"); - usage(); - } - iface = strdup(optarg); - break; - case 'h': - default: - usage(); - break; - } - } - if (optind < argc) - usage(); - - if (iface == NULL) - usage(); - - if (daemonize) { - ret = daemon(1, 0); - if (ret) { - printf("Error: Failed to daemonize\n"); - return -1; - } - } - - if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_TYPE))) < 0 ) - { - printf("Error: could not open socket %d\n",socketfd); - return -1; - } - - memset(&buffer, 0x00, sizeof(buffer)); - strncpy(buffer.ifr_name, (char *)iface, IFNAMSIZ); - if (ioctl(socketfd, SIOCGIFINDEX, &buffer) < 0) - { - printf("Error: could not get interface index\n"); - close(socketfd); - return -1; - } - - key = 1234; - if ((shmid = shmget(key, MAC_ADDR_LEN, IPC_CREAT | 0666)) < 0) { - printf("Error : Failed to allocate the Shared Memory\n"); - close(socketfd); - return -1; - } - - if ((maap_shm_mem = shmat(shmid, NULL, 0)) == (uint8_t *) -1) { - printf("Error : Failed to attach the created segment id by function \ - shmget()"); - close(socketfd); - return -1; - } - - ifindex = buffer.ifr_ifindex; - if (ioctl(socketfd, SIOCGIFHWADDR, &buffer) < 0) { - printf("Error: could not get interface address\n"); - close(socketfd); - return -1; - } - memcpy(src_mac, buffer.ifr_hwaddr.sa_data, MAC_ADDR_LEN); - - get_multicast_mac_adr(dest_mac); - - memset((void*)&saddrll, 0, sizeof(saddrll)); - saddrll.sll_family = AF_PACKET; - saddrll.sll_ifindex = ifindex; - saddrll.sll_halen = MAC_ADDR_LEN; - memcpy((void*)(saddrll.sll_addr), (void*)dest_mac, MAC_ADDR_LEN); - - if (bind(socketfd, (struct sockaddr*)&saddrll, sizeof(saddrll))) { - printf("Error: could not bind datagram socket\n"); - return -1; - } - - /* filter multicast address */ - memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifindex; - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = 6; - memcpy(mreq.mr_address, dest_mac, mreq.mr_alen); - - if (setsockopt(socketfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, - sizeof(mreq)) < 0) { - printf("setsockopt PACKET_ADD_MEMBERSHIP failed\n"); - return -1; - } - - pthread_mutex_init(&(lock), NULL); - seed = src_mac[5] + time(NULL); - srand(seed); - - maap_Info = (maap_info_t *)calloc(1,sizeof(maap_info_t)); - - /* Initialize packet header and data */ - Init(maap_Info, src_mac); - - while (1) { - state_transit(maap_Info); - } - - close(socketfd); - - free(maap_Info); - - return 0; -} - -void delay(int seconds, int millisecond) -{ - sleep(seconds); - usleep(millisecond * 1000); -} - -void create_thread(maap_info_t *maap_info, void *announce) -{ - pthread_create(&thread, NULL, announce, (void *)(maap_info)); -} - -void destroy_thread() -{ - pthread_cancel(thread); -} - -double rand_frange(double min_n, double max_n) -{ - return (double)rand()/RAND_MAX * (max_n - min_n) + min_n; -} - -int rand_range(int min_n, int max_n) -{ - return rand() % (max_n - min_n + 1) + min_n; -} - -void send_packet(ethpkt_t *pkt_tx) -{ - int result; - if ((result = (sendto(socketfd, pkt_tx, ETH_PKT_LEN, 0, - (struct sockaddr*)&saddrll, sizeof(saddrll)) > 0))) - DBG("send successful %d\n", result); - else - DBG("Error: sending of packet failed\n"); -} - -int recv_packet(ethpkt_t *pkt_rx, int flag) -{ - int result; - socklen_t fmlen = sizeof(saddrll); - - if (flag == NON_BLOCK) - flag = MSG_DONTWAIT; - - result = recvfrom(socketfd, pkt_rx, ETH_PKT_LEN, flag, - (struct sockaddr*)&saddrll, &fmlen); - return result; -} - -void Lock() -{ - pthread_mutex_lock(&lock); -} - -void UnLock() -{ - pthread_mutex_unlock(&lock); -} - -uint16_t hton_s(uint16_t val) -{ - return htons(val); -} diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c new file mode 100644 index 00000000..47782cff --- /dev/null +++ b/daemons/maap/linux/src/maap_linux.c @@ -0,0 +1,312 @@ +/************************************************************************* + Copyright (c) 2015 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ + All rights reserved. + + 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. + + 3. Neither the name of the Vayavya labs nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. + +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "maap.h" +#include "maap_parse.h" + + +#define VERSION_STR "0.1" + +static const char *version_str = + "maap_daemon v" VERSION_STR "\n" + "Copyright (c) 2014-2015, VAYAVYA LABS PVT LTD\n" + "Copyright (c) 2016, Harman International Industries Inc.\n"; + +void usage(void) +{ + fprintf(stderr, + "\n" + "usage: maap_daemon [-d] -i interface-name" + "\n" + "options:\n" + " -d run daemon in the background\n" + " -i specify interface to monitor\n" + "\n" "%s" "\n", version_str); + exit(1); +} + +int main(int argc, char *argv[]) +{ + int c; + int daemonize = 0; + int ret; + char *iface = NULL; + int socketfd; + struct ifreq ifbuffer; + uint8_t dest_mac[ETH_ALEN] = MAAP_DEST_MAC; + uint8_t src_mac[ETH_ALEN]; + int ifindex; + struct sockaddr_ll sockaddr; + struct packet_mreq mreq; + Maap_Client mc; + struct timeval tv; +// fd_set master; // master file descriptor list + fd_set read_fds; // temp file descriptor list for select() + int fdmax; // maximum file descriptor number + char recvbuffer[1600]; + int recvbytes; + Maap_Cmd recvcmd; + + /* + * Parse the arguments + */ + + while ((c = getopt(argc, argv, "hdi:")) >= 0) + { + switch (c) + { + case 'd': + daemonize = 1; + break; + + case 'i': + if (iface) + { + printf("only one interface per daemon is supported\n"); + usage(); + } + iface = strdup(optarg); + break; + + case 'h': + default: + usage(); + break; + } + } + if (optind < argc) + { + usage(); + } + + if (iface == NULL) + { + printf("A network interface is required\n"); + usage(); + } + + if (daemonize) { + ret = daemon(1, 0); + if (ret) { + printf("Error: Failed to daemonize\n"); + return -1; + } + } + + + /* + * Initialize the networking support. + */ + + if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(MAAP_TYPE))) < 0 ) + { + printf("Error: could not open socket %d\n",socketfd); + return -1; + } + + if (fcntl(socketfd, F_SETFL, O_NONBLOCK) < 0) + { + printf("Error: could not set the socket to non-blocking\n"); + return -1; + } + + memset(&ifbuffer, 0x00, sizeof(ifbuffer)); + strncpy(ifbuffer.ifr_name, iface, IFNAMSIZ); + if (ioctl(socketfd, SIOCGIFINDEX, &ifbuffer) < 0) + { + printf("Error: could not get interface index\n"); + close(socketfd); + return -1; + } + free(iface); + iface = NULL; + + ifindex = ifbuffer.ifr_ifindex; + if (ioctl(socketfd, SIOCGIFHWADDR, &ifbuffer) < 0) { + printf("Error: could not get interface address\n"); + close(socketfd); + return -1; + } + + memcpy(src_mac, ifbuffer.ifr_hwaddr.sa_data, ETH_ALEN); + + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sll_family = AF_PACKET; + sockaddr.sll_ifindex = ifindex; + sockaddr.sll_halen = ETH_ALEN; + memcpy(sockaddr.sll_addr, dest_mac, ETH_ALEN); + + if (bind(socketfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) { + printf("Error: could not bind datagram socket\n"); + return -1; + } + +#if 0 + /* filter multicast address */ + memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = ifindex; + mreq.mr_type = PACKET_MR_MULTICAST; + mreq.mr_alen = 6; + memcpy(mreq.mr_address, dest_mac, mreq.mr_alen); + + if (setsockopt(socketfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, + sizeof(mreq)) < 0) { + printf("setsockopt PACKET_ADD_MEMBERSHIP failed\n"); + return -1; + } +#endif + + + /* + * Initialize the low-level MAAP support, using the default MAAP Dynamic Allocation Pool. + */ + + memset(&mc, 0, sizeof(mc)); +#if 0 + if (maap_init_client(&mc, MAAP_DEST_64 | MAAP_RANGE_SIZE_64) < 0) + { + printf("maap_init_client() failed\n"); + return -1; + } +#endif + + + /* + * Start an event loop: Events are received packets, received client messages, + and timers elapsing + */ + + while (1) + { + /* Wait for something to happen. */ + FD_ZERO(&read_fds); + fdmax = 0; + FD_SET(socketfd, &read_fds); + fdmax++; + FD_SET(STDIN_FILENO, &read_fds); + fdmax++; + tv.tv_sec = 10; + tv.tv_usec = 0; + //printf("Calling select()\n"); + ret = select(fdmax+1, &read_fds, NULL, NULL, &tv); + if (ret < 0) + { + printf("select() error %d\n", errno); + break; + } + if (ret == 0) + { + /* TODO: The timer timed out. Handle the timer. */ + //printf("select() timed out\n"); + continue; + } + //printf("select() triggered\n"); + + /* Handle any packets received. */ + if (FD_ISSET(socketfd, &read_fds)) + { + while ((recvbytes = recv(socketfd, recvbuffer, sizeof(recvbuffer), 0)) > 0) + { + printf("Received %d byte packet\n", recvbytes); + maap_handle_packet(&mc, (uint8_t *)recvbuffer, recvbytes); + } + if (recvbytes < 0 && errno != EWOULDBLOCK) + { + /* Something went wrong. Abort! */ + printf("Error %d reading from network socket\n", errno); + break; + } + } + + /* Handle any commands received via stdin. */ + if (FD_ISSET(STDIN_FILENO, &read_fds)) + { + recvbytes = read(STDIN_FILENO, recvbuffer, sizeof(recvbuffer)); + if (recvbytes < 0) + { + printf("Error %d reading from stdin\n", errno); + recvbytes = 0; + } + else + { + recvbuffer[recvbytes] = '\0'; + } + recvbuffer[recvbytes] = '\0'; + + /* Process the data (may be binary or text.) */ + //for (int i = 0; i < recvbytes; ++i) printf("*%c*\n", recvbuffer[i]); + memset(&recvcmd, 0, sizeof(recvcmd)); +printf("stdin point 1\n"); + if (parse_text_cmd(recvbuffer, &recvcmd)) + { +printf("stdin point 2.1\n"); + /* Process the results from the text parsing. */ + parse_write(&mc, (char *)&recvcmd); + } + else + { +printf("stdin point 2.2\n"); + /* See if we were passed a binary data blob. */ + parse_write(&mc, recvbuffer); + } +printf("stdin point 3\n"); + } + } + + close(socketfd); + + maap_deinit_client(&mc); + + return 0; +} -- cgit v1.2.1 From a4dd3e582fad61dba8e74d8b8b68b3d6cc9c99eb Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Fri, 30 Sep 2016 15:10:30 -0600 Subject: Updates so that the main loop delays for, and handles the timers. Cleaned up the stdin command parsing. --- daemons/maap/common/maap.c | 36 +++++++++++--- daemons/maap/common/maap.h | 13 ++++- daemons/maap/common/maap_parse.c | 81 +++++++++++-------------------- daemons/maap/common/maap_timer.h | 9 ++++ daemons/maap/common/platform.h | 3 +- daemons/maap/linux/src/maap_linux.c | 50 ++++++++----------- daemons/maap/linux/src/maap_timer_linux.c | 35 ++++++++++++- daemons/maap/test/maap_timer_dummy.c | 6 +++ 8 files changed, 141 insertions(+), 92 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index fe74add1..537c0f86 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -215,7 +215,7 @@ int schedule_timer(Maap_Client *mc, Range *range) { } else if (range->state == MAAP_STATE_DEFENDING) { ns = MAAP_ANNOUNCE_INTERVAL_BASE + rand_ms(MAAP_ANNOUNCE_INTERVAL_VARIATION); ns = ns * 1000000; - printf("Scheduling defend timer for %" PRIx64 " ns from now\n", ns); + printf("Scheduling defend timer for %" PRIu64 " ns from now\n", ns); Time_setFromNanos(&ts, (uint64_t)ns); Time_setFromMonotonicTimer(&range->next_act_time); Time_add(&range->next_act_time, &ts); @@ -413,15 +413,20 @@ int handle_defend_timer(Maap_Client *mc, Range *range) { return 0; } -int maap_handle_timer(Maap_Client *mc, Time *time) { +int maap_handle_timer(Maap_Client *mc) { + Time currenttime; Range *range; + /* Get the current time. */ + Time_setFromMonotonicTimer(¤ttime); + printf("Current time is: "); + Time_dump(¤ttime); + printf("\n"); + mc->timer_running = 0; - while ((range = mc->timer_queue) && Time_passed(time, &range->next_act_time)) { - printf("Current time:"); - Time_dump(time); - printf("\nDue timer:"); + while ((range = mc->timer_queue) && Time_passed(¤ttime, &range->next_act_time)) { + printf("Due timer: "); Time_dump(&range->next_act_time); mc->timer_queue = range->next_timer; range->next_timer = NULL; @@ -444,3 +449,22 @@ int maap_handle_timer(Maap_Client *mc, Time *time) { return 0; } + +int64_t maap_get_delay_to_next_timer(Maap_Client *mc) +{ + int64_t timeRemaining; + + if (!(mc->timer) || !(mc->timer_queue)) + { + /* There are no timers waiting, so wait for an hour. + * (No particular reason; it just sounded reasonable.) */ + timeRemaining = 60LL * 60LL * 1000000000LL; + } + else + { + /* Get the time remaining for the next timer. */ + timeRemaining = Time_remaining(mc->timer); + } + printf("Next delay: %" PRId64 " ns\n\n", timeRemaining); + return timeRemaining; +} diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index 4cfdafa8..16c92976 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -65,11 +65,22 @@ typedef struct { int maap_init_client(Maap_Client *mc, uint64_t range_info); void maap_deinit_client(Maap_Client *mc); + int maap_reserve_range(Maap_Client *mc, uint16_t length); int maap_release_range(Maap_Client *mc, int id); int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len); -int maap_handle_timer(Maap_Client *mc, Time *time); +int maap_handle_timer(Maap_Client *mc); + +/** + * Get the number of nanoseconds until the next timer event. + * + * @param mc Pointer to the Maap_Client to use + * + * @return Number of nanoseconds until the next timer expires, or a very large value if there are no timers waiting. + */ +int64_t maap_get_delay_to_next_timer(Maap_Client *mc); + void add_notify(Maap_Client *mc, Maap_Notify *mn); int get_notify(Maap_Client *mc, Maap_Notify *mn); diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c index 2977c452..2c96afa1 100644 --- a/daemons/maap/common/maap_parse.c +++ b/daemons/maap/common/maap_parse.c @@ -8,74 +8,47 @@ #include #include #include -#include #include "maap.h" #include "maap_parse.h" int parse_text_cmd(char *buf, Maap_Cmd *cmd) { - char *argv[40]; + char *argv[5]; int argc = 0; - char *p, opt; - int set_cmd = 0, set_data = 0; + char *p; + int set_cmd = 0; - argv[argc++] = "maap-app"; p = strtok(buf, " \r\n"); - while ((p != NULL) && (argc < 40)) { + while ((p != NULL) && (argc < sizeof(argv) / sizeof(*argv))) { argv[argc++] = p; p = strtok(NULL, " \r\n"); } - optind = 1; - - while (!set_cmd || !set_data) { - opt = getopt(argc, argv, "c:m:l:i:"); - switch (opt) { - case 'c': - if (set_cmd) { - printf("Only one command type at a time\n"); - return 0; - } - if (strncmp(optarg, "init", 4) == 0) { - cmd->kind = MAAP_INIT; - set_cmd = 1; - } else if (strncmp(optarg, "reserve", 7) == 0) { - cmd->kind = MAAP_RESERVE; - set_cmd = 1; - } else if (strncmp(optarg, "release", 7) == 0) { - cmd->kind = MAAP_RELEASE; - set_cmd = 1; - } else { - printf("Invalid command type\n"); - return 0; - } - break; - case 'm': - if (set_data) { - printf("Only one data argument can be used at a time\n"); - return 0; - } - cmd->param.range_info = strtoull(optarg, NULL, 16); - set_data = 1; - break; - case 'l': - if (set_data) { - printf("Only one data argument can be used at a time\n"); - return 0; - } - cmd->param.length = (uint16_t)strtoul(optarg, NULL, 0); - set_data = 1; - break; - case 'i': - if (set_data) { - printf("Only one data argument can be used at a time\n"); - return 0; - } - cmd->param.id = (int)strtoul(optarg, NULL, 0); - set_data = 1; - break; + if (argc == 2) + { + if (strncmp(argv[0], "init", 4) == 0) { + cmd->kind = MAAP_INIT; + cmd->param.range_info = strtoull(argv[1], NULL, 16); + set_cmd = 1; + } else if (strncmp(argv[0], "reserve", 7) == 0) { + cmd->kind = MAAP_RESERVE; + cmd->param.length = (uint16_t)strtoul(argv[1], NULL, 0); + set_cmd = 1; + } else if (strncmp(argv[0], "release", 7) == 0) { + cmd->kind = MAAP_RELEASE; + cmd->param.id = (int)strtoul(argv[1], NULL, 0); + set_cmd = 1; + } else { + printf("Invalid command type\n"); } } + + if (!set_cmd) + { + printf("input usage: init|reserve|release \n"); + return 0; + } + return 1; } diff --git a/daemons/maap/common/maap_timer.h b/daemons/maap/common/maap_timer.h index 1bdd2f81..4cf793e4 100644 --- a/daemons/maap/common/maap_timer.h +++ b/daemons/maap/common/maap_timer.h @@ -14,13 +14,22 @@ void Time_delTimer(Timer *timer); void Time_setTimer(Timer *timer, Time *t); +int64_t Time_remaining(Timer *timer); + +/** + * Adds the second time to the first time. + * + * @param a Time that the second time is added to. This value is modified. + * @param b Time that is added to the first time. This value is not modified. + */ void Time_add(Time *a, Time *b); int Time_cmp(Time *a, Time *b); int Time_passed(Time *current, Time *target); + void Time_setFromNanos(Time *t, uint64_t nsec); void Time_setFromMonotonicTimer(Time *t); diff --git a/daemons/maap/common/platform.h b/daemons/maap/common/platform.h index 7bdc33af..999aada3 100644 --- a/daemons/maap/common/platform.h +++ b/daemons/maap/common/platform.h @@ -4,8 +4,9 @@ #if defined(__linux__) #include +#include -#define OS_TIME_TYPE struct timespec +typedef struct timespec OS_TIME_TYPE; #elif defined(__APPLE__) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 47782cff..5f89fe70 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -90,6 +90,7 @@ int main(int argc, char *argv[]) struct sockaddr_ll sockaddr; struct packet_mreq mreq; Maap_Client mc; + int64_t waittime; struct timeval tv; // fd_set master; // master file descriptor list fd_set read_fds; // temp file descriptor list for select() @@ -192,7 +193,6 @@ int main(int argc, char *argv[]) return -1; } -#if 0 /* filter multicast address */ memset(&mreq, 0, sizeof(mreq)); mreq.mr_ifindex = ifindex; @@ -205,7 +205,6 @@ int main(int argc, char *argv[]) printf("setsockopt PACKET_ADD_MEMBERSHIP failed\n"); return -1; } -#endif /* @@ -223,12 +222,25 @@ int main(int argc, char *argv[]) /* - * Start an event loop: Events are received packets, received client messages, - and timers elapsing + * Main event loop */ while (1) { + /* Determine how long to wait. */ + waittime = maap_get_delay_to_next_timer(&mc); + if (waittime > 0) + { + tv.tv_sec = waittime / 1000000000; + tv.tv_usec = (waittime % 1000000000) / 1000; + } + else + { + /* Act immediately. */ + tv.tv_sec = 0; + tv.tv_usec = 0; + } + /* Wait for something to happen. */ FD_ZERO(&read_fds); fdmax = 0; @@ -236,9 +248,6 @@ int main(int argc, char *argv[]) fdmax++; FD_SET(STDIN_FILENO, &read_fds); fdmax++; - tv.tv_sec = 10; - tv.tv_usec = 0; - //printf("Calling select()\n"); ret = select(fdmax+1, &read_fds, NULL, NULL, &tv); if (ret < 0) { @@ -247,11 +256,10 @@ int main(int argc, char *argv[]) } if (ret == 0) { - /* TODO: The timer timed out. Handle the timer. */ - //printf("select() timed out\n"); + /* The timer timed out. Handle the timer. */ + maap_handle_timer(&mc); continue; } - //printf("select() triggered\n"); /* Handle any packets received. */ if (FD_ISSET(socketfd, &read_fds)) @@ -272,35 +280,19 @@ int main(int argc, char *argv[]) /* Handle any commands received via stdin. */ if (FD_ISSET(STDIN_FILENO, &read_fds)) { - recvbytes = read(STDIN_FILENO, recvbuffer, sizeof(recvbuffer)); + recvbytes = read(STDIN_FILENO, recvbuffer, sizeof(recvbuffer) - 1); if (recvbytes < 0) { printf("Error %d reading from stdin\n", errno); - recvbytes = 0; } else { recvbuffer[recvbytes] = '\0'; - } - recvbuffer[recvbytes] = '\0'; - /* Process the data (may be binary or text.) */ - //for (int i = 0; i < recvbytes; ++i) printf("*%c*\n", recvbuffer[i]); - memset(&recvcmd, 0, sizeof(recvcmd)); -printf("stdin point 1\n"); - if (parse_text_cmd(recvbuffer, &recvcmd)) - { -printf("stdin point 2.1\n"); - /* Process the results from the text parsing. */ - parse_write(&mc, (char *)&recvcmd); - } - else - { -printf("stdin point 2.2\n"); - /* See if we were passed a binary data blob. */ + /* Process the data (may be binary or text.) */ + memset(&recvcmd, 0, sizeof(recvcmd)); parse_write(&mc, recvbuffer); } -printf("stdin point 3\n"); } } diff --git a/daemons/maap/linux/src/maap_timer_linux.c b/daemons/maap/linux/src/maap_timer_linux.c index eda243ba..b2d5f0f4 100644 --- a/daemons/maap/linux/src/maap_timer_linux.c +++ b/daemons/maap/linux/src/maap_timer_linux.c @@ -1,7 +1,9 @@ #include #include +#include #include #include +#include struct maap_timer { timer_t timer_id; @@ -12,12 +14,28 @@ struct maap_timer { Timer *Time_newTimer(void) { - return malloc(sizeof (Timer)); + struct sigevent sev; + Timer * newTimer = malloc(sizeof (Timer)); + if (newTimer) + { + sev.sigev_notify = SIGEV_NONE; + sev.sigev_signo = 0; + sev.sigev_value.sival_ptr = NULL; + if (timer_create(CLOCK_MONOTONIC, &sev, &(newTimer->timer_id)) < 0) + { + newTimer->timer_id = (timer_t)(-1); + } + } + return newTimer; } void Time_delTimer(Timer *timer) { assert(timer); + if (timer && timer->timer_id != (timer_t)(-1)) + { + timer_delete(timer->timer_id); + } free(timer); } @@ -31,6 +49,21 @@ void Time_setTimer(Timer *timer, Time *t) timer_settime(timer->timer_id, TIMER_ABSTIME, &tspec, NULL); } +int64_t Time_remaining(Timer *timer) +{ + struct itimerspec curr_value; + + assert(timer); + if (timer_gettime(timer->timer_id, &curr_value) < 0) + { + printf("Error %d getting the timer time remaining\n", errno); + return -1; + } + + return (curr_value.it_value.tv_sec * 1000000000L + curr_value.it_value.tv_nsec); +} + + void Time_add(Time *a, Time *b) { a->tv_sec = a->tv_sec + b->tv_sec; diff --git a/daemons/maap/test/maap_timer_dummy.c b/daemons/maap/test/maap_timer_dummy.c index fd0071db..57bd7316 100644 --- a/daemons/maap/test/maap_timer_dummy.c +++ b/daemons/maap/test/maap_timer_dummy.c @@ -26,6 +26,12 @@ void Time_setTimer(Timer *timer, Time *t) (void)timer; (void)t; } +int64_t Time_remaining(Timer *timer) +{ + (void)timer; + return 1; +} + void Time_add(Time *a, Time *b) { a->tv_sec = a->tv_sec + b->tv_sec; -- cgit v1.2.1 From cf1777de1684772a6d1d02b8ec56d1fd4196ee38 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 3 Oct 2016 17:24:38 -0600 Subject: Added support to send network packets. Network packets include the correct source address. --- daemons/maap/common/maap.c | 8 +-- daemons/maap/common/maap.h | 3 +- daemons/maap/common/maap_net.h | 8 ++- daemons/maap/common/maap_packet.c | 18 ++++-- daemons/maap/common/maap_packet.h | 4 +- daemons/maap/linux/src/maap_linux.c | 35 ++++++++-- daemons/maap/linux/src/maap_net_linux.c | 111 ++++++++++++++++++++++++++++---- 7 files changed, 158 insertions(+), 29 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index 537c0f86..51c34917 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -30,14 +30,14 @@ static int send_packet(Maap_Client *mc, MAAP_Packet *p) { pack_maap(p, pbuf); - ret = Net_sendPacket(mc->net, pbuf); + ret = Net_queuePacket(mc->net, pbuf); return ret; } static int send_probe(Maap_Client *mc, Range *range) { MAAP_Packet p; - init_packet(&p); + init_packet(&p, mc->dest_mac, mc->src_mac); p.message_type = MAAP_PROBE; p.requested_start_address = get_start_address(mc, range); @@ -49,7 +49,7 @@ static int send_probe(Maap_Client *mc, Range *range) { static int send_announce(Maap_Client *mc, Range *range) { MAAP_Packet p; - init_packet(&p); + init_packet(&p, mc->dest_mac, mc->src_mac); p.message_type = MAAP_ANNOUNCE; p.requested_start_address = get_start_address(mc, range); @@ -62,7 +62,7 @@ static int send_defend(Maap_Client *mc, Range *range, uint64_t start, uint16_t count, uint64_t destination) { MAAP_Packet p; - init_packet(&p); + init_packet(&p, mc->dest_mac, mc->src_mac); p.DA = destination; p.message_type = MAAP_DEFEND; diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index 16c92976..5646abc8 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -25,7 +25,6 @@ #define MAAP_CB_YIELDED 1 #define MAAP_DEST_MAC {0x91, 0xE0, 0xF0, 0x00, 0xFF, 0x00} -#define MAAP_DEST_64 0x000091E0F000FF00LL #define MAAP_RANGE_SIZE 0xFFDF #define MAAP_RANGE_SIZE_64 (((uint64_t)MAAP_RANGE_SIZE) << 48) #define MAAP_TYPE 0x22F0 @@ -51,6 +50,8 @@ struct range { }; typedef struct { + uint64_t dest_mac; + uint64_t src_mac; uint64_t address_base; uint32_t range_len; Interval *ranges; diff --git a/daemons/maap/common/maap_net.h b/daemons/maap/common/maap_net.h index 25208f9c..1f04da0a 100644 --- a/daemons/maap/common/maap_net.h +++ b/daemons/maap/common/maap_net.h @@ -1,6 +1,8 @@ #ifndef MAAP_NET_H #define MAAP_NET_H +#define MAAP_NET_BUFFER_SIZE 64 + typedef struct maap_net Net; Net *Net_newNet(void); @@ -9,6 +11,10 @@ void Net_delNet(Net *net); void *Net_getPacketBuffer(Net *net); -int Net_sendPacket(Net *net, void *buffer); +int Net_queuePacket(Net *net, void *buffer); + +void *Net_getNextQueuedPacket(Net *net); + +int Net_freeQueuedPacket(Net *net, void *buffer); #endif diff --git a/daemons/maap/common/maap_packet.c b/daemons/maap/common/maap_packet.c index a3f41fc4..5b27b776 100644 --- a/daemons/maap/common/maap_packet.c +++ b/daemons/maap/common/maap_packet.c @@ -119,12 +119,13 @@ int pack_maap(MAAP_Packet *packet, uint8_t *stream) { return 0; } -void init_packet(MAAP_Packet *packet) { +void init_packet(MAAP_Packet *packet, uint64_t dest_mac, uint64_t src_mac) { assert(packet); + assert(dest_mac != 0); + assert(src_mac != 0); - packet->DA = MAAP_DEST_64; - // packet->DA = 0xFFFFFFFFFFFF; - packet->SA = 0x0; + packet->DA = dest_mac; + packet->SA = src_mac; packet->Ethertype = MAAP_TYPE; packet->CD = 1; packet->subtype = 0x7e; @@ -139,3 +140,12 @@ void init_packet(MAAP_Packet *packet) { packet->start_address = 0; packet->count = 0; } + +uint64_t convert_mac_address(uint8_t macaddr[]) +{ + uint64_t retVal; + + assert(macaddr); + retVal = BE64TOH(*(uint64_t *)macaddr) >> 16; + return retVal; +} diff --git a/daemons/maap/common/maap_packet.h b/daemons/maap/common/maap_packet.h index 231456bb..e26e6cca 100644 --- a/daemons/maap/common/maap_packet.h +++ b/daemons/maap/common/maap_packet.h @@ -28,8 +28,10 @@ typedef struct maap_packet { uint16_t count; } MAAP_Packet; -void init_packet(MAAP_Packet *packet); +void init_packet(MAAP_Packet *packet, uint64_t dest_mac, uint64_t src_mac); int pack_maap(MAAP_Packet *packet, uint8_t *stream); int unpack_maap(MAAP_Packet *packet, uint8_t *stream); +uint64_t convert_mac_address(uint8_t macaddr[]); + #endif diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 5f89fe70..f0cb41f4 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -53,6 +53,7 @@ #include #include "maap.h" +#include "maap_packet.h" #include "maap_parse.h" @@ -90,6 +91,7 @@ int main(int argc, char *argv[]) struct sockaddr_ll sockaddr; struct packet_mreq mreq; Maap_Client mc; + void *packet_data; int64_t waittime; struct timeval tv; // fd_set master; // master file descriptor list @@ -193,6 +195,7 @@ int main(int argc, char *argv[]) return -1; } +#if 1 /* filter multicast address */ memset(&mreq, 0, sizeof(mreq)); mreq.mr_ifindex = ifindex; @@ -205,14 +208,22 @@ int main(int argc, char *argv[]) printf("setsockopt PACKET_ADD_MEMBERSHIP failed\n"); return -1; } +#endif /* - * Initialize the low-level MAAP support, using the default MAAP Dynamic Allocation Pool. + * Initialize the Maap_Client data structure. */ - memset(&mc, 0, sizeof(mc)); + mc.dest_mac = convert_mac_address(dest_mac); + mc.src_mac = convert_mac_address(src_mac); + + #if 0 + /* + * Initialize the low-level MAAP support, using the default MAAP Dynamic Allocation Pool. + */ + if (maap_init_client(&mc, MAAP_DEST_64 | MAAP_RANGE_SIZE_64) < 0) { printf("maap_init_client() failed\n"); @@ -227,6 +238,18 @@ int main(int argc, char *argv[]) while (1) { + /* Send any queued packets. */ + while (mc.net != NULL && (packet_data = Net_getNextQueuedPacket(mc.net)) != NULL) + { + if (send(socketfd, packet_data, MAAP_NET_BUFFER_SIZE, 0) < 0) + { + /* Something went wrong. Abort! */ + printf("Error %d writing to network socket\n", errno); + break; + } + Net_freeQueuedPacket(mc.net, packet_data); + } + /* Determine how long to wait. */ waittime = maap_get_delay_to_next_timer(&mc); if (waittime > 0) @@ -243,12 +266,10 @@ int main(int argc, char *argv[]) /* Wait for something to happen. */ FD_ZERO(&read_fds); - fdmax = 0; - FD_SET(socketfd, &read_fds); - fdmax++; FD_SET(STDIN_FILENO, &read_fds); - fdmax++; - ret = select(fdmax+1, &read_fds, NULL, NULL, &tv); + FD_SET(socketfd, &read_fds); + fdmax = socketfd; + ret = select(fdmax, &read_fds, NULL, NULL, &tv); if (ret < 0) { printf("select() error %d\n", errno); diff --git a/daemons/maap/linux/src/maap_net_linux.c b/daemons/maap/linux/src/maap_net_linux.c index 48a066b9..c6b01e4d 100644 --- a/daemons/maap/linux/src/maap_net_linux.c +++ b/daemons/maap/linux/src/maap_net_linux.c @@ -1,36 +1,125 @@ +#include #include +#include #include #include "maap_net.h" +#define NUM_BUFFERS 4 + struct maap_net { - char net_buffer[64]; + char net_buffer[NUM_BUFFERS][MAAP_NET_BUFFER_SIZE]; + int buffer_available[NUM_BUFFERS]; + int index_to_send[NUM_BUFFERS]; }; Net *Net_newNet(void) { - return malloc(sizeof (Net)); + Net *pNew; + int i; + + pNew = malloc(sizeof(Net)); + if (!pNew) { return NULL; } + memset(pNew, 0, sizeof(Net)); + for (i = 0; i < NUM_BUFFERS; ++i) + { + pNew->buffer_available[i] = 1; + pNew->index_to_send[i] = -1; + } + return pNew; } void Net_delNet(Net *net) { - assert(net); - free(net); + assert(net); + free(net); } void *Net_getPacketBuffer(Net *net) { - assert(net); - return (void*)net->net_buffer; + int i; + + assert(net); + for (i = 0; i < NUM_BUFFERS; ++i) + { + if (net->buffer_available[i]) + { + net->buffer_available[i] = 0; + printf("Allocated buffer %d\n", i); + return (void *)(net->net_buffer[i]); + } + } + return NULL; +} + +int Net_queuePacket(Net *net, void *buffer) +{ + int buffer_index, queue_index; + + assert(net); + /* @TODO: This could be done mathematically, rather than in a loop. */ + for (buffer_index = 0; buffer_index < NUM_BUFFERS; ++buffer_index) + { + if (net->net_buffer[buffer_index] == buffer) + { + /* We found the index of the buffer provided. */ + printf("Queuing buffer %d\n", buffer_index); + break; + } + } + if (buffer_index >= NUM_BUFFERS) { return -1; } + + for (queue_index = 0; queue_index < NUM_BUFFERS; ++queue_index) + { + assert(net->index_to_send[queue_index] != buffer_index); + if (net->index_to_send[queue_index] < 0) + { + /* We can add the buffer to this spot in the queue. */ + net->index_to_send[queue_index] = buffer_index; + printf("Buffer %d queued at index %d\n", buffer_index, queue_index); + return 0; + } + } + return -1; } -int Net_sendPacket(Net *net, void *buffer) +void *Net_getNextQueuedPacket(Net *net) { - assert(net); - assert(buffer == (void*)net->net_buffer); - /* @TODO Send Packet Here */ + void *pBuffer = NULL; + int i; + + assert(net); + if (net->index_to_send[0] >= 0) + { + printf("Buffer %d pulled from queue\n", net->index_to_send[0]); + pBuffer = net->net_buffer[net->index_to_send[0]]; + for (i = 0; i < NUM_BUFFERS - 1; ++i) + { + net->index_to_send[i] = net->index_to_send[i + 1]; + } + net->index_to_send[NUM_BUFFERS - 1] = -1; + } - return 1; + return pBuffer; } +int Net_freeQueuedPacket(Net *net, void *buffer) +{ + int buffer_index; + + assert(net); + /* @TODO: This could be done mathematically, rather than in a loop. */ + for (buffer_index = 0; buffer_index < NUM_BUFFERS; ++buffer_index) + { + if (net->net_buffer[buffer_index] == buffer) + { + /* We found the index of the buffer provided. */ + printf("Freed buffer %d\n", buffer_index); + break; + } + } + if (buffer_index >= NUM_BUFFERS) { return -1; } + net->buffer_available[buffer_index] = 1; + return 0; +} -- cgit v1.2.1 From 1b446e5e9d45ca97cbdcb2dc7f48c485f6c0aa2b Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Mon, 3 Oct 2016 18:54:39 -0600 Subject: Select needs max fd number plus one --- daemons/maap/linux/src/maap_linux.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index f0cb41f4..2b0cac4a 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -269,7 +269,7 @@ int main(int argc, char *argv[]) FD_SET(STDIN_FILENO, &read_fds); FD_SET(socketfd, &read_fds); fdmax = socketfd; - ret = select(fdmax, &read_fds, NULL, NULL, &tv); + ret = select(fdmax+1, &read_fds, NULL, NULL, &tv); if (ret < 0) { printf("select() error %d\n", errno); @@ -285,7 +285,10 @@ int main(int argc, char *argv[]) /* Handle any packets received. */ if (FD_ISSET(socketfd, &read_fds)) { - while ((recvbytes = recv(socketfd, recvbuffer, sizeof(recvbuffer), 0)) > 0) + struct sockaddr_ll ll_addr; + socklen_t addr_len; + + while ((recvbytes = recvfrom(socketfd, recvbuffer, sizeof(recvbuffer), MSG_DONTWAIT, (struct sockaddr*)&ll_addr, &addr_len)) > 0) { printf("Received %d byte packet\n", recvbytes); maap_handle_packet(&mc, (uint8_t *)recvbuffer, recvbytes); @@ -315,6 +318,7 @@ int main(int argc, char *argv[]) parse_write(&mc, recvbuffer); } } + } close(socketfd); -- cgit v1.2.1 From af9d1ad2398f07a00d3ae2166203dc6c32fd2a0e Mon Sep 17 00:00:00 2001 From: Levi Pearson Date: Mon, 3 Oct 2016 19:24:17 -0600 Subject: Fixes to the maap_test code --- daemons/maap/test/maap_test.c | 156 ++++++++++++++++++++++++++++++------------ 1 file changed, 112 insertions(+), 44 deletions(-) diff --git a/daemons/maap/test/maap_test.c b/daemons/maap/test/maap_test.c index 4c775f63..0a902b00 100644 --- a/daemons/maap/test/maap_test.c +++ b/daemons/maap/test/maap_test.c @@ -17,6 +17,7 @@ void test1_setup(void); void test2_setup(void); void test3_setup(void); +void delay_setup(void); /* MAAP packet encoding/decoding */ #define MAAP_RESERVED 0 @@ -110,10 +111,10 @@ int pack_maap(maap_packet_t *packet, uint8_t *stream) { stream += 2; *stream = (packet->CD << 7) | (packet->subtype & 0x7f); stream++; - *stream = (packet->SV << 7) | ((packet->version & 0x07) << 4) | + *stream = (packet->SV << 7) | ((packet->version & 0x07) << 4) | (packet->message_type & 0x0f); stream++; - *(uint16_t *)stream = htobe16(((packet->status & 0x001f) << 11) | + *(uint16_t *)stream = htobe16(((packet->status & 0x001f) << 11) | (packet->MAAP_data_length & 0x07ff)); stream += 2; *(uint64_t *)stream = htobe64(packet->stream_id); @@ -139,26 +140,26 @@ struct maap_test_state { uint64_t hwaddr; }; -struct maap_test_state test_state = {NULL, 0, 0}; +struct maap_test_state test_state = {NULL, 0, 0, 0}; int get_raw_sock(int ethertype) { int rawsock; - + if((rawsock = socket(PF_PACKET, SOCK_RAW, htons(ethertype))) == -1) { perror("Error creating raw sock: "); exit(-1); } - + return rawsock; } int bind_sock(char *device, int rawsock, int protocol) { struct sockaddr_ll sll; struct ifreq ifr; - + bzero(&sll, sizeof(sll)); bzero(&ifr, sizeof(ifr)); - + /* First, get the interface index */ strncpy((char *)ifr.ifr_name, device, IFNAMSIZ); if((ioctl(rawsock, SIOCGIFINDEX, &ifr)) == -1) { @@ -183,10 +184,10 @@ int bind_sock(char *device, int rawsock, int protocol) { if((bind(rawsock, (struct sockaddr*)&sll, sizeof(sll))) == -1) { perror("Error binding raw socket to interface\n"); - exit(-1); + exit(-1); } - - return 1; + + return 1; } int send_packet(int rawsock, maap_packet_t *mp) { @@ -196,7 +197,7 @@ int send_packet(int rawsock, maap_packet_t *mp) { mp->SA = test_state.hwaddr; pack_maap(mp, pkt); - if((sent = write(rawsock, pkt, 60)) != 60) { + if((sent = write(rawsock, pkt, 60)) != 60) { return 0; } return 1; @@ -210,10 +211,15 @@ int main(int argc, char *argv[]) { bpf_u_int32 mask; bpf_u_int32 net; - dev = pcap_lookupdev(errbuf); - if (dev == NULL) { - fprintf(stderr, "Couldn't find default device: %s\n", errbuf); - return 2; + if (argc < 2) { + dev = pcap_lookupdev(errbuf); + if (dev == NULL) { + fprintf(stderr, "Couldn't find default device: %s\n", errbuf); + fprintf(stderr, "Try specifying the device you want: %s \n", argv[0]); + return 2; + } + } else { + dev = argv[1]; } if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { @@ -245,15 +251,19 @@ int main(int argc, char *argv[]) { test_state.rawsock = get_raw_sock(0x22F0); bind_sock(dev, test_state.rawsock, 0x22F0); - test3_setup(); + test1_setup(); pcap_loop(handle, -1, parse_packet, NULL); + + return 0; } void parse_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { maap_packet_t mp; + (void)args; (void)header; + unpack_maap(&mp, (uint8_t *)packet); dump_packed_packet(&mp); @@ -266,7 +276,7 @@ void parse_packet(u_char *args, const struct pcap_pkthdr *header, if (test_state.pkt_handler) { test_state.pkt_handler(&mp); } - + return; } @@ -274,11 +284,12 @@ void parse_packet(u_char *args, const struct pcap_pkthdr *header, * Test functions *************************************************************************/ -/* Wait for a probe, send a defense response, see if next probe is for a +/* Wait for a probe, send a defense response, see if next probe is for a different range */ #define WAITING_FOR_1ST_PROBE 0 #define WAITING_FOR_2ND_PROBE 1 +#define WAITING_FOR_3RD_PROBE 2 int test1_handler(maap_packet_t *mp) { static uint64_t start; @@ -320,15 +331,53 @@ int test1_handler(maap_packet_t *mp) { /* Make sure we got a probe in response */ if (mp->message_type != MAAP_PROBE) { - fprintf(stderr, "Test 1: FAIL - Got a non-probe packet, type %d.\n", + fprintf(stderr, "Test 1: FAIL - Got a non-probe packet, type %d.\n", mp->message_type); exit(2); } printf("Received a probe from %012llx for %d addresses starting at %012llx\n", - (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->SA, mp->requested_count, (long long unsigned int)mp->requested_start_address); + /* See if the address range has changed */ + if (mp->requested_start_address == start) { + /* They may have sent before we did; give them one more try */ + mp->DA = mp->SA; + mp->SA = 0; + mp->message_type = MAAP_DEFEND; + mp->start_address = start; + mp->count = count; + send_packet(test_state.rawsock, mp); + printf("Sent another defend packet\n"); + + /* Update testing state */ + test_state.state = WAITING_FOR_3RD_PROBE; + + } else { + + /* Success! */ + printf("Test 1: PASS\n"); + + test2_setup(); + + } + + break; + + case WAITING_FOR_3RD_PROBE: + + /* Make sure we got a probe in response */ + if (mp->message_type != MAAP_PROBE) { + fprintf(stderr, "Test 1: FAIL - Got a non-probe packet, type %d.\n", + mp->message_type); + exit(2); + } + + printf("Received a probe from %012llx for %d addresses starting at %012llx\n", + (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->requested_start_address); + /* Make sure the address range has changed */ if (mp->requested_start_address == start) { fprintf(stderr, "Test 1: FAIL - Got a probe for the same range.\n"); @@ -337,11 +386,13 @@ int test1_handler(maap_packet_t *mp) { /* Success! */ printf("Test 1: PASS\n"); - + test2_setup(); break; } + + return 0; } void test1_setup(void) { @@ -372,7 +423,7 @@ int test2_handler(maap_packet_t *mp) { break; } printf("Received an announce from %012llx for %d addresses starting at %012llx\n", - (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->SA, mp->requested_count, (long long unsigned int)mp->requested_start_address); /* Store the range from the ANNOUNCE so we can check the defense of this @@ -392,7 +443,7 @@ int test2_handler(maap_packet_t *mp) { case WAITING_FOR_DEFEND: if (mp->message_type != MAAP_DEFEND) { - fprintf(stderr, "Test 2: FAIL - Got a non-defend packet, type %d.\n", + fprintf(stderr, "Test 2: FAIL - Got a non-defend packet, type %d.\n", mp->message_type); exit(2); } @@ -405,7 +456,7 @@ int test2_handler(maap_packet_t *mp) { } if (mp->requested_count != count) { fprintf(stderr, "Test 2: FAIL - Requested count wasn't filled out with the value from the probe.\n"); - fprintf(stderr, "Requested count: %d Probe count: %d\n", + fprintf(stderr, "Requested count: %d Probe count: %d\n", mp->requested_count, count); exit(2); } @@ -421,15 +472,17 @@ int test2_handler(maap_packet_t *mp) { fprintf(stderr, "Defend count: %d Conflicting count: %d\n", mp->count, count); exit(2); } - + /* Success! */ printf("Test 2: PASS\n"); - + test3_setup(); break; - + } + + return 0; } void test2_setup(void) { @@ -458,7 +511,7 @@ int test3_handler(maap_packet_t *mp) { break; } printf("Received an announce from %012llx for %d addresses starting at %012llx\n", - (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->SA, mp->requested_count, (long long unsigned int)mp->requested_start_address); /* Store the range from the ANNOUNCE so we can check the defense of this @@ -480,34 +533,34 @@ int test3_handler(maap_packet_t *mp) { case WAITING_FOR_DEFEND: if (mp->message_type != MAAP_DEFEND) { - fprintf(stderr, "test 3: FAIL - Got a non-defend packet, type %d.\n", + fprintf(stderr, "test 3: FAIL - Got a non-defend packet, type %d.\n", mp->message_type); - return; + exit(2); } if (mp->requested_start_address != start) { fprintf(stderr, "test 3: FAIL - Requested start address wasn't filled out with the value from the probe.\n"); fprintf(stderr, "Req start address: %012llx Probe address: %012llx\n", (unsigned long long)mp->requested_start_address, (unsigned long long)start); - return; + exit(2); } if (mp->requested_count != count) { fprintf(stderr, "test 3: FAIL - Requested count wasn't filled out with the value from the probe.\n"); - fprintf(stderr, "Requested count: %d Probe count: %d\n", + fprintf(stderr, "Requested count: %d Probe count: %d\n", mp->requested_count, count); - return; + exit(2); } if (mp->start_address != start) { fprintf(stderr, "test 3: FAIL - Start address wasn't filled out with the first conflicting address from the probe.\n"); fprintf(stderr, "Start address: %012llx Conflicting address: %012llx\n", (unsigned long long)mp->start_address, (unsigned long long)start); - return; + exit(2); } if (mp->count != count) { fprintf(stderr, "test 3: FAIL - Count wasn't filled out with the number of addresses conflicting with the probe.\n"); fprintf(stderr, "Defend count: %d Conflicting count: %d\n", mp->count, count); - return; + exit(2); } /* Send out the same announce again */ @@ -522,13 +575,13 @@ int test3_handler(maap_packet_t *mp) { case WAITING_FOR_PROBE: /* Make sure we got a probe in response */ if (mp->message_type != MAAP_PROBE) { - fprintf(stderr, "Test 3: FAIL - Got a non-probe packet, type %d.\n", + fprintf(stderr, "Test 3: FAIL - Got a non-probe packet, type %d.\n", mp->message_type); - return; + exit(2); } printf("Received a probe from %012llx for %d addresses starting at %012llx\n", - (long long unsigned int)mp->SA, mp->requested_count, + (long long unsigned int)mp->SA, mp->requested_count, (long long unsigned int)mp->requested_start_address); /* Make sure the address range has changed */ @@ -540,20 +593,35 @@ int test3_handler(maap_packet_t *mp) { /* Success! */ printf("Test 3: PASS\n"); - printf("Waiting 5 min for next test...."); - sleep(300); - - test3_setup(); + delay_setup(); break; - + } + + return 0; } void test3_setup(void) { test_state.state = WAITING_FOR_ANNOUNCE; test_state.pkt_handler = test3_handler; - printf("Starting test 3: yielding a reservation after 2 announces\n"); + printf("Starting Test 3: yielding a reservation after 2 announces\n"); printf("Waiting for an announce packet...\n"); } +int delay_handler(maap_packet_t *mp) { + if (mp->message_type == MAAP_ANNOUNCE) { + test_state.state += 1; + if (test_state.state == 10) { + printf("Received 10 Announce messages.\n"); + test3_setup(); + } + } + return 0; +} + +void delay_setup(void) { + test_state.state = 0; + test_state.pkt_handler = delay_handler; + printf("Waiting for ~5min (10 Announces)\n"); +} -- cgit v1.2.1 From 757d4f37ddcec3ae918e673c4308c09197639696 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Tue, 4 Oct 2016 11:36:15 -0600 Subject: Debugging Cleanup Code debug message cleanup. Added DEBUG_NET_MSG define to hide unwanted network queue printf details. Added DEBUG_TIMER_MSG define to hide unwanted timer printf details. Added strerror() calls to show what error numbers represent. --- daemons/maap/common/maap.c | 41 ++++++++++++++++++++++++++----- daemons/maap/common/maap_iface.h | 3 --- daemons/maap/common/maap_protocol.c | 2 +- daemons/maap/linux/src/maap_linux.c | 14 +++++------ daemons/maap/linux/src/maap_net_linux.c | 16 ++++++++++-- daemons/maap/linux/src/maap_timer_linux.c | 3 ++- 6 files changed, 58 insertions(+), 21 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index 51c34917..f4f383de 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -12,6 +12,10 @@ #include #include +/* Uncomment the DEBUG_TIMER_MSG define to display debug messages. */ +/* #define DEBUG_TIMER_MSG */ + + static int get_count(Maap_Client *mc, Range *range) { (void)mc; return range->interval->high - range->interval->low + 1; @@ -76,7 +80,7 @@ static int send_defend(Maap_Client *mc, Range *range, uint64_t start, static int inform_acquired(Maap_Client *mc, Range *range) { Maap_Notify note; - printf("Address range acquired: %" PRIx64 " %d\n", + printf("Address range acquired: 0x%" PRIx64 " %d\n", get_start_address(mc, range), get_count(mc, range)); @@ -171,7 +175,7 @@ int maap_init_client(Maap_Client *mc, uint64_t range_info) { mc->initialized = 1; - printf("MAAP initialized, start: %012llx, max: %08x\n", + printf("MAAP initialized, start: 0x%012llx, max: 0x%04x\n", (unsigned long long)range_info & MAAP_BASE_MASK, (unsigned int)((range_info & MAAP_RANGE_MASK) >> (ETH_ALEN * 8)) - 1); return 0; @@ -201,26 +205,38 @@ int schedule_timer(Maap_Client *mc, Range *range) { if (range->state == MAAP_STATE_PROBING) { ns = MAAP_PROBE_INTERVAL_BASE + rand_ms(MAAP_PROBE_INTERVAL_VARIATION); ns = ns * 1000000; +#ifdef DEBUG_TIMER_MSG printf("Scheduling probe timer for %" PRIu64 " ns from now\n", ns); +#endif Time_setFromNanos(&ts, ns); +#ifdef DEBUG_TIMER_MSG printf("Which is a timespec of: "); Time_dump(&ts); +#endif Time_setFromMonotonicTimer(&range->next_act_time); +#ifdef DEBUG_TIMER_MSG printf("\nCurrent time is: "); Time_dump(&range->next_act_time); +#endif Time_add(&range->next_act_time, &ts); +#ifdef DEBUG_TIMER_MSG printf("\nExpiration time is: "); Time_dump(&range->next_act_time); printf("\n\n"); +#endif } else if (range->state == MAAP_STATE_DEFENDING) { ns = MAAP_ANNOUNCE_INTERVAL_BASE + rand_ms(MAAP_ANNOUNCE_INTERVAL_VARIATION); ns = ns * 1000000; +#ifdef DEBUG_TIMER_MSG printf("Scheduling defend timer for %" PRIu64 " ns from now\n", ns); +#endif Time_setFromNanos(&ts, (uint64_t)ns); Time_setFromMonotonicTimer(&range->next_act_time); Time_add(&range->next_act_time, &ts); +#ifdef DEBUG_TIMER_MSG Time_dump(&range->next_act_time); printf("\n\n"); +#endif } if (mc->timer_queue == NULL || @@ -323,17 +339,18 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { int rv; unsigned long long int a, b, c, d; - printf("RECEIVED MAAP PACKET LEN %d\n", len); + /* printf("RECEIVED MAAP PACKET LEN %d\n", len); */ if (len < 42) { printf("Truncated MAAP packet received, discarding\n"); return 0; } rv = unpack_maap(&p, stream); if (rv != 0) { + printf("Error unpacking the MAAP packet\n"); return rv; } - printf("Unpacked packet\n"); + /* printf("Unpacked packet\n"); */ a = p.requested_start_address + p.requested_count - 1; b = mc->address_base; @@ -341,7 +358,7 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { d = p.requested_start_address; if (a < b || c < d) { printf("Packet refers to a range outside of our concern\n"); - printf("%016llx < %016llx || %016llx < %016llx\n", a, b, c, d); + printf("0x%016llx < 0x%016llx || 0x%016llx < 0x%016llx\n", a, b, c, d); return 0; } @@ -419,27 +436,37 @@ int maap_handle_timer(Maap_Client *mc) { /* Get the current time. */ Time_setFromMonotonicTimer(¤ttime); +#ifdef DEBUG_TIMER_MSG printf("Current time is: "); Time_dump(¤ttime); printf("\n"); +#endif mc->timer_running = 0; while ((range = mc->timer_queue) && Time_passed(¤ttime, &range->next_act_time)) { +#ifdef DEBUG_TIMER_MSG printf("Due timer: "); Time_dump(&range->next_act_time); + printf("\n"); +#endif mc->timer_queue = range->next_timer; range->next_timer = NULL; - printf("\n"); if (range->state == MAAP_STATE_PROBING) { +#ifdef DEBUG_TIMER_MSG printf("Handling probe timer\n"); +#endif handle_probe_timer(mc, range); } else if (range->state == MAAP_STATE_DEFENDING) { +#ifdef DEBUG_TIMER_MSG printf("Handling defend timer\n"); +#endif handle_defend_timer(mc, range); } else if (range->state == MAAP_STATE_RELEASED) { +#ifdef DEBUG_TIMER_MSG printf("Freeing released timer\n"); +#endif free(range); } @@ -465,6 +492,8 @@ int64_t maap_get_delay_to_next_timer(Maap_Client *mc) /* Get the time remaining for the next timer. */ timeRemaining = Time_remaining(mc->timer); } +#ifdef DEBUG_TIMER_MSG printf("Next delay: %" PRId64 " ns\n\n", timeRemaining); +#endif return timeRemaining; } diff --git a/daemons/maap/common/maap_iface.h b/daemons/maap/common/maap_iface.h index 3c4a7d68..9abff5be 100644 --- a/daemons/maap/common/maap_iface.h +++ b/daemons/maap/common/maap_iface.h @@ -3,9 +3,6 @@ #include -//#define MAAP_SOCKET_NAME "/var/tmp/maap.socket" -//#define MAAP_CMD_BUF_SZ 500 - /* MAAP Request Format * * This is the format of the request the driver expects to receive from the diff --git a/daemons/maap/common/maap_protocol.c b/daemons/maap/common/maap_protocol.c index b9530adb..66df2c61 100644 --- a/daemons/maap/common/maap_protocol.c +++ b/daemons/maap/common/maap_protocol.c @@ -83,7 +83,7 @@ int state_transit(maap_info_t *maap_info) num_bytes = recv_packet(pkt_rx, NON_BLOCK); if (num_bytes > 0) { msg_type = pkt_rx->data.message_type; - DBG("msg_type %x \n",msg_type); + DBG("msg_type 0x%x \n",msg_type); if (msg_type == MAAP_DEFEND || msg_type == MAAP_ANNOUNCE || diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 2b0cac4a..7300d8fb 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -94,9 +94,8 @@ int main(int argc, char *argv[]) void *packet_data; int64_t waittime; struct timeval tv; -// fd_set master; // master file descriptor list - fd_set read_fds; // temp file descriptor list for select() - int fdmax; // maximum file descriptor number + fd_set read_fds; + int fdmax; char recvbuffer[1600]; int recvbytes; Maap_Cmd recvcmd; @@ -244,7 +243,7 @@ int main(int argc, char *argv[]) if (send(socketfd, packet_data, MAAP_NET_BUFFER_SIZE, 0) < 0) { /* Something went wrong. Abort! */ - printf("Error %d writing to network socket\n", errno); + printf("Error %d writing to network socket (%s)\n", errno, strerror(errno)); break; } Net_freeQueuedPacket(mc.net, packet_data); @@ -272,7 +271,7 @@ int main(int argc, char *argv[]) ret = select(fdmax+1, &read_fds, NULL, NULL, &tv); if (ret < 0) { - printf("select() error %d\n", errno); + printf("select() error %d (%s)\n", errno, strerror(errno)); break; } if (ret == 0) @@ -290,13 +289,12 @@ int main(int argc, char *argv[]) while ((recvbytes = recvfrom(socketfd, recvbuffer, sizeof(recvbuffer), MSG_DONTWAIT, (struct sockaddr*)&ll_addr, &addr_len)) > 0) { - printf("Received %d byte packet\n", recvbytes); maap_handle_packet(&mc, (uint8_t *)recvbuffer, recvbytes); } if (recvbytes < 0 && errno != EWOULDBLOCK) { /* Something went wrong. Abort! */ - printf("Error %d reading from network socket\n", errno); + printf("Error %d reading from network socket (%s)\n", errno, strerror(errno)); break; } } @@ -307,7 +305,7 @@ int main(int argc, char *argv[]) recvbytes = read(STDIN_FILENO, recvbuffer, sizeof(recvbuffer) - 1); if (recvbytes < 0) { - printf("Error %d reading from stdin\n", errno); + printf("Error %d reading from stdin (%s)\n", errno, strerror(errno)); } else { diff --git a/daemons/maap/linux/src/maap_net_linux.c b/daemons/maap/linux/src/maap_net_linux.c index c6b01e4d..c5129907 100644 --- a/daemons/maap/linux/src/maap_net_linux.c +++ b/daemons/maap/linux/src/maap_net_linux.c @@ -7,6 +7,10 @@ #define NUM_BUFFERS 4 +/* Uncomment the DEBUG_NET_MSG define to display debug messages. */ +/* #define DEBUG_NET_MSG */ + + struct maap_net { char net_buffer[NUM_BUFFERS][MAAP_NET_BUFFER_SIZE]; int buffer_available[NUM_BUFFERS]; @@ -45,7 +49,9 @@ void *Net_getPacketBuffer(Net *net) if (net->buffer_available[i]) { net->buffer_available[i] = 0; +#ifdef DEBUG_NET_MSG printf("Allocated buffer %d\n", i); +#endif return (void *)(net->net_buffer[i]); } } @@ -57,13 +63,14 @@ int Net_queuePacket(Net *net, void *buffer) int buffer_index, queue_index; assert(net); - /* @TODO: This could be done mathematically, rather than in a loop. */ for (buffer_index = 0; buffer_index < NUM_BUFFERS; ++buffer_index) { if (net->net_buffer[buffer_index] == buffer) { /* We found the index of the buffer provided. */ +#ifdef DEBUG_NET_MSG printf("Queuing buffer %d\n", buffer_index); +#endif break; } } @@ -76,7 +83,9 @@ int Net_queuePacket(Net *net, void *buffer) { /* We can add the buffer to this spot in the queue. */ net->index_to_send[queue_index] = buffer_index; +#ifdef DEBUG_NET_MSG printf("Buffer %d queued at index %d\n", buffer_index, queue_index); +#endif return 0; } } @@ -91,7 +100,9 @@ void *Net_getNextQueuedPacket(Net *net) assert(net); if (net->index_to_send[0] >= 0) { +#ifdef DEBUG_NET_MSG printf("Buffer %d pulled from queue\n", net->index_to_send[0]); +#endif pBuffer = net->net_buffer[net->index_to_send[0]]; for (i = 0; i < NUM_BUFFERS - 1; ++i) { @@ -108,13 +119,14 @@ int Net_freeQueuedPacket(Net *net, void *buffer) int buffer_index; assert(net); - /* @TODO: This could be done mathematically, rather than in a loop. */ for (buffer_index = 0; buffer_index < NUM_BUFFERS; ++buffer_index) { if (net->net_buffer[buffer_index] == buffer) { /* We found the index of the buffer provided. */ +#ifdef DEBUG_NET_MSG printf("Freed buffer %d\n", buffer_index); +#endif break; } } diff --git a/daemons/maap/linux/src/maap_timer_linux.c b/daemons/maap/linux/src/maap_timer_linux.c index b2d5f0f4..80e8726b 100644 --- a/daemons/maap/linux/src/maap_timer_linux.c +++ b/daemons/maap/linux/src/maap_timer_linux.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,7 @@ int64_t Time_remaining(Timer *timer) assert(timer); if (timer_gettime(timer->timer_id, &curr_value) < 0) { - printf("Error %d getting the timer time remaining\n", errno); + printf("Error %d getting the timer time remaining (%s)\n", errno, strerror(errno)); return -1; } -- cgit v1.2.1 From c99dfe44d5ca4ed5b7591a6a57210141dc16b940 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Tue, 4 Oct 2016 11:37:16 -0600 Subject: Changed stdin processing to make it more intuitive. --- daemons/maap/common/maap.h | 1 + daemons/maap/common/maap_parse.c | 26 ++++++++++++++++++-------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index 5646abc8..adcb3de4 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -25,6 +25,7 @@ #define MAAP_CB_YIELDED 1 #define MAAP_DEST_MAC {0x91, 0xE0, 0xF0, 0x00, 0xFF, 0x00} +#define MAAP_DEST_64 0x000091E0F000FF00LL #define MAAP_RANGE_SIZE 0xFFDF #define MAAP_RANGE_SIZE_64 (((uint64_t)MAAP_RANGE_SIZE) << 48) #define MAAP_TYPE 0x22F0 diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c index 2c96afa1..4c84efba 100644 --- a/daemons/maap/common/maap_parse.c +++ b/daemons/maap/common/maap_parse.c @@ -24,17 +24,23 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { p = strtok(NULL, " \r\n"); } - if (argc == 2) + if (argc >= 1 && argc <= 3) { if (strncmp(argv[0], "init", 4) == 0) { - cmd->kind = MAAP_INIT; - cmd->param.range_info = strtoull(argv[1], NULL, 16); - set_cmd = 1; - } else if (strncmp(argv[0], "reserve", 7) == 0) { + if (argc == 1) { + cmd->kind = MAAP_INIT; + cmd->param.range_info = MAAP_DEST_64 | MAAP_RANGE_SIZE_64; + set_cmd = 1; + } else if (argc == 3) { + cmd->kind = MAAP_INIT; + cmd->param.range_info = strtoull(argv[1], NULL, 16) | (strtoull(argv[2], NULL, 16) << 48); + set_cmd = 1; + } + } else if (strncmp(argv[0], "reserve", 7) == 0 && argc == 2) { cmd->kind = MAAP_RESERVE; cmd->param.length = (uint16_t)strtoul(argv[1], NULL, 0); set_cmd = 1; - } else if (strncmp(argv[0], "release", 7) == 0) { + } else if (strncmp(argv[0], "release", 7) == 0 && argc == 2) { cmd->kind = MAAP_RELEASE; cmd->param.id = (int)strtoul(argv[1], NULL, 0); set_cmd = 1; @@ -45,7 +51,11 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { if (!set_cmd) { - printf("input usage: init|reserve|release \n"); + printf("input usage:\n"); + printf(" init [ ]\n"); + printf(" If not specified, range_base=0x%llx, range_size=0x%04x\n", MAAP_DEST_64, MAAP_RANGE_SIZE); + printf(" reserve \n"); + printf(" release \n\n"); return 0; } @@ -74,7 +84,7 @@ void parse_write(Maap_Client *mc, char *buf) { if (rv) { switch(cmd.kind) { case MAAP_INIT: - printf("Got cmd maap_init_client, range_info: %016llx\n", (unsigned long long)cmd.param.range_info); + printf("Got cmd maap_init_client, range_info: 0x%016llx\n", (unsigned long long)cmd.param.range_info); rv = maap_init_client(mc, cmd.param.range_info); break; case MAAP_RESERVE: -- cgit v1.2.1 From 055b2e21b484e3b2e537cdcd1a6c252c4fe1f593 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Tue, 4 Oct 2016 14:36:34 -0600 Subject: Range checking fix. Fixed an issue where get_start_address was returning the wrong value. Added MAAP incoming packet verification of the message type. More debug messages regarding range checking. --- daemons/maap/common/maap.c | 47 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index f4f383de..34f55b4e 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -9,7 +9,6 @@ #include /* Linux-specific header files */ -#include #include /* Uncomment the DEBUG_TIMER_MSG define to display debug messages. */ @@ -21,7 +20,11 @@ static int get_count(Maap_Client *mc, Range *range) { return range->interval->high - range->interval->low + 1; } -static uint64_t get_start_address(Maap_Client *mc, Range *range) { +static unsigned long long int get_start_address(Maap_Client *mc, Range *range) { + return mc->address_base + range->interval->low; +} + +static unsigned long long int get_end_address(Maap_Client *mc, Range *range) { return mc->address_base + range->interval->high; } @@ -80,8 +83,9 @@ static int send_defend(Maap_Client *mc, Range *range, uint64_t start, static int inform_acquired(Maap_Client *mc, Range *range) { Maap_Notify note; - printf("Address range acquired: 0x%" PRIx64 " %d\n", + printf("Address range acquired: 0x%012llx-0x%012llx (Size %d)\n", get_start_address(mc, range), + get_end_address(mc, range), get_count(mc, range)); note.kind = MAAP_ACQUIRED; @@ -299,6 +303,7 @@ int maap_reserve_range(Maap_Client *mc, uint16_t length) { range->next_timer = NULL; assign_interval(mc, range, length); + printf("Selected address range 0x%012llx-0x%012llx\n", get_start_address(mc, range), get_end_address(mc, range)); send_probe(mc, range); range->counter--; schedule_timer(mc, range); @@ -337,10 +342,10 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { uint32_t start; Range *range; int rv; - unsigned long long int a, b, c, d; + unsigned long long int own_base, own_max, incoming_base, incoming_max; /* printf("RECEIVED MAAP PACKET LEN %d\n", len); */ - if (len < 42) { + if (len < MAAP_PKT_SIZE) { printf("Truncated MAAP packet received, discarding\n"); return 0; } @@ -352,13 +357,25 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { /* printf("Unpacked packet\n"); */ - a = p.requested_start_address + p.requested_count - 1; - b = mc->address_base; - c = mc->address_base + mc->range_len - 1; - d = p.requested_start_address; - if (a < b || c < d) { + if (p.message_type < MAAP_PROBE || p.message_type > MAAP_ANNOUNCE) { + printf("Maap packet message type %u not recognized\n", p.message_type); + return 0; + } + + own_base = mc->address_base; + own_max = mc->address_base + mc->range_len - 1; + incoming_base = p.requested_start_address; + incoming_max = p.requested_start_address + p.requested_count - 1; + +#if 0 + if (p.message_type == MAAP_PROBE) { printf("Received PROBE for range 0x%012llx-0x%012llx (Size %u)\n", incoming_base, incoming_max, p.requested_count); } + if (p.message_type == MAAP_DEFEND) { printf("Received DEFEND for range 0x%012llx-0x%012llx (Size %u)\n", incoming_base, incoming_max, p.requested_count); } + if (p.message_type == MAAP_ANNOUNCE) { printf("Received ANNOUNCE for range 0x%012llx-0x%012llx (Size %u)\n", incoming_base, incoming_max, p.requested_count); } +#endif + + if (incoming_max < own_base || own_max < incoming_base) { printf("Packet refers to a range outside of our concern\n"); - printf("0x%016llx < 0x%016llx || 0x%016llx < 0x%016llx\n", a, b, c, d); + printf("0x%012llx < 0x%012llx || 0x%012llx < 0x%012llx\n", incoming_max, own_base, own_max, incoming_base); return 0; } @@ -368,6 +385,10 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { range = iv->data; if (range->state == MAAP_STATE_PROBING) { printf("Found a conflicting preexisting range, look for a new one\n"); + printf(" Response of 0x%012llx-0x%012llx overlaps our\n", + incoming_base, incoming_max); + printf(" request of 0x%012llx-0x%012llx\n", + get_start_address(mc, range), get_end_address(mc, range)); /* Find an alternate interval, remove old interval, and restart probe counter */ assign_interval(mc, range, iv->high - iv->low + 1); @@ -376,6 +397,10 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { range->counter = MAAP_PROBE_RETRANSMITS; } else if (range->state == MAAP_STATE_DEFENDING) { printf("Someone is messing with our range!\n"); + printf(" Request of 0x%012llx-0x%012llx inside our\n", + incoming_base, incoming_max); + printf(" range of 0x%012llx-0x%012llx\n", + get_start_address(mc, range), get_end_address(mc, range)); if (p.message_type == MAAP_PROBE) { printf("DEFEND!\n"); send_defend(mc, range, p.requested_start_address, p.requested_count, -- cgit v1.2.1 From b674ad3dc8d0067c2ffe3756f4261d2db802b3a0 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Tue, 4 Oct 2016 14:37:32 -0600 Subject: Seeds the random number generator Seeds the random number generator. Removed unnecessary header files. --- daemons/maap/linux/src/maap_linux.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 7300d8fb..3d041339 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -32,10 +32,6 @@ #include #include -#include -#include -#include -#include #include #include @@ -45,8 +41,6 @@ #include #include -#include -#include #include #include #include @@ -194,7 +188,6 @@ int main(int argc, char *argv[]) return -1; } -#if 1 /* filter multicast address */ memset(&mreq, 0, sizeof(mreq)); mreq.mr_ifindex = ifindex; @@ -207,7 +200,6 @@ int main(int argc, char *argv[]) printf("setsockopt PACKET_ADD_MEMBERSHIP failed\n"); return -1; } -#endif /* @@ -218,17 +210,12 @@ int main(int argc, char *argv[]) mc.src_mac = convert_mac_address(src_mac); -#if 0 /* - * Initialize the low-level MAAP support, using the default MAAP Dynamic Allocation Pool. + * Seed the random number generator. */ - if (maap_init_client(&mc, MAAP_DEST_64 | MAAP_RANGE_SIZE_64) < 0) - { - printf("maap_init_client() failed\n"); - return -1; - } -#endif + srand((unsigned int)mc.src_mac ^ (unsigned int)time(NULL)); + /* -- cgit v1.2.1 From 5896508391340fc35604a2053cdccebc944d9866 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Tue, 4 Oct 2016 14:51:48 -0600 Subject: Added Reserve and Release error checking Ignore reserve or release commands if not initialized. Don't attempt to release if the ID is not valid. --- daemons/maap/common/maap.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index 34f55b4e..da2c97db 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -289,6 +289,11 @@ int maap_reserve_range(Maap_Client *mc, uint16_t length) { int id; Range *range; + if (!mc->initialized) { + printf("Reserve not allowed, as MAAP not initialized\n"); + return -1; + } + range = malloc(sizeof (Range)); if (range == NULL) { return -1; @@ -317,23 +322,28 @@ int maap_reserve_range(Maap_Client *mc, uint16_t length) { int maap_release_range(Maap_Client *mc, int id) { Interval *iv; Range *range; - int rv = -1; + + if (!mc->initialized) { + printf("Release not allowed, as MAAP not initialized\n"); + return -1; + } range = mc->timer_queue; while (range) { - if (range->id == id) { + if (range->id == id && range->state != MAAP_STATE_RELEASED) { iv = range->interval; iv = remove_interval(&mc->ranges, iv); free_interval(iv); /* memory for range will be freed the next time its timer elapses */ range->state = MAAP_STATE_RELEASED; printf("Released range id %d\n", id); - rv = 0; + return 0; } range = range->next_timer; } - return rv; + printf("Range id %d does not exist to release\n", id); + return -1; } int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { -- cgit v1.2.1 From 637076f509281cdf3c80b470d8928232e21ae0e1 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Tue, 4 Oct 2016 15:14:21 -0600 Subject: Added an "exit" command. --- daemons/maap/common/maap.c | 17 +++++++++-------- daemons/maap/common/maap_iface.h | 1 + daemons/maap/common/maap_parse.c | 15 +++++++++++++-- daemons/maap/common/maap_parse.h | 18 +++++++++++++++++- daemons/maap/linux/src/maap_linux.c | 5 ++++- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index da2c97db..aa2e7296 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -186,15 +186,16 @@ int maap_init_client(Maap_Client *mc, uint64_t range_info) { } void maap_deinit_client(Maap_Client *mc) { - assert(!mc->initialized); - assert(!mc->timer_queue); - - Time_delTimer(mc->timer); - Net_delNet(mc->net); + if (mc->initialized) { + if (mc->timer_queue) { + Time_delTimer(mc->timer); + Net_delNet(mc->net); + } - mc->timer = NULL; - mc->net = NULL; - mc->initialized = 0; + mc->timer = NULL; + mc->net = NULL; + mc->initialized = 0; + } } int rand_ms(int variation) { diff --git a/daemons/maap/common/maap_iface.h b/daemons/maap/common/maap_iface.h index 9abff5be..a24515bb 100644 --- a/daemons/maap/common/maap_iface.h +++ b/daemons/maap/common/maap_iface.h @@ -14,6 +14,7 @@ typedef enum { MAAP_INIT, MAAP_RESERVE, MAAP_RELEASE, + MAAP_EXIT, } Maap_Cmd_Tag; typedef struct { diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c index 4c84efba..a3f3f506 100644 --- a/daemons/maap/common/maap_parse.c +++ b/daemons/maap/common/maap_parse.c @@ -44,6 +44,9 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { cmd->kind = MAAP_RELEASE; cmd->param.id = (int)strtoul(argv[1], NULL, 0); set_cmd = 1; + } else if (strncmp(argv[0], "exit", 4) == 0 && argc == 1) { + cmd->kind = MAAP_EXIT; + set_cmd = 1; } else { printf("Invalid command type\n"); } @@ -55,16 +58,18 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { printf(" init [ ]\n"); printf(" If not specified, range_base=0x%llx, range_size=0x%04x\n", MAAP_DEST_64, MAAP_RANGE_SIZE); printf(" reserve \n"); - printf(" release \n\n"); + printf(" release \n"); + printf(" exit\n\n"); return 0; } return 1; } -void parse_write(Maap_Client *mc, char *buf) { +int parse_write(Maap_Client *mc, char *buf) { Maap_Cmd *bufcmd, cmd; int rv = 0; + int retVal = 0; bufcmd = (Maap_Cmd *)buf; @@ -95,10 +100,16 @@ void parse_write(Maap_Client *mc, char *buf) { printf("Got cmd maap_release_range, id: %d\n", cmd.param.id); rv = maap_release_range(mc, cmd.param.id); break; + case MAAP_EXIT: + printf("Got cmd maap_exit\n"); + retVal = 1; /* Indicate that we should exit. */ + break; default: printf("Error parsing in parse_write\n"); rv = 0; break; } } + + return retVal; } diff --git a/daemons/maap/common/maap_parse.h b/daemons/maap/common/maap_parse.h index 1718c2a1..ae9c5366 100644 --- a/daemons/maap/common/maap_parse.h +++ b/daemons/maap/common/maap_parse.h @@ -10,8 +10,24 @@ #include "maap_iface.h" +/** + * Parse the incoming text data for a command. + * + * @param buf Binary or text data to parse + * @param mc Pointer to the Maap_Cmd to fill with the binary equivalent of the command + * + * @return 1 if a valid command was received, 0 otherwise. + */ int parse_text_cmd(char *buf, Maap_Cmd *cmd); -void parse_write(Maap_Client *mc, char *buf); +/** + * Parse the incoming binary or text data, and perform the specified command, if any. + * + * @param mc Pointer to the Maap_Client to use + * @param buf Binary or text data to parse + * + * @return 1 if the exit command was received, 0 otherwise. + */ +int parse_write(Maap_Client *mc, char *buf); #endif /* COMMON_MAAP_PARSE_H_ */ diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 3d041339..46cc368e 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -300,7 +300,10 @@ int main(int argc, char *argv[]) /* Process the data (may be binary or text.) */ memset(&recvcmd, 0, sizeof(recvcmd)); - parse_write(&mc, recvbuffer); + if (parse_write(&mc, recvbuffer)) { + /* Received a command to exit. */ + break; + } } } -- cgit v1.2.1 From 41d176e50f30b1b6a10fa7aebd835e9acd85af2b Mon Sep 17 00:00:00 2001 From: Andrew Elder Date: Thu, 22 Sep 2016 16:09:36 -0400 Subject: gPTP: IEEE1588Port::processEvent(), start and stop pDelay on LINKUP/DOWN events Without stopping pDelay timers, continuous log output is generated when the network cable is disconnected. --- daemons/gptp/common/ieee1588port.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 71fde4ae..3af275b4 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -712,6 +712,8 @@ void IEEE1588Port::processEvent(Event e) break; case LINKUP: + haltPdelay(false); + startPDelay(); if (automotive_profile) { GPTP_LOG_EXCEPTION("LINKUP"); } @@ -771,6 +773,8 @@ void IEEE1588Port::processEvent(Event e) break; case LINKDOWN: + setAsCapable(false); + stopPDelay(); if (automotive_profile) { GPTP_LOG_EXCEPTION("LINK DOWN"); } -- cgit v1.2.1 From 89cdcbdffcc14106844b0d7dfdf4697e4b620ee1 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Thu, 6 Oct 2016 08:43:17 -0600 Subject: Added DEBUG_NEGOTIATE_MSG define Added a new DEBUG_NEGOTIATE_MSG define to hide the address acquisition negotiation details. Minor debug message cleanup. --- daemons/maap/common/maap.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index aa2e7296..ed6672b2 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -11,9 +11,12 @@ /* Linux-specific header files */ #include -/* Uncomment the DEBUG_TIMER_MSG define to display debug messages. */ +/* Uncomment the DEBUG_TIMER_MSG define to display timer debug messages. */ /* #define DEBUG_TIMER_MSG */ +/* Uncomment the DEBUG_NEGOTIATE_MSG define to display negotiation debug messages. */ +/* #define DEBUG_NEGOTIATE_MSG */ + static int get_count(Maap_Client *mc, Range *range) { (void)mc; @@ -204,14 +207,14 @@ int rand_ms(int variation) { int schedule_timer(Maap_Client *mc, Range *range) { Range *rp; - uint64_t ns; + unsigned long long int ns; Time ts; if (range->state == MAAP_STATE_PROBING) { ns = MAAP_PROBE_INTERVAL_BASE + rand_ms(MAAP_PROBE_INTERVAL_VARIATION); ns = ns * 1000000; #ifdef DEBUG_TIMER_MSG - printf("Scheduling probe timer for %" PRIu64 " ns from now\n", ns); + printf("Scheduling probe timer for %llu ns from now\n", ns); #endif Time_setFromNanos(&ts, ns); #ifdef DEBUG_TIMER_MSG @@ -233,7 +236,7 @@ int schedule_timer(Maap_Client *mc, Range *range) { ns = MAAP_ANNOUNCE_INTERVAL_BASE + rand_ms(MAAP_ANNOUNCE_INTERVAL_VARIATION); ns = ns * 1000000; #ifdef DEBUG_TIMER_MSG - printf("Scheduling defend timer for %" PRIu64 " ns from now\n", ns); + printf("Scheduling defend timer for %llu ns from now\n", ns); #endif Time_setFromNanos(&ts, (uint64_t)ns); Time_setFromMonotonicTimer(&range->next_act_time); @@ -309,13 +312,15 @@ int maap_reserve_range(Maap_Client *mc, uint16_t length) { range->next_timer = NULL; assign_interval(mc, range, length); - printf("Selected address range 0x%012llx-0x%012llx\n", get_start_address(mc, range), get_end_address(mc, range)); send_probe(mc, range); range->counter--; schedule_timer(mc, range); start_timer(mc); printf("Requested address range, id %d\n", id); +#ifdef DEBUG_NEGOTIATE_MSG + printf("Selected address range 0x%012llx-0x%012llx\n", get_start_address(mc, range), get_end_address(mc, range)); +#endif return id; } @@ -378,7 +383,7 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { incoming_base = p.requested_start_address; incoming_max = p.requested_start_address + p.requested_count - 1; -#if 0 +#ifdef DEBUG_NEGOTIATE_MSG if (p.message_type == MAAP_PROBE) { printf("Received PROBE for range 0x%012llx-0x%012llx (Size %u)\n", incoming_base, incoming_max, p.requested_count); } if (p.message_type == MAAP_DEFEND) { printf("Received DEFEND for range 0x%012llx-0x%012llx (Size %u)\n", incoming_base, incoming_max, p.requested_count); } if (p.message_type == MAAP_ANNOUNCE) { printf("Received ANNOUNCE for range 0x%012llx-0x%012llx (Size %u)\n", incoming_base, incoming_max, p.requested_count); } @@ -395,23 +400,23 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { if (iv != NULL) { range = iv->data; if (range->state == MAAP_STATE_PROBING) { - printf("Found a conflicting preexisting range, look for a new one\n"); - printf(" Response of 0x%012llx-0x%012llx overlaps our\n", - incoming_base, incoming_max); - printf(" request of 0x%012llx-0x%012llx\n", - get_start_address(mc, range), get_end_address(mc, range)); /* Find an alternate interval, remove old interval, and restart probe counter */ assign_interval(mc, range, iv->high - iv->low + 1); +#ifdef DEBUG_NEGOTIATE_MSG + printf("Selected address range 0x%012llx-0x%012llx\n", get_start_address(mc, range), get_end_address(mc, range)); +#endif iv = remove_interval(&mc->ranges, iv); free_interval(iv); range->counter = MAAP_PROBE_RETRANSMITS; } else if (range->state == MAAP_STATE_DEFENDING) { printf("Someone is messing with our range!\n"); +#ifdef DEBUG_NEGOTIATE_MSG printf(" Request of 0x%012llx-0x%012llx inside our\n", incoming_base, incoming_max); printf(" range of 0x%012llx-0x%012llx\n", get_start_address(mc, range), get_end_address(mc, range)); +#endif if (p.message_type == MAAP_PROBE) { printf("DEFEND!\n"); send_defend(mc, range, p.requested_start_address, p.requested_count, @@ -515,7 +520,7 @@ int maap_handle_timer(Maap_Client *mc) { int64_t maap_get_delay_to_next_timer(Maap_Client *mc) { - int64_t timeRemaining; + long long int timeRemaining; if (!(mc->timer) || !(mc->timer_queue)) { @@ -529,7 +534,7 @@ int64_t maap_get_delay_to_next_timer(Maap_Client *mc) timeRemaining = Time_remaining(mc->timer); } #ifdef DEBUG_TIMER_MSG - printf("Next delay: %" PRId64 " ns\n\n", timeRemaining); + printf("Next delay: %lld ns\n\n", timeRemaining); #endif return timeRemaining; } -- cgit v1.2.1 From 5fdb5fee849f5acf7901de713fc1b0a8f82a33df Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Thu, 6 Oct 2016 09:16:06 -0600 Subject: Seeding method follows IEEE 1722-2011 standard --- daemons/maap/linux/src/maap_linux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 46cc368e..0ce6c03b 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -212,9 +212,10 @@ int main(int argc, char *argv[]) /* * Seed the random number generator. + * This seeding is defined in IEEE 1722-2011 B.3.6.1. */ - srand((unsigned int)mc.src_mac ^ (unsigned int)time(NULL)); + srand((unsigned int)mc.src_mac + (unsigned int)time(NULL)); -- cgit v1.2.1 From 66074770634fbe064dec0940592f0c078c288918 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Thu, 6 Oct 2016 09:20:20 -0600 Subject: Added TODOs for improved address range selection. --- daemons/maap/common/maap.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index ed6672b2..12fca111 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -271,6 +271,14 @@ int assign_interval(Maap_Client *mc, Range *range, uint16_t len) { range_max = mc->range_len - 1; + /** @todo Return an error if range_max is too large, or no blocks of addresses the requested size are available. + * (The current code can get into an infinite loop.) */ + + /** @todo Use the saved MAAP_ANNOUNCE message ranges to search for addresses likely to be available. + * Old announced ranges (e.g. older than 2 minutes) can be deleted if there are no ranges available. + * We can also select new address blocks adjacent to our existing address blocks, which will fill the available address space more efficiently. + * While this doesn't strictly adhere to the 1722 MAAP specification, it is defensible (as the initial block was random). */ + while (rv == INTERVAL_OVERLAP) { iv = alloc_interval(random() % mc->range_len, len); if (iv->high > range_max) { @@ -395,6 +403,8 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { return 0; } + /** @todo If this is a MAAP_ANNOUNCE message, save the announced range and time received for later reference. */ + start = (uint64_t)p.requested_start_address - mc->address_base; iv = search_interval(mc->ranges, start, p.requested_count); if (iv != NULL) { -- cgit v1.2.1 From 3ead0d8cb3ca0d274c42cd585c848e7be651f787 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Thu, 6 Oct 2016 11:43:45 -0600 Subject: Values changed to match IEEE 1722-2011 Changed the MAAP_ANNOUNCE_INTERVAL_VARIATION, MAAP_DYNAMIC_POOL_BASE, and MAAP_DYNAMIC_POOL_SIZE to use the correct values. Documented where to find the values in IEEE 1722-2011. --- daemons/maap/common/maap.h | 23 ++++++++++++----------- daemons/maap/common/maap_packet.h | 7 +++---- daemons/maap/common/maap_parse.c | 4 ++-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index adcb3de4..5a429b16 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -9,13 +9,13 @@ #include "maap_timer.h" #include "maap_net.h" -#define MAAP_PROBE_RETRANSMITS 3 +#define MAAP_PROBE_RETRANSMITS 3 /**< Number of allowed probes - This value is defined in IEEE 1722-2011 Table B.3 */ /* Times are in milliseconds */ -#define MAAP_PROBE_INTERVAL_BASE 500 -#define MAAP_PROBE_INTERVAL_VARIATION 100 -#define MAAP_ANNOUNCE_INTERVAL_BASE 30000 -#define MAAP_ANNOUNCE_INTERVAL_VARIATION 1000 +#define MAAP_PROBE_INTERVAL_BASE 500 /**< Probe interval minimum time in milliseconds - This value is defined in IEEE 1722-2011 Table B.3 */ +#define MAAP_PROBE_INTERVAL_VARIATION 100 /**< Probe interval additional time in milliseconds - This value is defined in IEEE 1722-2011 Table B.3 */ +#define MAAP_ANNOUNCE_INTERVAL_BASE 30000 /**< Announce interval minimum time in milliseconds - This value is defined in IEEE 1722-2011 Table B.3 */ +#define MAAP_ANNOUNCE_INTERVAL_VARIATION 2000 /**< Announce interval additional time in milliseconds - This value is defined in IEEE 1722-2011 Table B.3 */ #define MAAP_STATE_PROBING 0 #define MAAP_STATE_DEFENDING 1 @@ -24,12 +24,13 @@ #define MAAP_CB_ACQUIRED 0 #define MAAP_CB_YIELDED 1 -#define MAAP_DEST_MAC {0x91, 0xE0, 0xF0, 0x00, 0xFF, 0x00} -#define MAAP_DEST_64 0x000091E0F000FF00LL -#define MAAP_RANGE_SIZE 0xFFDF -#define MAAP_RANGE_SIZE_64 (((uint64_t)MAAP_RANGE_SIZE) << 48) -#define MAAP_TYPE 0x22F0 -#define MAAP_SUBTYPE 0xFE +#define MAAP_DEST_MAC {0x91, 0xE0, 0xF0, 0x00, 0xFF, 0x00} /**< MAAP multicast Address - Defined in IEEE 1722-2011 Table B.5 */ + +#define MAAP_DYNAMIC_POOL_BASE 0x91E0F0000000LL /**< MAAP dynamic allocation pool base address - Defined in IEEE 1722-2011 Table B.4 */ +#define MAAP_DYNAMIC_POOL_SIZE 0xFE00 /**< MAAP dynamic allocation pool size - Defined in IEEE 1722-2011 Table B.4 */ + +#define MAAP_TYPE 0x22F0 /**< AVTP Ethertype - Defined in IEEE 1722-2011 Table 5.1 */ +#define MAAP_SUBTYPE 0xFE /**< AVTP MAAP subtype - Defined in IEEE 1722-2011 Table 5.2 */ #define MAAP_PKT_SIZE 42 #define MAAP_RANGE_MASK 0xFFFF000000000000LL #define MAAP_BASE_MASK 0x0000FFFFFFFFFFFFLL diff --git a/daemons/maap/common/maap_packet.h b/daemons/maap/common/maap_packet.h index e26e6cca..477860cd 100644 --- a/daemons/maap/common/maap_packet.h +++ b/daemons/maap/common/maap_packet.h @@ -5,10 +5,9 @@ #include "platform.h" -#define MAAP_RESERVED 0 -#define MAAP_PROBE 1 -#define MAAP_DEFEND 2 -#define MAAP_ANNOUNCE 3 +#define MAAP_PROBE 1 /* MAAP Probe MAC address(es) PDU - Defined in IEEE 1722-2011 Table B.1 */ +#define MAAP_DEFEND 2 /* MAAP Defend address(es) response PDU - Defined in IEEE 1722-2011 Table B.1 */ +#define MAAP_ANNOUNCE 3 /* MAAP Announce MAC address(es) acquired PDU - Defined in IEEE 1722-2011 Table B.1 */ typedef struct maap_packet { uint64_t DA; diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c index a3f3f506..4d2bfbdc 100644 --- a/daemons/maap/common/maap_parse.c +++ b/daemons/maap/common/maap_parse.c @@ -29,7 +29,7 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { if (strncmp(argv[0], "init", 4) == 0) { if (argc == 1) { cmd->kind = MAAP_INIT; - cmd->param.range_info = MAAP_DEST_64 | MAAP_RANGE_SIZE_64; + cmd->param.range_info = MAAP_DYNAMIC_POOL_BASE | (((uint64_t)MAAP_DYNAMIC_POOL_SIZE) << 48); set_cmd = 1; } else if (argc == 3) { cmd->kind = MAAP_INIT; @@ -56,7 +56,7 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { { printf("input usage:\n"); printf(" init [ ]\n"); - printf(" If not specified, range_base=0x%llx, range_size=0x%04x\n", MAAP_DEST_64, MAAP_RANGE_SIZE); + printf(" If not specified, range_base=0x%llx, range_size=0x%04x\n", MAAP_DYNAMIC_POOL_BASE, MAAP_DYNAMIC_POOL_SIZE); printf(" reserve \n"); printf(" release \n"); printf(" exit\n\n"); -- cgit v1.2.1 From 4ec84d4641d5a7184afa1638e261e4a4ac555752 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Thu, 6 Oct 2016 16:53:46 -0600 Subject: Added support to accept command and control connections. Code still needs to be tested with a client. Also addressed some memory leaks. --- daemons/maap/linux/src/maap_linux.c | 245 +++++++++++++++++++++++++++++++++--- 1 file changed, 226 insertions(+), 19 deletions(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 0ce6c03b..f6bad3a7 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -30,6 +30,15 @@ ****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include #include #include @@ -39,17 +48,14 @@ #include -#include -#include -#include -#include -#include -#include +#include #include "maap.h" #include "maap_packet.h" #include "maap_parse.h" +#define MAX_CLIENT_CONNECTIONS 32 +#define DEFAULT_PORT "15364" #define VERSION_STR "0.1" @@ -58,25 +64,41 @@ static const char *version_str = "Copyright (c) 2014-2015, VAYAVYA LABS PVT LTD\n" "Copyright (c) 2016, Harman International Industries Inc.\n"; -void usage(void) +static void usage(void) { fprintf(stderr, "\n" - "usage: maap_daemon [-d] -i interface-name" + "usage: maap_daemon [-d] -i interface-name [-p port_num]" "\n" "options:\n" " -d run daemon in the background\n" " -i specify interface to monitor\n" + " -p specify the control port to listen to (default " DEFAULT_PORT ")\n" "\n" "%s" "\n", version_str); exit(1); } +/* get sockaddr, IPv4 or IPv6 */ +static void *get_in_addr(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) { + return &(((struct sockaddr_in*)sa)->sin_addr); + } + + return &(((struct sockaddr_in6*)sa)->sin6_addr); +} + + int main(int argc, char *argv[]) { + Maap_Client mc; + int c; int daemonize = 0; - int ret; char *iface = NULL; + char *listenport = NULL; + int ret; + int socketfd; struct ifreq ifbuffer; uint8_t dest_mac[ETH_ALEN] = MAAP_DEST_MAC; @@ -84,21 +106,34 @@ int main(int argc, char *argv[]) int ifindex; struct sockaddr_ll sockaddr; struct packet_mreq mreq; - Maap_Client mc; + + int listener; + struct addrinfo hints, *ai, *p; + int yes=1; + + int newfd; + socklen_t addrlen; + struct sockaddr_storage remoteaddr; + char remoteIP[INET6_ADDRSTRLEN]; + int clientfd[MAX_CLIENT_CONNECTIONS]; + int i, nextclientindex; + + fd_set master, read_fds; + int fdmax; + void *packet_data; int64_t waittime; struct timeval tv; - fd_set read_fds; - int fdmax; char recvbuffer[1600]; int recvbytes; Maap_Cmd recvcmd; + /* * Parse the arguments */ - while ((c = getopt(argc, argv, "hdi:")) >= 0) + while ((c = getopt(argc, argv, "hdi:p:")) >= 0) { switch (c) { @@ -109,12 +144,21 @@ int main(int argc, char *argv[]) case 'i': if (iface) { - printf("only one interface per daemon is supported\n"); + printf("Only one interface per daemon is supported\n"); usage(); } iface = strdup(optarg); break; + case 'p': + if (listenport) + { + printf("Only one port per daemon is supported\n"); + usage(); + } + listenport = strdup(optarg); + break; + case 'h': default: usage(); @@ -140,6 +184,12 @@ int main(int argc, char *argv[]) } } + if (listenport == NULL) + { + /* Use the default port. */ + listenport = strdup(DEFAULT_PORT); + } + /* * Initialize the networking support. @@ -201,10 +251,73 @@ int main(int argc, char *argv[]) return -1; } + FD_ZERO(&read_fds); + FD_ZERO(&master); + FD_SET(STDIN_FILENO, &master); + FD_SET(socketfd, &master); + fdmax = socketfd; + /* * Initialize the Maap_Client data structure. */ + + /* get us a localhost socket and bind it */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + if ((ret = getaddrinfo("localhost", listenport, &hints, &ai)) != 0) { + fprintf(stderr, "selectserver: %s\n", gai_strerror(ret)); + exit(1); + } + + for(p = ai; p != NULL; p = p->ai_next) { + listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (listener < 0) { + continue; + } + + /* Lose the pesky "address already in use" error message */ + setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); + + if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) { + close(listener); + continue; + } + + break; + } + + /* If we got here, it means we didn't get bound */ + if (p == NULL) { + fprintf(stderr, "selectserver: failed to bind\n"); + exit(2); + } + + freeaddrinfo(ai); + + if (listen(listener, 10) == -1) { + perror("listen"); + exit(3); + } + + /* Add the listener to the master set */ + FD_SET(listener, &master); + + /* Keep track of the biggest file descriptor */ + if (listener > fdmax) { + fdmax = listener; + } + + for (i = 0; i < MAX_CLIENT_CONNECTIONS; ++i) { clientfd[i] = -1; } + nextclientindex = 0; + + + /* + * Initialize the Maap_Client data structure. + */ + memset(&mc, 0, sizeof(mc)); mc.dest_mac = convert_mac_address(dest_mac); mc.src_mac = convert_mac_address(src_mac); @@ -252,10 +365,7 @@ int main(int argc, char *argv[]) } /* Wait for something to happen. */ - FD_ZERO(&read_fds); - FD_SET(STDIN_FILENO, &read_fds); - FD_SET(socketfd, &read_fds); - fdmax = socketfd; + read_fds = master; ret = select(fdmax+1, &read_fds, NULL, NULL, &tv); if (ret < 0) { @@ -287,11 +397,60 @@ int main(int argc, char *argv[]) } } + /* Accept any new connections. */ + if (FD_ISSET(listener, &read_fds)) { + addrlen = sizeof remoteaddr; + newfd = accept(listener, + (struct sockaddr *)&remoteaddr, + &addrlen); + + if (newfd == -1) { + perror("accept"); + } else { + printf("selectserver: new connection from %s on " + "socket %d\n", + inet_ntop(remoteaddr.ss_family, + get_in_addr((struct sockaddr*)&remoteaddr), + remoteIP, INET6_ADDRSTRLEN), + newfd); + + /* Add the socket to our array of connected sockets. */ + if (clientfd[nextclientindex] != -1) + { + /* Find the next available index. */ + for (i = (nextclientindex + 1) % MAX_CLIENT_CONNECTIONS; i != nextclientindex; i = (i + 1) % MAX_CLIENT_CONNECTIONS) + { + if (clientfd[nextclientindex] == -1) + { + /* Found an empty array slot. */ + break; + } + } + if (i == nextclientindex) + { + /* No more client slots available. Connection rejected. */ + printf("Out of client connection slots. Connection rejected.\n"); + close(newfd); + newfd = -1; + } + } + + if (newfd != -1) + { + clientfd[nextclientindex] = newfd; + FD_SET(newfd, &master); /* add to master set */ + if (newfd > fdmax) { /* keep track of the max */ + fdmax = newfd; + } + } + } + } + /* Handle any commands received via stdin. */ if (FD_ISSET(STDIN_FILENO, &read_fds)) { recvbytes = read(STDIN_FILENO, recvbuffer, sizeof(recvbuffer) - 1); - if (recvbytes < 0) + if (recvbytes <= 0) { printf("Error %d reading from stdin (%s)\n", errno, strerror(errno)); } @@ -308,11 +467,59 @@ int main(int argc, char *argv[]) } } + /* Run through the existing connections looking for data to read. */ + for (i = 0; i < MAX_CLIENT_CONNECTIONS; ++i) + { + if (clientfd[i] != -1 && FD_ISSET(clientfd[i], &read_fds)) + { + recvbytes = recv(clientfd[i], recvbuffer, sizeof(recvbuffer), 0); + if (recvbytes < 0) + { + printf("Error %d reading from socket %d (%s). Connection closed.\n", errno, clientfd[i], strerror(errno)); + close(clientfd[i]); + FD_CLR(clientfd[i], &master); /* remove from master set */ + clientfd[i] = -1; + nextclientindex = i; /* We know this slot will be empty. */ + } + else if (recvbytes == 0) + { + printf("Socket %d closed\n", clientfd[i]); + close(clientfd[i]); + FD_CLR(clientfd[i], &master); /* remove from master set */ + clientfd[i] = -1; + nextclientindex = i; /* We know this slot will be empty. */ + } + else + { + recvbuffer[recvbytes] = '\0'; + + /* Process the data (may be binary or text.) */ + memset(&recvcmd, 0, sizeof(recvcmd)); + if (parse_write(&mc, recvbuffer)) { + /* Received a command to exit. */ + break; + } + } + } + } + } close(socketfd); + close(listener); + + /** Close any connected sockets. */ + for (i = 0; i < MAX_CLIENT_CONNECTIONS; ++i) { + if (clientfd[i] != -1) { + close(clientfd[i]); + clientfd[i] = -1; + } + } maap_deinit_client(&mc); + free(iface); + free(listenport); + return 0; } -- cgit v1.2.1 From be3cd2e2b89c7521f7ca6cd4b46c3136f50ccdcf Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Fri, 7 Oct 2016 10:53:22 -0600 Subject: Errors printed on stderr instead of stdout Made the error handling more consistent. --- daemons/maap/linux/src/maap_linux.c | 50 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index f6bad3a7..6707a7cc 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -144,7 +144,7 @@ int main(int argc, char *argv[]) case 'i': if (iface) { - printf("Only one interface per daemon is supported\n"); + fprintf(stderr, "Only one interface per daemon is supported\n"); usage(); } iface = strdup(optarg); @@ -153,7 +153,7 @@ int main(int argc, char *argv[]) case 'p': if (listenport) { - printf("Only one port per daemon is supported\n"); + fprintf(stderr, "Only one port per daemon is supported\n"); usage(); } listenport = strdup(optarg); @@ -172,14 +172,14 @@ int main(int argc, char *argv[]) if (iface == NULL) { - printf("A network interface is required\n"); + fprintf(stderr, "A network interface is required\n"); usage(); } if (daemonize) { ret = daemon(1, 0); if (ret) { - printf("Error: Failed to daemonize\n"); + fprintf(stderr, "Error: Failed to daemonize\n"); return -1; } } @@ -197,13 +197,13 @@ int main(int argc, char *argv[]) if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(MAAP_TYPE))) < 0 ) { - printf("Error: could not open socket %d\n",socketfd); + fprintf(stderr, "Error: could not open socket %d\n",socketfd); return -1; } if (fcntl(socketfd, F_SETFL, O_NONBLOCK) < 0) { - printf("Error: could not set the socket to non-blocking\n"); + fprintf(stderr, "Error: could not set the socket to non-blocking\n"); return -1; } @@ -211,7 +211,7 @@ int main(int argc, char *argv[]) strncpy(ifbuffer.ifr_name, iface, IFNAMSIZ); if (ioctl(socketfd, SIOCGIFINDEX, &ifbuffer) < 0) { - printf("Error: could not get interface index\n"); + fprintf(stderr, "Error: could not get interface index\n"); close(socketfd); return -1; } @@ -220,7 +220,7 @@ int main(int argc, char *argv[]) ifindex = ifbuffer.ifr_ifindex; if (ioctl(socketfd, SIOCGIFHWADDR, &ifbuffer) < 0) { - printf("Error: could not get interface address\n"); + fprintf(stderr, "Error: could not get interface address\n"); close(socketfd); return -1; } @@ -234,7 +234,7 @@ int main(int argc, char *argv[]) memcpy(sockaddr.sll_addr, dest_mac, ETH_ALEN); if (bind(socketfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) { - printf("Error: could not bind datagram socket\n"); + fprintf(stderr, "Error: could not bind datagram socket\n"); return -1; } @@ -247,7 +247,7 @@ int main(int argc, char *argv[]) if (setsockopt(socketfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { - printf("setsockopt PACKET_ADD_MEMBERSHIP failed\n"); + fprintf(stderr, "setsockopt PACKET_ADD_MEMBERSHIP failed\n"); return -1; } @@ -268,8 +268,8 @@ int main(int argc, char *argv[]) hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if ((ret = getaddrinfo("localhost", listenport, &hints, &ai)) != 0) { - fprintf(stderr, "selectserver: %s\n", gai_strerror(ret)); - exit(1); + fprintf(stderr, "getaddrinfo failure %s\n", gai_strerror(ret)); + return -1; } for(p = ai; p != NULL; p = p->ai_next) { @@ -291,14 +291,14 @@ int main(int argc, char *argv[]) /* If we got here, it means we didn't get bound */ if (p == NULL) { - fprintf(stderr, "selectserver: failed to bind\n"); - exit(2); + fprintf(stderr, "Socket failed to bind error %d (%s)\n", errno, strerror(errno)); + return -1; } freeaddrinfo(ai); - if (listen(listener, 10) == -1) { - perror("listen"); + if (listen(listener, 10) < 0) { + fprintf(stderr, "Socket listen error %d (%s)\n", errno, strerror(errno)); exit(3); } @@ -344,7 +344,8 @@ int main(int argc, char *argv[]) if (send(socketfd, packet_data, MAAP_NET_BUFFER_SIZE, 0) < 0) { /* Something went wrong. Abort! */ - printf("Error %d writing to network socket (%s)\n", errno, strerror(errno)); + fprintf(stderr, "Error %d writing to network socket (%s)\n", errno, strerror(errno)); + Net_freeQueuedPacket(mc.net, packet_data); break; } Net_freeQueuedPacket(mc.net, packet_data); @@ -369,7 +370,7 @@ int main(int argc, char *argv[]) ret = select(fdmax+1, &read_fds, NULL, NULL, &tv); if (ret < 0) { - printf("select() error %d (%s)\n", errno, strerror(errno)); + fprintf(stderr, "select() error %d (%s)\n", errno, strerror(errno)); break; } if (ret == 0) @@ -392,7 +393,7 @@ int main(int argc, char *argv[]) if (recvbytes < 0 && errno != EWOULDBLOCK) { /* Something went wrong. Abort! */ - printf("Error %d reading from network socket (%s)\n", errno, strerror(errno)); + fprintf(stderr, "Error %d reading from network socket (%s)\n", errno, strerror(errno)); break; } } @@ -405,10 +406,9 @@ int main(int argc, char *argv[]) &addrlen); if (newfd == -1) { - perror("accept"); + fprintf(stderr, "Error %d accepting connection (%s)\n", errno, strerror(errno)); } else { - printf("selectserver: new connection from %s on " - "socket %d\n", + printf("New connection from %s on socket %d\n", inet_ntop(remoteaddr.ss_family, get_in_addr((struct sockaddr*)&remoteaddr), remoteIP, INET6_ADDRSTRLEN), @@ -429,7 +429,7 @@ int main(int argc, char *argv[]) if (i == nextclientindex) { /* No more client slots available. Connection rejected. */ - printf("Out of client connection slots. Connection rejected.\n"); + fprintf(stderr, "Out of client connection slots. Connection rejected.\n"); close(newfd); newfd = -1; } @@ -452,7 +452,7 @@ int main(int argc, char *argv[]) recvbytes = read(STDIN_FILENO, recvbuffer, sizeof(recvbuffer) - 1); if (recvbytes <= 0) { - printf("Error %d reading from stdin (%s)\n", errno, strerror(errno)); + fprintf(stderr, "Error %d reading from stdin (%s)\n", errno, strerror(errno)); } else { @@ -475,7 +475,7 @@ int main(int argc, char *argv[]) recvbytes = recv(clientfd[i], recvbuffer, sizeof(recvbuffer), 0); if (recvbytes < 0) { - printf("Error %d reading from socket %d (%s). Connection closed.\n", errno, clientfd[i], strerror(errno)); + fprintf(stderr, "Error %d reading from socket %d (%s). Connection closed.\n", errno, clientfd[i], strerror(errno)); close(clientfd[i]); FD_CLR(clientfd[i], &master); /* remove from master set */ clientfd[i] = -1; -- cgit v1.2.1 From fd96440f312c2f7a35cf9143aec8a96a91656786 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Fri, 7 Oct 2016 15:04:51 -0600 Subject: Added initial client support. The -c flag allows the app to act as a client, using networking command and control to affect the exiting MAAP daemon. Code to process responses is still needed. --- daemons/maap/common/maap_parse.c | 1 + daemons/maap/linux/src/maap_linux.c | 233 ++++++++++++++++++++++++++++++++---- 2 files changed, 212 insertions(+), 22 deletions(-) diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c index 4d2bfbdc..8d56c96b 100644 --- a/daemons/maap/common/maap_parse.c +++ b/daemons/maap/common/maap_parse.c @@ -77,6 +77,7 @@ int parse_write(Maap_Client *mc, char *buf) { case MAAP_INIT: case MAAP_RESERVE: case MAAP_RELEASE: + case MAAP_EXIT: memcpy(&cmd, bufcmd, sizeof (Maap_Cmd)); rv = 1; break; diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 6707a7cc..f33e8a57 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -59,6 +59,10 @@ #define VERSION_STR "0.1" +static int act_as_client(const char *listenport); +static void process_response(const char *pData, int nDataLen); + + static const char *version_str = "maap_daemon v" VERSION_STR "\n" "Copyright (c) 2014-2015, VAYAVYA LABS PVT LTD\n" @@ -68,12 +72,14 @@ static void usage(void) { fprintf(stderr, "\n" - "usage: maap_daemon [-d] -i interface-name [-p port_num]" + "usage: maap_daemon [-c | [-d] -i interface-name] [-p port_num]" "\n" "options:\n" - " -d run daemon in the background\n" - " -i specify interface to monitor\n" - " -p specify the control port to listen to (default " DEFAULT_PORT ")\n" + "\t-c Run as a client (sends commands to the daemon)\n" + "\t-d Run daemon in the background\n" + "\t-i Specify daemon interface to monitor\n" + "\t-p Specify the control port to connect to (client) or listen to (daemon).\n" + "\t The default port is " DEFAULT_PORT ".\n" "\n" "%s" "\n", version_str); exit(1); } @@ -94,7 +100,7 @@ int main(int argc, char *argv[]) Maap_Client mc; int c; - int daemonize = 0; + int as_client = 0, daemonize = 0; char *iface = NULL; char *listenport = NULL; int ret; @@ -127,16 +133,21 @@ int main(int argc, char *argv[]) char recvbuffer[1600]; int recvbytes; Maap_Cmd recvcmd; + int exit_received = 0; /* * Parse the arguments */ - while ((c = getopt(argc, argv, "hdi:p:")) >= 0) + while ((c = getopt(argc, argv, "hcdi:p:")) >= 0) { switch (c) { + case 'c': + as_client = 1; + break; + case 'd': daemonize = 1; break; @@ -170,9 +181,20 @@ int main(int argc, char *argv[]) usage(); } - if (iface == NULL) + if (as_client && daemonize) + { + fprintf(stderr, "Cannot run as both a client and a daemon\n"); + usage(); + } + + if (!as_client && iface == NULL) + { + fprintf(stderr, "A network interface is required as a daemon\n"); + usage(); + } + if (as_client && iface != NULL) { - fprintf(stderr, "A network interface is required\n"); + fprintf(stderr, "A network interface is not supported as a client\n"); usage(); } @@ -190,12 +212,20 @@ int main(int argc, char *argv[]) listenport = strdup(DEFAULT_PORT); } + if (as_client) + { + /* Run as a client instead of a server. */ + ret = act_as_client(listenport); + free(listenport); + return ret; + } + /* * Initialize the networking support. */ - if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(MAAP_TYPE))) < 0 ) + if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(MAAP_TYPE))) == -1 ) { fprintf(stderr, "Error: could not open socket %d\n",socketfd); return -1; @@ -267,14 +297,14 @@ int main(int argc, char *argv[]) hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; - if ((ret = getaddrinfo("localhost", listenport, &hints, &ai)) != 0) { + if ((ret = getaddrinfo(NULL, listenport, &hints, &ai)) != 0) { fprintf(stderr, "getaddrinfo failure %s\n", gai_strerror(ret)); return -1; } for(p = ai; p != NULL; p = p->ai_next) { listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (listener < 0) { + if (listener == -1) { continue; } @@ -289,14 +319,14 @@ int main(int argc, char *argv[]) break; } + freeaddrinfo(ai); + /* If we got here, it means we didn't get bound */ if (p == NULL) { fprintf(stderr, "Socket failed to bind error %d (%s)\n", errno, strerror(errno)); return -1; } - freeaddrinfo(ai); - if (listen(listener, 10) < 0) { fprintf(stderr, "Socket listen error %d (%s)\n", errno, strerror(errno)); exit(3); @@ -331,12 +361,11 @@ int main(int argc, char *argv[]) srand((unsigned int)mc.src_mac + (unsigned int)time(NULL)); - /* * Main event loop */ - while (1) + while (!exit_received) { /* Send any queued packets. */ while (mc.net != NULL && (packet_data = Net_getNextQueuedPacket(mc.net)) != NULL) @@ -458,11 +487,12 @@ int main(int argc, char *argv[]) { recvbuffer[recvbytes] = '\0'; - /* Process the data (may be binary or text.) */ + /* Process the command data (may be binary or text). */ memset(&recvcmd, 0, sizeof(recvcmd)); - if (parse_write(&mc, recvbuffer)) { + if (parse_write(&mc, recvbuffer)) + { /* Received a command to exit. */ - break; + exit_received = 1; } } } @@ -493,11 +523,12 @@ int main(int argc, char *argv[]) { recvbuffer[recvbytes] = '\0'; - /* Process the data (may be binary or text.) */ + /* Process the command data (may be binary or text). */ memset(&recvcmd, 0, sizeof(recvcmd)); - if (parse_write(&mc, recvbuffer)) { + if (parse_write(&mc, recvbuffer)) + { /* Received a command to exit. */ - break; + exit_received = 1; } } } @@ -521,5 +552,163 @@ int main(int argc, char *argv[]) free(iface); free(listenport); - return 0; + return (exit_received ? 0 : -1); +} + + +/* Local function to handle client side of network command & control. */ +static int act_as_client(const char *listenport) +{ + int socketfd; + struct addrinfo hints, *ai, *p; + int ret; + + fd_set master, read_fds; + int fdmax; + + char recvbuffer[200]; + int recvbytes; + Maap_Cmd recvcmd; + int exit_received = 0; + + /* Create a localhost socket. */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = 0; + if ((ret = getaddrinfo("localhost", listenport, &hints, &ai)) != 0) { + fprintf(stderr, "getaddrinfo failure %s\n", gai_strerror(ret)); + return -1; + } + + for(p = ai; p != NULL; p = p->ai_next) { + socketfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (socketfd != -1) { + break; + } + } + + if (p == NULL) { + fprintf(stderr, "Socket creation error %d (%s)\n", errno, strerror(errno)); + freeaddrinfo(ai); + return -1; + } + + /* Connect to the MAAP daemon. */ + if (connect(socketfd, p->ai_addr, p->ai_addrlen) < 0) + { + fprintf(stderr, "Unable to connect to the daemon, error %d (%s)\n", errno, strerror(errno)); + freeaddrinfo(ai); + close(socketfd); + return -1; + } + + freeaddrinfo(ai); + + if (fcntl(socketfd, F_SETFL, O_NONBLOCK) < 0) + { + fprintf(stderr, "Error: could not set the socket to non-blocking\n"); + close(socketfd); + return -1; + } + + FD_ZERO(&read_fds); + FD_ZERO(&master); + FD_SET(STDIN_FILENO, &master); + FD_SET(socketfd, &master); + fdmax = socketfd; + + + /* + * Main event loop + */ + + while (!exit_received) + { + /* Wait for something to happen. */ + read_fds = master; + ret = select(fdmax+1, &read_fds, NULL, NULL, NULL); + if (ret <= 0) + { + fprintf(stderr, "select() error %d (%s)\n", errno, strerror(errno)); + break; + } + + /* Handle any responses received. */ + if (FD_ISSET(socketfd, &read_fds)) + { + while ((recvbytes = recv(socketfd, recvbuffer, sizeof(recvbuffer) - 1, 0)) > 0) + { + recvbuffer[recvbytes] = '\0'; + + /* Process the response data (will be binary). */ + process_response(recvbuffer, recvbytes); + } + if (recvbytes == 0) + { + /* The MAAP daemon closed the connection. Assume it shut down, and we should too. */ + printf("MAAP daemon exited. Closing application.\n"); + exit_received = 1; + } + if (recvbytes < 0 && errno != EWOULDBLOCK) + { + /* Something went wrong. Abort! */ + fprintf(stderr, "Error %d reading from network socket (%s)\n", errno, strerror(errno)); + break; + } + } + + /* Handle any commands received via stdin. */ + if (FD_ISSET(STDIN_FILENO, &read_fds)) + { + recvbytes = read(STDIN_FILENO, recvbuffer, sizeof(recvbuffer) - 1); + if (recvbytes <= 0) + { + fprintf(stderr, "Error %d reading from stdin (%s)\n", errno, strerror(errno)); + } + else + { + Maap_Cmd *bufcmd = (Maap_Cmd *) recvbuffer; + int rv = 0; + + recvbuffer[recvbytes] = '\0'; + + /* Determine the command requested (may be binary or text). */ + switch (bufcmd->kind) { + case MAAP_INIT: + case MAAP_RESERVE: + case MAAP_RELEASE: + case MAAP_EXIT: + memcpy(&recvcmd, bufcmd, sizeof(Maap_Cmd)); + rv = 1; + break; + default: + memset(&recvcmd, 0, sizeof(Maap_Cmd)); + rv = parse_text_cmd(recvbuffer, &recvcmd); + break; + } + + /* If the command is valid, Send it to the MAAP daemon. */ + if (rv) + { + if (send(socketfd, (char *) &recvcmd, sizeof(Maap_Cmd), 0) < 0) + { + /* Something went wrong. Abort! */ + fprintf(stderr, "Error %d writing to network socket (%s)\n", errno, strerror(errno)); + break; + } + } + } + } + + } + + close(socketfd); + + return (exit_received ? 0 : -1); +} + + +static void process_response(const char *pData, int nDataLen) +{ } -- cgit v1.2.1 From b710cbbd2d63187b113257669215fceb630cf1ed Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Fri, 7 Oct 2016 16:48:48 -0600 Subject: Cleanup of the message cmd and notify structures. Prepared the command and notify structures for use. Added initial support for allowing the notifications to be socket-specific. --- daemons/maap/common/maap.c | 75 ++++++++++++++++++++++++------------- daemons/maap/common/maap.h | 15 ++++---- daemons/maap/common/maap_iface.h | 28 +++++++------- daemons/maap/common/maap_packet.c | 6 +-- daemons/maap/common/maap_packet.h | 6 +-- daemons/maap/common/maap_parse.c | 57 ++++++++++++++++------------ daemons/maap/common/maap_parse.h | 3 +- daemons/maap/linux/src/maap_linux.c | 12 +++--- 8 files changed, 118 insertions(+), 84 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index 12fca111..dcab9471 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -84,32 +84,32 @@ static int send_defend(Maap_Client *mc, Range *range, uint64_t start, return send_packet(mc, &p); } -static int inform_acquired(Maap_Client *mc, Range *range) { +static int inform_acquired(Maap_Client *mc, void *sender, Range *range) { Maap_Notify note; printf("Address range acquired: 0x%012llx-0x%012llx (Size %d)\n", get_start_address(mc, range), get_end_address(mc, range), get_count(mc, range)); - note.kind = MAAP_ACQUIRED; + note.kind = MAAP_NOTIFY_ACQUIRED; note.id = range->id; note.start = get_start_address(mc, range); note.count = get_count(mc, range); - add_notify(mc, ¬e); + add_notify(mc, sender, ¬e); return 0; } -static int inform_yielded(Maap_Client *mc, Range *range) { +static int inform_yielded(Maap_Client *mc, void *sender, Range *range) { Maap_Notify note; printf("Address range yielded\n"); - note.kind = MAAP_YIELDED; + note.kind = MAAP_NOTIFY_YIELDED; note.id = range->id; note.start = get_start_address(mc, range); note.count = get_count(mc, range); - add_notify(mc, ¬e); + add_notify(mc, sender, ¬e); return 0; } @@ -122,9 +122,10 @@ static void start_timer(Maap_Client *mc) { mc->timer_running = 1; } -void add_notify(Maap_Client *mc, Maap_Notify *mn) { +void add_notify(Maap_Client *mc, const void *sender, const Maap_Notify *mn) { Maap_Notify_List *tmp, *li = calloc(1, sizeof (Maap_Notify_List)); memcpy(&li->notify, mn, sizeof (Maap_Notify)); + li->sender = sender; if (mc->notifies == NULL) { mc->notifies = li; @@ -137,7 +138,7 @@ void add_notify(Maap_Client *mc, Maap_Notify *mn) { } } -int get_notify(Maap_Client *mc, Maap_Notify *mn) { +int get_notify(Maap_Client *mc, void *sender, Maap_Notify *mn) { Maap_Notify_List *tmp; if (mc->notifies) { @@ -150,9 +151,20 @@ int get_notify(Maap_Client *mc, Maap_Notify *mn) { return 0; } -int maap_init_client(Maap_Client *mc, uint64_t range_info) { +int maap_init_client(Maap_Client *mc, const void *sender, uint64_t range_address_base, uint32_t range_len) { + Maap_Notify note; + if (mc->initialized) { printf("MAAP already initialized\n"); + + /* Let the sender know the range that was already specified. */ + memset(¬e, 0, sizeof(note)); + note.kind = MAAP_NOTIFY_INIT; + note.id = -1; /* N/A */ + note.start = mc->address_base; + note.count = mc->range_len; + add_notify(mc, sender, ¬e); + return -1; } @@ -169,11 +181,8 @@ int maap_init_client(Maap_Client *mc, uint64_t range_info) { return -1; } - mc->address_base = range_info & MAAP_BASE_MASK; - /* Consider 0 to be 0x10000, since 0 doesn't make sense and 0x10000 is - the maximum number of values that can be stored in 16 bits */ - mc->range_len = (range_info & MAAP_RANGE_MASK) >> (ETH_ALEN * 8); - if (mc->range_len == 0) { mc->range_len = 0x10000; } + mc->address_base = range_address_base; + mc->range_len = range_len; mc->ranges = NULL; mc->timer_queue = NULL; mc->maxid = 0; @@ -183,20 +192,36 @@ int maap_init_client(Maap_Client *mc, uint64_t range_info) { mc->initialized = 1; printf("MAAP initialized, start: 0x%012llx, max: 0x%04x\n", - (unsigned long long)range_info & MAAP_BASE_MASK, - (unsigned int)((range_info & MAAP_RANGE_MASK) >> (ETH_ALEN * 8)) - 1); + (unsigned long long) mc->address_base, + (unsigned int) mc->range_len); + + /* Let the sender know the range is now specified. */ + memset(¬e, 0, sizeof(note)); + note.kind = MAAP_NOTIFY_INIT; + note.id = -1; /* N/A */ + note.start = mc->address_base; + note.count = mc->range_len; + add_notify(mc, sender, ¬e); + return 0; } void maap_deinit_client(Maap_Client *mc) { if (mc->initialized) { if (mc->timer_queue) { - Time_delTimer(mc->timer); - Net_delNet(mc->net); + /** @todo Free reservation memory */ + } + + if (mc->timer) { + Time_delTimer(mc->timer); + mc->timer = NULL; + } + + if (mc->net) { + Net_delNet(mc->net); + mc->net = NULL; } - mc->timer = NULL; - mc->net = NULL; mc->initialized = 0; } } @@ -297,7 +322,7 @@ int assign_interval(Maap_Client *mc, Range *range, uint16_t len) { return 0; } -int maap_reserve_range(Maap_Client *mc, uint16_t length) { +int maap_reserve_range(Maap_Client *mc, const void *sender, uint32_t length) { int id; Range *range; @@ -333,7 +358,7 @@ int maap_reserve_range(Maap_Client *mc, uint16_t length) { return id; } -int maap_release_range(Maap_Client *mc, int id) { +int maap_release_range(Maap_Client *mc, const void *sender, int id) { Interval *iv; Range *range; @@ -360,7 +385,7 @@ int maap_release_range(Maap_Client *mc, int id) { return -1; } -int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { +int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len) { MAAP_Packet p; Interval *iv; uint32_t start; @@ -440,7 +465,7 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { range->counter = 1; } else { printf("Yield vs. ANNOUNCE\n"); - inform_yielded(mc, range); + inform_yielded(mc, NULL /** @todo Need the socket handle */, range); iv = remove_interval(&mc->ranges, iv); free_interval(iv); /* memory will be freed the next time its timer elapses */ @@ -461,7 +486,7 @@ int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len) { int handle_probe_timer(Maap_Client *mc, Range *range) { if (range->counter == 0) { - inform_acquired(mc, range); + inform_acquired(mc, NULL /** @todo Need the socket handle */, range); range->state = MAAP_STATE_DEFENDING; send_announce(mc, range); schedule_timer(mc, range); diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index 5a429b16..2b0dc9ae 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -32,12 +32,11 @@ #define MAAP_TYPE 0x22F0 /**< AVTP Ethertype - Defined in IEEE 1722-2011 Table 5.1 */ #define MAAP_SUBTYPE 0xFE /**< AVTP MAAP subtype - Defined in IEEE 1722-2011 Table 5.2 */ #define MAAP_PKT_SIZE 42 -#define MAAP_RANGE_MASK 0xFFFF000000000000LL -#define MAAP_BASE_MASK 0x0000FFFFFFFFFFFFLL typedef struct maap_notify_list Maap_Notify_List; struct maap_notify_list { Maap_Notify notify; + const void *sender; Maap_Notify_List *next; }; @@ -66,13 +65,13 @@ typedef struct { int initialized; } Maap_Client; -int maap_init_client(Maap_Client *mc, uint64_t range_info); +int maap_init_client(Maap_Client *mc, const void *sender, uint64_t range_address_base, uint32_t range_len); void maap_deinit_client(Maap_Client *mc); -int maap_reserve_range(Maap_Client *mc, uint16_t length); -int maap_release_range(Maap_Client *mc, int id); +int maap_reserve_range(Maap_Client *mc, const void *sender, uint32_t length); +int maap_release_range(Maap_Client *mc, const void *sender, int id); -int maap_handle_packet(Maap_Client *mc, uint8_t *stream, int len); +int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len); int maap_handle_timer(Maap_Client *mc); /** @@ -84,7 +83,7 @@ int maap_handle_timer(Maap_Client *mc); */ int64_t maap_get_delay_to_next_timer(Maap_Client *mc); -void add_notify(Maap_Client *mc, Maap_Notify *mn); -int get_notify(Maap_Client *mc, Maap_Notify *mn); +void add_notify(Maap_Client *mc, const void *sender, const Maap_Notify *mn); +int get_notify(Maap_Client *mc, void *sender, Maap_Notify *mn); #endif diff --git a/daemons/maap/common/maap_iface.h b/daemons/maap/common/maap_iface.h index a24515bb..1ad1b4e9 100644 --- a/daemons/maap/common/maap_iface.h +++ b/daemons/maap/common/maap_iface.h @@ -10,32 +10,32 @@ */ typedef enum { - MAAP_INVALID = 0, - MAAP_INIT, - MAAP_RESERVE, - MAAP_RELEASE, - MAAP_EXIT, + MAAP_CMD_INVALID = 0, + MAAP_CMD_INIT, + MAAP_CMD_RESERVE, + MAAP_CMD_RELEASE, + MAAP_CMD_EXIT, } Maap_Cmd_Tag; typedef struct { Maap_Cmd_Tag kind; - union { - uint64_t range_info; - uint16_t length; - int id; - } param; + int32_t id; + uint64_t start; + uint32_t count; } Maap_Cmd; + typedef enum { - MAAP_ACQUIRED, - MAAP_YIELDED, + MAAP_NOTIFY_INIT, + MAAP_NOTIFY_ACQUIRED, + MAAP_NOTIFY_YIELDED, } Maap_Notify_Tag; typedef struct { Maap_Notify_Tag kind; - int id; + int32_t id; uint64_t start; - uint16_t count; + uint32_t count; } Maap_Notify; #endif diff --git a/daemons/maap/common/maap_packet.c b/daemons/maap/common/maap_packet.c index 5b27b776..fcfadb45 100644 --- a/daemons/maap/common/maap_packet.c +++ b/daemons/maap/common/maap_packet.c @@ -3,7 +3,7 @@ #include "maap.h" #include "maap_packet.h" -int unpack_maap(MAAP_Packet *packet, uint8_t *stream) { +int unpack_maap(MAAP_Packet *packet, const uint8_t *stream) { uint64_t tmp64; uint16_t tmp16; uint8_t tmp8; @@ -63,7 +63,7 @@ int unpack_maap(MAAP_Packet *packet, uint8_t *stream) { return 0; } -int pack_maap(MAAP_Packet *packet, uint8_t *stream) { +int pack_maap(const MAAP_Packet *packet, uint8_t *stream) { uint64_t tmp64; uint16_t tmp16; uint8_t tmp8; @@ -141,7 +141,7 @@ void init_packet(MAAP_Packet *packet, uint64_t dest_mac, uint64_t src_mac) { packet->count = 0; } -uint64_t convert_mac_address(uint8_t macaddr[]) +uint64_t convert_mac_address(const uint8_t macaddr[]) { uint64_t retVal; diff --git a/daemons/maap/common/maap_packet.h b/daemons/maap/common/maap_packet.h index 477860cd..3b70b1b0 100644 --- a/daemons/maap/common/maap_packet.h +++ b/daemons/maap/common/maap_packet.h @@ -28,9 +28,9 @@ typedef struct maap_packet { } MAAP_Packet; void init_packet(MAAP_Packet *packet, uint64_t dest_mac, uint64_t src_mac); -int pack_maap(MAAP_Packet *packet, uint8_t *stream); -int unpack_maap(MAAP_Packet *packet, uint8_t *stream); +int pack_maap(const MAAP_Packet *packet, uint8_t *stream); +int unpack_maap(MAAP_Packet *packet, const uint8_t *stream); -uint64_t convert_mac_address(uint8_t macaddr[]); +uint64_t convert_mac_address(const uint8_t macaddr[]); #endif diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c index 8d56c96b..04185f5e 100644 --- a/daemons/maap/common/maap_parse.c +++ b/daemons/maap/common/maap_parse.c @@ -26,26 +26,34 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { if (argc >= 1 && argc <= 3) { + /* Give all parameters default values. */ + cmd->kind = MAAP_CMD_INVALID; + cmd->id = -1; /* N/A */ + cmd->start = 0; /* N/A */ + cmd->count = 0; /* N/A */ + if (strncmp(argv[0], "init", 4) == 0) { if (argc == 1) { - cmd->kind = MAAP_INIT; - cmd->param.range_info = MAAP_DYNAMIC_POOL_BASE | (((uint64_t)MAAP_DYNAMIC_POOL_SIZE) << 48); + cmd->kind = MAAP_CMD_INIT; + cmd->start = MAAP_DYNAMIC_POOL_BASE; + cmd->count = MAAP_DYNAMIC_POOL_SIZE; set_cmd = 1; } else if (argc == 3) { - cmd->kind = MAAP_INIT; - cmd->param.range_info = strtoull(argv[1], NULL, 16) | (strtoull(argv[2], NULL, 16) << 48); + cmd->kind = MAAP_CMD_INIT; + cmd->start = strtoull(argv[1], NULL, 16); + cmd->count = strtoul(argv[2], NULL, 0); set_cmd = 1; } } else if (strncmp(argv[0], "reserve", 7) == 0 && argc == 2) { - cmd->kind = MAAP_RESERVE; - cmd->param.length = (uint16_t)strtoul(argv[1], NULL, 0); + cmd->kind = MAAP_CMD_RESERVE; + cmd->count = strtoul(argv[1], NULL, 0); set_cmd = 1; } else if (strncmp(argv[0], "release", 7) == 0 && argc == 2) { - cmd->kind = MAAP_RELEASE; - cmd->param.id = (int)strtoul(argv[1], NULL, 0); + cmd->kind = MAAP_CMD_RELEASE; + cmd->id = (int)strtoul(argv[1], NULL, 0); set_cmd = 1; } else if (strncmp(argv[0], "exit", 4) == 0 && argc == 1) { - cmd->kind = MAAP_EXIT; + cmd->kind = MAAP_CMD_EXIT; set_cmd = 1; } else { printf("Invalid command type\n"); @@ -66,7 +74,7 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { return 1; } -int parse_write(Maap_Client *mc, char *buf) { +int parse_write(Maap_Client *mc, const void *sender, char *buf) { Maap_Cmd *bufcmd, cmd; int rv = 0; int retVal = 0; @@ -74,10 +82,10 @@ int parse_write(Maap_Client *mc, char *buf) { bufcmd = (Maap_Cmd *)buf; switch (bufcmd->kind) { - case MAAP_INIT: - case MAAP_RESERVE: - case MAAP_RELEASE: - case MAAP_EXIT: + case MAAP_CMD_INIT: + case MAAP_CMD_RESERVE: + case MAAP_CMD_RELEASE: + case MAAP_CMD_EXIT: memcpy(&cmd, bufcmd, sizeof (Maap_Cmd)); rv = 1; break; @@ -89,19 +97,20 @@ int parse_write(Maap_Client *mc, char *buf) { if (rv) { switch(cmd.kind) { - case MAAP_INIT: - printf("Got cmd maap_init_client, range_info: 0x%016llx\n", (unsigned long long)cmd.param.range_info); - rv = maap_init_client(mc, cmd.param.range_info); + case MAAP_CMD_INIT: + printf("Got cmd maap_init_client, range_base: 0x%016llx, range_size: 0x%04x\n", + (unsigned long long)cmd.start, cmd.count); + rv = maap_init_client(mc, sender, cmd.start, cmd.count); break; - case MAAP_RESERVE: - printf("Got cmd maap_reserve_range, length: %u\n", (unsigned)cmd.param.length); - rv = maap_reserve_range(mc, cmd.param.length); + case MAAP_CMD_RESERVE: + printf("Got cmd maap_reserve_range, length: %u\n", (unsigned) cmd.count); + rv = maap_reserve_range(mc, sender, cmd.count); break; - case MAAP_RELEASE: - printf("Got cmd maap_release_range, id: %d\n", cmd.param.id); - rv = maap_release_range(mc, cmd.param.id); + case MAAP_CMD_RELEASE: + printf("Got cmd maap_release_range, id: %d\n", (int) cmd.id); + rv = maap_release_range(mc, sender, cmd.id); break; - case MAAP_EXIT: + case MAAP_CMD_EXIT: printf("Got cmd maap_exit\n"); retVal = 1; /* Indicate that we should exit. */ break; diff --git a/daemons/maap/common/maap_parse.h b/daemons/maap/common/maap_parse.h index ae9c5366..f8eb921c 100644 --- a/daemons/maap/common/maap_parse.h +++ b/daemons/maap/common/maap_parse.h @@ -24,10 +24,11 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd); * Parse the incoming binary or text data, and perform the specified command, if any. * * @param mc Pointer to the Maap_Client to use + * @param sender Sender information to track the requesting application * @param buf Binary or text data to parse * * @return 1 if the exit command was received, 0 otherwise. */ -int parse_write(Maap_Client *mc, char *buf); +int parse_write(Maap_Client *mc, const void *sender, char *buf); #endif /* COMMON_MAAP_PARSE_H_ */ diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index f33e8a57..a6947b12 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -489,7 +489,7 @@ int main(int argc, char *argv[]) /* Process the command data (may be binary or text). */ memset(&recvcmd, 0, sizeof(recvcmd)); - if (parse_write(&mc, recvbuffer)) + if (parse_write(&mc, (void *)(uintptr_t) -1, recvbuffer)) { /* Received a command to exit. */ exit_received = 1; @@ -525,7 +525,7 @@ int main(int argc, char *argv[]) /* Process the command data (may be binary or text). */ memset(&recvcmd, 0, sizeof(recvcmd)); - if (parse_write(&mc, recvbuffer)) + if (parse_write(&mc, (void *)(uintptr_t) clientfd[i], recvbuffer)) { /* Received a command to exit. */ exit_received = 1; @@ -675,10 +675,10 @@ static int act_as_client(const char *listenport) /* Determine the command requested (may be binary or text). */ switch (bufcmd->kind) { - case MAAP_INIT: - case MAAP_RESERVE: - case MAAP_RELEASE: - case MAAP_EXIT: + case MAAP_CMD_INIT: + case MAAP_CMD_RESERVE: + case MAAP_CMD_RELEASE: + case MAAP_CMD_EXIT: memcpy(&recvcmd, bufcmd, sizeof(Maap_Cmd)); rv = 1; break; -- cgit v1.2.1 From 4db98a10d6de1b9c040a1017bb08b9acca7d5939 Mon Sep 17 00:00:00 2001 From: andrew-elder Date: Mon, 10 Oct 2016 10:24:49 -0400 Subject: gPTP: IEEE1588Port::processEvent(), auto profile should not set !asCapable on LINK_DOWN --- daemons/gptp/common/ieee1588port.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemons/gptp/common/ieee1588port.cpp b/daemons/gptp/common/ieee1588port.cpp index 3af275b4..1f43d5a9 100644 --- a/daemons/gptp/common/ieee1588port.cpp +++ b/daemons/gptp/common/ieee1588port.cpp @@ -773,12 +773,12 @@ void IEEE1588Port::processEvent(Event e) break; case LINKDOWN: - setAsCapable(false); stopPDelay(); if (automotive_profile) { GPTP_LOG_EXCEPTION("LINK DOWN"); } else { + setAsCapable(false); GPTP_LOG_STATUS("LINK DOWN"); } if (testMode) { -- cgit v1.2.1 From 66e0659d51a2729944ae716d438d15c7bcfc0054 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 12:01:44 -0600 Subject: Added DEBUG_CMD_MSG define to hide cmd messages. --- daemons/maap/common/maap_parse.c | 12 ++++++++++++ daemons/maap/common/maap_parse.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c index 04185f5e..b27c586f 100644 --- a/daemons/maap/common/maap_parse.c +++ b/daemons/maap/common/maap_parse.c @@ -12,6 +12,10 @@ #include "maap.h" #include "maap_parse.h" +/* Uncomment the DEBUG_CMD_MSG define to display command debug messages. */ +/* #define DEBUG_CMD_MSG */ + + int parse_text_cmd(char *buf, Maap_Cmd *cmd) { char *argv[5]; int argc = 0; @@ -98,20 +102,28 @@ int parse_write(Maap_Client *mc, const void *sender, char *buf) { if (rv) { switch(cmd.kind) { case MAAP_CMD_INIT: +#ifdef DEBUG_CMD_MSG printf("Got cmd maap_init_client, range_base: 0x%016llx, range_size: 0x%04x\n", (unsigned long long)cmd.start, cmd.count); +#endif rv = maap_init_client(mc, sender, cmd.start, cmd.count); break; case MAAP_CMD_RESERVE: +#ifdef DEBUG_CMD_MSG printf("Got cmd maap_reserve_range, length: %u\n", (unsigned) cmd.count); +#endif rv = maap_reserve_range(mc, sender, cmd.count); break; case MAAP_CMD_RELEASE: +#ifdef DEBUG_CMD_MSG printf("Got cmd maap_release_range, id: %d\n", (int) cmd.id); +#endif rv = maap_release_range(mc, sender, cmd.id); break; case MAAP_CMD_EXIT: +#ifdef DEBUG_CMD_MSG printf("Got cmd maap_exit\n"); +#endif retVal = 1; /* Indicate that we should exit. */ break; default: diff --git a/daemons/maap/common/maap_parse.h b/daemons/maap/common/maap_parse.h index f8eb921c..8c0e8ecf 100644 --- a/daemons/maap/common/maap_parse.h +++ b/daemons/maap/common/maap_parse.h @@ -24,7 +24,7 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd); * Parse the incoming binary or text data, and perform the specified command, if any. * * @param mc Pointer to the Maap_Client to use - * @param sender Sender information to track the requesting application + * @param sender Sender information pointer used to track the entity requesting the command * @param buf Binary or text data to parse * * @return 1 if the exit command was received, 0 otherwise. -- cgit v1.2.1 From c725a8243f4274f825393835dc00f763e3d3dc60 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 12:09:13 -0600 Subject: Added code to send command notifications. Clients are now sent Maap_Notify structure buffers that contain the results of actions. Multiple clients are supported, and receive notifications only for their commands. --- daemons/maap/common/maap.c | 206 +++++++++++++++++++++++++++++------- daemons/maap/common/maap.h | 28 ++++- daemons/maap/common/maap_iface.h | 15 ++- daemons/maap/linux/src/maap_linux.c | 38 +++++-- 4 files changed, 237 insertions(+), 50 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index dcab9471..d793ed6b 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -27,9 +27,11 @@ static unsigned long long int get_start_address(Maap_Client *mc, Range *range) { return mc->address_base + range->interval->low; } +#ifdef DEBUG_NEGOTIATE_MSG static unsigned long long int get_end_address(Maap_Client *mc, Range *range) { return mc->address_base + range->interval->high; } +#endif static int send_packet(Maap_Client *mc, MAAP_Packet *p) { uint8_t *pbuf = NULL; @@ -84,32 +86,69 @@ static int send_defend(Maap_Client *mc, Range *range, uint64_t start, return send_packet(mc, &p); } -static int inform_acquired(Maap_Client *mc, void *sender, Range *range) { +static int inform_initialized(Maap_Client *mc, const void *sender, Maap_Notify_Error result) { + Maap_Notify note; + + note.kind = MAAP_NOTIFY_INITIALIZED; + note.id = -1; /* Not used */ + note.start = mc->address_base; + note.count = mc->range_len; + note.result = result; + + add_notify(mc, sender, ¬e); + return 0; +} + +static int inform_acquired(Maap_Client *mc, Range *range, Maap_Notify_Error result) { Maap_Notify note; - printf("Address range acquired: 0x%012llx-0x%012llx (Size %d)\n", - get_start_address(mc, range), - get_end_address(mc, range), - get_count(mc, range)); note.kind = MAAP_NOTIFY_ACQUIRED; note.id = range->id; note.start = get_start_address(mc, range); note.count = get_count(mc, range); + note.result = result; + + add_notify(mc, range->sender, ¬e); + return 0; +} + +static int inform_not_acquired(Maap_Client *mc, const void *sender, int range_size, Maap_Notify_Error result) { + Maap_Notify note; + + note.kind = MAAP_NOTIFY_ACQUIRED; + note.id = -1; + note.start = 0; + note.count = range_size; + note.result = result; + + add_notify(mc, sender, ¬e); + return 0; +} + + +static int inform_released(Maap_Client *mc, const void *sender, int id, Range *range, Maap_Notify_Error result) { + Maap_Notify note; + + note.kind = MAAP_NOTIFY_RELEASED; + note.id = id; + note.start = (range ? get_start_address(mc, range) : 0); + note.count = (range ? get_count(mc, range) : 0); + note.result = result; add_notify(mc, sender, ¬e); return 0; } -static int inform_yielded(Maap_Client *mc, void *sender, Range *range) { +static int inform_yielded(Maap_Client *mc, Range *range, int result) { Maap_Notify note; - printf("Address range yielded\n"); note.kind = MAAP_NOTIFY_YIELDED; note.id = range->id; note.start = get_start_address(mc, range); note.count = get_count(mc, range); + note.result = result; - add_notify(mc, sender, ¬e); + add_notify(mc, range->sender, ¬e); return 0; } @@ -138,12 +177,13 @@ void add_notify(Maap_Client *mc, const void *sender, const Maap_Notify *mn) { } } -int get_notify(Maap_Client *mc, void *sender, Maap_Notify *mn) { +int get_notify(Maap_Client *mc, const void **sender, Maap_Notify *mn) { Maap_Notify_List *tmp; if (mc->notifies) { tmp = mc->notifies; - memcpy(mn, tmp, sizeof (Maap_Notify)); + memcpy(mn, &(tmp->notify), sizeof (Maap_Notify)); + if (sender) { *sender = tmp->sender; } mc->notifies = tmp->next; free(tmp); return 1; @@ -151,32 +191,117 @@ int get_notify(Maap_Client *mc, void *sender, Maap_Notify *mn) { return 0; } +void print_notify(Maap_Notify *mn) +{ + assert(mn); + + switch (mn->result) + { + case MAAP_NOTIFY_ERROR_NONE: + /* No error. Don't display anything. */ + break; + case MAAP_NOTIFY_ERROR_REQUIRES_INITIALIZATION: + printf("Error: MAAP is not initialized, so the command cannot be performed.\n"); + break; + case MAAP_NOTIFY_ERROR_ALREADY_INITIALIZED: + printf("Error: MAAP is already initialized, so the values cannot be changed.\n"); + break; + case MAAP_NOTIFY_ERROR_RESERVE_NOT_AVAILABLE: + printf("Error: The MAAP reservation is not available.\n"); + break; + case MAAP_NOTIFY_ERROR_RELEASE_INVALID_ID: + printf("Error: The MAAP reservation ID is not valid, so cannot be released.\n"); + break; + case MAAP_NOTIFY_ERROR_OUT_OF_MEMORY: + printf("Error: The MAAP application is out of memory.\n"); + break; + case MAAP_NOTIFY_ERROR_INTERNAL: + printf("Error: The MAAP application experienced an internal error.\n"); + break; + default: + printf("Error: The MAAP application returned an unknown error %d.\n", mn->result); + break; + } + + switch (mn->kind) + { + case MAAP_NOTIFY_INITIALIZED: + if (mn->result == MAAP_NOTIFY_ERROR_NONE) { + printf("MAAP initialized: 0x%012llx-0x%012llx (Size: %d)\n", + (unsigned long long) mn->start, + (unsigned long long) mn->start + mn->count - 1, + (unsigned int) mn->count); + } else { + printf("MAAP previously initialized: 0x%012llx-0x%012llx (Size: %d)\n", + (unsigned long long) mn->start, + (unsigned long long) mn->start + mn->count - 1, + (unsigned int) mn->count); + } + break; + case MAAP_NOTIFY_ACQUIRED: + if (mn->result == MAAP_NOTIFY_ERROR_NONE) { + printf("Address range %d acquired: 0x%012llx-0x%012llx (Size %d)\n", + mn->id, + (unsigned long long) mn->start, + (unsigned long long) mn->start + mn->count - 1, + mn->count); + } else { + printf("Address range of size %d not acquired\n", + mn->count); + } + break; + case MAAP_NOTIFY_RELEASED: + if (mn->result == MAAP_NOTIFY_ERROR_NONE) { + printf("Address range %d released: 0x%012llx-0x%012llx (Size %d)\n", + mn->id, + (unsigned long long) mn->start, + (unsigned long long) mn->start + mn->count - 1, + mn->count); + } else { + printf("Address range %d not released\n", + mn->id); + } + break; + case MAAP_NOTIFY_YIELDED: + if (mn->result == MAAP_NOTIFY_ERROR_NONE) { + printf("Address range %d yielded: 0x%012llx-0x%012llx (Size %d)\n", + mn->id, + (unsigned long long) mn->start, + (unsigned long long) mn->start + mn->count - 1, + mn->count); + } else { + printf("Unexpected yield error\n"); + } + break; + default: + printf("Notification type %d not recognized\n", mn->kind); + break; + } +} + + int maap_init_client(Maap_Client *mc, const void *sender, uint64_t range_address_base, uint32_t range_len) { - Maap_Notify note; if (mc->initialized) { - printf("MAAP already initialized\n"); - - /* Let the sender know the range that was already specified. */ - memset(¬e, 0, sizeof(note)); - note.kind = MAAP_NOTIFY_INIT; - note.id = -1; /* N/A */ - note.start = mc->address_base; - note.count = mc->range_len; - add_notify(mc, sender, ¬e); + /* If the desired values are the same as the initialized values, pretend the command succeeded. + * Otherwise, let the sender know the range that was already specified and cannot change. */ + inform_initialized(mc, sender, + (range_address_base == mc->address_base && range_len == mc->range_len ? + MAAP_NOTIFY_ERROR_NONE : + MAAP_NOTIFY_ERROR_ALREADY_INITIALIZED)); return -1; } mc->timer = Time_newTimer(); if (!mc->timer) { - printf("Failed to create Timer\n"); + fprintf(stderr, "Failed to create Timer\n"); return -1; } mc->net = Net_newNet(); if (!mc->net) { - printf("Failed to create Net\n"); + fprintf(stderr, "Failed to create Net\n"); Time_delTimer(mc->timer); return -1; } @@ -191,17 +316,8 @@ int maap_init_client(Maap_Client *mc, const void *sender, uint64_t range_address mc->initialized = 1; - printf("MAAP initialized, start: 0x%012llx, max: 0x%04x\n", - (unsigned long long) mc->address_base, - (unsigned int) mc->range_len); - /* Let the sender know the range is now specified. */ - memset(¬e, 0, sizeof(note)); - note.kind = MAAP_NOTIFY_INIT; - note.id = -1; /* N/A */ - note.start = mc->address_base; - note.count = mc->range_len; - add_notify(mc, sender, ¬e); + inform_initialized(mc, sender, MAAP_NOTIFY_ERROR_NONE); return 0; } @@ -328,11 +444,13 @@ int maap_reserve_range(Maap_Client *mc, const void *sender, uint32_t length) { if (!mc->initialized) { printf("Reserve not allowed, as MAAP not initialized\n"); + inform_not_acquired(mc, sender, length, MAAP_NOTIFY_ERROR_REQUIRES_INITIALIZATION); return -1; } range = malloc(sizeof (Range)); if (range == NULL) { + inform_not_acquired(mc, sender, length, MAAP_NOTIFY_ERROR_OUT_OF_MEMORY); return -1; } @@ -342,6 +460,7 @@ int maap_reserve_range(Maap_Client *mc, const void *sender, uint32_t length) { range->counter = MAAP_PROBE_RETRANSMITS; Time_setFromMonotonicTimer(&range->next_act_time); range->interval = NULL; + range->sender = sender; range->next_timer = NULL; assign_interval(mc, range, length); @@ -364,24 +483,33 @@ int maap_release_range(Maap_Client *mc, const void *sender, int id) { if (!mc->initialized) { printf("Release not allowed, as MAAP not initialized\n"); + inform_released(mc, sender, id, NULL, MAAP_NOTIFY_ERROR_REQUIRES_INITIALIZATION); return -1; } range = mc->timer_queue; while (range) { if (range->id == id && range->state != MAAP_STATE_RELEASED) { + inform_released(mc, sender, id, range, MAAP_NOTIFY_ERROR_NONE); + if (sender != range->sender) + { + /* Also inform the sender that originally reserved this range. */ + inform_released(mc, range->sender, id, range, MAAP_NOTIFY_ERROR_NONE); + } + iv = range->interval; iv = remove_interval(&mc->ranges, iv); free_interval(iv); /* memory for range will be freed the next time its timer elapses */ range->state = MAAP_STATE_RELEASED; - printf("Released range id %d\n", id); + return 0; } range = range->next_timer; } printf("Range id %d does not exist to release\n", id); + inform_released(mc, sender, id, NULL, MAAP_NOTIFY_ERROR_RELEASE_INVALID_ID); return -1; } @@ -395,19 +523,19 @@ int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len) { /* printf("RECEIVED MAAP PACKET LEN %d\n", len); */ if (len < MAAP_PKT_SIZE) { - printf("Truncated MAAP packet received, discarding\n"); + fprintf(stderr, "Truncated MAAP packet received, discarding\n"); return 0; } rv = unpack_maap(&p, stream); if (rv != 0) { - printf("Error unpacking the MAAP packet\n"); + fprintf(stderr, "Error unpacking the MAAP packet\n"); return rv; } /* printf("Unpacked packet\n"); */ if (p.message_type < MAAP_PROBE || p.message_type > MAAP_ANNOUNCE) { - printf("Maap packet message type %u not recognized\n", p.message_type); + fprintf(stderr, "Maap packet message type %u not recognized\n", p.message_type); return 0; } @@ -424,7 +552,7 @@ int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len) { if (incoming_max < own_base || own_max < incoming_base) { printf("Packet refers to a range outside of our concern\n"); - printf("0x%012llx < 0x%012llx || 0x%012llx < 0x%012llx\n", incoming_max, own_base, own_max, incoming_base); + printf("\t0x%012llx < 0x%012llx || 0x%012llx < 0x%012llx\n", incoming_max, own_base, own_max, incoming_base); return 0; } @@ -465,7 +593,7 @@ int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len) { range->counter = 1; } else { printf("Yield vs. ANNOUNCE\n"); - inform_yielded(mc, NULL /** @todo Need the socket handle */, range); + inform_yielded(mc, range, MAAP_NOTIFY_ERROR_NONE); iv = remove_interval(&mc->ranges, iv); free_interval(iv); /* memory will be freed the next time its timer elapses */ @@ -486,7 +614,7 @@ int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len) { int handle_probe_timer(Maap_Client *mc, Range *range) { if (range->counter == 0) { - inform_acquired(mc, NULL /** @todo Need the socket handle */, range); + inform_acquired(mc, range, MAAP_NOTIFY_ERROR_NONE); range->state = MAAP_STATE_DEFENDING; send_announce(mc, range); schedule_timer(mc, range); diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index 2b0dc9ae..93dd3b73 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -47,6 +47,7 @@ struct range { int counter; Time next_act_time; Interval *interval; + const void *sender; Range *next_timer; }; @@ -83,7 +84,32 @@ int maap_handle_timer(Maap_Client *mc); */ int64_t maap_get_delay_to_next_timer(Maap_Client *mc); + +/** + * Add a notification to the end of the notifications queue. + * + * @param mc Pointer to the Maap_Client to use + * @param sender Sender information pointer used to track the entity requesting the command + * @param mn Maap_Notify structure with the notification information to use + */ void add_notify(Maap_Client *mc, const void *sender, const Maap_Notify *mn); -int get_notify(Maap_Client *mc, void *sender, Maap_Notify *mn); + +/** + * Get the next notification from the notifications queue. + * + * @param mc Pointer to the Maap_Client to use + * @param sender Pointer to empty sender information pointer to receive the entity requesting the command + * @param mn Empty Maap_Notify structure to fill with the notification information + * + * @return 1 if a notification was returned, 0 if there are no more queued notifications. + */ +int get_notify(Maap_Client *mc, const void **sender, Maap_Notify *mn); + +/** + * Output the text equivalent of the notification information to stdout. + * + * @param mn Pointer to the notification information structure. + */ +void print_notify(Maap_Notify *mn); #endif diff --git a/daemons/maap/common/maap_iface.h b/daemons/maap/common/maap_iface.h index 1ad1b4e9..d028e78c 100644 --- a/daemons/maap/common/maap_iface.h +++ b/daemons/maap/common/maap_iface.h @@ -26,16 +26,29 @@ typedef struct { typedef enum { - MAAP_NOTIFY_INIT, + MAAP_NOTIFY_INVALID = 0, + MAAP_NOTIFY_INITIALIZED, MAAP_NOTIFY_ACQUIRED, + MAAP_NOTIFY_RELEASED, MAAP_NOTIFY_YIELDED, } Maap_Notify_Tag; +typedef enum { + MAAP_NOTIFY_ERROR_NONE = 0, /**< Command was successful */ + MAAP_NOTIFY_ERROR_REQUIRES_INITIALIZATION, /**< MAAP is not initialized, so the command cannot be performed */ + MAAP_NOTIFY_ERROR_ALREADY_INITIALIZED, /**< MAAP is already initialized, so the values cannot be changed */ + MAAP_NOTIFY_ERROR_RESERVE_NOT_AVAILABLE, /**< The MAAP reservation is not available */ + MAAP_NOTIFY_ERROR_RELEASE_INVALID_ID, /**< The MAAP reservation ID is not valid, so cannot be released */ + MAAP_NOTIFY_ERROR_OUT_OF_MEMORY, /**< The MAAP application is out of memory */ + MAAP_NOTIFY_ERROR_INTERNAL, /**< The MAAP application experienced an internal error */ +} Maap_Notify_Error; + typedef struct { Maap_Notify_Tag kind; int32_t id; uint64_t start; uint32_t count; + Maap_Notify_Error result; } Maap_Notify; #endif diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index a6947b12..2885841f 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -60,7 +60,6 @@ #define VERSION_STR "0.1" static int act_as_client(const char *listenport); -static void process_response(const char *pData, int nDataLen); static const char *version_str = @@ -133,6 +132,8 @@ int main(int argc, char *argv[]) char recvbuffer[1600]; int recvbytes; Maap_Cmd recvcmd; + Maap_Notify recvnotify; + uintptr_t notifysocket; int exit_received = 0; @@ -380,6 +381,22 @@ int main(int argc, char *argv[]) Net_freeQueuedPacket(mc.net, packet_data); } + /* Process any notifications. */ + while (get_notify(&mc, (void *)¬ifysocket, &recvnotify) > 0) + { + print_notify(&recvnotify); + + if ((int) notifysocket != -1) + { + /* Send the notification information to the client. */ + if (send((int) notifysocket, &recvnotify, sizeof(recvnotify), 0) < 0) + { + /* Something went wrong. Assume the socket will be closed below. */ + fprintf(stderr, "Error %d writing to client socket %d (%s)\n", errno, (int) notifysocket, strerror(errno)); + } + } + } + /* Determine how long to wait. */ waittime = maap_get_delay_to_next_timer(&mc); if (waittime > 0) @@ -467,6 +484,7 @@ int main(int argc, char *argv[]) if (newfd != -1) { clientfd[nextclientindex] = newfd; + nextclientindex = (nextclientindex + 1) % MAX_CLIENT_CONNECTIONS; /* Next slot used for the next try. */ FD_SET(newfd, &master); /* add to master set */ if (newfd > fdmax) { /* keep track of the max */ fdmax = newfd; @@ -489,7 +507,7 @@ int main(int argc, char *argv[]) /* Process the command data (may be binary or text). */ memset(&recvcmd, 0, sizeof(recvcmd)); - if (parse_write(&mc, (void *)(uintptr_t) -1, recvbuffer)) + if (parse_write(&mc, (const void *)(uintptr_t) -1, recvbuffer)) { /* Received a command to exit. */ exit_received = 1; @@ -525,7 +543,7 @@ int main(int argc, char *argv[]) /* Process the command data (may be binary or text). */ memset(&recvcmd, 0, sizeof(recvcmd)); - if (parse_write(&mc, (void *)(uintptr_t) clientfd[i], recvbuffer)) + if (parse_write(&mc, (const void *)(uintptr_t) clientfd[i], recvbuffer)) { /* Received a command to exit. */ exit_received = 1; @@ -642,7 +660,14 @@ static int act_as_client(const char *listenport) recvbuffer[recvbytes] = '\0'; /* Process the response data (will be binary). */ - process_response(recvbuffer, recvbytes); + if (recvbytes == sizeof(Maap_Notify)) + { + print_notify((Maap_Notify *) recvbuffer); + } + else + { + fprintf(stderr, "Received unexpected response of size %d\n", recvbytes); + } } if (recvbytes == 0) { @@ -707,8 +732,3 @@ static int act_as_client(const char *listenport) return (exit_received ? 0 : -1); } - - -static void process_response(const char *pData, int nDataLen) -{ -} -- cgit v1.2.1 From 0a38302e43f8d6a7d9ddbc15a08a7f4ddd134bbd Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 13:27:41 -0600 Subject: Removed unused endian.h header file. --- daemons/maap/test/endian.h | 96 ---------------------------------------------- 1 file changed, 96 deletions(-) delete mode 100755 daemons/maap/test/endian.h diff --git a/daemons/maap/test/endian.h b/daemons/maap/test/endian.h deleted file mode 100755 index 37d030a2..00000000 --- a/daemons/maap/test/endian.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (C) 1992, 1996, 1997, 2000, 2008 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _ENDIAN_H -#define _ENDIAN_H 1 - -#include - -/* Definitions for byte order, according to significance of bytes, - from low addresses to high addresses. The value is what you get by - putting '4' in the most significant byte, '3' in the second most - significant byte, '2' in the second least significant byte, and '1' - in the least significant byte, and then writing down one digit for - each byte, starting with the byte at the lowest address at the left, - and proceeding to the byte with the highest address at the right. */ - -#define __LITTLE_ENDIAN 1234 -#define __BIG_ENDIAN 4321 -#define __PDP_ENDIAN 3412 - -/* This file defines `__BYTE_ORDER' for the particular machine. */ -#include - -/* Some machines may need to use a different endianness for floating point - values. */ -#ifndef __FLOAT_WORD_ORDER -# define __FLOAT_WORD_ORDER __BYTE_ORDER -#endif - -#ifdef __USE_BSD -# define LITTLE_ENDIAN __LITTLE_ENDIAN -# define BIG_ENDIAN __BIG_ENDIAN -# define PDP_ENDIAN __PDP_ENDIAN -# define BYTE_ORDER __BYTE_ORDER -#endif - -#if __BYTE_ORDER == __LITTLE_ENDIAN -# define __LONG_LONG_PAIR(HI, LO) LO, HI -#elif __BYTE_ORDER == __BIG_ENDIAN -# define __LONG_LONG_PAIR(HI, LO) HI, LO -#endif - - -#ifdef __USE_BSD -/* Conversion interfaces. */ -# include - -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define htobe16(x) __bswap_16 (x) -# define htole16(x) (x) -# define be16toh(x) __bswap_16 (x) -# define le16toh(x) (x) - -# define htobe32(x) __bswap_32 (x) -# define htole32(x) (x) -# define be32toh(x) __bswap_32 (x) -# define le32toh(x) (x) - -# define htobe64(x) __bswap_64 (x) -# define htole64(x) (x) -# define be64toh(x) __bswap_64 (x) -# define le64toh(x) (x) -# else -# define htobe16(x) (x) -# define htole16(x) __bswap_16 (x) -# define be16toh(x) (x) -# define le16toh(x) __bswap_16 (x) - -# define htobe32(x) (x) -# define htole32(x) __bswap_32 (x) -# define be32toh(x) (x) -# define le32toh(x) __bswap_32 (x) - -# define htobe64(x) (x) -# define htole64(x) __bswap_64 (x) -# define be64toh(x) (x) -# define le64toh(x) __bswap_64 (x) -# endif -#endif - -#endif /* endian.h */ -- cgit v1.2.1 From fb5a904b710ea3a73304ddd522205ea77a258ea6 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 13:32:51 -0600 Subject: Whitespace changes --- daemons/maap/linux/src/maap_linux.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 2885841f..419823fa 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -86,11 +86,11 @@ static void usage(void) /* get sockaddr, IPv4 or IPv6 */ static void *get_in_addr(struct sockaddr *sa) { - if (sa->sa_family == AF_INET) { - return &(((struct sockaddr_in*)sa)->sin_addr); - } + if (sa->sa_family == AF_INET) { + return &(((struct sockaddr_in*)sa)->sin_addr); + } - return &(((struct sockaddr_in6*)sa)->sin6_addr); + return &(((struct sockaddr_in6*)sa)->sin6_addr); } @@ -119,9 +119,9 @@ int main(int argc, char *argv[]) int newfd; socklen_t addrlen; struct sockaddr_storage remoteaddr; - char remoteIP[INET6_ADDRSTRLEN]; - int clientfd[MAX_CLIENT_CONNECTIONS]; - int i, nextclientindex; + char remoteIP[INET6_ADDRSTRLEN]; + int clientfd[MAX_CLIENT_CONNECTIONS]; + int i, nextclientindex; fd_set master, read_fds; int fdmax; @@ -515,7 +515,7 @@ int main(int argc, char *argv[]) } } - /* Run through the existing connections looking for data to read. */ + /* Run through the existing connections looking for data to read. */ for (i = 0; i < MAX_CLIENT_CONNECTIONS; ++i) { if (clientfd[i] != -1 && FD_ISSET(clientfd[i], &read_fds)) -- cgit v1.2.1 From e224dc71846de719cb69b9d53835ad9c192d150c Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 13:41:21 -0600 Subject: Verify that the client socket is still valid Before sending a notification to a client socket, verify that the socket is still valid and has not been closed. --- daemons/maap/linux/src/maap_linux.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 419823fa..5202a359 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -389,10 +389,21 @@ int main(int argc, char *argv[]) if ((int) notifysocket != -1) { /* Send the notification information to the client. */ - if (send((int) notifysocket, &recvnotify, sizeof(recvnotify), 0) < 0) + for (i = 0; i < MAX_CLIENT_CONNECTIONS; ++i) { - /* Something went wrong. Assume the socket will be closed below. */ - fprintf(stderr, "Error %d writing to client socket %d (%s)\n", errno, (int) notifysocket, strerror(errno)); + if (clientfd[i] == (int) notifysocket) + { + if (send((int) notifysocket, &recvnotify, sizeof(recvnotify), 0) < 0) + { + /* Something went wrong. Assume the socket will be closed below. */ + fprintf(stderr, "Error %d writing to client socket %d (%s)\n", errno, (int) notifysocket, strerror(errno)); + } + break; + } + } + if (i >= MAX_CLIENT_CONNECTIONS) + { + printf("Notification for client socket %d, but that socket no longer exists\n", (int) notifysocket); } } } -- cgit v1.2.1 From a31ed3490d1b180963d5bd6793bf08d0ca586f9d Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 14:03:59 -0600 Subject: Added "status" command support. Added a new status command to get the range of addresses associated with a supplied ID. --- daemons/maap/common/maap.c | 50 ++++++++++++++++++++++++++++++++++++- daemons/maap/common/maap.h | 1 + daemons/maap/common/maap_iface.h | 2 ++ daemons/maap/common/maap_parse.c | 28 +++++++++++++++------ daemons/maap/linux/src/maap_linux.c | 1 + 5 files changed, 73 insertions(+), 9 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index d793ed6b..4ae3b487 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -125,7 +125,6 @@ static int inform_not_acquired(Maap_Client *mc, const void *sender, int range_si return 0; } - static int inform_released(Maap_Client *mc, const void *sender, int id, Range *range, Maap_Notify_Error result) { Maap_Notify note; @@ -139,6 +138,19 @@ static int inform_released(Maap_Client *mc, const void *sender, int id, Range *r return 0; } +static int inform_status(Maap_Client *mc, const void *sender, int id, Range *range, Maap_Notify_Error result) { + Maap_Notify note; + + note.kind = MAAP_NOTIFY_STATUS; + note.id = id; + note.start = (range ? get_start_address(mc, range) : 0); + note.count = (range ? get_count(mc, range) : 0); + note.result = result; + + add_notify(mc, sender, ¬e); + return 0; +} + static int inform_yielded(Maap_Client *mc, Range *range, int result) { Maap_Notify note; @@ -262,6 +274,18 @@ void print_notify(Maap_Notify *mn) mn->id); } break; + case MAAP_NOTIFY_STATUS: + if (mn->result == MAAP_NOTIFY_ERROR_NONE) { + printf("ID %d is address range 0x%012llx-0x%012llx (Size %d)\n", + mn->id, + (unsigned long long) mn->start, + (unsigned long long) mn->start + mn->count - 1, + mn->count); + } else { + printf("ID %d is not valid\n", + mn->id); + } + break; case MAAP_NOTIFY_YIELDED: if (mn->result == MAAP_NOTIFY_ERROR_NONE) { printf("Address range %d yielded: 0x%012llx-0x%012llx (Size %d)\n", @@ -513,6 +537,30 @@ int maap_release_range(Maap_Client *mc, const void *sender, int id) { return -1; } +void maap_range_status(Maap_Client *mc, const void *sender, int id) +{ + Range *range; + + if (!mc->initialized) { + printf("Status not allowed, as MAAP not initialized\n"); + inform_status(mc, sender, id, NULL, MAAP_NOTIFY_ERROR_REQUIRES_INITIALIZATION); + return; + } + + range = mc->timer_queue; + while (range) { + if (range->id == id && range->state != MAAP_STATE_RELEASED) { + inform_status(mc, sender, id, range, MAAP_NOTIFY_ERROR_NONE); + return; + } + range = range->next_timer; + } + + printf("Range id %d does not exist\n", id); + inform_status(mc, sender, id, NULL, MAAP_NOTIFY_ERROR_RELEASE_INVALID_ID); +} + + int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len) { MAAP_Packet p; Interval *iv; diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index 93dd3b73..737e2885 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -71,6 +71,7 @@ void maap_deinit_client(Maap_Client *mc); int maap_reserve_range(Maap_Client *mc, const void *sender, uint32_t length); int maap_release_range(Maap_Client *mc, const void *sender, int id); +void maap_range_status(Maap_Client *mc, const void *sender, int id); int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len); int maap_handle_timer(Maap_Client *mc); diff --git a/daemons/maap/common/maap_iface.h b/daemons/maap/common/maap_iface.h index d028e78c..d8a27b8b 100644 --- a/daemons/maap/common/maap_iface.h +++ b/daemons/maap/common/maap_iface.h @@ -14,6 +14,7 @@ typedef enum { MAAP_CMD_INIT, MAAP_CMD_RESERVE, MAAP_CMD_RELEASE, + MAAP_CMD_STATUS, MAAP_CMD_EXIT, } Maap_Cmd_Tag; @@ -30,6 +31,7 @@ typedef enum { MAAP_NOTIFY_INITIALIZED, MAAP_NOTIFY_ACQUIRED, MAAP_NOTIFY_RELEASED, + MAAP_NOTIFY_STATUS, MAAP_NOTIFY_YIELDED, } Maap_Notify_Tag; diff --git a/daemons/maap/common/maap_parse.c b/daemons/maap/common/maap_parse.c index b27c586f..93674902 100644 --- a/daemons/maap/common/maap_parse.c +++ b/daemons/maap/common/maap_parse.c @@ -56,6 +56,10 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { cmd->kind = MAAP_CMD_RELEASE; cmd->id = (int)strtoul(argv[1], NULL, 0); set_cmd = 1; + } else if (strncmp(argv[0], "status", 7) == 0 && argc == 2) { + cmd->kind = MAAP_CMD_STATUS; + cmd->id = (int)strtoul(argv[1], NULL, 0); + set_cmd = 1; } else if (strncmp(argv[0], "exit", 4) == 0 && argc == 1) { cmd->kind = MAAP_CMD_EXIT; set_cmd = 1; @@ -67,11 +71,12 @@ int parse_text_cmd(char *buf, Maap_Cmd *cmd) { if (!set_cmd) { printf("input usage:\n"); - printf(" init [ ]\n"); + printf(" init [ ] - Initialize the MAAP daemon to recognize the specified range of addresses\n"); printf(" If not specified, range_base=0x%llx, range_size=0x%04x\n", MAAP_DYNAMIC_POOL_BASE, MAAP_DYNAMIC_POOL_SIZE); - printf(" reserve \n"); - printf(" release \n"); - printf(" exit\n\n"); + printf(" reserve - Reserve a range of addresses of size in the initialized range\n"); + printf(" release - Release the range of addresses with identifier ID\n"); + printf(" status - Get the range of addresses associated with identifier ID\n"); + printf(" exit - Shutdown the MAAP daemon\n\n"); return 0; } @@ -89,6 +94,7 @@ int parse_write(Maap_Client *mc, const void *sender, char *buf) { case MAAP_CMD_INIT: case MAAP_CMD_RESERVE: case MAAP_CMD_RELEASE: + case MAAP_CMD_STATUS: case MAAP_CMD_EXIT: memcpy(&cmd, bufcmd, sizeof (Maap_Cmd)); rv = 1; @@ -103,26 +109,32 @@ int parse_write(Maap_Client *mc, const void *sender, char *buf) { switch(cmd.kind) { case MAAP_CMD_INIT: #ifdef DEBUG_CMD_MSG - printf("Got cmd maap_init_client, range_base: 0x%016llx, range_size: 0x%04x\n", + printf("Got cmd MAAP_CMD_INIT, range_base: 0x%016llx, range_size: 0x%04x\n", (unsigned long long)cmd.start, cmd.count); #endif rv = maap_init_client(mc, sender, cmd.start, cmd.count); break; case MAAP_CMD_RESERVE: #ifdef DEBUG_CMD_MSG - printf("Got cmd maap_reserve_range, length: %u\n", (unsigned) cmd.count); + printf("Got cmd MAAP_CMD_RESERVE, length: %u\n", (unsigned) cmd.count); #endif rv = maap_reserve_range(mc, sender, cmd.count); break; case MAAP_CMD_RELEASE: #ifdef DEBUG_CMD_MSG - printf("Got cmd maap_release_range, id: %d\n", (int) cmd.id); + printf("Got cmd MAAP_CMD_RELEASE, id: %d\n", (int) cmd.id); #endif rv = maap_release_range(mc, sender, cmd.id); break; + case MAAP_CMD_STATUS: +#ifdef DEBUG_CMD_MSG + printf("Got cmd MAAP_CMD_STATUS, id: %d\n", (int) cmd.id); +#endif + maap_range_status(mc, sender, cmd.id); + break; case MAAP_CMD_EXIT: #ifdef DEBUG_CMD_MSG - printf("Got cmd maap_exit\n"); + printf("Got cmd MAAP_CMD_EXIT\n"); #endif retVal = 1; /* Indicate that we should exit. */ break; diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 5202a359..20d92bbb 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -714,6 +714,7 @@ static int act_as_client(const char *listenport) case MAAP_CMD_INIT: case MAAP_CMD_RESERVE: case MAAP_CMD_RELEASE: + case MAAP_CMD_STATUS: case MAAP_CMD_EXIT: memcpy(&recvcmd, bufcmd, sizeof(Maap_Cmd)); rv = 1; -- cgit v1.2.1 From 8ae58751bbabc2d6a18b16156ce67aa6e77b5c1c Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 15:03:35 -0600 Subject: Uses the correct MAAP AVTP Subtype value. --- daemons/maap/common/maap.h | 2 +- daemons/maap/common/maap_packet.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/daemons/maap/common/maap.h b/daemons/maap/common/maap.h index 737e2885..7211c480 100644 --- a/daemons/maap/common/maap.h +++ b/daemons/maap/common/maap.h @@ -30,7 +30,7 @@ #define MAAP_DYNAMIC_POOL_SIZE 0xFE00 /**< MAAP dynamic allocation pool size - Defined in IEEE 1722-2011 Table B.4 */ #define MAAP_TYPE 0x22F0 /**< AVTP Ethertype - Defined in IEEE 1722-2011 Table 5.1 */ -#define MAAP_SUBTYPE 0xFE /**< AVTP MAAP subtype - Defined in IEEE 1722-2011 Table 5.2 */ +#define MAAP_SUBTYPE 0x7E /**< AVTP MAAP subtype - Defined in IEEE 1722-2011 Table 5.2 */ #define MAAP_PKT_SIZE 42 typedef struct maap_notify_list Maap_Notify_List; diff --git a/daemons/maap/common/maap_packet.c b/daemons/maap/common/maap_packet.c index fcfadb45..0f7877bb 100644 --- a/daemons/maap/common/maap_packet.c +++ b/daemons/maap/common/maap_packet.c @@ -128,7 +128,7 @@ void init_packet(MAAP_Packet *packet, uint64_t dest_mac, uint64_t src_mac) { packet->SA = src_mac; packet->Ethertype = MAAP_TYPE; packet->CD = 1; - packet->subtype = 0x7e; + packet->subtype = MAAP_SUBTYPE; packet->SV = 0; packet->version = 1; packet->message_type = 0; -- cgit v1.2.1 From e4928f3f40bf6731c3573806998d5d9bdccaeab8 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 15:15:45 -0600 Subject: Updated comments regarding memory frees on shutdown Also includes some whitespace changes. --- daemons/maap/common/maap.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index 4ae3b487..2900b79d 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -194,7 +194,7 @@ int get_notify(Maap_Client *mc, const void **sender, Maap_Notify *mn) { if (mc->notifies) { tmp = mc->notifies; - memcpy(mn, &(tmp->notify), sizeof (Maap_Notify)); + if (mn) { memcpy(mn, &(tmp->notify), sizeof (Maap_Notify)); } if (sender) { *sender = tmp->sender; } mc->notifies = tmp->next; free(tmp); @@ -348,8 +348,14 @@ int maap_init_client(Maap_Client *mc, const void *sender, uint64_t range_address void maap_deinit_client(Maap_Client *mc) { if (mc->initialized) { + if (mc->ranges) { + /** @todo Free reservation memory */ + mc->ranges = NULL; + } + if (mc->timer_queue) { /** @todo Free reservation memory */ + mc->timer_queue = NULL; } if (mc->timer) { @@ -362,6 +368,8 @@ void maap_deinit_client(Maap_Client *mc) { mc->net = NULL; } + while (get_notify(mc, NULL, NULL)) { /* Do nothing with the result */ } + mc->initialized = 0; } } @@ -624,9 +632,9 @@ int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len) { printf("Someone is messing with our range!\n"); #ifdef DEBUG_NEGOTIATE_MSG printf(" Request of 0x%012llx-0x%012llx inside our\n", - incoming_base, incoming_max); + incoming_base, incoming_max); printf(" range of 0x%012llx-0x%012llx\n", - get_start_address(mc, range), get_end_address(mc, range)); + get_start_address(mc, range), get_end_address(mc, range)); #endif if (p.message_type == MAAP_PROBE) { printf("DEFEND!\n"); -- cgit v1.2.1 From 970ec93c6268b2b6c02ec5a67159b5a0f2951547 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Mon, 10 Oct 2016 16:38:26 -0600 Subject: Reduced the main() function size. Functionality moved to new init_maap_networking() and get_listener_socket() functions to make the code easier to follow. --- daemons/maap/linux/src/maap_linux.c | 240 +++++++++++++++++++++--------------- 1 file changed, 139 insertions(+), 101 deletions(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 20d92bbb..5447e48f 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -59,6 +59,8 @@ #define VERSION_STR "0.1" +static int init_maap_networking(const char *iface, uint8_t src_mac[ETH_ALEN], uint8_t dest_mac[ETH_ALEN]); +static int get_listener_socket(const char *listenport); static int act_as_client(const char *listenport); @@ -105,21 +107,11 @@ int main(int argc, char *argv[]) int ret; int socketfd; - struct ifreq ifbuffer; uint8_t dest_mac[ETH_ALEN] = MAAP_DEST_MAC; uint8_t src_mac[ETH_ALEN]; - int ifindex; - struct sockaddr_ll sockaddr; - struct packet_mreq mreq; int listener; - struct addrinfo hints, *ai, *p; - int yes=1; - int newfd; - socklen_t addrlen; - struct sockaddr_storage remoteaddr; - char remoteIP[INET6_ADDRSTRLEN]; int clientfd[MAX_CLIENT_CONNECTIONS]; int i, nextclientindex; @@ -226,62 +218,14 @@ int main(int argc, char *argv[]) * Initialize the networking support. */ - if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(MAAP_TYPE))) == -1 ) - { - fprintf(stderr, "Error: could not open socket %d\n",socketfd); + socketfd = init_maap_networking(iface, src_mac, dest_mac); + if (socketfd == -1) { return -1; } - if (fcntl(socketfd, F_SETFL, O_NONBLOCK) < 0) - { - fprintf(stderr, "Error: could not set the socket to non-blocking\n"); - return -1; - } - - memset(&ifbuffer, 0x00, sizeof(ifbuffer)); - strncpy(ifbuffer.ifr_name, iface, IFNAMSIZ); - if (ioctl(socketfd, SIOCGIFINDEX, &ifbuffer) < 0) - { - fprintf(stderr, "Error: could not get interface index\n"); - close(socketfd); - return -1; - } free(iface); iface = NULL; - ifindex = ifbuffer.ifr_ifindex; - if (ioctl(socketfd, SIOCGIFHWADDR, &ifbuffer) < 0) { - fprintf(stderr, "Error: could not get interface address\n"); - close(socketfd); - return -1; - } - - memcpy(src_mac, ifbuffer.ifr_hwaddr.sa_data, ETH_ALEN); - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sll_family = AF_PACKET; - sockaddr.sll_ifindex = ifindex; - sockaddr.sll_halen = ETH_ALEN; - memcpy(sockaddr.sll_addr, dest_mac, ETH_ALEN); - - if (bind(socketfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) { - fprintf(stderr, "Error: could not bind datagram socket\n"); - return -1; - } - - /* filter multicast address */ - memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifindex; - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = 6; - memcpy(mreq.mr_address, dest_mac, mreq.mr_alen); - - if (setsockopt(socketfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, - sizeof(mreq)) < 0) { - fprintf(stderr, "setsockopt PACKET_ADD_MEMBERSHIP failed\n"); - return -1; - } - FD_ZERO(&read_fds); FD_ZERO(&master); FD_SET(STDIN_FILENO, &master); @@ -290,48 +234,17 @@ int main(int argc, char *argv[]) /* - * Initialize the Maap_Client data structure. + * Initialize the client connection listen socket. */ - /* get us a localhost socket and bind it */ - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - if ((ret = getaddrinfo(NULL, listenport, &hints, &ai)) != 0) { - fprintf(stderr, "getaddrinfo failure %s\n", gai_strerror(ret)); - return -1; - } - - for(p = ai; p != NULL; p = p->ai_next) { - listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (listener == -1) { - continue; - } - - /* Lose the pesky "address already in use" error message */ - setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); - - if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) { - close(listener); - continue; - } - - break; - } - - freeaddrinfo(ai); - - /* If we got here, it means we didn't get bound */ - if (p == NULL) { - fprintf(stderr, "Socket failed to bind error %d (%s)\n", errno, strerror(errno)); + listener = get_listener_socket(listenport); + if (listener == -1) { + close(socketfd); return -1; } - if (listen(listener, 10) < 0) { - fprintf(stderr, "Socket listen error %d (%s)\n", errno, strerror(errno)); - exit(3); - } + free(listenport); + listenport = NULL; /* Add the listener to the master set */ FD_SET(listener, &master); @@ -457,6 +370,11 @@ int main(int argc, char *argv[]) /* Accept any new connections. */ if (FD_ISSET(listener, &read_fds)) { + int newfd; + socklen_t addrlen; + struct sockaddr_storage remoteaddr; + char remoteIP[INET6_ADDRSTRLEN]; + addrlen = sizeof remoteaddr; newfd = accept(listener, (struct sockaddr *)&remoteaddr, @@ -568,7 +486,7 @@ int main(int argc, char *argv[]) close(socketfd); close(listener); - /** Close any connected sockets. */ + /* Close any connected sockets. */ for (i = 0; i < MAX_CLIENT_CONNECTIONS; ++i) { if (clientfd[i] != -1) { close(clientfd[i]); @@ -578,12 +496,132 @@ int main(int argc, char *argv[]) maap_deinit_client(&mc); - free(iface); - free(listenport); - return (exit_received ? 0 : -1); } +/* Initializes the MAAP raw socket support, and returns a socket handle for that socket. */ +static int init_maap_networking(const char *iface, uint8_t src_mac[ETH_ALEN], uint8_t dest_mac[ETH_ALEN]) +{ + int socketfd; + struct ifreq ifbuffer; + int ifindex; + struct sockaddr_ll sockaddr; + struct packet_mreq mreq; + + if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(MAAP_TYPE))) == -1 ) + { + fprintf(stderr, "Error: could not open socket %d\n",socketfd); + return -1; + } + + if (fcntl(socketfd, F_SETFL, O_NONBLOCK) < 0) + { + fprintf(stderr, "Error: could not set the socket to non-blocking\n"); + close(socketfd); + return -1; + } + + memset(&ifbuffer, 0x00, sizeof(ifbuffer)); + strncpy(ifbuffer.ifr_name, iface, IFNAMSIZ); + if (ioctl(socketfd, SIOCGIFINDEX, &ifbuffer) < 0) + { + fprintf(stderr, "Error: could not get interface index\n"); + close(socketfd); + return -1; + } + + ifindex = ifbuffer.ifr_ifindex; + if (ioctl(socketfd, SIOCGIFHWADDR, &ifbuffer) < 0) { + fprintf(stderr, "Error: could not get interface address\n"); + close(socketfd); + return -1; + } + + memcpy(src_mac, ifbuffer.ifr_hwaddr.sa_data, ETH_ALEN); + + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sll_family = AF_PACKET; + sockaddr.sll_ifindex = ifindex; + sockaddr.sll_halen = ETH_ALEN; + memcpy(sockaddr.sll_addr, dest_mac, ETH_ALEN); + + if (bind(socketfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) { + fprintf(stderr, "Error: could not bind datagram socket\n"); + close(socketfd); + return -1; + } + + /* filter multicast address */ + memset(&mreq, 0, sizeof(mreq)); + mreq.mr_ifindex = ifindex; + mreq.mr_type = PACKET_MR_MULTICAST; + mreq.mr_alen = 6; + memcpy(mreq.mr_address, dest_mac, mreq.mr_alen); + + if (setsockopt(socketfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, + sizeof(mreq)) < 0) { + fprintf(stderr, "setsockopt PACKET_ADD_MEMBERSHIP failed\n"); + close(socketfd); + return -1; + } + + return socketfd; +} + +/* Initializes the listener socket, and returns a socket handle for that socket. */ +static int get_listener_socket(const char *listenport) +{ + int listener; + struct addrinfo hints, *ai, *p; + int yes=1; + int ret; + + /* Get us a localhost socket and bind it */ + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + if ((ret = getaddrinfo(NULL, listenport, &hints, &ai)) != 0) { + fprintf(stderr, "getaddrinfo failure %s\n", gai_strerror(ret)); + return -1; + } + + for(p = ai; p != NULL; p = p->ai_next) { + listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (listener == -1) { + continue; + } + + /* Lose the pesky "address already in use" error message */ + setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); + + if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) { + freeaddrinfo(ai); + close(listener); + continue; + } + + break; + } + + freeaddrinfo(ai); + + /* If we got here, it means we didn't get bound */ + if (p == NULL) { + fprintf(stderr, "Socket failed to bind error %d (%s)\n", errno, strerror(errno)); + close(listener); + return -1; + } + + if (listen(listener, 10) < 0) { + fprintf(stderr, "Socket listen error %d (%s)\n", errno, strerror(errno)); + close(listener); + return -1; + } + + return listener; +} + /* Local function to handle client side of network command & control. */ static int act_as_client(const char *listenport) -- cgit v1.2.1 From c977308009bed67f0cbd749a79959f6ab8ee76de Mon Sep 17 00:00:00 2001 From: andrew-elder Date: Mon, 10 Oct 2016 14:56:35 -0400 Subject: MRP: BUGFIX - memory leak in MSRP when checking for interesting streams Note: This memory leak only occurs if TalkerAdv stream pruning is active (cmdline option -p). Attributes that were selected to be pruned during event processing were not being free'd. --- daemons/mrpd/msrp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/daemons/mrpd/msrp.c b/daemons/mrpd/msrp.c index 2e8c3713..bbfa5464 100644 --- a/daemons/mrpd/msrp.c +++ b/daemons/mrpd/msrp.c @@ -628,6 +628,9 @@ int msrp_event(int event, struct msrp_attribute *rattrib) #if LOG_MSRP msrp_print_debug_info(event, attrib); #endif + } else { + /* free this attrib if we are not interested */ + free(rattrib); } break; -- cgit v1.2.1 From 7050d8e8238f8a1d1eb01f8850aa3dd8a6748ba8 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Tue, 11 Oct 2016 16:25:02 -0600 Subject: Bug fixes Changes to address Valgrind warnings and crash on startup. --- daemons/maap/linux/src/maap_linux.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/daemons/maap/linux/src/maap_linux.c b/daemons/maap/linux/src/maap_linux.c index 5447e48f..94960a35 100644 --- a/daemons/maap/linux/src/maap_linux.c +++ b/daemons/maap/linux/src/maap_linux.c @@ -353,8 +353,8 @@ int main(int argc, char *argv[]) /* Handle any packets received. */ if (FD_ISSET(socketfd, &read_fds)) { - struct sockaddr_ll ll_addr; - socklen_t addr_len; + struct sockaddr_ll ll_addr = {0}; + socklen_t addr_len = 0; while ((recvbytes = recvfrom(socketfd, recvbuffer, sizeof(recvbuffer), MSG_DONTWAIT, (struct sockaddr*)&ll_addr, &addr_len)) > 0) { @@ -596,7 +596,6 @@ static int get_listener_socket(const char *listenport) setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) { - freeaddrinfo(ai); close(listener); continue; } -- cgit v1.2.1 From cda007089c6f92e96c70284b4d38f124f51dd3fb Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Tue, 11 Oct 2016 16:32:32 -0600 Subject: Packet structure updates Updated the packet structure field names to match those in the IEEE 1722-2011 specification. Fixed the version values. Added checks that the MAAP packet is valid. Added Doxygen support. --- daemons/maap/common/maap.c | 16 +++++- daemons/maap/common/maap_packet.c | 32 +++++------ daemons/maap/common/maap_packet.h | 86 +++++++++++++++++++++------- daemons/maap/test/test_maap_packet_packing.c | 18 +++--- 4 files changed, 105 insertions(+), 47 deletions(-) diff --git a/daemons/maap/common/maap.c b/daemons/maap/common/maap.c index 2900b79d..aa406efe 100644 --- a/daemons/maap/common/maap.c +++ b/daemons/maap/common/maap.c @@ -80,8 +80,8 @@ static int send_defend(Maap_Client *mc, Range *range, uint64_t start, p.message_type = MAAP_DEFEND; p.requested_start_address = start; p.requested_count = count; - p.start_address = get_start_address(mc, range); - p.count = get_count(mc, range); + p.conflict_start_address = get_start_address(mc, range); + p.conflict_count = get_count(mc, range); return send_packet(mc, &p); } @@ -590,6 +590,18 @@ int maap_handle_packet(Maap_Client *mc, const uint8_t *stream, int len) { /* printf("Unpacked packet\n"); */ + if (p.Ethertype != MAAP_TYPE || + p.CD != 1 || p.subtype != MAAP_SUBTYPE || + p.maap_data_length != 16 ) + { + /* This is not a MAAP packet. Ignore it. */ + } + + if (p.version != 0) { + fprintf(stderr, "AVTP version %u not supported\n", p.version); + return 0; + } + if (p.message_type < MAAP_PROBE || p.message_type > MAAP_ANNOUNCE) { fprintf(stderr, "Maap packet message type %u not recognized\n", p.message_type); return 0; diff --git a/daemons/maap/common/maap_packet.c b/daemons/maap/common/maap_packet.c index 0f7877bb..10494407 100644 --- a/daemons/maap/common/maap_packet.c +++ b/daemons/maap/common/maap_packet.c @@ -35,10 +35,10 @@ int unpack_maap(MAAP_Packet *packet, const uint8_t *stream) { stream++; memcpy(&tmp8, stream, 1); - packet->status = (tmp8 & 0xf8) >> 3; + packet->maap_version = (tmp8 & 0xf8) >> 3; memcpy(&tmp16, stream, 2); - packet->MAAP_data_length = BE16TOH(tmp16) & 0x07ff; + packet->maap_data_length = BE16TOH(tmp16) & 0x07ff; stream += 2; memcpy(&tmp64, stream, 8); @@ -54,11 +54,11 @@ int unpack_maap(MAAP_Packet *packet, const uint8_t *stream) { stream += 2; memcpy(&tmp64, stream, 6); - packet->start_address = BE64TOH(tmp64) >> 16; + packet->conflict_start_address = BE64TOH(tmp64) >> 16; stream += 6; memcpy(&tmp16, stream, 2); - packet->count = BE16TOH(tmp16); + packet->conflict_count = BE16TOH(tmp16); return 0; } @@ -92,8 +92,8 @@ int pack_maap(const MAAP_Packet *packet, uint8_t *stream) { memcpy(stream, &tmp8, 1); stream++; - tmp16 = HTOBE16(((packet->status & 0x001f) << 11) | - (packet->MAAP_data_length & 0x07ff)); + tmp16 = HTOBE16(((packet->maap_version & 0x001f) << 11) | + (packet->maap_data_length & 0x07ff)); memcpy(stream, &tmp16, 2); stream += 2; @@ -109,11 +109,11 @@ int pack_maap(const MAAP_Packet *packet, uint8_t *stream) { memcpy(stream, &tmp16, 2); stream += 2; - tmp64 = HTOBE64(packet->start_address << 16); + tmp64 = HTOBE64(packet->conflict_start_address << 16); memcpy(stream, &tmp64, 6); stream += 6; - tmp16 = HTOBE16(packet->count); + tmp16 = HTOBE16(packet->conflict_count); memcpy(stream, &tmp16, 2); return 0; @@ -127,18 +127,18 @@ void init_packet(MAAP_Packet *packet, uint64_t dest_mac, uint64_t src_mac) { packet->DA = dest_mac; packet->SA = src_mac; packet->Ethertype = MAAP_TYPE; - packet->CD = 1; + packet->CD = 1; /* CD is 1 - Defined in IEEE 1722-2011 B.2.1 */ packet->subtype = MAAP_SUBTYPE; - packet->SV = 0; - packet->version = 1; + packet->SV = 0; /* SV is 0 - Defined in IEEE 1722-2011 B.2.3 */ + packet->version = 0; /* AVTP version is 0 - Defined in IEEE 1722-2011 5.2.4 */ packet->message_type = 0; - packet->status = 0; - packet->MAAP_data_length = 16; - packet->stream_id = 0; + packet->maap_version = 1; /* MAAP version is 1 - Defined in IEEE 1722-2011 B.2.6 */ + packet->maap_data_length = 16; /* MAAP data length is 16 - Defined in IEEE 1722-2011 B.2.7 */ + packet->stream_id = 0; /* MAAP stream_id is 0 - Defined in IEEE 1722-2011 B.2.8 */ packet->requested_start_address = 0; packet->requested_count = 0; - packet->start_address = 0; - packet->count = 0; + packet->conflict_start_address = 0; + packet->conflict_count = 0; } uint64_t convert_mac_address(const uint8_t macaddr[]) diff --git a/daemons/maap/common/maap_packet.h b/daemons/maap/common/maap_packet.h index 3b70b1b0..b0b7f056 100644 --- a/daemons/maap/common/maap_packet.h +++ b/daemons/maap/common/maap_packet.h @@ -5,32 +5,78 @@ #include "platform.h" -#define MAAP_PROBE 1 /* MAAP Probe MAC address(es) PDU - Defined in IEEE 1722-2011 Table B.1 */ -#define MAAP_DEFEND 2 /* MAAP Defend address(es) response PDU - Defined in IEEE 1722-2011 Table B.1 */ -#define MAAP_ANNOUNCE 3 /* MAAP Announce MAC address(es) acquired PDU - Defined in IEEE 1722-2011 Table B.1 */ - -typedef struct maap_packet { - uint64_t DA; - uint64_t SA; - uint16_t Ethertype; - uint8_t CD; - uint16_t subtype; - uint8_t SV; - uint8_t version; - uint8_t message_type; - uint8_t status; - uint16_t MAAP_data_length; - uint64_t stream_id; - uint64_t requested_start_address; - uint16_t requested_count; - uint64_t start_address; - uint16_t count; +/** + * @file + * + * @brief Support for packing and unpacking MAAP packets + * + * These functions convert a binary stream of bytes into a #MAAP_Packet structure, or vice versa. + */ + + +#define MAAP_PROBE 1 /**< MAAP Probe MAC address(es) PDU - Defined in IEEE 1722-2011 Table B.1 */ +#define MAAP_DEFEND 2 /**< MAAP Defend address(es) response PDU - Defined in IEEE 1722-2011 Table B.1 */ +#define MAAP_ANNOUNCE 3 /**< MAAP Announce MAC address(es) acquired PDU - Defined in IEEE 1722-2011 Table B.1 */ + +/** MAAP Packet contents - Defined in IEEE 1722-2011 B.2 */ +typedef struct { + uint64_t DA; /**< Destination Address */ + uint64_t SA; /**< Source Address */ + uint16_t Ethertype; /**< AVTB Ethertype (i.e. @p MAAP_TYPE) */ + uint8_t CD; /**< Control/Data Indicator */ + uint16_t subtype; /**< AVTP Subtype (i.e. @p MAAP_SUBTYPE) */ + uint8_t SV; /**< 1 if stream_id is valid, 0 otherwise. Always 0 for MAAP. */ + uint8_t version; /**< AVTP Version. Always 0 for MAAP */ + uint8_t message_type; /**< MAAP message type (MAAP_PROBE, MAAP_DEFEND, or MAAP_ANNOUNCE) */ + uint8_t maap_version; /**< MAAP Version. Currently 1 for MAAP. */ + uint16_t maap_data_length; /**< MAAP Data Length in Bytes. Always 16 for MAAP. */ + uint64_t stream_id; /**< MAAP stream_id. Always 0 for MAAP. */ + uint64_t requested_start_address; /**< Starting address for a MAAP_PROBE or MAAP_ANNOUNCE. + * For a MAAP_DEFEND, the same address as the MAAP_PROBE or MAAP_ANNOUNCE that initiated the defend. */ + uint16_t requested_count; /**< Number of addresses for a MAAP_PROBE or MAAP_ANNOUNCE. + * For a MAAP_DEFEND, the same number of addresses as the MAAP_PROBE or MAAP_ANNOUNCE that initiated the defend. */ + uint64_t conflict_start_address; /**< For a MAAP_DEFEND, the starting address of the block that conflicts with the MAAP_PROBE or MAAP_ANNOUNCE. */ + uint16_t conflict_count; /**< For a MAAP_DEFEND, the number of addresses in the block that conflicts with the MAAP_PROBE or MAAP_ANNOUNCE. */ } MAAP_Packet; +/** + * Initialize a #MAAP_Packet structure to prepare for sending a MAAP packet. + * + * @param packet Pointer to an empty #MAAP_Packet structure to fill + * @param dest_mac Destination MAC Address for the packet + * @param src_mac Source MAC Address for the packet + */ void init_packet(MAAP_Packet *packet, uint64_t dest_mac, uint64_t src_mac); + +/** + * Convert (pack) a #MAAP_Packet structure into a binary stream of bytes. + * + * @param packet #MAAP_Packet structure to convert + * @param stream Pointer to the buffer to fill with the binary stream + * + * @return 0 if successful, -1 if an error occurred. + */ int pack_maap(const MAAP_Packet *packet, uint8_t *stream); + +/** + * Convert (unpack) a binary stream of bytes into a #MAAP_Packet structure + * + * @param packet #MAAP_Packet structure to fill with the packet contents + * @param stream Pointer to the buffer containing the binary stream + * + * @return 0 if successful, -1 if an error occurred. + */ int unpack_maap(MAAP_Packet *packet, const uint8_t *stream); +/** + * Convert a byte-order MAC Address into a 64-bit number. + * + * The 64-bit number format is used to fill #MAAP_Packet#DA and #MAAP_Packet#SA in the #MAAP_Packet structure. + * + * @param macaddr Pointer to the byte-order MAC Address to convert + * + * @return A 64-bit number equivalent to the supplied MAC Address + */ uint64_t convert_mac_address(const uint8_t macaddr[]); #endif diff --git a/daemons/maap/test/test_maap_packet_packing.c b/daemons/maap/test/test_maap_packet_packing.c index 7d228cca..72978ff6 100644 --- a/daemons/maap/test/test_maap_packet_packing.c +++ b/daemons/maap/test/test_maap_packet_packing.c @@ -55,16 +55,16 @@ void dump_maap_packet(MAAP_Packet *packet) { printf("SV: %d\n", packet->SV); printf("version: %d\n", packet->version); printf("message_type: %d\n", packet->message_type); - printf("status: %d\n", packet->status); - printf("MAAP_data_length: %d\n", packet->MAAP_data_length); + printf("maap_version: %d\n", packet->maap_version); + printf("maap_data_length: %d\n", packet->maap_data_length); printf("stream_id: 0x%016llx\n", (unsigned long long int)packet->stream_id); printf("requested_start_address: 0x%012llx\n", (unsigned long long int)packet->requested_start_address); printf("requested_count: %d\n", packet->requested_count); - printf("start_address: 0x%012llx\n", - (unsigned long long int)packet->start_address); - printf("count: %d\n", packet->count); + printf("conflict_start_address: 0x%012llx\n", + (unsigned long long int)packet->conflict_start_address); + printf("conflict_count: %d\n", packet->conflict_count); } int cmp_maap_packets(MAAP_Packet *a, MAAP_Packet *b) { @@ -76,13 +76,13 @@ int cmp_maap_packets(MAAP_Packet *a, MAAP_Packet *b) { a->SV == b->SV && a->version == b->version && a->message_type == b->message_type && - a->status == b->status && - a->MAAP_data_length && b->MAAP_data_length && + a->maap_version == b->maap_version && + a->maap_data_length && b->maap_data_length && a->stream_id == b->stream_id && a->requested_start_address == b->requested_start_address && a->requested_count == b->requested_count && - a->start_address == b->start_address && - a->count == b->count); + a->conflict_start_address == b->conflict_start_address && + a->conflict_count == b->conflict_count); } int main(void) { -- cgit v1.2.1 From ce4d2f2aa6b497d481bb1143c10bac9f4b65bf3b Mon Sep 17 00:00:00 2001 From: Roland Hii Date: Wed, 12 Oct 2016 22:46:59 +0800 Subject: igb: replace nested if statements with conditional operators This will reduce the number of lines of code and also improve the code readability. Signed-off-by: Roland Hii --- kmod/igb/igb_ptp.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/kmod/igb/igb_ptp.c b/kmod/igb/igb_ptp.c index c1b0a44d..e36d8a37 100644 --- a/kmod/igb/igb_ptp.c +++ b/kmod/igb/igb_ptp.c @@ -563,17 +563,10 @@ static void igb_pin_perout(struct igb_adapter *igb, int chan, int pin, int freq) tssdp &= ~AUX1_TS_SDP_EN; tssdp &= ~ts_sdp_sel_clr[pin]; - if (freq) { - if (chan == 1) - tssdp |= ts_sdp_sel_fc1[pin]; - else - tssdp |= ts_sdp_sel_fc0[pin]; - } else { - if (chan == 1) - tssdp |= ts_sdp_sel_tt1[pin]; - else - tssdp |= ts_sdp_sel_tt0[pin]; - } + if (freq) + tssdp |= (chan == 1) ? ts_sdp_sel_fc1[pin] : ts_sdp_sel_fc0[pin]; + else + tssdp |= (chan == 1) ? ts_sdp_sel_tt1[pin] : ts_sdp_sel_tt0[pin]; tssdp |= ts_sdp_en[pin]; E1000_WRITE_REG(hw, E1000_TSSDP, tssdp); -- cgit v1.2.1 From 07efb506120717eb892d540aad7cc20affcd6677 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Wed, 12 Oct 2016 09:34:16 -0600 Subject: Removed legacy MAAP files --- daemons/maap/common/maap_protocol.c | 334 ----------------------------- daemons/maap/common/maap_protocol.h | 175 --------------- daemons/maap/linux/src/maap_linux_legacy.c | 279 ------------------------ 3 files changed, 788 deletions(-) delete mode 100644 daemons/maap/common/maap_protocol.c delete mode 100644 daemons/maap/common/maap_protocol.h delete mode 100644 daemons/maap/linux/src/maap_linux_legacy.c diff --git a/daemons/maap/common/maap_protocol.c b/daemons/maap/common/maap_protocol.c deleted file mode 100644 index 66df2c61..00000000 --- a/daemons/maap/common/maap_protocol.c +++ /dev/null @@ -1,334 +0,0 @@ -/************************************************************************* - Copyright (c) 2015 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ - All rights reserved. - - 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. - - 3. Neither the name of the Vayavya labs nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. - -****************************************************************************/ - -/* MAC Address Acquisition Protocol- dynamically allocate multicast MAC address */ -#include "maap_protocol.h" - -extern uint8_t *maap_shm_mem; - -/* generate pseudo random mac_address in the MAAP range */ -void generate_address(maap_info_t *maap_info) -{ - uint16_t val; - uint8_t maap_address_llimit[6] = {0x91,0xE0,0xF0,0x00,0x00,0x00}; - - memcpy(maap_info->requested_mac_add, maap_address_llimit, MAC_ADDR_LEN); - val = rand_range(0x0000, 0xFDFF); - maap_info->requested_mac_add[4] = (val & 0xff00) >> 8; - maap_info->requested_mac_add[5] = val & 0x00ff; -} - -int state_transit(maap_info_t *maap_info) -{ - state_t current_state = maap_info->state; - maap_pdu_t *maap_pdu = &maap_info->ethpkt.data; - ethpkt_t *pkt_tx = &maap_info->ethpkt; - ethpkt_t *pkt_rx = &maap_info->ethpkt_rx; - msg_type_t msg_type = 0; - uint8_t *s = NULL; - int i= 0; - int num_bytes = 0; - int maap_probe_count = 0; - - switch (current_state) { - case INITIAL: - DBG("state: INITIAL\n"); - generate_address(maap_info); - maap_probe_count = MAAP_PROBE_RETRANSMITS; - maap_info->state = PROBE; - break; - - case PROBE: - DBG("state: PROBE\n"); - prepare_ethpkt(maap_info, MAAP_PROBE); - - while (maap_probe_count) { - /* send MAAP_PROBE */ - send_packet(pkt_tx); - printf("\nSENT MAAP_PROBE \n"); - - delay(0, PROBE_TIMER_MS); - - memset(pkt_rx, 0x00, ETH_PKT_LEN); - /* Listen for MAAP_DEFEND */ - num_bytes = recv_packet(pkt_rx, NON_BLOCK); - if (num_bytes > 0) { - msg_type = pkt_rx->data.message_type; - DBG("msg_type 0x%x \n",msg_type); - - if (msg_type == MAAP_DEFEND || - msg_type == MAAP_ANNOUNCE || - msg_type == MAAP_PROBE) { - if (compare_mac(pkt_rx->data.requested_start_address, - maap_pdu->requested_start_address)) { - DBG("\nReceived\ - MAAP_DEFEND frame from \ - Mac Address: "); - DBG_ADDR(pkt_rx->header.h_source); - DBG("\nRequested\ - Address of recv frame: "); - DBG_ADDR(pkt_rx->data.requested_start_address); - DBG("\nRequested Address: "); - DBG_ADDR(maap_pdu->requested_start_address); - - maap_info->state = INITIAL; - return 1; - } - } else { - printf("\n Invalid MAAP packet\n"); - } - } else { - maap_probe_count -=1; - } - } - - maap_info->acquired_mac_count = - maap_info->requested_mac_count; - memcpy(maap_info->acquired_mac_add, - maap_info->requested_mac_add, MAC_ADDR_LEN); - - prepare_ethpkt(maap_info, MAAP_ANNOUNCE); - send_packet(pkt_tx); - - create_thread(maap_info, send_announce); - - printf("\nSENT MAAP_ANNOUNCE \n\nANNOUNCED ADDRESS:\n"); - DBG_ADDR(maap_info->acquired_mac_add); - - s = maap_shm_mem; - /* writing allocated mac-address to shared memory */ - for (i = 0; i < MAC_ADDR_LEN ; i++) { - *s++ = maap_info->acquired_mac_add[i]; - } - - maap_info->state = DEFEND; - printf("\n\nSTATE change to DEFEND:\n"); - break; - - case DEFEND: - memset(pkt_rx, 0x00, ETH_PKT_LEN); - /* Listen MAAP_PROBE */ - num_bytes = recv_packet(pkt_rx, BLOCK); - - if (num_bytes > 0) { - msg_type = pkt_rx->data.message_type; - if (compare_mac(pkt_rx->data.requested_start_address, - maap_info->acquired_mac_add)) { - if (msg_type == MAAP_PROBE) { - memcpy(maap_info->conflict_mac_add, - pkt_rx->data.requested_start_address, - MAC_ADDR_LEN); - maap_info->conflict_mac_count = - pkt_rx->data.requested_count; - - DBG("\n Received frame\ - MAAP_PROBE \n Source address of\ - the received frame:"); - DBG_ADDR(pkt_rx->header.h_source); - DBG("\n Requested start address\ - of received frame :"); - DBG_ADDR(pkt_rx->data.requested_start_address); - DBG("\n Announced Address :"); - DBG_ADDR(maap_info->acquired_mac_add); - - Lock(); - prepare_ethpkt(maap_info, - MAAP_DEFEND); - send_packet(pkt_tx); - UnLock(); - DBG(" SENT DEFEND \n"); - } else if (msg_type == MAAP_ANNOUNCE || - msg_type == MAAP_DEFEND) { - DBG("\n Received \ - msg_type-MAAP_ANNOUNCE \ - Source Address: "); - DBG_ADDR(pkt_rx->header.h_source); - DBG("\n Destination Address: "); - DBG_ADDR(pkt_rx->header.h_dest); - - destroy_thread(); - maap_info->state = INITIAL; - DBG("\nstate change to INITIAL"); - } - } - } - break; - - default: - printf("Error: Undefined State\n"); - break; - } - - return 0; -} - - -void Init(maap_info_t *maap_info, uint8_t src_mac_adr[6]) -{ - maap_pdu_t *maap_pkt = &maap_info->ethpkt.data; - uint8_t dest_mac[6]; - int i; - - DBG("Init\n"); - maap_info->state = INITIAL; - maap_pkt->subtype = MAAP_SUBTYPE; - maap_pkt->cd = 0x1; - maap_pkt->message_type = 0x0; - maap_pkt->version = 0x0; - maap_pkt->sv = 0x0; - maap_pkt->maap_version_data_length = hton_s(MAAP_VER_DATA_LEN); - maap_pkt->stream_id = 0x00; - AGN_ADR(maap_pkt->requested_start_address, 0x00); - AGN_ADR(maap_pkt->conflict_start_address, 0x00); - maap_pkt->requested_count = 0x00; - maap_pkt->conflict_count = 0x00; - - get_multicast_mac_adr(dest_mac); - memcpy(maap_info->src_mac, src_mac_adr, MAC_ADDR_LEN); - - memcpy(maap_info->ethpkt.header.h_dest, dest_mac, MAC_ADDR_LEN); - memcpy(maap_info->ethpkt.header.h_source, src_mac_adr, MAC_ADDR_LEN); - maap_info->ethpkt.header.eth_type = hton_s(ETH_TYPE); - - maap_info->requested_mac_count = hton_s(0x0001); -} - -void prepare_ethpkt(maap_info_t *maap_info, msg_type_t msg_type) -{ - ethpkt_t *pkt_tx = &maap_info->ethpkt; - ethpkt_t *pkt_rx = &maap_info->ethpkt_rx; - maap_pdu_t *maap_pkt = &maap_info->ethpkt.data; - uint8_t src_mac[6]; - uint8_t dest_mac[6]; - int i; - - maap_pkt->message_type = msg_type; - memcpy(src_mac, maap_info->src_mac, MAC_ADDR_LEN); - get_multicast_mac_adr(dest_mac); - - switch(msg_type) - { - case MAAP_PROBE: - memcpy(maap_pkt->requested_start_address, - maap_info->requested_mac_add, MAC_ADDR_LEN); - AGN_ADR(maap_pkt->conflict_start_address, 0x00); - maap_pkt->requested_count = - maap_info->requested_mac_count; - maap_pkt->conflict_count = 0x00; - memcpy(pkt_tx->header.h_dest, dest_mac, MAC_ADDR_LEN); - memcpy(pkt_tx->header.h_source, src_mac, MAC_ADDR_LEN); - break; - - case MAAP_DEFEND: - memcpy(maap_pkt->requested_start_address, - maap_info->requested_mac_add, MAC_ADDR_LEN); - memcpy(maap_pkt->conflict_start_address, - maap_info->conflict_mac_add, MAC_ADDR_LEN); - maap_pkt->requested_count = - maap_info->requested_mac_count; - maap_pkt->conflict_count = - maap_info->conflict_mac_count; - /* - * DEST_MAC set to source mac address received in - * MAAP_PROBE - */ - memcpy(pkt_tx->header.h_dest, pkt_rx->header.h_source, - MAC_ADDR_LEN); - memcpy(pkt_tx->header.h_source, src_mac, MAC_ADDR_LEN); - break; - - case MAAP_ANNOUNCE: - memcpy(maap_pkt->requested_start_address, - maap_info->acquired_mac_add, MAC_ADDR_LEN); - AGN_ADR(maap_pkt->conflict_start_address, 0x00); - maap_pkt->requested_count = - maap_info->acquired_mac_count; - maap_pkt->conflict_count = 0x00; - memcpy(pkt_tx->header.h_dest, dest_mac, MAC_ADDR_LEN); - memcpy(pkt_tx->header.h_source, src_mac, MAC_ADDR_LEN); - break; - - default: - printf("Error: Message type not set\n"); - break; - } -} - -/* - * compare MAC address from received MAAP PDU and receiving station MAC address - * return TRUE if they are same(different from what given in the protocol which is - * to return TRUE if MAC address of receiving station is lower than received MAAP PDU) - */ -int compare_mac(uint8_t rcv_add[6], uint8_t req_addr[6]) -{ - int i, flag = 0; - - for (i=0; i<6; i++) { - if (rcv_add[i] == req_addr[i]) - { - flag = 1; - } else { - flag = 0; - break; - } - } - return flag; -} - -void *send_announce(void *maap_Info) -{ - maap_info_t *maap_info; - maap_info = (maap_info_t *)maap_Info; - - ethpkt_t *pkt_tx = &maap_info->ethpkt; - - while(1) - { - delay(ANNOUNCE_TIMER_S, 0); - Lock(); - prepare_ethpkt(maap_info, MAAP_ANNOUNCE); - send_packet(pkt_tx); - UnLock(); - printf("\nSENT MAAP_ANNOUNCE"); - } -} - -/* Multicast MAAP MAC address */ -void get_multicast_mac_adr(uint8_t *dest_mac) -{ - dest_mac[0] = 0x91; - dest_mac[1] = 0xE0; - dest_mac[2] = 0xF0; - dest_mac[3] = 0x00; - dest_mac[4] = 0xFF; - dest_mac[5] = 0x00; -} diff --git a/daemons/maap/common/maap_protocol.h b/daemons/maap/common/maap_protocol.h deleted file mode 100644 index c75f6646..00000000 --- a/daemons/maap/common/maap_protocol.h +++ /dev/null @@ -1,175 +0,0 @@ -/************************************************************************* - Copyright (c) 2015 VAYAVYA LABS PVT LTD - http://vayavyalabs.com/ - All rights reserved. - - 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. - - 3. Neither the name of the Vayavya labs nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. - -****************************************************************************/ - -#ifndef __MAAP__PROTOCOL__ - -#define __MAAP__PROTOCOL__ - -#include -#include -#include -#include - -#define MAAP_PROBE_RETRANSMITS 3 -#define MAAP_PROBE_INTERVAL_BASE_MS 500 -#define MAAP_PROBE_INTERVAL_VARIATION_MS 100 -#define MAAP_ANNOUNCE_INTERVAL_BASE_S 30 -#define MAAP_ANNOUNCE_INTERVAL_VARIATION_S 2 - -#define PROBE_TIMER_MS rand_frange(MAAP_PROBE_INTERVAL_BASE_MS,\ - MAAP_PROBE_INTERVAL_BASE_MS + MAAP_PROBE_INTERVAL_VARIATION_MS) -#define ANNOUNCE_TIMER_S rand_frange(MAAP_ANNOUNCE_INTERVAL_BASE_S,\ - MAAP_ANNOUNCE_INTERVAL_BASE_S + MAAP_ANNOUNCE_INTERVAL_VARIATION_S) - -#define MAAP_SUBTYPE 0x7E -#define MAAP_VER_DATA_LEN (((0x01 & 0x1F) << 11) | (0x010 & 0x7FF)) -#define ETH_TYPE 0x22F0 -#define ETH_PKT_LEN sizeof(ethpkt_t) -#define MAC_ADDR_LEN 6 -#define BLOCK 0 -#define NON_BLOCK 1 - -#define AGN_ADR(ADDR, val) for(i=0; i -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "maap_protocol.h" - -uint8_t *maap_shm_mem; -struct sockaddr_ll saddrll; -pthread_t thread; -pthread_mutex_t lock; -int socketfd; - -#define VERSION_STR "0.0" - -static const char *version_str = - "maap_daemon v" VERSION_STR "\n" "Copyright (c) 2014, VAYAVYA LABS PVT LTD\n"; - -void usage(void) -{ - fprintf(stderr, - "\n" - "usage: maap_daemon [-d] -i interface-name" - "\n" - "options:\n" - " -d run daemon in the background\n" - " -i specify interface to monitor\n" - "\n" "%s" "\n", version_str); - exit(1); -} - -int main(int argc, char *argv[]) -{ - char *iface = NULL; - struct ifreq buffer; - int ifindex; - struct packet_mreq mreq; - maap_info_t *maap_Info; - uint32_t seed; - uint8_t dest_mac[6]; - uint8_t src_mac[6]; - int daemonize = 0; - int shmid; - key_t key; - int ret; - int c; - - for (;;) { - c = getopt(argc, argv, "hdi:"); - - if (c < 0) - break; - - switch (c) { - case 'd': - daemonize = 1; - break; - case 'i': - if (iface) { - printf - ("only one interface per daemon is supported\n"); - usage(); - } - iface = strdup(optarg); - break; - case 'h': - default: - usage(); - break; - } - } - if (optind < argc) - usage(); - - if (iface == NULL) - usage(); - - if (daemonize) { - ret = daemon(1, 0); - if (ret) { - printf("Error: Failed to daemonize\n"); - return -1; - } - } - - if ((socketfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_TYPE))) < 0 ) - { - printf("Error: could not open socket %d\n",socketfd); - return -1; - } - - memset(&buffer, 0x00, sizeof(buffer)); - strncpy(buffer.ifr_name, (char *)iface, IFNAMSIZ); - if (ioctl(socketfd, SIOCGIFINDEX, &buffer) < 0) - { - printf("Error: could not get interface index\n"); - close(socketfd); - return -1; - } - - key = 1234; - if ((shmid = shmget(key, MAC_ADDR_LEN, IPC_CREAT | 0666)) < 0) { - printf("Error : Failed to allocate the Shared Memory\n"); - close(socketfd); - return -1; - } - - if ((maap_shm_mem = shmat(shmid, NULL, 0)) == (uint8_t *) -1) { - printf("Error : Failed to attach the created segment id by function \ - shmget()"); - close(socketfd); - return -1; - } - - ifindex = buffer.ifr_ifindex; - if (ioctl(socketfd, SIOCGIFHWADDR, &buffer) < 0) { - printf("Error: could not get interface address\n"); - close(socketfd); - return -1; - } - memcpy(src_mac, buffer.ifr_hwaddr.sa_data, MAC_ADDR_LEN); - - get_multicast_mac_adr(dest_mac); - - memset((void*)&saddrll, 0, sizeof(saddrll)); - saddrll.sll_family = AF_PACKET; - saddrll.sll_ifindex = ifindex; - saddrll.sll_halen = MAC_ADDR_LEN; - memcpy((void*)(saddrll.sll_addr), (void*)dest_mac, MAC_ADDR_LEN); - - if (bind(socketfd, (struct sockaddr*)&saddrll, sizeof(saddrll))) { - printf("Error: could not bind datagram socket\n"); - return -1; - } - - /* filter multicast address */ - memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifindex; - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = 6; - memcpy(mreq.mr_address, dest_mac, mreq.mr_alen); - - if (setsockopt(socketfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, - sizeof(mreq)) < 0) { - printf("setsockopt PACKET_ADD_MEMBERSHIP failed\n"); - return -1; - } - - pthread_mutex_init(&(lock), NULL); - seed = src_mac[5] + time(NULL); - srand(seed); - - maap_Info = (maap_info_t *)calloc(1,sizeof(maap_info_t)); - - /* Initialize packet header and data */ - Init(maap_Info, src_mac); - - while (1) { - state_transit(maap_Info); - } - - close(socketfd); - - free(maap_Info); - - return 0; -} - -void delay(int seconds, int millisecond) -{ - sleep(seconds); - usleep(millisecond * 1000); -} - -void create_thread(maap_info_t *maap_info, void *announce) -{ - pthread_create(&thread, NULL, announce, (void *)(maap_info)); -} - -void destroy_thread() -{ - pthread_cancel(thread); -} - -double rand_frange(double min_n, double max_n) -{ - return (double)rand()/RAND_MAX * (max_n - min_n) + min_n; -} - -int rand_range(int min_n, int max_n) -{ - return rand() % (max_n - min_n + 1) + min_n; -} - -void send_packet(ethpkt_t *pkt_tx) -{ - int result; - if ((result = (sendto(socketfd, pkt_tx, ETH_PKT_LEN, 0, - (struct sockaddr*)&saddrll, sizeof(saddrll)) > 0))) - DBG("send successful %d\n", result); - else - DBG("Error: sending of packet failed\n"); -} - -int recv_packet(ethpkt_t *pkt_rx, int flag) -{ - int result; - socklen_t fmlen = sizeof(saddrll); - - if (flag == NON_BLOCK) - flag = MSG_DONTWAIT; - - result = recvfrom(socketfd, pkt_rx, ETH_PKT_LEN, flag, - (struct sockaddr*)&saddrll, &fmlen); - return result; -} - -void Lock() -{ - pthread_mutex_lock(&lock); -} - -void UnLock() -{ - pthread_mutex_unlock(&lock); -} - -uint16_t hton_s(uint16_t val) -{ - return htons(val); -} -- cgit v1.2.1 From e0dc97aae93cd632526df990130df356604c99a6 Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Wed, 12 Oct 2016 09:47:49 -0600 Subject: Simlified interval support Removed the unnecessary "max" member from the class, simplifying the code. Added Doxygen comments for the interval_node structure. Added some additional testing to make sure searching isn't broken. --- daemons/maap/common/intervals.c | 32 +++------------------- daemons/maap/common/intervals.h | 32 ++++++++++++---------- daemons/maap/test/test_intervals.c | 55 ++++++++++++++++++++++++++++++-------- 3 files changed, 66 insertions(+), 53 deletions(-) diff --git a/daemons/maap/common/intervals.c b/daemons/maap/common/intervals.c index 5be06a1b..549e81ec 100644 --- a/daemons/maap/common/intervals.c +++ b/daemons/maap/common/intervals.c @@ -10,7 +10,7 @@ Interval *alloc_interval(uint32_t start, uint32_t count) { i = calloc(1, sizeof (Interval)); if (i) { i->low = start; - i->high = i->max = start + count - 1; + i->high = start + count - 1; } return i; } @@ -49,18 +49,12 @@ int insert_interval(Interval **root, Interval *node) { } } } - current = node; - while (current->parent) { - if (current->max > current->parent->max) { - current->parent->max = current->max; - } - current = current->parent; - } + return INTERVAL_SUCCESS; } Interval *remove_interval(Interval **root, Interval *node) { - Interval *snip, *child, *current; + Interval *snip, *child; /* If the node to remove does not have two children, we will snip it, otherwise we will swap it with its successor and snip that one */ @@ -98,27 +92,9 @@ Interval *remove_interval(Interval **root, Interval *node) { if (snip != node) { node->low = snip->low; node->high = snip->high; - node->max = snip->max; node->data = snip->data; } - /* If the snipped node was not the root, propagate the max value back up the - tree */ - if (snip->parent) { - current = snip->parent; - if (current->left_child && current->left_child->max > current->max) { - current->max = current->left_child->max; - } - if (current->right_child && current->right_child->max > current->max) { - current->max = current->right_child->max; - } - while (current->parent) { - if (current->max > current->parent->max) { - current->parent->max = current->max; - } - current = current->parent; - } - } return snip; } @@ -187,7 +163,7 @@ Interval *search_interval(Interval *root, uint32_t start, uint32_t count) { current = root; while (current && !check_overlap(current, &i)) { - if (current->left_child && current->left_child->max >= i.low) { + if (current->low > i.low) { current = current->left_child; } else { current = current->right_child; diff --git a/daemons/maap/common/intervals.h b/daemons/maap/common/intervals.h index c8aa1fee..a2e85319 100644 --- a/daemons/maap/common/intervals.h +++ b/daemons/maap/common/intervals.h @@ -1,10 +1,7 @@ -#ifndef INTERVALS_H -#define INTERVALS_H - -#include - /** - * Augmented Binary Search Tree for Intervals + * @file + * + * @brief Augmented Binary Search Tree for Intervals * * This library will keep track of non-overlapping intervals in the uint32 range * @@ -19,6 +16,11 @@ * which will update the pointer if the root node of the tree changes. */ +#ifndef INTERVALS_H +#define INTERVALS_H + +#include + /* Return values for insert_interval */ /** @@ -41,14 +43,16 @@ typedef struct interval_node Interval; */ typedef void (*Visitor)(Interval *); +/** + * Structure for each node of the interval tree + */ struct interval_node { - uint32_t low; - uint32_t high; - uint32_t max; - void *data; - Interval *parent; - Interval *left_child; - Interval *right_child; + uint32_t low; /**< Low value of this interval */ + uint32_t high; /**< High value of this interval */ + void *data; /**< Pointer to the data associated with this interval */ + Interval *parent; /**< Pointer to the parent of the current tree, or NULL if this is the root node */ + Interval *left_child; /**< Pointer to a subtree with smaller intervals, or NULL if none */ + Interval *right_child; /**< Pointer to a subtree with larger intervals, or NULL if none */ }; /** @@ -87,7 +91,7 @@ int insert_interval(Interval **root, Interval *node); /** * Remove an Interval from the set of tracked Intervals. * - * @WARNING: Because the actual node removed from the tree might not be the same + * @note Because the actual node removed from the tree might not be the same * as the one passed in, the return value MUST be stored and used to free the * Interval that was removed from the set. * diff --git a/daemons/maap/test/test_intervals.c b/daemons/maap/test/test_intervals.c index f0bbdacf..2fef0f8c 100644 --- a/daemons/maap/test/test_intervals.c +++ b/daemons/maap/test/test_intervals.c @@ -3,6 +3,9 @@ #include #include "intervals.h" +#define INTERVALS_TO_ADD 1000 +#define INTERVALS_TO_REPLACE 100000 + int last_high = 0; int total = 0; @@ -17,7 +20,7 @@ void print_node(Interval *node) { } int main(void) { - Interval *set = NULL, *inter, *over; + Interval *set = NULL, *inter, *over, *prev; int i, rv, count; time((time_t *)&i); @@ -44,7 +47,7 @@ int main(void) { free_interval(inter); } - count = 1000; + count = INTERVALS_TO_ADD; printf("\nInserting %d random intervals into a set\n", count); for (i = 0; i < count;) { @@ -53,7 +56,7 @@ int main(void) { if (rv == INTERVAL_OVERLAP) { over = search_interval(set, inter->low, inter->high - inter->low + 1); printf("[%d,%d] overlapped existing entry [%d,%d]\n", - inter->low, inter->high, over->low, over->high); + inter->low, inter->high, over->low, over->high); free_interval(inter); } else { printf("Inserted [%d,%d]:\n", inter->low, inter->high); @@ -61,7 +64,7 @@ int main(void) { } } - count = 100000; + count = INTERVALS_TO_REPLACE; printf("\nReplacing %d random intervals\n", count); for (i = 0, over = NULL; i < count;) { @@ -69,14 +72,14 @@ int main(void) { inter = alloc_interval(random() % 0xfffff, random() % 128 + 1); rv = insert_interval(&set, inter); if (rv == INTERVAL_SUCCESS) { - printf("Replaced [%d,%d] with [%d,%d]\n", - over->low, over->high, inter->low, inter->high); - free_interval(over); - over = NULL; - i++; + printf("Replaced [%d,%d] with [%d,%d]\n", + over->low, over->high, inter->low, inter->high); + free_interval(over); + over = NULL; + i++; } else { - printf("Overlapping replacement interval\n"); - free_interval(inter); + printf("Overlapping replacement interval\n"); + free_interval(inter); } } else { over = search_interval(set, random() % 0xfffff, random() % 128 + 1); @@ -84,6 +87,36 @@ int main(void) { } } + /* Test next_interval and search_interval */ + i = 0; + count = INTERVALS_TO_ADD; + inter = minimum_interval(set); + prev = NULL; + while (inter) { + i++; + if (prev && prev->high >= inter->low) { printf("Overlapping or out-of-order interval detected\n"); } + if (search_interval(set, inter->low, 1) != inter) { printf("Search for interval [%d,%d] failed\n", inter->low, inter->high); } + prev = inter; + inter = next_interval(inter); + } + if (i != count) { printf("Error: Found %d intervals during next_interval interation\n", i); } + if (prev != maximum_interval(set)) { printf("Error: next_interval iteration didn't end at maximum_interval\n"); } + + /* Test previous_interval and search_interval */ + i = 0; + count = INTERVALS_TO_ADD; + inter = maximum_interval(set); + prev = NULL; + while (inter) { + i++; + if (prev && prev->low <= inter->high) { printf("Overlapping or out-of-order interval detected\n"); } + if (search_interval(set, inter->high, 1) != inter) { printf("Search for interval [%d,%d] failed\n", inter->low, inter->high); } + prev = inter; + inter = prev_interval(inter); + } + if (i != count) { printf("Error: Found %d intervals during next_interval interation\n", i); } + if (prev != minimum_interval(set)) { printf("Error: prev_interval iteration didn't end at minimum_interval\n"); } + inter = minimum_interval(set); printf("\nMinimum Interval: [%d,%d]\n", inter->low, inter->high); inter = maximum_interval(set); -- cgit v1.2.1 From 76f9ca0d43ed7e5a69543472bf3ec10f85ccd98b Mon Sep 17 00:00:00 2001 From: Brant Thomsen Date: Wed, 12 Oct 2016 15:08:06 -0600 Subject: Doxygen supporting files --- daemons/maap/doc/CMakeLists.txt | 24 + daemons/maap/doc/Doxyfile.in | 2430 +++++++++++++++++++++++++++++++++++++++ daemons/maap/doc/mainpage.dox | 24 + 3 files changed, 2478 insertions(+) create mode 100644 daemons/maap/doc/CMakeLists.txt create mode 100644 daemons/maap/doc/Doxyfile.in create mode 100644 daemons/maap/doc/mainpage.dox diff --git a/daemons/maap/doc/CMakeLists.txt b/daemons/maap/doc/CMakeLists.txt new file mode 100644 index 00000000..c6fc3dcc --- /dev/null +++ b/daemons/maap/doc/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.8) + +# add a target to generate API documentation with Doxygen +find_package(Doxygen) +option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" ${DOXYGEN_FOUND}) + +if(BUILD_DOCUMENTATION) + if(NOT DOXYGEN_FOUND) + message(FATAL_ERROR "Doxygen is needed to build the documentation.") + endif() + + set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) + set(doxyfile ${CMAKE_CURRENT_SOURCE_DIR}/build/Doxyfile) + + configure_file(${doxyfile_in} ${doxyfile} @ONLY) + + add_custom_target(doc + COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM) + + #install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html DESTINATION share/doc) +endif() diff --git a/daemons/maap/doc/Doxyfile.in b/daemons/maap/doc/Doxyfile.in new file mode 100644 index 00000000..2a917719 --- /dev/null +++ b/daemons/maap/doc/Doxyfile.in @@ -0,0 +1,2430 @@ +# Doxyfile 1.8.11 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "MAAP Documentation" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../doc/build + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = YES + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ../common \ + ../linux/src \ + ../doc/mainpage.dox + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, +# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. + +FILE_PATTERNS = *.h \ + *.hpp + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /