2008-09-01 15:59:54 +02:00
|
|
|
/****************************************************************************
|
2014-06-29 02:07:02 +02:00
|
|
|
* net/devif/devif_callback.c
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
2024-09-11 14:39:39 +02:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*
|
2020-04-11 22:23:39 +02:00
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright ownership. The
|
|
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
|
|
* "License"); you may not use this file except in compliance with the
|
|
|
|
* License. You may obtain a copy of the License at
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
2020-04-11 22:23:39 +02:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
2020-04-11 22:23:39 +02:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#if defined(CONFIG_NET)
|
|
|
|
|
2009-12-15 15:53:45 +01:00
|
|
|
#include <stdint.h>
|
2017-07-08 17:56:08 +02:00
|
|
|
#include <stdbool.h>
|
2008-09-01 15:59:54 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <debug.h>
|
2014-07-22 02:46:47 +02:00
|
|
|
#include <assert.h>
|
2008-09-01 15:59:54 +02:00
|
|
|
|
2022-01-01 15:05:07 +01:00
|
|
|
#include <nuttx/kmalloc.h>
|
2014-06-24 16:53:28 +02:00
|
|
|
#include <nuttx/net/netconfig.h>
|
2014-07-05 00:38:51 +02:00
|
|
|
#include <nuttx/net/net.h>
|
2014-06-24 17:28:44 +02:00
|
|
|
#include <nuttx/net/netdev.h>
|
2008-09-01 15:59:54 +02:00
|
|
|
|
2015-05-29 19:01:03 +02:00
|
|
|
#include "netdev/netdev.h"
|
2014-06-29 02:07:02 +02:00
|
|
|
#include "devif/devif.h"
|
2008-09-01 15:59:54 +02:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-02-13 17:30:21 +01:00
|
|
|
#if CONFIG_NET_PREALLOC_DEVIF_CALLBACKS > 0
|
|
|
|
static struct devif_callback_s
|
|
|
|
g_cbprealloc[CONFIG_NET_PREALLOC_DEVIF_CALLBACKS];
|
2022-01-01 15:05:07 +01:00
|
|
|
#endif
|
2014-06-29 20:59:34 +02:00
|
|
|
static FAR struct devif_callback_s *g_cbfreelist = NULL;
|
2008-09-01 15:59:54 +02:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: devif_callback_free
|
2015-06-03 16:11:57 +02:00
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Return a callback container to the free list.
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
* This function is called with the network locked.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void devif_callback_free(FAR struct net_driver_s *dev,
|
|
|
|
FAR struct devif_callback_s *cb,
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
FAR struct devif_callback_s **list_head,
|
|
|
|
FAR struct devif_callback_s **list_tail)
|
2015-06-03 16:11:57 +02:00
|
|
|
{
|
|
|
|
FAR struct devif_callback_s *prev;
|
|
|
|
FAR struct devif_callback_s *curr;
|
|
|
|
|
|
|
|
if (cb)
|
|
|
|
{
|
2016-12-03 23:28:19 +01:00
|
|
|
net_lock();
|
2015-06-03 16:11:57 +02:00
|
|
|
|
2016-06-11 22:14:08 +02:00
|
|
|
#ifdef CONFIG_DEBUG_FEATURES
|
2015-06-03 16:11:57 +02:00
|
|
|
/* Check for double freed callbacks */
|
|
|
|
|
|
|
|
curr = g_cbfreelist;
|
|
|
|
|
|
|
|
while (curr != NULL)
|
|
|
|
{
|
|
|
|
DEBUGASSERT(cb != curr);
|
|
|
|
curr = curr->nxtconn;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Remove the callback structure from the device notification list if
|
|
|
|
* it is supposed to be in the device notification list.
|
|
|
|
*/
|
|
|
|
|
2017-10-19 19:55:51 +02:00
|
|
|
if (dev != NULL)
|
2015-06-03 16:11:57 +02:00
|
|
|
{
|
|
|
|
/* Find the callback structure in the device event list */
|
|
|
|
|
|
|
|
for (prev = NULL, curr = dev->d_devcb;
|
2017-10-19 19:55:51 +02:00
|
|
|
curr != NULL && curr != cb;
|
2020-04-11 22:23:39 +02:00
|
|
|
prev = curr, curr = curr->nxtdev)
|
|
|
|
{
|
|
|
|
}
|
2015-06-03 16:11:57 +02:00
|
|
|
|
|
|
|
/* Remove the structure from the device event list */
|
|
|
|
|
2017-10-19 19:55:51 +02:00
|
|
|
if (curr != NULL)
|
2015-06-03 16:11:57 +02:00
|
|
|
{
|
|
|
|
if (prev)
|
|
|
|
{
|
|
|
|
prev->nxtdev = cb->nxtdev;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dev->d_devcb = cb->nxtdev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove the callback structure from the data notification list if
|
|
|
|
* it is supposed to be in the data notification list.
|
|
|
|
*/
|
|
|
|
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
if (list_head)
|
2015-06-03 16:11:57 +02:00
|
|
|
{
|
2021-09-21 05:43:31 +02:00
|
|
|
prev = cb->prevconn;
|
2015-06-03 16:11:57 +02:00
|
|
|
|
|
|
|
/* Remove the structure from the connection event list */
|
|
|
|
|
2021-09-21 05:43:31 +02:00
|
|
|
if (prev)
|
2015-06-03 16:11:57 +02:00
|
|
|
{
|
2021-09-21 05:43:31 +02:00
|
|
|
/* The item to be removed is not in the head. */
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
|
2021-09-21 05:43:31 +02:00
|
|
|
prev->nxtconn = cb->nxtconn;
|
|
|
|
|
|
|
|
if (cb->nxtconn)
|
2015-06-03 16:11:57 +02:00
|
|
|
{
|
2021-09-21 05:43:31 +02:00
|
|
|
/* The item to be removed is not in the tail. */
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
|
2021-09-21 05:43:31 +02:00
|
|
|
cb->nxtconn->prevconn = prev;
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
}
|
2021-09-21 05:43:31 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The item to be removed is in the head. */
|
|
|
|
|
|
|
|
*list_head = cb->nxtconn;
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
|
2021-09-21 05:43:31 +02:00
|
|
|
if (cb->nxtconn)
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
{
|
2021-09-21 05:43:31 +02:00
|
|
|
/* There are more items besides the head item. */
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
|
2021-09-21 05:43:31 +02:00
|
|
|
cb->nxtconn->prevconn = NULL;
|
2015-06-03 16:11:57 +02:00
|
|
|
}
|
|
|
|
}
|
2021-09-21 05:43:31 +02:00
|
|
|
|
|
|
|
if (!cb->nxtconn)
|
|
|
|
{
|
|
|
|
/* If the tail item is being removed,
|
|
|
|
* update the tail pointer.
|
|
|
|
*/
|
|
|
|
|
|
|
|
DEBUGASSERT(list_tail);
|
|
|
|
*list_tail = prev;
|
|
|
|
}
|
2015-06-03 16:11:57 +02:00
|
|
|
}
|
|
|
|
|
2023-02-13 17:30:21 +01:00
|
|
|
/* If this is a preallocated or a batch allocated callback store it in
|
|
|
|
* the free callbacks list. Else free it.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS == 1
|
|
|
|
if (cb < g_cbprealloc || cb >= (g_cbprealloc +
|
|
|
|
CONFIG_NET_PREALLOC_DEVIF_CALLBACKS))
|
|
|
|
{
|
|
|
|
kmm_free(cb);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
cb->nxtconn = g_cbfreelist;
|
|
|
|
cb->nxtdev = NULL;
|
|
|
|
g_cbfreelist = cb;
|
|
|
|
}
|
2015-06-03 16:11:57 +02:00
|
|
|
|
2016-12-03 23:28:19 +01:00
|
|
|
net_unlock();
|
2015-06-03 16:11:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-08 17:56:08 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Name: devif_event_trigger
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Return true if the current set of events should trigger a callback to
|
|
|
|
* occur.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2017-07-08 17:56:08 +02:00
|
|
|
* events - The set of events that has occurred.
|
|
|
|
* triggers - The set of events that will trigger a callback.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static bool devif_event_trigger(uint16_t events, uint16_t triggers)
|
|
|
|
{
|
|
|
|
/* The events are divided into a set of individual bits that may be ORed
|
|
|
|
* together PLUS a field that encodes a single poll event.
|
|
|
|
*
|
|
|
|
* First check if any of the individual event bits will trigger the
|
|
|
|
* callback.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((events & triggers & ~DEVPOLL_MASK) != 0)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No... check the encoded device event. */
|
|
|
|
|
|
|
|
if ((events & DEVPOLL_MASK) == (triggers & DEVPOLL_MASK))
|
|
|
|
{
|
2019-11-27 14:59:52 +01:00
|
|
|
return (triggers & DEVPOLL_MASK) != 0;
|
2017-07-08 17:56:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* No.. this event set will not generate the callback */
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-09-01 15:59:54 +02:00
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: devif_callback_init
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
* Description:
|
2014-04-12 20:13:01 +02:00
|
|
|
* Configure the pre-allocated callback structures into a free list.
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
* Assumptions:
|
2018-06-23 23:03:01 +02:00
|
|
|
* Called early in the initialization sequence so that no special
|
|
|
|
* protection is required.
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2014-06-29 02:36:09 +02:00
|
|
|
void devif_callback_init(void)
|
2008-09-01 15:59:54 +02:00
|
|
|
{
|
2023-02-13 17:30:21 +01:00
|
|
|
#if CONFIG_NET_PREALLOC_DEVIF_CALLBACKS > 0
|
2008-09-01 15:59:54 +02:00
|
|
|
int i;
|
2015-05-28 20:01:38 +02:00
|
|
|
|
2023-02-13 17:30:21 +01:00
|
|
|
for (i = 0; i < CONFIG_NET_PREALLOC_DEVIF_CALLBACKS; i++)
|
2008-09-01 15:59:54 +02:00
|
|
|
{
|
2015-05-28 20:01:38 +02:00
|
|
|
g_cbprealloc[i].nxtconn = g_cbfreelist;
|
|
|
|
g_cbfreelist = &g_cbprealloc[i];
|
2008-09-01 15:59:54 +02:00
|
|
|
}
|
2022-01-01 15:05:07 +01:00
|
|
|
#endif
|
2008-09-01 15:59:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: devif_callback_alloc
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Allocate a callback container from the free list.
|
|
|
|
*
|
2015-06-03 16:11:57 +02:00
|
|
|
* If dev is non-NULL, then this function verifies that the device
|
|
|
|
* reference is still valid and that the device is still UP status. If
|
|
|
|
* those conditions are not true, this function will fail to allocate the
|
|
|
|
* callback.
|
|
|
|
*
|
2008-09-01 15:59:54 +02:00
|
|
|
* Assumptions:
|
2015-06-03 16:11:57 +02:00
|
|
|
* This function is called with the network locked.
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2015-05-28 20:01:38 +02:00
|
|
|
FAR struct devif_callback_s *
|
|
|
|
devif_callback_alloc(FAR struct net_driver_s *dev,
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
FAR struct devif_callback_s **list_head,
|
|
|
|
FAR struct devif_callback_s **list_tail)
|
2008-09-01 15:59:54 +02:00
|
|
|
{
|
2014-06-29 20:59:34 +02:00
|
|
|
FAR struct devif_callback_s *ret;
|
2023-02-13 17:30:21 +01:00
|
|
|
#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS > 0
|
2022-01-01 15:05:07 +01:00
|
|
|
int i;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
net_lock();
|
|
|
|
|
2021-09-19 04:08:48 +02:00
|
|
|
/* Verify that the device pointer is valid, i.e., that it still
|
|
|
|
* points to a registered network device and also that the network
|
|
|
|
* device in the UP state.
|
|
|
|
*/
|
|
|
|
|
2022-01-06 14:33:11 +01:00
|
|
|
/* Note: dev->d_flags may be asynchronously changed by netdev_ifdown()
|
|
|
|
* (in net/netdev/netdev_ioctl.c). Nevertheless, net_lock() / net_unlock()
|
|
|
|
* are not required in netdev_ifdown() to prevent dev->d_flags from
|
|
|
|
* asynchronous change here. There is not an issue because net_lock() and
|
|
|
|
* net_unlock() present inside of devif_dev_event(). That should be enough
|
|
|
|
* to de-allocate connection callbacks reliably on NETDEV_DOWN event.
|
|
|
|
*/
|
|
|
|
|
2023-09-13 09:38:58 +02:00
|
|
|
if (dev && !(netdev_verify(dev) && (dev->d_flags & IFF_UP) != 0))
|
2021-09-19 04:08:48 +02:00
|
|
|
{
|
|
|
|
net_unlock();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-01-01 15:05:07 +01:00
|
|
|
/* Allocate the callback entry from heap */
|
|
|
|
|
2023-02-13 17:30:21 +01:00
|
|
|
#if CONFIG_NET_ALLOC_DEVIF_CALLBACKS > 0
|
2022-01-01 15:05:07 +01:00
|
|
|
if (g_cbfreelist == NULL)
|
|
|
|
{
|
|
|
|
ret = kmm_zalloc(sizeof(struct devif_callback_s) *
|
2023-02-13 17:30:21 +01:00
|
|
|
CONFIG_NET_ALLOC_DEVIF_CALLBACKS);
|
2022-01-01 15:05:07 +01:00
|
|
|
if (ret != NULL)
|
|
|
|
{
|
2023-02-13 17:30:21 +01:00
|
|
|
for (i = 0; i < CONFIG_NET_ALLOC_DEVIF_CALLBACKS; i++)
|
2022-01-01 15:05:07 +01:00
|
|
|
{
|
|
|
|
ret[i].nxtconn = g_cbfreelist;
|
|
|
|
g_cbfreelist = &ret[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2008-09-01 15:59:54 +02:00
|
|
|
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
/* Check the head of the free list */
|
2008-09-01 15:59:54 +02:00
|
|
|
|
2022-01-01 15:05:07 +01:00
|
|
|
ret = g_cbfreelist;
|
2008-09-01 15:59:54 +02:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
/* Remove the next instance from the head of the free list */
|
|
|
|
|
2015-05-28 20:01:38 +02:00
|
|
|
g_cbfreelist = ret->nxtconn;
|
2014-06-29 20:59:34 +02:00
|
|
|
memset(ret, 0, sizeof(struct devif_callback_s));
|
2008-09-01 15:59:54 +02:00
|
|
|
|
2015-05-28 20:01:38 +02:00
|
|
|
/* Add the newly allocated instance to the head of the device event
|
|
|
|
* list.
|
|
|
|
*/
|
2015-10-04 23:28:54 +02:00
|
|
|
|
2015-05-28 20:01:38 +02:00
|
|
|
if (dev)
|
|
|
|
{
|
2015-05-29 22:32:56 +02:00
|
|
|
ret->nxtdev = dev->d_devcb;
|
|
|
|
dev->d_devcb = ret;
|
2015-05-28 20:01:38 +02:00
|
|
|
}
|
|
|
|
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
/* Add the newly allocated instance to the tail of the specified list */
|
2008-09-01 15:59:54 +02:00
|
|
|
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
if (list_head && list_tail)
|
2008-09-01 15:59:54 +02:00
|
|
|
{
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
ret->nxtconn = NULL;
|
2021-09-21 05:43:31 +02:00
|
|
|
ret->prevconn = *list_tail;
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
|
|
|
|
if (*list_tail)
|
|
|
|
{
|
|
|
|
/* If the list is not empty, add the item to the tail. */
|
|
|
|
|
|
|
|
(*list_tail)->nxtconn = ret;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If the list is empty, add the first item to the list. */
|
|
|
|
|
|
|
|
*list_head = ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update the tail pointer */
|
|
|
|
|
|
|
|
*list_tail = ret;
|
2008-09-01 15:59:54 +02:00
|
|
|
}
|
|
|
|
}
|
2016-06-11 22:14:08 +02:00
|
|
|
#ifdef CONFIG_DEBUG_FEATURES
|
2008-09-01 15:59:54 +02:00
|
|
|
else
|
|
|
|
{
|
2016-06-20 20:44:38 +02:00
|
|
|
nerr("ERROR: Failed to allocate callback\n");
|
2008-09-01 15:59:54 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-12-03 23:28:19 +01:00
|
|
|
net_unlock();
|
2008-09-01 15:59:54 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: devif_conn_callback_free
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
* Description:
|
2015-06-03 16:11:57 +02:00
|
|
|
* Return a connection/port callback container to the free list.
|
|
|
|
*
|
|
|
|
* This function is just a front-end for devif_callback_free(). If the
|
|
|
|
* dev argument is non-NULL, it will verify that the device reference is
|
|
|
|
* still valid before attempting to free the callback structure. A
|
|
|
|
* non-NULL list pointer is assumed to be valid in any case.
|
|
|
|
*
|
|
|
|
* The callback structure will be freed in any event.
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
* Assumptions:
|
2015-06-03 16:11:57 +02:00
|
|
|
* This function is called with the network locked.
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
void devif_conn_callback_free(FAR struct net_driver_s *dev,
|
|
|
|
FAR struct devif_callback_s *cb,
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
FAR struct devif_callback_s **list_head,
|
|
|
|
FAR struct devif_callback_s **list_tail)
|
2008-09-01 15:59:54 +02:00
|
|
|
{
|
2015-06-03 16:11:57 +02:00
|
|
|
/* Check if the device pointer is still valid. It could be invalid if, for
|
|
|
|
* example, the device were unregistered between the time when the callback
|
|
|
|
* was allocated and the time when the callback was freed.
|
|
|
|
*/
|
2008-09-01 15:59:54 +02:00
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
if (dev && !netdev_verify(dev))
|
2008-09-01 15:59:54 +02:00
|
|
|
{
|
2015-06-03 16:11:57 +02:00
|
|
|
/* The device reference is longer valid */
|
2014-01-13 19:04:01 +01:00
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
dev = NULL;
|
|
|
|
}
|
2014-01-13 19:04:01 +01:00
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
/* Then free the callback */
|
2014-01-13 19:04:01 +01:00
|
|
|
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
devif_callback_free(dev, cb, list_head, list_tail);
|
2015-06-03 16:11:57 +02:00
|
|
|
}
|
2015-05-28 20:01:38 +02:00
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: devif_dev_callback_free
|
2015-06-03 16:11:57 +02:00
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Return a device callback container to the free list.
|
|
|
|
*
|
|
|
|
* This function is just a front-end for devif_callback_free(). If the
|
|
|
|
* de argument is non-NULL, it will verify that the device reference is
|
|
|
|
* still valid before attempting to free the callback structure. It
|
|
|
|
* differs from devif_conn_callback_free in that connection/port-related
|
|
|
|
* connections are also associated with the device and, hence, also will
|
|
|
|
* not be valid if the device pointer is not valid.
|
|
|
|
*
|
|
|
|
* The callback structure will be freed in any event.
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
* This function is called with the network locked.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
2015-05-29 19:01:03 +02:00
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
void devif_dev_callback_free(FAR struct net_driver_s *dev,
|
|
|
|
FAR struct devif_callback_s *cb)
|
|
|
|
{
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
FAR struct devif_callback_s **list_head;
|
|
|
|
FAR struct devif_callback_s **list_tail;
|
2015-05-28 20:01:38 +02:00
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
/* Check if the device pointer is still valid. It could be invalid if, for
|
|
|
|
* example, the device were unregistered between the time when the callback
|
|
|
|
* was allocated and the time when the callback was freed.
|
|
|
|
*/
|
2015-05-28 20:01:38 +02:00
|
|
|
|
2017-07-08 17:56:08 +02:00
|
|
|
if (dev != NULL && netdev_verify(dev))
|
2015-06-03 16:11:57 +02:00
|
|
|
{
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
/* The device reference is valid. Then use the list pointer in the
|
2015-06-03 16:11:57 +02:00
|
|
|
* device structure as well.
|
2015-05-29 19:01:03 +02:00
|
|
|
*/
|
2008-09-01 15:59:54 +02:00
|
|
|
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
list_head = &dev->d_conncb;
|
|
|
|
list_tail = &dev->d_conncb_tail;
|
2015-06-03 16:11:57 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* The device reference is longer valid */
|
2008-09-01 15:59:54 +02:00
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
dev = NULL;
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
list_head = NULL;
|
|
|
|
list_tail = NULL;
|
2015-06-03 16:11:57 +02:00
|
|
|
}
|
2008-09-01 15:59:54 +02:00
|
|
|
|
2015-06-03 16:11:57 +02:00
|
|
|
/* Then free the callback */
|
2008-09-01 15:59:54 +02:00
|
|
|
|
net/devif/devif_callback.c: corrected the connection event list to work as FIFO instead of LIFO.
In case of enabled packet forwarding mode, packets were forwarded in a reverse order
because of LIFO behavior of the connection event list.
The issue exposed only during high network traffic. Thus the event list started to grow
that resulted in changing the order of packets inside of groups of several packets
like the following: 3, 2, 1, 6, 5, 4, 8, 7 etc.
Remarks concerning the connection event list implementation:
* Now the queue (list) is FIFO as it should be.
* The list is singly linked.
* The list has a head pointer (inside of outer net_driver_s structure),
and a tail pointer is added into outer net_driver_s structure.
* The list item is devif_callback_s structure.
It still has two pointers to two different list chains (*nxtconn and *nxtdev).
* As before the first argument (*dev) of the list functions can be NULL,
while the other argument (*list) is effective (not NULL).
* An extra (*tail) argument is added to devif_callback_alloc()
and devif_conn_callback_free() functions.
* devif_callback_alloc() time complexity is O(1) (i.e. O(n) to fill the whole list).
* devif_callback_free() time complexity is O(n) (i.e. O(n^2) to empty the whole list).
* devif_conn_event() time complexity is O(n).
2021-08-29 22:57:26 +02:00
|
|
|
devif_callback_free(dev, cb, list_head, list_tail);
|
2008-09-01 15:59:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: devif_conn_event
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
* Description:
|
2015-05-28 20:01:38 +02:00
|
|
|
* Execute a list of callbacks using the packet event chain.
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2015-05-27 19:39:44 +02:00
|
|
|
* dev - The network device state structure associated with the network
|
|
|
|
* device that initiated the callback event.
|
2015-05-28 20:01:38 +02:00
|
|
|
* flags - The bit set of events to be notified.
|
|
|
|
* list - The list to traverse in performing the notifications
|
2015-05-27 19:39:44 +02:00
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2015-05-27 19:39:44 +02:00
|
|
|
* The updated flags as modified by the callback functions.
|
|
|
|
*
|
2008-09-01 15:59:54 +02:00
|
|
|
* Assumptions:
|
2015-05-27 19:39:44 +02:00
|
|
|
* This function is called with the network locked.
|
2008-09-01 15:59:54 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2022-08-25 15:17:57 +02:00
|
|
|
uint16_t devif_conn_event(FAR struct net_driver_s *dev, uint16_t flags,
|
|
|
|
FAR struct devif_callback_s *list)
|
2008-09-01 15:59:54 +02:00
|
|
|
{
|
2014-06-29 20:59:34 +02:00
|
|
|
FAR struct devif_callback_s *next;
|
2008-09-01 15:59:54 +02:00
|
|
|
|
|
|
|
/* Loop for each callback in the list and while there are still events
|
|
|
|
* set in the flags set.
|
|
|
|
*/
|
|
|
|
|
2016-12-03 23:28:19 +01:00
|
|
|
net_lock();
|
2008-09-01 15:59:54 +02:00
|
|
|
while (list && flags)
|
|
|
|
{
|
|
|
|
/* Save the pointer to the next callback in the lists. This is done
|
|
|
|
* because the callback action might delete the entry pointed to by
|
|
|
|
* list.
|
|
|
|
*/
|
|
|
|
|
2015-05-28 20:01:38 +02:00
|
|
|
next = list->nxtconn;
|
2008-09-01 15:59:54 +02:00
|
|
|
|
|
|
|
/* Check if this callback handles any of the events in the flag set */
|
|
|
|
|
2017-07-08 17:56:08 +02:00
|
|
|
if (list->event != NULL && devif_event_trigger(flags, list->flags))
|
2008-09-01 15:59:54 +02:00
|
|
|
{
|
|
|
|
/* Yes.. perform the callback. Actions perform by the callback
|
|
|
|
* may delete the current list entry or add a new list entry to
|
|
|
|
* beginning of the list (which will be ignored on this pass)
|
|
|
|
*/
|
|
|
|
|
2022-08-25 15:17:57 +02:00
|
|
|
flags = list->event(dev, list->priv, flags);
|
2008-09-01 15:59:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set up for the next time through the loop */
|
|
|
|
|
|
|
|
list = next;
|
|
|
|
}
|
|
|
|
|
2016-12-03 23:28:19 +01:00
|
|
|
net_unlock();
|
2008-09-01 15:59:54 +02:00
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2015-05-28 20:01:38 +02:00
|
|
|
/****************************************************************************
|
2017-04-22 00:33:14 +02:00
|
|
|
* Name: devif_dev_event
|
2015-05-28 20:01:38 +02:00
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Execute a list of callbacks using the device event chain.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2015-05-28 20:01:38 +02:00
|
|
|
* dev - The network device state structure associated with the network
|
|
|
|
* device that initiated the callback event.
|
|
|
|
* flags - The bit set of events to be notified.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2015-05-28 20:01:38 +02:00
|
|
|
* The updated flags as modified by the callback functions.
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
* This function is called with the network locked.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2022-08-25 15:17:57 +02:00
|
|
|
uint16_t devif_dev_event(FAR struct net_driver_s *dev, uint16_t flags)
|
2015-05-28 20:01:38 +02:00
|
|
|
{
|
|
|
|
FAR struct devif_callback_s *cb;
|
|
|
|
FAR struct devif_callback_s *next;
|
|
|
|
|
|
|
|
/* Loop for each callback in the list and while there are still events
|
|
|
|
* set in the flags set.
|
|
|
|
*/
|
|
|
|
|
2016-12-03 23:28:19 +01:00
|
|
|
net_lock();
|
2015-05-28 20:01:38 +02:00
|
|
|
for (cb = dev->d_devcb; cb != NULL && flags != 0; cb = next)
|
|
|
|
{
|
|
|
|
/* Save the pointer to the next callback in the lists. This is done
|
|
|
|
* because the callback action might delete the entry pointed to by
|
|
|
|
* list.
|
|
|
|
*/
|
|
|
|
|
|
|
|
next = cb->nxtdev;
|
|
|
|
|
|
|
|
/* Check if this callback handles any of the events in the flag set */
|
|
|
|
|
2017-07-08 17:56:08 +02:00
|
|
|
if (cb->event != NULL && devif_event_trigger(flags, cb->flags))
|
2015-05-28 20:01:38 +02:00
|
|
|
{
|
|
|
|
/* Yes.. perform the callback. Actions perform by the callback
|
|
|
|
* may delete the current list entry or add a new list entry to
|
|
|
|
* beginning of the list (which will be ignored on this pass)
|
|
|
|
*/
|
|
|
|
|
2022-08-25 15:17:57 +02:00
|
|
|
flags = cb->event(dev, cb->priv, flags);
|
2015-05-28 20:01:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-03 23:28:19 +01:00
|
|
|
net_unlock();
|
2015-05-28 20:01:38 +02:00
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2008-09-01 15:59:54 +02:00
|
|
|
#endif /* CONFIG_NET */
|