summaryrefslogtreecommitdiff
path: root/lib/avtp_pipeline/platform/Linux/rawsock/atl_rawsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/avtp_pipeline/platform/Linux/rawsock/atl_rawsock.c')
-rw-r--r--lib/avtp_pipeline/platform/Linux/rawsock/atl_rawsock.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/lib/avtp_pipeline/platform/Linux/rawsock/atl_rawsock.c b/lib/avtp_pipeline/platform/Linux/rawsock/atl_rawsock.c
new file mode 100644
index 00000000..9424ea96
--- /dev/null
+++ b/lib/avtp_pipeline/platform/Linux/rawsock/atl_rawsock.c
@@ -0,0 +1,271 @@
+/*************************************************************************************************************
+Copyright (c) 2019, Aquantia 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.
+
+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 "atl_rawsock.h"
+#include "pcap_rawsock.h"
+#include "simple_rawsock.h"
+#include "avb.h"
+#include "openavb_atl.h"
+#include "avb_sched.h"
+
+#include "openavb_trace.h"
+
+#define AVB_LOG_COMPONENT "Raw Socket"
+#include "openavb_log.h"
+
+// needed for gptplocaltime()
+extern gPtpTimeData gPtpTD;
+
+void *atlRawsockOpen(atl_rawsock_t* rawsock, const char *ifname, bool rx_mode, bool tx_mode, U16 ethertype, U32 frame_size, U32 num_frames)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK);
+
+ if (!pcapRawsockOpen((pcap_rawsock_t*)rawsock, ifname, rx_mode,
+ tx_mode, ethertype, frame_size, num_frames))
+ {
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
+ return NULL;
+ }
+
+ if (tx_mode) {
+ // Deal with frame size.
+ if (frame_size == 0) {
+ // use interface MTU as max frames size, if none specified
+ rawsock->base.frameSize = ATL_MTU;
+ }
+ else if (frame_size > ATL_MTU) {
+ AVB_LOGF_ERROR("Creating rawsock; requested frame size exceeds %d", ATL_MTU);
+ atlRawsockClose(rawsock);
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
+ return NULL;
+ } else {
+ rawsock->base.frameSize = frame_size;
+ }
+
+ // ATL setup
+ rawsock->atl_dev = atlAcquireDevice(ifname);
+
+ // select class B queue by default
+ rawsock->queue = 1;
+ }
+
+ // fill virtual functions table
+ rawsock_cb_t *cb = &rawsock->base.cb;
+ cb->close = atlRawsockClose;
+ cb->getTxFrame = atlRawsockGetTxFrame;
+ cb->relTxFrame = atlRawsockRelTxFrame;
+ cb->txSetMark = atlRawsockTxSetMark;
+ cb->txFrameReady = atlRawsockTxFrameReady;
+ cb->send = atlRawsockSend;
+ cb->txBufLevel = atlRawsockTxBufLevel;
+ cb->getTXOutOfBuffers = atlRawsockGetTXOutOfBuffers;
+ cb->getTXOutOfBuffersCyclic = atlRawsockGetTXOutOfBuffersCyclic;
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
+ return rawsock;
+}
+
+void atlRawsockClose(void *pvRawsock)
+{
+ atl_rawsock_t *rawsock = (atl_rawsock_t*)pvRawsock;
+ if (rawsock->atl_dev) {
+ atlReleaseDevice(rawsock->atl_dev);
+ }
+
+ pcapRawsockClose((pcap_rawsock_t*)rawsock);
+}
+
+bool atlRawsockTxSetMark(void *pvRawsock, int mark)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
+
+ atl_rawsock_t *rawsock = (atl_rawsock_t*)pvRawsock;
+ if (!VALID_TX_RAWSOCK(rawsock)) {
+ AVB_LOG_ERROR("Setting TX mark; invalid argument passed");
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return FALSE;
+ }
+
+ int fwmarkClass = TC_AVB_MARK_CLASS(mark);
+
+ if (fwmarkClass == SR_CLASS_A) {
+ rawsock->queue = 0;
+ } else if (fwmarkClass == SR_CLASS_B) {
+ rawsock->queue = 1;
+ } else {
+ AVB_LOGF_ERROR("fwmarkClass %d is not proper SR_CLASS", fwmarkClass);
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return FALSE;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return TRUE;
+}
+
+// Get a buffer from the ring to use for TX
+U8 *atlRawsockGetTxFrame(void *pvRawsock, bool blocking, unsigned int *len)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
+
+ atl_rawsock_t *rawsock = (atl_rawsock_t*)pvRawsock;
+
+ if (!VALID_TX_RAWSOCK(rawsock) || len == NULL) {
+ AVB_LOG_ERROR("Getting TX frame; bad arguments");
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return NULL;
+ }
+
+ U8 *ret = NULL;
+ int bBufferBusyReported = 0;
+ U32 iterationCount = 10;
+
+ do {
+ rawsock->tx_packet = atlGetTxPacket(rawsock->atl_dev);
+ if (!rawsock->tx_packet && blocking) {
+ if (0 == bBufferBusyReported) {
+ if (!rawsock->txOutOfBuffer) {
+ AVB_LOGF_DEBUG("Getting TX frame (%p): TX buffer busy", rawsock);
+ }
+ ++rawsock->txOutOfBuffer;
+ ++rawsock->txOutOfBufferCyclic;
+ } else if (1 == bBufferBusyReported) {
+ AVB_LOGF_DEBUG("Getting TX frame (%p): TX buffer busy after usleep(10) verify if there are any late frames", rawsock);
+ }
+ ++bBufferBusyReported;
+ usleep(10);
+ }
+ } while (!rawsock->tx_packet && blocking && iterationCount--);
+
+ if (rawsock->tx_packet) {
+ *len = rawsock->base.frameSize;
+ ret = rawsock->tx_packet->vaddr;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return ret;
+}
+
+// Release a TX frame, without marking it as ready to send
+bool atlRawsockRelTxFrame(void *pvRawsock, U8 *pBuffer)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
+ atl_rawsock_t *rawsock = (atl_rawsock_t*)pvRawsock;
+ if (!VALID_TX_RAWSOCK(rawsock) || pBuffer == NULL) {
+ AVB_LOG_ERROR("Releasing TX frame; invalid argument");
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return FALSE;
+ }
+
+ atlRelTxPacket(rawsock->atl_dev, rawsock->queue, rawsock->tx_packet);
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return TRUE;
+}
+
+// Release a TX frame, and mark it as ready to send
+bool atlRawsockTxFrameReady(void *pvRawsock, U8 *pBuffer, unsigned int len, U64 timeNsec)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
+ atl_rawsock_t *rawsock = (atl_rawsock_t*)pvRawsock;
+
+ if (!VALID_TX_RAWSOCK(rawsock)) {
+ AVB_LOG_ERROR("Send; invalid argument");
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return -1;
+ }
+
+ int err;
+
+ rawsock->tx_packet->len = len;
+
+#if ATL_LAUNCHTIME_ENABLED
+ gptpmaster2local(&gPtpTD, timeNsec, &rawsock->tx_packet->attime);
+#else
+ rawsock->tx_packet->attime = 0;
+#endif
+ err = atl_xmit(rawsock->atl_dev, rawsock->queue, &rawsock->tx_packet);
+ if (err) {
+ AVB_LOGF_ERROR("atl_xmit failed: %s", strerror(err));
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return !err;
+}
+// Send all packets that are ready (i.e. tell kernel to send them)
+int atlRawsockSend(void *pvRawsock)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
+
+ // atlRawsock sends frames in atlRawsockTxFrameReady
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return 1;
+}
+
+int atlRawsockTxBufLevel(void *pvRawsock)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
+ atl_rawsock_t *rawsock = (atl_rawsock_t*)pvRawsock;
+
+ int nInUse = atlTxBufLevel(rawsock->atl_dev);
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
+ return nInUse;
+}
+
+unsigned long atlRawsockGetTXOutOfBuffers(void *pvRawsock)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK);
+ unsigned long counter = 0;
+ atl_rawsock_t *rawsock = (atl_rawsock_t*)pvRawsock;
+
+ if(VALID_TX_RAWSOCK(rawsock)) {
+ counter = rawsock->txOutOfBuffer;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
+ return counter;
+}
+
+unsigned long atlRawsockGetTXOutOfBuffersCyclic(void *pvRawsock)
+{
+ AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK);
+ unsigned long counter = 0;
+ atl_rawsock_t *rawsock = (atl_rawsock_t*)pvRawsock;
+
+ if(VALID_TX_RAWSOCK(rawsock)) {
+ counter = rawsock->txOutOfBufferCyclic;
+ rawsock->txOutOfBufferCyclic = 0;
+ }
+
+ AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
+ return counter;
+}
+