diff --git a/drivers/can/CMakeLists.txt b/drivers/can/CMakeLists.txt index 37dca4f0727..9f3ececce9d 100644 --- a/drivers/can/CMakeLists.txt +++ b/drivers/can/CMakeLists.txt @@ -16,4 +16,3 @@ zephyr_library_sources_ifdef(CONFIG_CAN_RCAR can_rcar.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE can_handlers.c) zephyr_library_sources_ifdef(CONFIG_CAN_SHELL can_shell.c) -zephyr_library_sources_ifdef(CONFIG_CAN_NET can_net.c) diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index e24b763b0fc..58099f0381e 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -101,6 +101,5 @@ source "drivers/can/Kconfig.mcp2515" source "drivers/can/Kconfig.mcan" source "drivers/can/Kconfig.rcar" source "drivers/can/Kconfig.loopback" -source "drivers/can/Kconfig.net" endif # CAN diff --git a/drivers/can/Kconfig.net b/drivers/can/Kconfig.net deleted file mode 100644 index 7aa37866f8c..00000000000 --- a/drivers/can/Kconfig.net +++ /dev/null @@ -1,35 +0,0 @@ -# Configuration options for IPv6 over CAN - -# Copyright (c) 2019 Alexander Wachter -# SPDX-License-Identifier: Apache-2.0 - -config CAN_NET - bool "6loCAN network interface [EXPERIMENTAL]" - select EXPERIMENTAL - help - Enable IPv6 Networking over can (6loCAN) - -if CAN_NET - -module = CAN_NET -module-dep = NET_LOG -module-str = Log level for Network CAN -module-help = Enables logging for CAN L2 networking -source "subsys/net/Kconfig.template.log_config.net" - -config CAN_NET_NAME - string "Network device name" - default "NET_CAN" - help - Name of the network device driver for IPv6 over CAN. - -config CAN_NET_INIT_PRIORITY - int "CAN NET driver init priority" - default 80 - help - CAN NET device driver initialization priority. - Do not mess with it unless you know what you are doing. - Note that the priority needs to be lower than the net stack - so that it can start before the networking sub-system. - -endif # CAN_NET diff --git a/drivers/can/can_net.c b/drivers/can/can_net.c deleted file mode 100644 index ee87152caa2..00000000000 --- a/drivers/can/can_net.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright (c) 2019 Alexander Wachter - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include -LOG_MODULE_REGISTER(net_can, CONFIG_CAN_NET_LOG_LEVEL); - -struct mcast_filter_mapping { - const struct in6_addr *addr; - int filter_id; -}; - -struct net_can_context { - const struct device *can_dev; - struct net_if *iface; - int recv_filter_id; - struct mcast_filter_mapping mcast_mapping[NET_IF_MAX_IPV6_MADDR]; -#ifdef CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR - int eth_bridge_filter_id; - int all_mcast_filter_id; -#endif -}; - -static struct net_if_mcast_monitor mcast_monitor; - -struct mcast_filter_mapping *can_get_mcast_filter(struct net_can_context *ctx, - const struct in6_addr *addr) -{ - struct mcast_filter_mapping *map = ctx->mcast_mapping; - - for (int i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) { - if (map[i].addr == addr) { - return &map[i]; - } - } - - return NULL; -} - -static inline uint8_t can_get_frame_datalength(struct zcan_frame *frame) -{ - /* TODO: Needs update when CAN FD support is added */ - return frame->dlc; -} - -static inline uint16_t can_get_lladdr_src(struct zcan_frame *frame) -{ - return (frame->id >> CAN_NET_IF_ADDR_SRC_POS) & - CAN_NET_IF_ADDR_MASK; -} - -static inline uint16_t can_get_lladdr_dest(struct zcan_frame *frame) -{ - uint16_t addr = (frame->id >> CAN_NET_IF_ADDR_DEST_POS) & - CAN_NET_IF_ADDR_MASK; - - if (frame->id & CAN_NET_IF_ADDR_MCAST_MASK) { - addr |= CAN_NET_IF_IS_MCAST_BIT; - } - - return addr; -} - -static inline void can_set_lladdr(struct net_pkt *pkt, struct zcan_frame *frame) -{ - struct net_buf *buf = pkt->buffer; - - /* Put the destination at the beginning of the pkt. - * The net_canbus_lladdr has a size if 14 bits. To convert it to - * network byte order, we treat it as 16 bits here. - */ - net_pkt_lladdr_dst(pkt)->addr = buf->data; - net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_canbus_lladdr); - net_pkt_lladdr_dst(pkt)->type = NET_LINK_CANBUS; - net_buf_add_be16(buf, can_get_lladdr_dest(frame)); - net_buf_pull(buf, sizeof(uint16_t)); - - /* Do the same as above for the source address */ - net_pkt_lladdr_src(pkt)->addr = buf->data; - net_pkt_lladdr_src(pkt)->len = sizeof(struct net_canbus_lladdr); - net_pkt_lladdr_src(pkt)->type = NET_LINK_CANBUS; - net_buf_add_be16(buf, can_get_lladdr_src(frame)); - net_buf_pull(buf, sizeof(uint16_t)); -} - -static int net_can_send(const struct device *dev, - const struct zcan_frame *frame, - can_tx_callback_t cb, void *cb_arg, k_timeout_t timeout) -{ - struct net_can_context *ctx = dev->data; - - NET_ASSERT(frame->id_type == CAN_EXTENDED_IDENTIFIER); - return can_send(ctx->can_dev, frame, timeout, cb, cb_arg); -} - -static void net_can_recv(struct zcan_frame *frame, void *arg) -{ - struct net_can_context *ctx = (struct net_can_context *)arg; - size_t pkt_size = 2 * sizeof(struct net_canbus_lladdr) + - can_get_frame_datalength(frame); - struct net_pkt *pkt; - int ret; - - NET_DBG("Frame with ID 0x%x received", frame->id); - pkt = net_pkt_rx_alloc_with_buffer(ctx->iface, pkt_size, AF_UNSPEC, 0, - K_NO_WAIT); - if (!pkt) { - LOG_ERR("Failed to obtain net_pkt with size of %d", pkt_size); - goto drop; - } - - pkt->canbus_rx_ctx = NULL; - - can_set_lladdr(pkt, frame); - net_pkt_cursor_init(pkt); - ret = net_pkt_write(pkt, frame->data, can_get_frame_datalength(frame)); - if (ret) { - LOG_ERR("Failed to append frame data to net_pkt"); - goto drop; - } - - ret = net_recv_data(ctx->iface, pkt); - if (ret < 0) { - LOG_ERR("Packet dropped by NET stack"); - goto drop; - } - - return; - -drop: - NET_INFO("pkt dropped"); - - if (pkt) { - net_pkt_unref(pkt); - } -} - -static inline int add_mcast_filter(struct net_can_context *ctx, - const struct in6_addr *addr) -{ - static struct zcan_filter filter = { - .id_type = CAN_EXTENDED_IDENTIFIER, - .rtr = CAN_DATAFRAME, - .rtr_mask = 1, - .id_mask = CAN_NET_IF_ADDR_MCAST_MASK | - CAN_NET_IF_ADDR_DEST_MASK - }; - const uint16_t group = - sys_be16_to_cpu(UNALIGNED_GET((&addr->s6_addr16[7]))); - int filter_id; - - filter.id = CAN_NET_IF_ADDR_MCAST_MASK | - ((group & CAN_NET_IF_ADDR_MASK) << - CAN_NET_IF_ADDR_DEST_POS); - - filter_id = can_add_rx_filter(ctx->can_dev, net_can_recv, - ctx, &filter); - if (filter_id == CAN_NET_FILTER_NOT_SET) { - return CAN_NET_FILTER_NOT_SET; - } - - NET_DBG("Added mcast filter. Group 0x%04x. Filter:%d", - group, filter_id); - - return filter_id; -} - -static void mcast_cb(struct net_if *iface, const struct net_addr *addr, - bool is_joined) -{ - const struct device *dev = net_if_get_device(iface); - struct net_can_context *ctx = dev->data; - struct mcast_filter_mapping *filter_mapping; - int filter_id; - - if (addr->family != AF_INET6) { - return; - } - - if (is_joined) { - filter_mapping = can_get_mcast_filter(ctx, NULL); - if (!filter_mapping) { - NET_ERR("Can't get a free filter_mapping"); - } - - filter_id = add_mcast_filter(ctx, &addr->in6_addr); - if (filter_id < 0) { - NET_ERR("Can't add mcast filter"); - return; - } - - filter_mapping->addr = &addr->in6_addr; - filter_mapping->filter_id = filter_id; - } else { - filter_mapping = can_get_mcast_filter(ctx, &addr->in6_addr); - if (!filter_mapping) { - NET_ERR("No filter mapping found"); - return; - } - - can_remove_rx_filter(ctx->can_dev, filter_mapping->filter_id); - filter_mapping->addr = NULL; - } -} - -static void net_can_iface_init(struct net_if *iface) -{ - const struct device *dev = net_if_get_device(iface); - struct net_can_context *ctx = dev->data; - - ctx->iface = iface; - - NET_DBG("Init CAN network interface %p dev %p", iface, dev); - - net_6locan_init(iface); - - net_if_mcast_mon_register(&mcast_monitor, iface, mcast_cb); -} - -static int net_can_add_rx_filter(const struct device *dev, can_rx_callback_t cb, - void *cb_arg, const struct zcan_filter *filter) -{ - struct net_can_context *ctx = dev->data; - - return can_add_rx_filter(ctx->can_dev, cb, cb_arg, filter); -} - -static void net_can_remove_rx_filter(const struct device *dev, int filter_id) -{ - struct net_can_context *ctx = dev->data; - - if (filter_id >= 0) { - can_remove_rx_filter(ctx->can_dev, filter_id); - } -} - -static inline int can_add_unicast_filter(struct net_can_context *ctx) -{ - struct zcan_filter filter = { - .id_type = CAN_EXTENDED_IDENTIFIER, - .rtr = CAN_DATAFRAME, - .rtr_mask = 1, - .id_mask = CAN_NET_IF_ADDR_DEST_MASK - }; - const uint8_t *link_addr = net_if_get_link_addr(ctx->iface)->addr; - const uint16_t dest = sys_be16_to_cpu(UNALIGNED_GET((uint16_t *) link_addr)); - int filter_id; - - filter.id = (dest << CAN_NET_IF_ADDR_DEST_POS); - - filter_id = can_add_rx_filter(ctx->can_dev, net_can_recv, - ctx, &filter); - if (filter_id == CAN_NET_FILTER_NOT_SET) { - NET_ERR("Can't add FF filter"); - return CAN_NET_FILTER_NOT_SET; - } - - NET_DBG("Added FF filter %d", filter_id); - - return filter_id; -} - -#ifdef CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR -static inline int can_add_eth_bridge_filter(struct net_can_context *ctx) -{ - const struct zcan_filter filter = { - .id_type = CAN_EXTENDED_IDENTIFIER, - .rtr = CAN_DATAFRAME, - .rtr_mask = 1, - .id_mask = CAN_NET_IF_ADDR_DEST_MASK, - .id = (NET_CAN_ETH_TRANSLATOR_ADDR << - CAN_NET_IF_ADDR_DEST_POS) - }; - - int filter_id; - - filter_id = can_add_rx_filter(ctx->can_dev, net_can_recv, - ctx, &filter); - if (filter_id == CAN_NET_FILTER_NOT_SET) { - NET_ERR("Can't add ETH bridge filter"); - return CAN_NET_FILTER_NOT_SET; - } - - NET_DBG("Added ETH bridge filter %d", filter_id); - - return filter_id; -} - -static inline int can_add_all_mcast_filter(struct net_can_context *ctx) -{ - const struct zcan_filter filter = { - .id_type = CAN_EXTENDED_IDENTIFIER, - .rtr = CAN_DATAFRAME, - .rtr_mask = 1, - .id_mask = CAN_NET_IF_ADDR_MCAST_MASK, - .id = CAN_NET_IF_ADDR_MCAST_MASK - }; - - int filter_id; - - filter_id = can_add_rx_filter(ctx->can_dev, net_can_recv, - ctx, &filter); - if (filter_id == CAN_NET_FILTER_NOT_SET) { - NET_ERR("Can't add all mcast filter"); - return CAN_NET_FILTER_NOT_SET; - } - - NET_DBG("Added all mcast filter %d", filter_id); - - return filter_id; -} -#endif /*CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR*/ - -static int can_enable(const struct device *dev, bool enable) -{ - struct net_can_context *ctx = dev->data; - - if (enable) { - if (ctx->recv_filter_id == CAN_NET_FILTER_NOT_SET) { - ctx->recv_filter_id = can_add_unicast_filter(ctx); - if (ctx->recv_filter_id < 0) { - return -EIO; - } - } - -#ifdef CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR - if (ctx->eth_bridge_filter_id == CAN_NET_FILTER_NOT_SET) { - ctx->eth_bridge_filter_id = can_add_eth_bridge_filter(ctx); - if (ctx->eth_bridge_filter_id < 0) { - can_remove_rx_filter(ctx->can_dev, ctx->recv_filter_id); - return -EIO; - } - } - - if (ctx->all_mcast_filter_id == CAN_NET_FILTER_NOT_SET) { - ctx->all_mcast_filter_id = can_add_all_mcast_filter(ctx); - if (ctx->all_mcast_filter_id < 0) { - can_remove_rx_filter(ctx->can_dev, ctx->recv_filter_id); - can_remove_rx_filter(ctx->can_dev, ctx->eth_bridge_filter_id); - return -EIO; - } - } -#endif /*CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR*/ - } else { - if (ctx->recv_filter_id != CAN_NET_FILTER_NOT_SET) { - can_remove_rx_filter(ctx->can_dev, ctx->recv_filter_id); - } - -#ifdef CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR - if (ctx->eth_bridge_filter_id != CAN_NET_FILTER_NOT_SET) { - can_remove_rx_filter(ctx->can_dev, ctx->eth_bridge_filter_id); - } - - if (ctx->all_mcast_filter_id != CAN_NET_FILTER_NOT_SET) { - can_remove_rx_filter(ctx->can_dev, ctx->all_mcast_filter_id); - } -#endif /*CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR*/ - } - - return 0; -} - -static struct net_can_api net_can_api_inst = { - .iface_api.init = net_can_iface_init, - - .send = net_can_send, - .add_rx_filter = net_can_add_rx_filter, - .remove_rx_filter = net_can_remove_rx_filter, - .enable = can_enable, -}; - -static int net_can_init(const struct device *dev) -{ - const struct device *can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)); - struct net_can_context *ctx = dev->data; - - ctx->recv_filter_id = CAN_NET_FILTER_NOT_SET; -#ifdef CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR - ctx->eth_bridge_filter_id = CAN_NET_FILTER_NOT_SET; - ctx->all_mcast_filter_id = CAN_NET_FILTER_NOT_SET; -#endif /*CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR*/ - - if (!device_is_ready(can_dev)) { - NET_ERR("CAN device not ready"); - return -ENODEV; - } - - NET_DBG("Init net CAN device %p (%s) for dev %p (%s)", - dev, dev->name, can_dev, can_dev->name); - - ctx->can_dev = can_dev; - - return 0; -} - -static struct net_can_context net_can_context_1; - -NET_DEVICE_INIT(net_can_1, CONFIG_CAN_NET_NAME, net_can_init, - NULL, &net_can_context_1, NULL, - CONFIG_CAN_NET_INIT_PRIORITY, - &net_can_api_inst, - CANBUS_L2, NET_L2_GET_CTX_TYPE(CANBUS_L2), NET_CAN_MTU); diff --git a/drivers/ethernet/eth_stm32_hal.c b/drivers/ethernet/eth_stm32_hal.c index b59aef2b64a..64017f09018 100644 --- a/drivers/ethernet/eth_stm32_hal.c +++ b/drivers/ethernet/eth_stm32_hal.c @@ -93,35 +93,6 @@ static uint8_t dma_tx_buffer[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __eth_stm32_buf; static ETH_TxPacketConfig tx_config; #endif -#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) -#include - -static void set_mac_to_translator_addr(uint8_t *mac_addr) -{ - /* Set the last 14 bit to the translator link layer address to avoid - * address collissions with the 6LoCAN address range - */ - mac_addr[4] = (mac_addr[4] & 0xC0) | (NET_CAN_ETH_TRANSLATOR_ADDR >> 8); - mac_addr[5] = NET_CAN_ETH_TRANSLATOR_ADDR & 0xFF; -} - -static void enable_canbus_eth_translator_filter(ETH_HandleTypeDef *heth, - uint8_t *mac_addr) -{ - heth->Instance->MACA1LR = (mac_addr[3] << 24U) | (mac_addr[2] << 16U) | - (mac_addr[1] << 8U) | mac_addr[0]; - -#if defined(CONFIG_SOC_SERIES_STM32H7X) - heth->Instance->MACA1HR = ETH_MACAHR_AE | ETH_MACAHR_MBC_HBITS15_8 | - ETH_MACAHR_MBC_HBITS7_0; -#else - /*enable filter 1 and ignore byte 5 and 6 for filtering*/ - heth->Instance->MACA1HR = ETH_MACA1HR_AE | ETH_MACA1HR_MBC_HBits15_8 | - ETH_MACA1HR_MBC_HBits7_0; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ -} -#endif /*CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR*/ - static HAL_StatusTypeDef read_eth_phy_register(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, @@ -839,10 +810,6 @@ static int eth_initialize(const struct device *dev) #if defined(CONFIG_ETH_STM32_HAL_RANDOM_MAC) generate_mac(dev_data->mac_addr); #endif -#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) - set_mac_to_translator_addr(dev_data->mac_addr); -#endif - heth->Init.MACAddr = dev_data->mac_addr; #if defined(CONFIG_SOC_SERIES_STM32H7X) @@ -927,10 +894,6 @@ static int eth_initialize(const struct device *dev) disable_mcast_filter(heth); -#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) - enable_canbus_eth_translator_filter(heth, dev_data->mac_addr); -#endif - #if defined(CONFIG_SOC_SERIES_STM32H7X) /* Adjust MDC clock range depending on HCLK frequency: */ HAL_ETH_SetMDIOClockRange(heth); diff --git a/include/net/can.h b/include/net/can.h deleted file mode 100644 index e8b8c36e2cb..00000000000 --- a/include/net/can.h +++ /dev/null @@ -1,244 +0,0 @@ -/** @file - * @brief IPv6 Networking over CAN definitions. - * - * Definitions for IPv6 Networking over CAN support. - */ - -/* - * Copyright (c) 2019 Alexander Wachter - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_NET_CAN_H_ -#define ZEPHYR_INCLUDE_NET_CAN_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @brief IPv6 over CAN library - * @defgroup net_can Network Core Library - * @ingroup networking - * @{ - */ - -/** - * CAN L2 driver API. Used by 6loCAN. - */ - -/* - * Abbreviations - * BS Block Size - * CAN_DL CAN LL data size - * CF Consecutive Frame - * CTS Continue to send - * DLC Data length code - * FC Flow Control - * FF First Frame - * FS Flow Status - */ - -/** @cond INTERNAL_HIDDEN */ - -#define NET_CAN_DL 8 -#define NET_CAN_MTU 0x0FFF - -/* 0x3DFF - bit 4 to 10 must not be zero. Also prevent stuffing bit*/ -#define NET_CAN_MULTICAST_ADDR 0x3DFF -#define NET_CAN_DAD_ADDR 0x3DFE -#define NET_CAN_ETH_TRANSLATOR_ADDR 0x3DF0 -#define NET_CAN_MAX_ADDR 0x3DEF -#define NET_CAN_MIN_ADDR 0x0100 - -#define CAN_NET_IF_ADDR_MASK 0x3FFF -#define CAN_NET_IF_ADDR_BYTE_LEN 2U -#define CAN_NET_IF_ADDR_DEST_POS 14U -#define CAN_NET_IF_ADDR_DEST_MASK (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_DEST_POS) -#define CAN_NET_IF_ADDR_SRC_POS 0U -#define CAN_NET_IF_ADDR_SRC_MASK (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_SRC_POS) -#define CAN_NET_IF_ADDR_MCAST_POS 28U -#define CAN_NET_IF_ADDR_MCAST_MASK (1UL << CAN_NET_IF_ADDR_MCAST_POS) - -#define CAN_NET_IF_IS_MCAST_BIT (1U << 14) - -#define CAN_NET_FILTER_NOT_SET -1 - -/** @endcond */ - -/* - * +-----------+ +-----------+ - * | | | | - * | IPv6 | | IPv6 | - * | 6LoCAN | | 6LoCAN | - * | | | | - * +----+-+----+ +----+-+----+ - * | | | | +---+ - * +----+ | | | | / \ +-+ - * | | | | | | +--+ / \_/ \ - * +++ +---+ +--+----+ +-------+ +--+----+ +--/ \_/ \ - * | | \ / | \ / \ / | \ / / | - * | | X | X CAN X | X | Internet | - * | | / \ | / \ / \ | / \ \ / - * +++ +---+ +----+--+ +-------+ +----+--+ +--+ / - * | | +-------------------+ - * +----+ - */ -struct net_can_api { - /** - * The net_if_api must be placed in first position in this - * struct so that we are compatible with network interface API. - */ - struct net_if_api iface_api; - - /** Send a single CAN frame */ - int (*send)(const struct device *dev, const struct zcan_frame *frame, - can_tx_callback_t cb, void *cb_arg, k_timeout_t timeout); - /** Add a filter with its callback */ - int (*add_rx_filter)(const struct device *dev, can_rx_callback_t cb, - void *cb_arg, const struct zcan_filter *filter); - /** Remove a filter */ - void (*remove_rx_filter)(const struct device *dev, int filter_id); - /** Enable or disable the reception of frames for net CAN */ - int (*enable)(const struct device *dev, bool enable); -}; - -/* Make sure that the network interface API is properly setup inside - * net_can_api struct (it is the first one). - */ -BUILD_ASSERT(offsetof(struct net_can_api, iface_api) == 0); - -/** @cond INTERNAL_HIDDEN */ - -#define CANBUS_L2_CTX_TYPE struct net_canbus_context * - -/** - * Context for canbus net device. - */ -struct canbus_net_ctx { - /** Filter ID for link layer duplicate address detection. */ - int dad_filter_id; - /** Work item for responding to link layer DAD requests. */ - struct k_work dad_work; - /** The interface associated with this device */ - struct net_if *iface; - /** The link layer address chosen for this interface */ - uint16_t ll_addr; - /** TX queue */ - struct k_fifo tx_queue; - /** RX error queue */ - struct k_fifo rx_err_queue; - /** Queue handler thread */ - struct k_thread queue_handler; - /** Queue handler thread stack */ - K_KERNEL_STACK_MEMBER(queue_stack, 512); -}; - -/** - * Canbus link layer addresses have a length of 14 bit for source and destination. - * Both together are 28 bit to fit a CAN extended identifier with 29 bit length. - */ -struct net_canbus_lladdr { - uint16_t addr : 14; -}; - -/** - * STmin is split in two valid ranges: - * 0-127: 0ms-127ms - * 128-240: Reserved - * 241-249: 100us-900us (multiples of 100us) - * 250- : Reserved - */ -struct canbus_fc_opts { - /** Block size. Number of CF PDUs before next CF is sent */ - uint8_t bs; - /**< Minimum separation time. Min time between frames */ - uint8_t stmin; -}; - -/** - * Context for a transmission of messages that didn't fit in a single frame. - * These messages Start with a FF (First Frame) that is in case of unicast - * acknowledged by a FC (Frame Control). After that, one or more CF - * (Consecutive frames) carry the rest of the message. - */ -struct canbus_isotp_tx_ctx { - /** Pkt containing the data to transmit */ - struct net_pkt *pkt; - /** Timeout for TX Timeout and separation time */ - struct _timeout timeout; - /** Frame Control options received from FC frame */ - struct canbus_fc_opts opts; - /** CAN destination address */ - struct net_canbus_lladdr dest_addr; - /** Remaining data to transmit in bytes */ - uint16_t rem_len; - /** Number of bytes in the tx queue */ - int8_t tx_backlog; - /** State of the transmission */ - uint8_t state; - /** Actual block number that is transmitted. Counts from BS to 0 */ - uint8_t act_block_nr; - /** Number of WAIT frames received */ - uint8_t wft; - /** Sequence number that is added to CF */ - uint8_t sn : 4; - /** Transmission is multicast */ - uint8_t is_mcast : 1; -}; - -/** - * Context for reception of messages that are not single frames. - * This is the counterpart of the canbus_isotp_tx_ctx. - */ -struct canbus_isotp_rx_ctx { - /** Pkt that is large enough to hold the entire message */ - struct net_pkt *pkt; - /** Timeout for RX timeout*/ - struct _timeout timeout; - /** Remaining data to receive. Goes from message length to zero */ - uint16_t rem_len; - /** State of the reception */ - uint8_t state; - /** Number of frames received in this block. Counts from BS to 0 */ - uint8_t act_block_nr; - /** Number of WAIT frames transmitted */ - uint8_t wft; - /** Expected sequence number in CF */ - uint8_t sn : 4; -}; - -/** - * Initialization of the canbus L2. - * - * This function starts the TX workqueue and does some initialization. - */ -void net_6locan_init(struct net_if *iface); - -/** - * Ethernet frame input function for Ethernet to 6LoCAN translation - * - * This function checks the destination link layer address for addresses - * that has to be forwarded. Frames that need to be forwarded are forwarded here. - */ -enum net_verdict net_canbus_translate_eth_frame(struct net_if *iface, - struct net_pkt *pkt); - -/** @endcond */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_INCLUDE_NET_CAN_H_ */ diff --git a/include/net/net_ip.h b/include/net/net_ip.h index cbade3f2537..1d0d8d82586 100644 --- a/include/net/net_ip.h +++ b/include/net/net_ip.h @@ -1248,8 +1248,7 @@ static inline void net_ipv6_addr_create_iid(struct in6_addr *addr, /* The generated IPv6 shall not toggle the * Universal/Local bit. RFC 6282 ch 3.2.2 */ - if (lladdr->type == NET_LINK_IEEE802154 || - lladdr->type == NET_LINK_CANBUS) { + if (lladdr->type == NET_LINK_IEEE802154) { UNALIGNED_PUT(0, &addr->s6_addr32[2]); addr->s6_addr[11] = 0xff; addr->s6_addr[12] = 0xfe; diff --git a/include/net/net_l2.h b/include/net/net_l2.h index 6af004b5ac4..f7c66fd6a60 100644 --- a/include/net/net_l2.h +++ b/include/net/net_l2.h @@ -127,11 +127,6 @@ NET_L2_DECLARE_PUBLIC(OPENTHREAD_L2); NET_L2_DECLARE_PUBLIC(CANBUS_RAW_L2); #endif /* CONFIG_NET_L2_CANBUS_RAW */ -#ifdef CONFIG_NET_L2_CANBUS -#define CANBUS_L2 CANBUS -NET_L2_DECLARE_PUBLIC(CANBUS_L2); -#endif /* CONFIG_NET_L2_CANBUS */ - #ifdef CONFIG_NET_L2_CUSTOM_IEEE802154 #ifndef CUSTOM_IEEE802154_L2 #define CUSTOM_IEEE802154_L2 CUSTOM_IEEE802154 diff --git a/include/net/net_linkaddr.h b/include/net/net_linkaddr.h index e6b0747ce08..ffa605b1939 100644 --- a/include/net/net_linkaddr.h +++ b/include/net/net_linkaddr.h @@ -57,8 +57,6 @@ enum net_link_type { NET_LINK_DUMMY, /** CANBUS link address. */ NET_LINK_CANBUS_RAW, - /** 6loCAN link address. */ - NET_LINK_CANBUS, } __packed; /** diff --git a/include/net/net_pkt.h b/include/net/net_pkt.h index 05f9d9151d5..1c945983f65 100644 --- a/include/net/net_pkt.h +++ b/include/net/net_pkt.h @@ -41,9 +41,6 @@ extern "C" { */ struct net_context; -struct canbus_net_isotp_tx_ctx; -struct canbus_net_isotp_rx_ctx; - /* buffer cursor used in net_pkt */ struct net_pkt_cursor { @@ -261,12 +258,6 @@ struct net_pkt { uint32_t ieee802154_ack_fc; /* Frame counter set in the ACK */ uint8_t ieee802154_ack_keyid; /* Key index set in the ACK */ #endif -#endif -#if defined(CONFIG_NET_L2_CANBUS) - union { - struct canbus_isotp_tx_ctx *canbus_tx_ctx; - struct canbus_isotp_rx_ctx *canbus_rx_ctx; - }; #endif /* @endcond */ }; diff --git a/samples/net/sockets/echo_client/overlay-6locan.conf b/samples/net/sockets/echo_client/overlay-6locan.conf deleted file mode 100644 index f8ecbab4ea5..00000000000 --- a/samples/net/sockets/echo_client/overlay-6locan.conf +++ /dev/null @@ -1,12 +0,0 @@ -CONFIG_CAN=y -CONFIG_CAN_NET=y -CONFIG_CAN_MAX_FILTER=8 -CONFIG_NET_L2_CANBUS=y -CONFIG_NET_L2_CANBUS_BS=8 -CONFIG_NET_L2_CANBUS_STMIN=0 -CONFIG_NET_IPV4=n -CONFIG_NET_IPV6=y -CONFIG_NET_CONFIG_NEED_IPV6=y -CONFIG_NET_CONFIG_NEED_IPV4=n -CONFIG_NET_CONFIG_MY_IPV4_ADDR="" -CONFIG_NET_CONFIG_PEER_IPV4_ADDR="" diff --git a/samples/net/sockets/echo_client/sample.yaml b/samples/net/sockets/echo_client/sample.yaml index 13cbb94f853..10ea0a5a7fe 100644 --- a/samples/net/sockets/echo_client/sample.yaml +++ b/samples/net/sockets/echo_client/sample.yaml @@ -11,9 +11,6 @@ tests: sample.net.sockets.echo_client: platform_allow: qemu_x86 frdm_k64f sam_e70_xplained qemu_cortex_m3 frdm_kw41z - sample.net.sockets.echo_client.6locan: - extra_args: OVERLAY_CONFIG="overlay-6locan.conf" - platform_allow: nucleo_f746zg sample.net.sockets.echo_client.802154: extra_args: OVERLAY_CONFIG="overlay-qemu_802154.conf" platform_allow: qemu_x86 diff --git a/samples/net/sockets/echo_server/overlay-6locan.conf b/samples/net/sockets/echo_server/overlay-6locan.conf deleted file mode 100644 index f8ecbab4ea5..00000000000 --- a/samples/net/sockets/echo_server/overlay-6locan.conf +++ /dev/null @@ -1,12 +0,0 @@ -CONFIG_CAN=y -CONFIG_CAN_NET=y -CONFIG_CAN_MAX_FILTER=8 -CONFIG_NET_L2_CANBUS=y -CONFIG_NET_L2_CANBUS_BS=8 -CONFIG_NET_L2_CANBUS_STMIN=0 -CONFIG_NET_IPV4=n -CONFIG_NET_IPV6=y -CONFIG_NET_CONFIG_NEED_IPV6=y -CONFIG_NET_CONFIG_NEED_IPV4=n -CONFIG_NET_CONFIG_MY_IPV4_ADDR="" -CONFIG_NET_CONFIG_PEER_IPV4_ADDR="" diff --git a/samples/net/sockets/echo_server/sample.yaml b/samples/net/sockets/echo_server/sample.yaml index 5a2c8f5c626..7c4799b5090 100644 --- a/samples/net/sockets/echo_server/sample.yaml +++ b/samples/net/sockets/echo_server/sample.yaml @@ -11,9 +11,6 @@ tests: sample.net.sockets.echo_server: platform_allow: qemu_x86 sam_e70_xplained frdm_k64f qemu_cortex_m3 frdm_kw41z - sample.net.sockets.echo_server.6locan: - extra_args: OVERLAY_CONFIG="overlay-6locan.conf" - platform_allow: nucleo_f746zg sample.net.sockets.echo_server.802154: extra_args: OVERLAY_CONFIG="overlay-qemu_802154.conf" platform_allow: qemu_x86 diff --git a/scripts/kconfig/hardened.csv b/scripts/kconfig/hardened.csv index 8b32c50f1cb..7b60b146738 100644 --- a/scripts/kconfig/hardened.csv +++ b/scripts/kconfig/hardened.csv @@ -64,7 +64,6 @@ NET_BUF_VARIABLE_DATA_SIZE,n,experimental NET_CONNECTION_MANAGER,n,experimental NET_GPTP,n,experimental NET_IPV4_AUTO,n,experimental -NET_L2_CANBUS,n,experimental NET_L2_IEEE802154_SECURITY,n,experimental NET_L2_PPP,n,experimental NET_L2_PTP,n,experimental diff --git a/subsys/net/ip/Kconfig b/subsys/net/ip/Kconfig index 82fe8b4393a..8e7da311232 100644 --- a/subsys/net/ip/Kconfig +++ b/subsys/net/ip/Kconfig @@ -737,10 +737,6 @@ config NET_DEFAULT_IF_DUMMY bool "Dummy testing interface" depends on NET_L2_DUMMY -config NET_DEFAULT_IF_CANBUS - bool "6LoCAN (IPv6 over CAN) interface" - depends on NET_L2_CANBUS - config NET_DEFAULT_IF_CANBUS_RAW bool "Socket CAN interface" depends on NET_L2_CANBUS_RAW diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 93aa21bb5f1..016464bc81c 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -578,9 +578,6 @@ struct net_if *net_if_get_default(void) #if defined(CONFIG_NET_DEFAULT_IF_CANBUS_RAW) iface = net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS_RAW)); #endif -#if defined(CONFIG_NET_DEFAULT_IF_CANBUS) - iface = net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS)); -#endif #if defined(CONFIG_NET_DEFAULT_IF_PPP) iface = net_if_get_first_by_type(&NET_L2_GET_NAME(PPP)); #endif diff --git a/subsys/net/ip/net_shell.c b/subsys/net/ip/net_shell.c index fff66db34ed..084a572909d 100644 --- a/subsys/net/ip/net_shell.c +++ b/subsys/net/ip/net_shell.c @@ -220,16 +220,6 @@ static const char *iface2str(struct net_if *iface, const char **extra) } #endif -#ifdef CONFIG_NET_L2_CANBUS - if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS)) { - if (extra) { - *extra = "======"; - } - - return "CANBUS"; - } -#endif - #ifdef CONFIG_NET_L2_CANBUS_RAW if (net_if_l2(iface) == &NET_L2_GET_NAME(CANBUS_RAW)) { if (extra) { @@ -1446,11 +1436,6 @@ static void conn_handler_cb(struct net_conn *conn, void *user_data) &net_sin(&conn->remote_addr)->sin_addr), ntohs(net_sin(&conn->remote_addr)->sin_port)); } else -#endif -#ifdef CONFIG_NET_L2_CANBUS - if (conn->local_addr.sa_family == AF_CAN) { - snprintk(addr_local, sizeof(addr_local), "-"); - } else #endif if (conn->local_addr.sa_family == AF_UNSPEC) { snprintk(addr_local, sizeof(addr_local), "AF_UNSPEC"); diff --git a/subsys/net/ip/tcp.c b/subsys/net/ip/tcp.c index da7d1f5266f..c5fac7a9580 100644 --- a/subsys/net/ip/tcp.c +++ b/subsys/net/ip/tcp.c @@ -287,9 +287,7 @@ end: ((IS_ENABLED(CONFIG_NET_L2_BT) && \ net_pkt_lladdr_dst(pkt)->type == NET_LINK_BLUETOOTH) || \ (IS_ENABLED(CONFIG_NET_L2_IEEE802154) && \ - net_pkt_lladdr_dst(pkt)->type == NET_LINK_IEEE802154) || \ - (IS_ENABLED(CONFIG_NET_L2_CANBUS) && \ - net_pkt_lladdr_dst(pkt)->type == NET_LINK_CANBUS))) + net_pkt_lladdr_dst(pkt)->type == NET_LINK_IEEE802154))) static void tcp_send(struct net_pkt *pkt) { diff --git a/subsys/net/l2/CMakeLists.txt b/subsys/net/l2/CMakeLists.txt index 270ae12a2f7..18782862be7 100644 --- a/subsys/net/l2/CMakeLists.txt +++ b/subsys/net/l2/CMakeLists.txt @@ -32,6 +32,6 @@ if(CONFIG_NET_L2_WIFI_MGMT OR CONFIG_NET_L2_WIFI_SHELL) add_subdirectory(wifi) endif() -if(CONFIG_NET_L2_CANBUS OR CONFIG_NET_L2_CANBUS_RAW) +if(CONFIG_NET_L2_CANBUS_RAW) add_subdirectory(canbus) endif() diff --git a/subsys/net/l2/canbus/6locan.c b/subsys/net/l2/canbus/6locan.c deleted file mode 100644 index cc5bd01223a..00000000000 --- a/subsys/net/l2/canbus/6locan.c +++ /dev/null @@ -1,1867 +0,0 @@ -/* - * Copyright (c) 2019 Alexander Wachter. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -LOG_MODULE_REGISTER(net_l2_canbus, CONFIG_NET_L2_CANBUS_LOG_LEVEL); - -#include -#include -#include -#include -#include -#include -#include "canbus_internal.h" -#include <6lo.h> -#include -#include -#include -#include -#include -#include -#include - -#define NET_CAN_WFTMAX 2 -#define NET_CAN_ALLOC_TIMEOUT K_MSEC(100) - -/* Minimal separation time betwee frames */ -#define NET_CAN_STMIN CONFIG_NET_L2_CANBUS_STMIN -#define NET_CAN_BS CONFIG_NET_L2_CANBUS_BS - -#define NET_CAN_DAD_SEND_RETRY 5 -#define NET_CAN_DAD_TIMEOUT K_MSEC(100) - -extern uint16_t net_calc_chksum(struct net_pkt *pkt, uint8_t proto); - -static struct canbus_l2_ctx l2_ctx; - -static struct k_work_q net_canbus_workq; -K_KERNEL_STACK_DEFINE(net_canbus_stack, 512); - -char *net_sprint_addr(sa_family_t af, const void *addr); - -#if CONFIG_NET_L2_CANBUS_LOG_LEVEL >= LOG_LEVEL_DBG -static void canbus_print_ip_hdr(struct net_ipv6_hdr *ip_hdr) -{ - uint8_t version = (ip_hdr->vtc >> 4); - uint8_t tc = ((ip_hdr->vtc & 0x0F) << 4) | ((ip_hdr->tcflow & 0xF0 >> 4)); - uint32_t flow = ((ip_hdr->tcflow & 0x0F) << 16) | ip_hdr->flow; - - NET_DBG("IP header: Version: 0x%x, TC: 0x%x, Flow Label: 0x%x, " - "Payload Length: %u, Next Header: 0x%x, Hop Limit: %u, " - "Src: %s, Dest: %s", - version, tc, flow, ntohs(ip_hdr->len), ip_hdr->nexthdr, - ip_hdr->hop_limit, - log_strdup(net_sprint_addr(AF_INET6, &ip_hdr->src)), - log_strdup(net_sprint_addr(AF_INET6, &ip_hdr->dst))); -} -#else -#define canbus_print_ip_hdr(...) -#endif - -static void canbus_free_tx_ctx(struct canbus_isotp_tx_ctx *ctx) -{ - k_mutex_lock(&l2_ctx.tx_ctx_mtx, K_FOREVER); - ctx->state = NET_CAN_TX_STATE_UNUSED; - k_mutex_unlock(&l2_ctx.tx_ctx_mtx); -} - -static void canbus_free_rx_ctx(struct canbus_isotp_rx_ctx *ctx) -{ - k_mutex_lock(&l2_ctx.rx_ctx_mtx, K_FOREVER); - ctx->state = NET_CAN_RX_STATE_UNUSED; - k_mutex_unlock(&l2_ctx.rx_ctx_mtx); -} - -static void canbus_tx_finish(struct net_pkt *pkt) -{ - struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx; - - if (ctx->state != NET_CAN_TX_STATE_RESET) { - z_abort_timeout(&ctx->timeout); - } - - canbus_free_tx_ctx(ctx); - net_pkt_unref(pkt); - k_sem_give(&l2_ctx.tx_sem); -} - -static void canbus_rx_finish(struct net_pkt *pkt) -{ - struct canbus_isotp_rx_ctx *ctx = pkt->canbus_rx_ctx; - - canbus_free_rx_ctx(ctx); -} - -static void canbus_tx_report_err(struct net_pkt *pkt) -{ - canbus_tx_finish(pkt); -} - -static void canbus_rx_report_err(struct net_pkt *pkt) -{ - canbus_rx_finish(pkt); - net_pkt_unref(pkt); -} - -static void rx_err_work_handler(struct net_pkt *pkt) -{ - canbus_rx_report_err(pkt); -} - -static void submit_to_queue(struct k_fifo *queue, struct net_pkt *pkt) -{ - k_fifo_put(queue, pkt); -} - -static void canbus_rx_report_err_from_isr(struct k_fifo *queue, - struct net_pkt *pkt) -{ - submit_to_queue(queue, pkt); -} - -static void canbus_tx_timeout(struct _timeout *t) -{ - struct canbus_isotp_tx_ctx *ctx = - CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout); - struct net_if *iface = net_pkt_iface(ctx->pkt); - struct canbus_net_ctx *net_ctx = net_if_l2_data(iface); - - NET_ERR("TX Timeout. CTX: %p", ctx); - ctx->state = NET_CAN_TX_STATE_ERR; - - submit_to_queue(&net_ctx->tx_queue, ctx->pkt); -} - -static void canbus_rx_timeout(struct _timeout *t) -{ - struct canbus_isotp_rx_ctx *ctx = - CONTAINER_OF(t, struct canbus_isotp_rx_ctx, timeout); - struct net_if *iface = net_pkt_iface(ctx->pkt); - struct canbus_net_ctx *net_ctx = net_if_l2_data(iface); - - NET_ERR("RX Timeout. CTX: %p", ctx); - ctx->state = NET_CAN_RX_STATE_TIMEOUT; - canbus_rx_report_err_from_isr(&net_ctx->rx_err_queue, ctx->pkt); -} - -static void canbus_st_min_timeout(struct _timeout *t) -{ - struct canbus_isotp_tx_ctx *ctx = - CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout); - struct net_if *iface = net_pkt_iface(ctx->pkt); - struct canbus_net_ctx *net_ctx = net_if_l2_data(iface); - - submit_to_queue(&net_ctx->tx_queue, ctx->pkt); -} - -static k_timeout_t canbus_stmin_to_ticks(uint8_t stmin) -{ - /* According to ISO 15765-2 stmin should be 127ms if value is corrupt */ - if (stmin > NET_CAN_STMIN_MAX || - (stmin > NET_CAN_STMIN_MS_MAX && stmin < NET_CAN_STMIN_US_BEGIN)) { - return K_MSEC(NET_CAN_STMIN_MS_MAX); - } else if (stmin >= NET_CAN_STMIN_US_BEGIN) { - return K_USEC((stmin + 1 - NET_CAN_STMIN_US_BEGIN) * 100U); - } - - return K_MSEC(stmin); -} - -static uint16_t canbus_get_lladdr(struct net_linkaddr *net_lladdr) -{ - NET_ASSERT(net_lladdr->len == sizeof(uint16_t)); - - return sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)net_lladdr->addr)); -} - -static uint16_t canbus_get_src_lladdr(struct net_pkt *pkt) -{ - return net_pkt_lladdr_src(pkt)->type == NET_LINK_CANBUS ? - canbus_get_lladdr(net_pkt_lladdr_src(pkt)) : - NET_CAN_ETH_TRANSLATOR_ADDR; -} - -static uint16_t canbus_get_dest_lladdr(struct net_pkt *pkt) -{ - return net_pkt_lladdr_dst(pkt)->type == NET_LINK_CANBUS && - net_pkt_lladdr_dst(pkt)->len == sizeof(struct net_canbus_lladdr) ? - canbus_get_lladdr(net_pkt_lladdr_dst(pkt)) : - NET_CAN_ETH_TRANSLATOR_ADDR; -} - -static inline bool canbus_dest_is_mcast(struct net_pkt *pkt) -{ - uint16_t lladdr_be = UNALIGNED_GET((uint16_t *)net_pkt_lladdr_dst(pkt)->addr); - - return (sys_be16_to_cpu(lladdr_be) & CAN_NET_IF_IS_MCAST_BIT); -} - -static bool canbus_src_is_translator(struct net_pkt *pkt) -{ - return ((canbus_get_src_lladdr(pkt) & CAN_NET_IF_ADDR_MASK) == - NET_CAN_ETH_TRANSLATOR_ADDR); -} - -static bool canbus_dest_is_translator(struct net_pkt *pkt) -{ - return (net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET || - net_pkt_lladdr_dst(pkt)->len == sizeof(struct net_eth_addr)); -} - -#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) -static bool canbus_is_for_translator(struct net_pkt *pkt) -{ - return ((net_pkt_lladdr_dst(pkt)->type == NET_LINK_CANBUS) && - (canbus_get_lladdr(net_pkt_lladdr_dst(pkt)) == - NET_CAN_ETH_TRANSLATOR_ADDR)); -} -#else -#define canbus_is_for_translator(...) false -#endif /* CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR */ - -static size_t canbus_total_lladdr_len(struct net_pkt *pkt) -{ - /* This pkt will be farowarded to Ethernet - * Destination MAC is carried inline, source is going to be extended - */ - if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) && - canbus_is_for_translator(pkt)) { - return sizeof(struct net_eth_addr) + - sizeof(struct net_canbus_lladdr); - } - - return 2U * sizeof(struct net_canbus_lladdr); -} - -static inline void canbus_cpy_lladdr(struct net_pkt *dst, struct net_pkt *src) -{ - struct net_linkaddr *lladdr; - - lladdr = net_pkt_lladdr_dst(dst); - lladdr->addr = net_pkt_cursor_get_pos(dst); - net_pkt_write(dst, net_pkt_lladdr_dst(src)->addr, - sizeof(struct net_canbus_lladdr)); - lladdr->len = sizeof(struct net_canbus_lladdr); - lladdr->type = NET_LINK_CANBUS; - - if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) && - canbus_is_for_translator(src)) { - /* Make room for address extension */ - net_pkt_skip(dst, sizeof(struct net_eth_addr) - - sizeof(struct net_canbus_lladdr)); - } - - lladdr = net_pkt_lladdr_src(dst); - lladdr->addr = net_pkt_cursor_get_pos(dst); - - if (canbus_src_is_translator(src)) { - net_pkt_copy(dst, src, sizeof(struct net_eth_addr)); - lladdr->len = sizeof(struct net_eth_addr); - lladdr->type = NET_LINK_ETHERNET; - NET_DBG("Inline MAC: %02x:%02x:%02x:%02x:%02x:%02x", - lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], - lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]); - } else { - net_pkt_write(dst, net_pkt_lladdr_src(src)->addr, - sizeof(struct net_canbus_lladdr)); - lladdr->len = sizeof(struct net_canbus_lladdr); - lladdr->type = NET_LINK_CANBUS; - } -} - - -static struct canbus_isotp_rx_ctx *canbus_get_rx_ctx(uint8_t state, - uint16_t src_addr) -{ - int i; - struct canbus_isotp_rx_ctx *ret = NULL; - - k_mutex_lock(&l2_ctx.rx_ctx_mtx, K_FOREVER); - for (i = 0; i < ARRAY_SIZE(l2_ctx.rx_ctx); i++) { - struct canbus_isotp_rx_ctx *ctx = &l2_ctx.rx_ctx[i]; - - if (ctx->state == state) { - if (state == NET_CAN_RX_STATE_UNUSED) { - ctx->state = NET_CAN_RX_STATE_RESET; - z_init_timeout(&ctx->timeout); - ret = ctx; - break; - } - - if (canbus_get_src_lladdr(ctx->pkt) == src_addr) { - ret = ctx; - break; - } - } - } - - k_mutex_unlock(&l2_ctx.rx_ctx_mtx); - return ret; -} - -static struct canbus_isotp_tx_ctx *canbus_get_tx_ctx(uint8_t state, - uint16_t dest_addr) -{ - int i; - struct canbus_isotp_tx_ctx *ret = NULL; - - k_mutex_lock(&l2_ctx.tx_ctx_mtx, K_FOREVER); - for (i = 0; i < ARRAY_SIZE(l2_ctx.tx_ctx); i++) { - struct canbus_isotp_tx_ctx *ctx = &l2_ctx.tx_ctx[i]; - - if (ctx->state == state) { - if (state == NET_CAN_TX_STATE_UNUSED) { - ctx->state = NET_CAN_TX_STATE_RESET; - z_init_timeout(&ctx->timeout); - ret = ctx; - break; - } - - if (ctx->dest_addr.addr == dest_addr) { - ret = ctx; - break; - } - } - } - - k_mutex_unlock(&l2_ctx.tx_ctx_mtx); - return ret; -} - -static inline uint16_t canbus_receive_get_ff_length(struct net_pkt *pkt) -{ - uint16_t len; - int ret; - - ret = net_pkt_read_be16(pkt, &len); - if (ret < 0) { - NET_ERR("Can't read length"); - } - - return len & 0x0FFF; -} - -static inline size_t canbus_get_sf_length(struct net_pkt *pkt) -{ - size_t len; - - net_buf_pull_u8(pkt->frags); - len = net_buf_pull_u8(pkt->frags); - - return len; -} - -static inline void canbus_set_frame_datalength(struct zcan_frame *frame, - uint8_t length) -{ - /* TODO: Needs update when CAN FD support is added */ - NET_ASSERT(length <= NET_CAN_DL); - frame->dlc = length; -} - -static enum net_verdict canbus_finish_pkt(struct net_pkt *pkt) -{ - /* Pull the ll addresses to ignore them in upper layers */ - net_buf_pull(pkt->buffer, net_pkt_lladdr_dst(pkt)->len + - net_pkt_lladdr_src(pkt)->len); - - if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) && - canbus_is_for_translator(pkt)) { - /* Pull room for address extension */ - net_buf_pull(pkt->buffer, sizeof(struct net_eth_addr) - - net_pkt_lladdr_src(pkt)->len); - /* Set the destination address to the inline MAC and pull it */ - net_pkt_cursor_init(pkt); - net_pkt_lladdr_dst(pkt)->addr = net_pkt_cursor_get_pos(pkt); - net_pkt_lladdr_dst(pkt)->type = NET_LINK_ETHERNET; - net_pkt_lladdr_dst(pkt)->len = sizeof(struct net_eth_addr); - net_buf_pull(pkt->buffer, sizeof(struct net_eth_addr)); - } - - net_pkt_cursor_init(pkt); - if (!net_6lo_uncompress(pkt)) { - NET_ERR("6lo uncompression failed"); - return NET_DROP; - } - - net_pkt_cursor_init(pkt); - - return NET_CONTINUE; -} - -static inline uint32_t canbus_addr_to_id(uint16_t dest, uint16_t src) -{ - return (dest << CAN_NET_IF_ADDR_DEST_POS) | - (src << CAN_NET_IF_ADDR_SRC_POS); -} - -static void canbus_set_frame_addr(struct zcan_frame *frame, - const struct net_canbus_lladdr *dest, - const struct net_canbus_lladdr *src, - bool mcast) -{ - frame->id_type = CAN_EXTENDED_IDENTIFIER; - frame->rtr = CAN_DATAFRAME; - - frame->id = canbus_addr_to_id(dest->addr, src->addr); - - if (mcast) { - frame->id |= CAN_NET_IF_ADDR_MCAST_MASK; - } -} - -static void canbus_set_frame_addr_pkt(struct zcan_frame *frame, - struct net_pkt *pkt, - struct net_canbus_lladdr *dest_addr, - bool mcast) -{ - struct net_canbus_lladdr src_addr; - - if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) && - net_pkt_lladdr_src(pkt)->type == NET_LINK_ETHERNET) { - src_addr.addr = NET_CAN_ETH_TRANSLATOR_ADDR; - } else { - src_addr.addr = canbus_get_lladdr(net_if_get_link_addr(pkt->iface)); - } - - canbus_set_frame_addr(frame, dest_addr, &src_addr, mcast); -} - -static void canbus_fc_send_cb(int error, void *arg) -{ - if (error != 0) { - NET_ERR("Sending FC frame failed: %d", error); - } -} - -static int canbus_send_fc(const struct device *net_can_dev, - struct net_canbus_lladdr *dest, - struct net_canbus_lladdr *src, uint8_t fs) -{ - const struct net_can_api *api = net_can_dev->api; - struct zcan_frame frame = { - .id_type = CAN_EXTENDED_IDENTIFIER, - .rtr = CAN_DATAFRAME, - }; - - NET_ASSERT(!(fs & NET_CAN_PCI_TYPE_MASK)); - - canbus_set_frame_addr(&frame, dest, src, false); - - frame.data[0] = NET_CAN_PCI_TYPE_FC | fs; - /* BS (Block Size) */ - frame.data[1] = NET_CAN_BS; - /* STmin (minimum Seperation Time) */ - frame.data[2] = NET_CAN_STMIN; - canbus_set_frame_datalength(&frame, 3); - - NET_DBG("Sending FC to ID: 0x%08x", frame.id); - return api->send(net_can_dev, &frame, canbus_fc_send_cb, NULL, - K_FOREVER); -} - -static int canbus_process_cf_data(struct net_pkt *frag_pkt, - struct canbus_isotp_rx_ctx *ctx) -{ - struct net_pkt *pkt = ctx->pkt; - size_t data_len = net_pkt_get_len(frag_pkt) - 1; - uint8_t pci; - int ret; - - pci = net_buf_pull_u8(frag_pkt->frags); - - if ((pci & NET_CAN_PCI_SN_MASK) != ctx->sn) { - NET_ERR("Sequence number missmatch. Expect %u, got %u", - ctx->sn, pci & NET_CAN_PCI_SN_MASK); - goto err; - } - - ctx->sn++; - - if (data_len > ctx->rem_len) { - NET_DBG("Remove padding of %d bytes", data_len - ctx->rem_len); - data_len = ctx->rem_len; - } - - net_pkt_cursor_init(frag_pkt); - NET_DBG("Appending CF data to pkt (%d bytes)", data_len); - ret = net_pkt_copy(pkt, frag_pkt, data_len); - if (ret < 0) { - NET_ERR("Failed to write data to pkt [%d]", ret); - goto err; - } - - ctx->rem_len -= data_len; - - NET_DBG("%u bytes remaining", ctx->rem_len); - - return 0; -err: - canbus_rx_report_err(pkt); - return -1; -} - -static enum net_verdict canbus_process_cf(struct net_pkt *pkt) -{ - struct canbus_isotp_rx_ctx *rx_ctx; - enum net_verdict ret; - const struct device *net_can_dev; - struct net_canbus_lladdr src, dest; - bool mcast; - - mcast = canbus_dest_is_mcast(pkt); - - rx_ctx = canbus_get_rx_ctx(NET_CAN_RX_STATE_CF, - canbus_get_src_lladdr(pkt)); - if (!rx_ctx) { - NET_INFO("Got CF but can't find a CTX that is waiting for it. " - "Src: 0x%04x", canbus_get_src_lladdr(pkt)); - return NET_DROP; - } - - z_abort_timeout(&rx_ctx->timeout); - - ret = canbus_process_cf_data(pkt, rx_ctx); - if (ret < 0) { - return NET_DROP; - } - - net_pkt_unref(pkt); - - if (rx_ctx->rem_len == 0) { - rx_ctx->state = NET_CAN_RX_STATE_FIN; - ret = net_recv_data(pkt->iface, rx_ctx->pkt); - if (ret < 0) { - NET_ERR("Packet dropped by NET stack"); - net_pkt_unref(pkt); - } - } else { - z_add_timeout(&rx_ctx->timeout, canbus_rx_timeout, - NET_CAN_BS_TIME); - - if (NET_CAN_BS != 0 && !mcast) { - rx_ctx->act_block_nr++; - if (rx_ctx->act_block_nr >= NET_CAN_BS) { - NET_DBG("BS reached. Send FC"); - src.addr = canbus_get_src_lladdr(pkt); - dest.addr = canbus_get_dest_lladdr(pkt); - net_can_dev = net_if_get_device(pkt->iface); - ret = canbus_send_fc(net_can_dev, &src, &dest, - NET_CAN_PCI_FS_CTS); - if (ret) { - NET_ERR("Failed to send FC CTS. BS: %d", - NET_CAN_BS); - canbus_rx_report_err(rx_ctx->pkt); - return NET_OK; - } - - rx_ctx->act_block_nr = 0; - } - } - } - - return NET_OK; -} - -static enum net_verdict canbus_process_ff(struct net_pkt *pkt) -{ - const struct device *net_can_dev = net_if_get_device(pkt->iface); - struct canbus_isotp_rx_ctx *rx_ctx = NULL; - struct net_pkt *new_pkt = NULL; - int ret; - struct net_canbus_lladdr src, dest; - uint16_t msg_len; - size_t new_pkt_len; - uint8_t data_len; - bool mcast; - - mcast = canbus_dest_is_mcast(pkt); - src.addr = canbus_get_src_lladdr(pkt); - dest.addr = canbus_get_dest_lladdr(pkt); - net_pkt_cursor_init(pkt); - - msg_len = canbus_receive_get_ff_length(pkt); - - new_pkt_len = msg_len + canbus_total_lladdr_len(pkt); - - new_pkt = net_pkt_rx_alloc_with_buffer(pkt->iface, new_pkt_len, - AF_INET6, 0, - NET_CAN_ALLOC_TIMEOUT); - if (!new_pkt) { - NET_ERR("Failed to obtain net_pkt with size of %d", new_pkt_len); - - if (!mcast) { - canbus_send_fc(net_can_dev, &src, &dest, - NET_CAN_PCI_FS_OVFLW); - } - - goto err; - } - - rx_ctx = canbus_get_rx_ctx(NET_CAN_RX_STATE_UNUSED, 0); - if (!rx_ctx) { - NET_ERR("No rx context left"); - - if (!mcast) { - canbus_send_fc(net_can_dev, &src, &dest, - NET_CAN_PCI_FS_OVFLW); - } - - goto err; - } - - rx_ctx->act_block_nr = 0; - rx_ctx->pkt = new_pkt; - new_pkt->canbus_rx_ctx = rx_ctx; - - net_pkt_cursor_init(new_pkt); - data_len = net_pkt_remaining_data(pkt); - canbus_cpy_lladdr(new_pkt, pkt); - rx_ctx->sn = 1; - - ret = net_pkt_copy(new_pkt, pkt, net_pkt_remaining_data(pkt)); - if (ret) { - NET_ERR("Failed to write to pkt [%d]", ret); - goto err; - } - - rx_ctx->rem_len = msg_len - data_len; - net_pkt_unref(pkt); - - if (!mcast) { - /* switch src and dest because we are answering */ - ret = canbus_send_fc(net_can_dev, &src, &dest, - NET_CAN_PCI_FS_CTS); - if (ret) { - NET_ERR("Failed to send FC CTS"); - canbus_rx_report_err(new_pkt); - return NET_OK; - } - } - - /* At this point we expect to get Consecutive frames directly */ - z_add_timeout(&rx_ctx->timeout, canbus_rx_timeout, NET_CAN_BS_TIME); - - rx_ctx->state = NET_CAN_RX_STATE_CF; - - NET_DBG("Processed FF from 0x%04x (%scast)" - "Msg length: %u CTX: %p", - src.addr, mcast ? "m" : "uni", msg_len, rx_ctx); - - return NET_OK; - -err: - if (new_pkt) { - net_pkt_unref(new_pkt); - } - - if (rx_ctx) { - canbus_free_rx_ctx(rx_ctx); - } - - return NET_DROP; -} - -static enum net_verdict canbus_process_sf(struct net_pkt *pkt) -{ - size_t data_len; - size_t pkt_len; - - net_pkt_set_family(pkt, AF_INET6); - - data_len = canbus_get_sf_length(pkt); - pkt_len = net_pkt_get_len(pkt); - - if (data_len > pkt_len) { - NET_ERR("SF datalen > pkt size"); - return NET_DROP; - } - - if (pkt_len != data_len) { - NET_DBG("Remove padding (%d byte)", pkt_len - data_len); - net_pkt_update_length(pkt, data_len); - } - - return canbus_finish_pkt(pkt); -} - -static void canbus_tx_frame_isr(int error, void *arg) -{ - struct net_pkt *pkt = (struct net_pkt *)arg; - struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx; - struct net_if *iface = net_pkt_iface(pkt); - struct canbus_net_ctx *net_ctx = net_if_l2_data(iface); - - ctx->tx_backlog--; - - if (ctx->state == NET_CAN_TX_STATE_WAIT_TX_BACKLOG) { - if (ctx->tx_backlog > 0) { - return; - } - - ctx->state = NET_CAN_TX_STATE_FIN; - } - - submit_to_queue(&net_ctx->tx_queue, pkt); -} - -static inline int canbus_send_cf(struct net_pkt *pkt) -{ - struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx; - const struct device *net_can_dev = net_if_get_device(pkt->iface); - const struct net_can_api *api = net_can_dev->api; - struct zcan_frame frame; - struct net_pkt_cursor cursor_backup; - int ret, len; - - canbus_set_frame_addr_pkt(&frame, pkt, &ctx->dest_addr, ctx->is_mcast); - - /* sn wraps around at 0xF automatically because it has a 4 bit size */ - frame.data[0] = NET_CAN_PCI_TYPE_CF | ctx->sn; - - len = MIN(ctx->rem_len, NET_CAN_DL - 1); - - canbus_set_frame_datalength(&frame, len + 1); - - net_pkt_cursor_backup(pkt, &cursor_backup); - net_pkt_read(pkt, &frame.data[1], len); - ret = api->send(net_can_dev, &frame, canbus_tx_frame_isr, - pkt, K_NO_WAIT); - if (ret == 0) { - ctx->sn++; - ctx->rem_len -= len; - ctx->act_block_nr--; - ctx->tx_backlog++; - } else { - net_pkt_cursor_restore(pkt, &cursor_backup); - } - - NET_DBG("CF sent. %d bytes left. CTX: %p", ctx->rem_len, ctx); - - return ret ? ret : ctx->rem_len; -} - -static void canbus_tx_work(struct net_pkt *pkt) -{ - int ret; - struct canbus_isotp_tx_ctx *ctx = pkt->canbus_tx_ctx; - - NET_ASSERT(ctx); - - switch (ctx->state) { - case NET_CAN_TX_STATE_SEND_CF: - do { - ret = canbus_send_cf(ctx->pkt); - if (!ret) { - ctx->state = NET_CAN_TX_STATE_WAIT_TX_BACKLOG; - break; - } - - if (ret < 0 && ret != -EAGAIN) { - NET_ERR("Failed to send CF. CTX: %p", ctx); - canbus_tx_report_err(pkt); - break; - } - - if (ctx->opts.bs && !ctx->is_mcast && - !ctx->act_block_nr) { - NET_DBG("BS reached. Wait for FC again. CTX: %p", - ctx); - ctx->state = NET_CAN_TX_STATE_WAIT_FC; - z_add_timeout(&ctx->timeout, canbus_tx_timeout, - NET_CAN_BS_TIME); - break; - } else if (ctx->opts.stmin) { - ctx->state = NET_CAN_TX_STATE_WAIT_ST; - break; - } - } while (ret > 0); - - break; - - case NET_CAN_TX_STATE_WAIT_ST: - NET_DBG("SM wait ST. CTX: %p", ctx); - z_add_timeout(&ctx->timeout, canbus_st_min_timeout, - canbus_stmin_to_ticks(ctx->opts.stmin)); - ctx->state = NET_CAN_TX_STATE_SEND_CF; - break; - - case NET_CAN_TX_STATE_ERR: - NET_DBG("SM handle error. CTX: %p", ctx); - canbus_tx_report_err(pkt); - break; - - case NET_CAN_TX_STATE_FIN: - canbus_tx_finish(ctx->pkt); - NET_DBG("SM finish. CTX: %p", ctx); - break; - - default: - break; - } -} - -static enum net_verdict canbus_process_fc_data(struct canbus_isotp_tx_ctx *ctx, - struct net_pkt *pkt) -{ - struct net_buf *buf = pkt->frags; - uint8_t pci; - - pci = net_buf_pull_u8(buf); - - switch (pci & NET_CAN_PCI_FS_MASK) { - case NET_CAN_PCI_FS_CTS: - if (net_buf_frags_len(buf) != 2) { - NET_ERR("Frame length error for CTS"); - canbus_tx_report_err(pkt); - return NET_DROP; - } - - ctx->state = NET_CAN_TX_STATE_SEND_CF; - ctx->wft = 0; - ctx->opts.bs = net_buf_pull_u8(buf); - ctx->opts.stmin = net_buf_pull_u8(buf); - ctx->act_block_nr = ctx->opts.bs; - z_abort_timeout(&ctx->timeout); - NET_DBG("Got CTS. BS: %d, STmin: %d. CTX: %p", - ctx->opts.bs, ctx->opts.stmin, ctx); - net_pkt_unref(pkt); - return NET_OK; - case NET_CAN_PCI_FS_WAIT: - NET_DBG("Got WAIT frame. CTX: %p", ctx); - z_abort_timeout(&ctx->timeout); - z_add_timeout(&ctx->timeout, canbus_tx_timeout, - NET_CAN_BS_TIME); - if (ctx->wft >= NET_CAN_WFTMAX) { - NET_INFO("Got to many wait frames. CTX: %p", ctx); - ctx->state = NET_CAN_TX_STATE_ERR; - } - - ctx->wft++; - return NET_OK; - case NET_CAN_PCI_FS_OVFLW: - NET_ERR("Got overflow FC frame. CTX: %p", ctx); - ctx->state = NET_CAN_TX_STATE_ERR; - return NET_OK; - default: - NET_ERR("Invalid Frame Status. CTX: %p", ctx); - ctx->state = NET_CAN_TX_STATE_ERR; - break; - } - - return NET_DROP; -} - -static enum net_verdict canbus_process_fc(struct net_pkt *pkt) -{ - struct canbus_isotp_tx_ctx *tx_ctx; - uint16_t src_addr = canbus_get_src_lladdr(pkt); - enum net_verdict ret; - struct net_if *iface = net_pkt_iface(pkt); - struct canbus_net_ctx *net_ctx = net_if_l2_data(iface); - - tx_ctx = canbus_get_tx_ctx(NET_CAN_TX_STATE_WAIT_FC, src_addr); - if (!tx_ctx) { - NET_WARN("Got FC frame from 0x%04x but can't find any " - "CTX waiting for it", src_addr); - return NET_DROP; - } - - ret = canbus_process_fc_data(tx_ctx, pkt); - if (ret == NET_OK) { - submit_to_queue(&net_ctx->tx_queue, tx_ctx->pkt); - } - - return ret; -} - -static inline int canbus_send_ff(struct net_pkt *pkt, size_t len, bool mcast, - struct net_canbus_lladdr *dest_addr) -{ - const struct device *net_can_dev = net_if_get_device(pkt->iface); - const struct net_can_api *api = net_can_dev->api; - struct net_linkaddr *lladdr_inline; - struct zcan_frame frame; - int ret, index = 0; - - canbus_set_frame_addr_pkt(&frame, pkt, dest_addr, mcast); - canbus_set_frame_datalength(&frame, NET_CAN_DL); - - if (mcast) { - NET_DBG("Sending FF (multicast). ID: 0x%08x. PKT len: %zu" - " CTX: %p", - frame.id, len, pkt->canbus_tx_ctx); - } else { - NET_DBG("Sending FF (unicast). ID: 0x%08x. PKT len: %zu" - " CTX: %p", - frame.id, len, pkt->canbus_tx_ctx); - } - -#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) - NET_ASSERT(mcast || !(canbus_dest_is_translator(pkt) && - canbus_src_is_translator(pkt))); - - if (canbus_src_is_translator(pkt)) { - len += net_pkt_lladdr_src(pkt)->len; - } -#endif - if (!mcast && canbus_dest_is_translator(pkt)) { - len += net_pkt_lladdr_dst(pkt)->len; - } - - frame.data[index++] = NET_CAN_PCI_TYPE_FF | (len >> 8); - frame.data[index++] = len & 0xFF; - - /* According to ISO, FF has sn 0 and is incremented to one - * alltough it's not part of the FF frame - */ - pkt->canbus_tx_ctx->sn = 1; - - if (!mcast && canbus_dest_is_translator(pkt)) { - lladdr_inline = net_pkt_lladdr_dst(pkt); - memcpy(&frame.data[index], lladdr_inline->addr, - lladdr_inline->len); - index += lladdr_inline->len; - } - - if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) && - net_pkt_lladdr_src(pkt)->type == NET_LINK_ETHERNET) { - lladdr_inline = net_pkt_lladdr_src(pkt); - memcpy(&frame.data[index], lladdr_inline->addr, - lladdr_inline->len); - index += lladdr_inline->len; - } - - net_pkt_read(pkt, &frame.data[index], NET_CAN_DL - index); - pkt->canbus_tx_ctx->rem_len -= NET_CAN_DL - index; - - ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER); - if (ret != 0) { - NET_ERR("Sending FF failed [%d]. CTX: %p", - ret, pkt->canbus_tx_ctx); - } - - return ret; -} - -static inline int canbus_send_single_frame(struct net_pkt *pkt, size_t len, - bool mcast, - struct net_canbus_lladdr *dest_addr) -{ - const struct device *net_can_dev = net_if_get_device(pkt->iface); - const struct net_can_api *api = net_can_dev->api; - int index = 0; - struct zcan_frame frame; - struct net_linkaddr *lladdr_dest; - int ret; - - canbus_set_frame_addr_pkt(&frame, pkt, dest_addr, mcast); - - frame.data[index++] = NET_CAN_PCI_TYPE_SF; - frame.data[index++] = len; - - NET_ASSERT((len + (!mcast && canbus_dest_is_translator(pkt)) ? - net_pkt_lladdr_dst(pkt)->len : 0) <= NET_CAN_DL - 1); - - if (!mcast && canbus_dest_is_translator(pkt)) { - lladdr_dest = net_pkt_lladdr_dst(pkt); - memcpy(&frame.data[index], lladdr_dest->addr, lladdr_dest->len); - index += lladdr_dest->len; - } - - net_pkt_read(pkt, &frame.data[index], len); - - canbus_set_frame_datalength(&frame, len + index); - - ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER); - if (ret != 0) { - NET_ERR("Sending SF failed [%d]", ret); - return -EIO; - } - - return 0; -} - -static void canbus_start_sending_cf(struct _timeout *t) -{ - struct canbus_isotp_tx_ctx *ctx = - CONTAINER_OF(t, struct canbus_isotp_tx_ctx, timeout); - struct net_if *iface = net_pkt_iface(ctx->pkt); - struct canbus_net_ctx *net_ctx = net_if_l2_data(iface); - - submit_to_queue(&net_ctx->tx_queue, ctx->pkt); -} - -static int canbus_send_multiple_frames(struct net_pkt *pkt, size_t len, - bool mcast, - struct net_canbus_lladdr *dest_addr) -{ - struct canbus_isotp_tx_ctx *tx_ctx = NULL; - int ret; - - tx_ctx = canbus_get_tx_ctx(NET_CAN_TX_STATE_UNUSED, 0); - - if (!tx_ctx) { - NET_ERR("No tx context left"); - k_sem_give(&l2_ctx.tx_sem); - return -EAGAIN; - } - - tx_ctx->pkt = pkt; - pkt->canbus_tx_ctx = tx_ctx; - tx_ctx->is_mcast = mcast; - tx_ctx->dest_addr = *dest_addr; - tx_ctx->rem_len = net_pkt_get_len(pkt); - tx_ctx->tx_backlog = 0; - - ret = canbus_send_ff(pkt, len, mcast, dest_addr); - if (ret != 0) { - NET_ERR("Failed to send FF [%d]", ret); - canbus_tx_report_err(pkt); - return -EIO; - } - - if (!mcast) { - z_add_timeout(&tx_ctx->timeout, canbus_tx_timeout, - NET_CAN_BS_TIME); - tx_ctx->state = NET_CAN_TX_STATE_WAIT_FC; - } else { - tx_ctx->state = NET_CAN_TX_STATE_SEND_CF; - z_add_timeout(&tx_ctx->timeout, canbus_start_sending_cf, - NET_CAN_FF_CF_TIME); - } - - return 0; -} - -static void canbus_ipv6_mcast_to_dest(struct net_pkt *pkt, - struct net_canbus_lladdr *dest_addr) -{ - dest_addr->addr = - sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)&NET_IPV6_HDR(pkt)->dst[14])); -} - -static inline uint16_t canbus_eth_to_can_addr(struct net_linkaddr *lladdr) -{ - return (sys_be16_to_cpu(UNALIGNED_GET((uint16_t *)&lladdr->addr[4])) & - CAN_NET_IF_ADDR_MASK); -} - -static int canbus_send(struct net_if *iface, struct net_pkt *pkt) -{ - int ret = 0; - int comp_len; - size_t pkt_len, inline_lladdr_len; - struct net_canbus_lladdr dest_addr; - bool mcast; - - if (net_pkt_family(pkt) != AF_INET6) { - return -EINVAL; - } - - mcast = net_ipv6_is_addr_mcast((struct in6_addr *)NET_IPV6_HDR(pkt)->dst); - if (mcast || canbus_dest_is_mcast(pkt)) { - canbus_ipv6_mcast_to_dest(pkt, &dest_addr); - } else if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) && - net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET) { - struct net_linkaddr *lladdr = net_pkt_lladdr_dst(pkt); - - lladdr->type = NET_LINK_CANBUS; - lladdr->len = sizeof(struct net_canbus_lladdr); - dest_addr.addr = canbus_eth_to_can_addr(net_pkt_lladdr_dst(pkt)); - NET_DBG("Translated %02x:%02x:%02x:%02x:%02x:%02x to 0x%04x", - lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], - lladdr->addr[3], lladdr->addr[4], lladdr->addr[5], - dest_addr.addr); - } else { - dest_addr.addr = canbus_get_dest_lladdr(pkt); - } - - net_pkt_cursor_init(pkt); - canbus_print_ip_hdr((struct net_ipv6_hdr *)net_pkt_cursor_get_pos(pkt)); - comp_len = net_6lo_compress(pkt, true); - if (comp_len < 0) { - NET_ERR("IPHC failed [%d]", comp_len); - return comp_len; - } - - NET_DBG("IPv6 hdr compressed by %d bytes", comp_len); - net_pkt_cursor_init(pkt); - pkt_len = net_pkt_get_len(pkt); - - net_capture_pkt(iface, pkt); - - NET_DBG("Send CAN frame to 0x%04x%s", dest_addr.addr, - mcast ? " (mcast)" : ""); - - inline_lladdr_len = (!mcast && canbus_dest_is_translator(pkt)) ? - net_pkt_lladdr_dst(pkt)->len : 0; - - if ((pkt_len + inline_lladdr_len) > (NET_CAN_DL - 1)) { - k_sem_take(&l2_ctx.tx_sem, K_FOREVER); - ret = canbus_send_multiple_frames(pkt, pkt_len, mcast, - &dest_addr); - } else { - ret = canbus_send_single_frame(pkt, pkt_len, mcast, &dest_addr); - canbus_tx_finish(pkt); - } - - return ret; -} - -static enum net_verdict canbus_process_frame(struct net_pkt *pkt) -{ - enum net_verdict ret = NET_DROP; - uint8_t pci_type; - - net_pkt_cursor_init(pkt); - ret = net_pkt_read_u8(pkt, &pci_type); - if (ret < 0) { - NET_ERR("Can't read PCI"); - } - pci_type = (pci_type & NET_CAN_PCI_TYPE_MASK) >> NET_CAN_PCI_TYPE_POS; - - switch (pci_type) { - case NET_CAN_PCI_SF: - ret = canbus_process_sf(pkt); - break; - case NET_CAN_PCI_FF: - ret = canbus_process_ff(pkt); - break; - case NET_CAN_PCI_CF: - ret = canbus_process_cf(pkt); - break; - case NET_CAN_PCI_FC: - ret = canbus_process_fc(pkt); - break; - default: - NET_ERR("Unknown PCI number %u", pci_type); - break; - } - - return ret; -} - -#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) -static void forward_eth_frame(struct net_pkt *pkt, struct net_if *canbus_iface) -{ - pkt->iface = canbus_iface; - net_if_queue_tx(canbus_iface, pkt); -} - -static struct net_ipv6_hdr *get_ip_hdr_from_eth_frame(struct net_pkt *pkt) -{ - return (struct net_ipv6_hdr *)((uint8_t *)net_pkt_data(pkt) + - sizeof(struct net_eth_hdr)); -} - -enum net_verdict net_canbus_translate_eth_frame(struct net_if *iface, - struct net_pkt *pkt) -{ - struct net_linkaddr *lladdr = net_pkt_lladdr_dst(pkt); - struct net_pkt *clone_pkt; - struct net_if *canbus_iface; - - /* Forward only IPv6 frames */ - if ((get_ip_hdr_from_eth_frame(pkt)->vtc & 0xf0) != 0x60) { - return NET_CONTINUE; - } - - /* This frame is for the Ethernet interface itself */ - if (net_linkaddr_cmp(net_if_get_link_addr(iface), lladdr)) { - NET_DBG("Frame is for Ethernet only %02x:%02x:%02x:%02x:%02x:%02x", - lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], - lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]); - return NET_CONTINUE; - } - - canbus_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(CANBUS)); - - net_pkt_cursor_init(pkt); - /* Forward all broadcasts */ - if (net_eth_is_addr_broadcast((struct net_eth_addr *)lladdr->addr) || - net_eth_is_addr_multicast((struct net_eth_addr *)lladdr->addr)) { - if (!canbus_iface || !net_if_is_up(canbus_iface)) { - NET_ERR("No canbus iface"); - return NET_CONTINUE; - } - - clone_pkt = net_pkt_shallow_clone(pkt, NET_CAN_ALLOC_TIMEOUT); - if (clone_pkt) { - NET_DBG("Frame is %scast %02x:%02x:%02x:%02x:%02x:%02x,", - net_eth_is_addr_broadcast( - (struct net_eth_addr *)lladdr->addr) ? "broad" : - "multi", - lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], - lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]); - net_pkt_set_family(clone_pkt, AF_INET6); - forward_eth_frame(clone_pkt, canbus_iface); - } else { - NET_ERR("PKT forwarding: cloning failed"); - } - - return NET_CONTINUE; - } - - if (!canbus_iface || !net_if_is_up(canbus_iface)) { - NET_ERR("No canbus iface"); - return NET_DROP; - } - - /* This frame is for 6LoCAN only */ - net_pkt_set_family(pkt, AF_INET6); - net_buf_pull(pkt->buffer, sizeof(struct net_eth_hdr)); - forward_eth_frame(pkt, canbus_iface); - NET_DBG("Frame is for CANBUS: 0x%04x", canbus_get_dest_lladdr(pkt)); - - return NET_OK; -} - -static void forward_can_frame(struct net_pkt *pkt, struct net_if *eth_iface) -{ - net_pkt_set_iface(pkt, eth_iface); - net_if_queue_tx(eth_iface, pkt); -} - -static void rewrite_icmp_hdr(struct net_pkt *pkt, struct net_icmp_hdr *icmp_hdr) -{ - int ret; - - net_pkt_cursor_init(pkt); - net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr)); - ret = net_icmpv6_create(pkt, icmp_hdr->type, icmp_hdr->code); - if (ret) { - NET_ERR("Can't create ICMP HDR"); - return; - } - - net_pkt_cursor_init(pkt); - net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr)); - ret = net_icmpv6_finalize(pkt); - if (ret) { - NET_ERR("Can't finalize ICMP HDR"); - } -} - -static void extend_llao(struct net_pkt *pkt, struct net_linkaddr *mac_addr) -{ - NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_access, struct net_icmp_hdr); - NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(icmp_opt_access, - struct net_icmpv6_nd_opt_hdr); - NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(llao_access, - struct net_eth_addr); - struct net_pkt_cursor cursor_backup; - struct net_icmp_hdr *icmp_hdr; - struct net_icmpv6_nd_opt_hdr *icmp_opt_hdr; - uint8_t *llao, llao_backup[2]; - int ret; - - net_pkt_cursor_backup(pkt, &cursor_backup); - net_pkt_cursor_init(pkt); - net_pkt_set_overwrite(pkt, true); - net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr)); - - if (net_calc_chksum(pkt, IPPROTO_ICMPV6) != 0U) { - NET_ERR("Invalid checksum"); - return; - } - - icmp_hdr = (struct net_icmp_hdr *)net_pkt_get_data(pkt, &icmp_access); - if (!icmp_hdr) { - NET_ERR("No ICMP6 HDR"); - goto done; - } - - switch (icmp_hdr->type) { - - case NET_ICMPV6_NS: - net_pkt_skip(pkt, sizeof(struct net_icmpv6_ns_hdr)); - NET_DBG("Extend NS SLLAO"); - break; - - case NET_ICMPV6_NA: - net_pkt_skip(pkt, sizeof(struct net_icmpv6_na_hdr)); - NET_DBG("Extend NA TLLAO"); - break; - - case NET_ICMPV6_RS: - net_pkt_skip(pkt, sizeof(struct net_icmpv6_rs_hdr)); - NET_DBG("Extend RS SLLAO"); - break; - - case NET_ICMPV6_RA: - net_pkt_skip(pkt, sizeof(struct net_icmpv6_ra_hdr)); - NET_DBG("Extend RA SLLAO"); - break; - - default: - goto done; - } - - net_pkt_acknowledge_data(pkt, &icmp_access); - - icmp_opt_hdr = (struct net_icmpv6_nd_opt_hdr *) - net_pkt_get_data(pkt, &icmp_opt_access); - if (!icmp_opt_hdr) { - NET_DBG("No LLAO opt to extend"); - goto done; - } - - net_pkt_acknowledge_data(pkt, &icmp_opt_access); - - if (icmp_opt_hdr->type != NET_ICMPV6_ND_OPT_SLLAO && - (icmp_hdr->type == NET_ICMPV6_NA && - icmp_opt_hdr->type != NET_ICMPV6_ND_OPT_TLLAO)) { - NET_DBG("opt was not LLAO"); - goto done; - } - - if (icmp_opt_hdr->len != 1) { - NET_ERR("LLAO len is %u. This should be 1 for 6LoCAN", - icmp_opt_hdr->len); - goto done; - } - - llao = (uint8_t *)net_pkt_get_data(pkt, &llao_access); - if (!llao) { - NET_ERR("Can't read LLAO"); - goto done; - } - - memcpy(llao_backup, llao, sizeof(struct net_canbus_lladdr)); - memcpy(llao, mac_addr->addr, mac_addr->len); - - llao[4] = (llao[4] & 0xC0) | llao_backup[0]; - llao[5] = llao_backup[1]; - - ret = net_pkt_set_data(pkt, &llao_access); - if (ret < 0) { - NET_ERR("Failed to write MAC to LLAO [%d]", ret); - goto done; - } - - rewrite_icmp_hdr(pkt, icmp_hdr); - - NET_DBG("LLAO extended to %02x:%02x:%02x:%02x:%02x:%02x", - llao[0], llao[1], llao[2], llao[3], llao[4], llao[5]); - -done: - net_pkt_cursor_restore(pkt, &cursor_backup); -} - -static bool pkt_is_icmp(struct net_pkt *pkt) -{ - NET_PKT_DATA_ACCESS_CONTIGUOUS_DEFINE(ipv6_access, struct net_ipv6_hdr); - struct net_ipv6_hdr *ipv6_hdr = - (struct net_ipv6_hdr *)net_pkt_get_data(pkt, &ipv6_access); - - if (!ipv6_hdr) { - NET_ERR("No IPv6 HDR"); - return false; - } - - return (ipv6_hdr->nexthdr == IPPROTO_ICMPV6); -} - -static void swap_scr_lladdr(struct net_pkt *pkt, struct net_pkt *pkt_clone) -{ - struct net_linkaddr *lladdr_origin = net_pkt_lladdr_src(pkt); - struct net_linkaddr *lladdr_clone = net_pkt_lladdr_src(pkt_clone); - size_t offset; - - offset = lladdr_origin->addr - pkt->buffer->data; - lladdr_clone->addr = pkt_clone->buffer->data + offset; -} - -static void can_to_eth_lladdr(struct net_pkt *pkt, struct net_if *eth_iface, - bool bcast) -{ - uint16_t src_can_addr = canbus_get_src_lladdr(pkt); - struct net_linkaddr *lladdr_src = net_pkt_lladdr_src(pkt); - struct net_linkaddr *lladdr_dst; - - if (bcast) { - lladdr_dst = net_pkt_lladdr_dst(pkt); - lladdr_dst->len = sizeof(struct net_eth_addr); - lladdr_dst->type = NET_LINK_ETHERNET; - lladdr_dst->addr = (uint8_t *)net_eth_broadcast_addr()->addr; - } - - lladdr_src->addr = net_pkt_lladdr_src(pkt)->addr - - (sizeof(struct net_eth_addr) - lladdr_src->len); - memcpy(lladdr_src->addr, net_if_get_link_addr(eth_iface)->addr, - sizeof(struct net_eth_addr)); - lladdr_src->addr[4] = (lladdr_src->addr[4] & 0xC0) | (src_can_addr >> 8U); - lladdr_src->addr[5] = src_can_addr & 0xFF; - lladdr_src->len = sizeof(struct net_eth_addr); - lladdr_src->type = NET_LINK_ETHERNET; -} - -void translate_to_eth_frame(struct net_pkt *pkt, bool is_bcast, - struct net_if *eth_iface) -{ - struct net_linkaddr *dest_addr = net_pkt_lladdr_dst(pkt); - struct net_linkaddr *src_addr = net_pkt_lladdr_src(pkt); - bool is_icmp; - - is_icmp = pkt_is_icmp(pkt); - - can_to_eth_lladdr(pkt, eth_iface, is_bcast); - canbus_print_ip_hdr((struct net_ipv6_hdr *)net_pkt_cursor_get_pos(pkt)); - NET_DBG("Forward frame to %02x:%02x:%02x:%02x:%02x:%02x. " - "Src: %02x:%02x:%02x:%02x:%02x:%02x", - dest_addr->addr[0], dest_addr->addr[1], dest_addr->addr[2], - dest_addr->addr[3], dest_addr->addr[4], dest_addr->addr[5], - src_addr->addr[0], src_addr->addr[1], src_addr->addr[2], - src_addr->addr[3], src_addr->addr[4], src_addr->addr[5]); - - if (is_icmp) { - extend_llao(pkt, net_if_get_link_addr(eth_iface)); - } -} - -static enum net_verdict canbus_forward_to_eth(struct net_pkt *pkt) -{ - struct net_pkt *pkt_clone; - struct net_if *eth_iface; - - eth_iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET)); - if (!eth_iface || !net_if_is_up(eth_iface)) { - NET_ERR("No Ethernet iface available"); - if (canbus_is_for_translator(pkt)) { - return NET_DROP; - } else { - return NET_CONTINUE; - } - } - - if (canbus_dest_is_mcast(pkt)) { - /* net_pkt_clone can't be called on a pkt where - * net_buf_pull was called on. We need to clone - * first and then finish the pkt. - */ - pkt_clone = net_pkt_clone(pkt, NET_CAN_ALLOC_TIMEOUT); - if (pkt_clone) { - swap_scr_lladdr(pkt, pkt_clone); - canbus_finish_pkt(pkt_clone); - translate_to_eth_frame(pkt_clone, true, eth_iface); - forward_can_frame(pkt_clone, eth_iface); - NET_DBG("Len: %zu", net_pkt_get_len(pkt_clone)); - } else { - NET_ERR("Failed to clone pkt"); - } - } - - canbus_finish_pkt(pkt); - - if (net_pkt_lladdr_dst(pkt)->type == NET_LINK_ETHERNET) { - translate_to_eth_frame(pkt, false, eth_iface); - forward_can_frame(pkt, eth_iface); - return NET_OK; - } - - return NET_CONTINUE; -} -#else -#define canbus_forward_to_eth(...) 0 -#endif /*CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR*/ - -static enum net_verdict canbus_recv(struct net_if *iface, - struct net_pkt *pkt) -{ - struct net_linkaddr *lladdr = net_pkt_lladdr_src(pkt); - enum net_verdict ret = NET_DROP; - - if (pkt->canbus_rx_ctx) { - if (lladdr->len == sizeof(struct net_canbus_lladdr)) { - NET_DBG("Push reassembled packet from 0x%04x through " - "stack again", canbus_get_src_lladdr(pkt)); - } else { - NET_DBG("Push reassembled packet from " - "%02x:%02x:%02x:%02x:%02x:%02x through stack again", - lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], - lladdr->addr[3], lladdr->addr[4], lladdr->addr[5]); - } - - if (pkt->canbus_rx_ctx->state == NET_CAN_RX_STATE_FIN) { - canbus_rx_finish(pkt); - - if (IS_ENABLED(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR)) { - ret = canbus_forward_to_eth(pkt); - } else { - canbus_finish_pkt(pkt); - canbus_print_ip_hdr(NET_IPV6_HDR(pkt)); - ret = NET_CONTINUE; - } - } else { - NET_ERR("Expected pkt in FIN state"); - } - } else { - ret = canbus_process_frame(pkt); - } - - return ret; -} - -static inline int canbus_send_dad_request(const struct device *net_can_dev, - struct net_canbus_lladdr *ll_addr) -{ - const struct net_can_api *api = net_can_dev->api; - struct zcan_frame frame; - int ret; - - canbus_set_frame_datalength(&frame, 0); - frame.rtr = CAN_REMOTEREQUEST; - frame.id_type = CAN_EXTENDED_IDENTIFIER; - frame.id = canbus_addr_to_id(ll_addr->addr, - sys_rand32_get() & CAN_NET_IF_ADDR_MASK); - - ret = api->send(net_can_dev, &frame, NULL, NULL, K_FOREVER); - if (ret != 0) { - NET_ERR("Sending DAD request failed [%d]", ret); - return -EIO; - } - - return 0; -} - -static void canbus_send_dad_resp_cb(int error, void *cb_arg) -{ - static uint8_t fail_cnt; - struct k_work *work = (struct k_work *)cb_arg; - - if (error != 0) { - NET_ERR("Failed to send dad response [%u]", error); - if (error != -ENETDOWN && - fail_cnt < NET_CAN_DAD_SEND_RETRY) { - k_work_submit_to_queue(&net_canbus_workq, work); - } - - fail_cnt++; - } else { - fail_cnt = 0; - } -} - -static inline void canbus_send_dad_response(struct k_work *item) -{ - struct canbus_net_ctx *ctx = CONTAINER_OF(item, struct canbus_net_ctx, - dad_work); - struct net_if *iface = ctx->iface; - struct net_linkaddr *ll_addr = net_if_get_link_addr(iface); - const struct device *net_can_dev = net_if_get_device(iface); - const struct net_can_api *api = net_can_dev->api; - struct zcan_frame frame; - int ret; - - canbus_set_frame_datalength(&frame, 0); - frame.rtr = CAN_DATAFRAME; - frame.id_type = CAN_EXTENDED_IDENTIFIER; - frame.id = canbus_addr_to_id(NET_CAN_DAD_ADDR, - ntohs(UNALIGNED_GET((uint16_t *) ll_addr->addr))); - - ret = api->send(net_can_dev, &frame, canbus_send_dad_resp_cb, item, - K_FOREVER); - if (ret != 0) { - NET_ERR("Sending SF failed [%d]", ret); - } else { - NET_INFO("DAD response sent"); - } -} - -static inline void canbus_remove_rx_filter(const struct device *net_can_dev, - int filter_id) -{ - const struct net_can_api *api = net_can_dev->api; - - api->remove_rx_filter(net_can_dev, filter_id); -} - -static void canbus_dad_resp_cb(struct zcan_frame *frame, void *arg) -{ - struct k_sem *dad_sem = (struct k_sem *)arg; - - k_sem_give(dad_sem); -} - -static inline -int canbus_add_dad_resp_filter(const struct device *net_can_dev, - struct net_canbus_lladdr *ll_addr, - struct k_sem *dad_sem) -{ - const struct net_can_api *api = net_can_dev->api; - struct zcan_filter filter = { - .id_type = CAN_EXTENDED_IDENTIFIER, - .rtr = CAN_DATAFRAME, - .rtr_mask = 1, - .id_mask = CAN_EXT_ID_MASK - }; - int filter_id; - - filter.id = canbus_addr_to_id(NET_CAN_DAD_ADDR, ll_addr->addr); - - filter_id = api->add_rx_filter(net_can_dev, canbus_dad_resp_cb, - dad_sem, &filter); - if (filter_id == -ENOSPC) { - NET_ERR("Can't add dad response filter"); - } - - return filter_id; -} - -static void canbus_dad_request_cb(struct zcan_frame *frame, void *arg) -{ - struct k_work *work = (struct k_work *)arg; - - k_work_submit_to_queue(&net_canbus_workq, work); -} - -static inline int canbus_add_dad_filter(const struct device *net_can_dev, - struct net_canbus_lladdr *ll_addr, - struct k_work *dad_work) -{ - const struct net_can_api *api = net_can_dev->api; - struct zcan_filter filter = { - .id_type = CAN_EXTENDED_IDENTIFIER, - .rtr = CAN_REMOTEREQUEST, - .rtr_mask = 1, - .id_mask = (CAN_NET_IF_ADDR_MASK << CAN_NET_IF_ADDR_DEST_POS) - }; - int filter_id; - - filter.id = canbus_addr_to_id(ll_addr->addr, 0); - - filter_id = api->add_rx_filter(net_can_dev, canbus_dad_request_cb, - dad_work, &filter); - if (filter_id == -ENOSPC) { - NET_ERR("Can't add dad filter"); - } - - return filter_id; -} - -static inline int canbus_init_ll_addr(struct net_if *iface) -{ - struct canbus_net_ctx *ctx = net_if_l2_data(iface); - const struct device *net_can_dev = net_if_get_device(iface); - int dad_resp_filter_id = CAN_NET_FILTER_NOT_SET; - struct net_canbus_lladdr ll_addr; - int ret; - struct k_sem dad_sem; - -#if defined(CONFIG_NET_L2_CANBUS_USE_FIXED_ADDR) - ll_addr.addr = CONFIG_NET_L2_CANBUS_FIXED_ADDR; -#else - do { - ll_addr.addr = sys_rand32_get() % (NET_CAN_MAX_ADDR + 1); - } while (ll_addr.addr < NET_CAN_MIN_ADDR); -#endif - - /* Add address early for DAD response */ - ctx->ll_addr = sys_cpu_to_be16(ll_addr.addr); - net_if_set_link_addr(iface, (uint8_t *)&ctx->ll_addr, sizeof(ll_addr), - NET_LINK_CANBUS); - - dad_resp_filter_id = canbus_add_dad_resp_filter(net_can_dev, &ll_addr, - &dad_sem); - if (dad_resp_filter_id < 0) { - return -EIO; - } - /* - * Add this filter now to defend this address instantly. - * This filter is not called for own DAD because loopback is not - * enabled. - */ - ctx->dad_filter_id = canbus_add_dad_filter(net_can_dev, &ll_addr, - &ctx->dad_work); - if (ctx->dad_filter_id < 0) { - ret = -EIO; - goto dad_err; - } - - k_sem_init(&dad_sem, 0, 1); - ret = canbus_send_dad_request(net_can_dev, &ll_addr); - if (ret) { - ret = -EIO; - goto dad_err; - } - - ret = k_sem_take(&dad_sem, NET_CAN_DAD_TIMEOUT); - canbus_remove_rx_filter(net_can_dev, dad_resp_filter_id); - dad_resp_filter_id = CAN_NET_FILTER_NOT_SET; - - if (ret != -EAGAIN) { - NET_INFO("DAD failed"); - ret = -EAGAIN; - goto dad_err; - } - - return 0; - -dad_err: - net_if_set_link_addr(iface, NULL, 0, NET_LINK_CANBUS); - if (ctx->dad_filter_id != CAN_NET_FILTER_NOT_SET) { - canbus_remove_rx_filter(net_can_dev, ctx->dad_filter_id); - ctx->dad_filter_id = CAN_NET_FILTER_NOT_SET; - } - - if (dad_resp_filter_id != CAN_NET_FILTER_NOT_SET) { - canbus_remove_rx_filter(net_can_dev, dad_resp_filter_id); - } - - return ret; -} - -static void queue_handler(struct canbus_net_ctx *ctx) -{ - struct k_poll_event events[] = { - K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, - K_POLL_MODE_NOTIFY_ONLY, - &ctx->tx_queue), - K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, - K_POLL_MODE_NOTIFY_ONLY, - &ctx->rx_err_queue), - }; - - struct net_pkt *pkt; - int ret; - - while (1) { - ret = k_poll(events, ARRAY_SIZE(events), K_FOREVER); - if (ret) { - continue; - } - - if (events[0].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) { - pkt = k_fifo_get(&ctx->tx_queue, K_NO_WAIT); - if (pkt != NULL) { - canbus_tx_work(pkt); - } - - events[0].state = K_POLL_STATE_NOT_READY; - } - - if (events[1].state == K_POLL_STATE_FIFO_DATA_AVAILABLE) { - pkt = k_fifo_get(&ctx->rx_err_queue, K_NO_WAIT); - if (pkt != NULL) { - rx_err_work_handler(pkt); - } - - events[1].state = K_POLL_STATE_NOT_READY; - } - } -} - -void net_6locan_init(struct net_if *iface) -{ - struct canbus_net_ctx *ctx = net_if_l2_data(iface); - int thread_priority; - k_tid_t tid; - int i; - - NET_DBG("Init CAN net interface"); - - for (i = 0; i < ARRAY_SIZE(l2_ctx.tx_ctx); i++) { - l2_ctx.tx_ctx[i].state = NET_CAN_TX_STATE_UNUSED; - } - - for (i = 0; i < ARRAY_SIZE(l2_ctx.rx_ctx); i++) { - l2_ctx.rx_ctx[i].state = NET_CAN_RX_STATE_UNUSED; - } - - ctx->dad_filter_id = CAN_NET_FILTER_NOT_SET; - ctx->iface = iface; - k_work_init(&ctx->dad_work, canbus_send_dad_response); - - k_mutex_init(&l2_ctx.tx_ctx_mtx); - k_mutex_init(&l2_ctx.rx_ctx_mtx); - k_sem_init(&l2_ctx.tx_sem, 1, K_SEM_MAX_LIMIT); - - /* This work queue should have precedence over the tx stream - * TODO thread_priority = tx_tc2thread(NET_TC_TX_COUNT -1) - 1; - */ - if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) { - thread_priority = K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1); - } else { - thread_priority = K_PRIO_PREEMPT(6); - } - - k_work_queue_start(&net_canbus_workq, net_canbus_stack, - K_KERNEL_STACK_SIZEOF(net_canbus_stack), - thread_priority, NULL); - k_thread_name_set(&net_canbus_workq.thread, "isotp_work"); - NET_DBG("Workq started. Thread ID: %p", &net_canbus_workq.thread); - - k_fifo_init(&ctx->tx_queue); - k_fifo_init(&ctx->rx_err_queue); - - tid = k_thread_create(&ctx->queue_handler, ctx->queue_stack, - K_KERNEL_STACK_SIZEOF(ctx->queue_stack), - (k_thread_entry_t)queue_handler, - ctx, NULL, NULL, - thread_priority, 0, K_FOREVER); - if (!tid) { - NET_ERR("Cannot create queue handler thread for %d", - net_if_get_by_iface(iface)); - } else { - if (IS_ENABLED(CONFIG_THREAD_NAME)) { -#define MAX_NAME_LEN sizeof("isotp[01]") - char name[MAX_NAME_LEN]; - - snprintk(name, sizeof(name), "isotp[%d]", - net_if_get_by_iface(iface)); - k_thread_name_set(tid, name); - } - - k_thread_start(tid); - } -} - -static int canbus_enable(struct net_if *iface, bool state) -{ - const struct device *net_can_dev = net_if_get_device(iface); - const struct net_can_api *api = net_can_dev->api; - struct canbus_net_ctx *ctx = net_if_l2_data(iface); - int dad_retry_cnt, ret; - - NET_DBG("start to bring iface %p %s", iface, state ? "up" : "down"); - - if (state) { - for (dad_retry_cnt = CONFIG_NET_L2_CANBUS_DAD_RETRIES; - dad_retry_cnt; dad_retry_cnt--) { - ret = canbus_init_ll_addr(iface); - if (ret == 0) { - break; - } else if (ret == -EIO) { - return -EIO; - } - } - - if (ret != 0) { - return ret; - } - - } else { - if (ctx->dad_filter_id != CAN_NET_FILTER_NOT_SET) { - canbus_remove_rx_filter(net_can_dev, ctx->dad_filter_id); - } - } - - ret = api->enable(net_can_dev, state); - if (!ret) { - NET_DBG("Iface %p is up", iface); - } - - return ret; -} - -static enum net_l2_flags canbus_net_flags(struct net_if *iface) -{ - return NET_L2_MULTICAST; -} - -NET_L2_INIT(CANBUS_L2, canbus_recv, canbus_send, canbus_enable, - canbus_net_flags); diff --git a/subsys/net/l2/canbus/CMakeLists.txt b/subsys/net/l2/canbus/CMakeLists.txt index d4773627427..84294f42594 100644 --- a/subsys/net/l2/canbus/CMakeLists.txt +++ b/subsys/net/l2/canbus/CMakeLists.txt @@ -7,4 +7,3 @@ zephyr_library_compile_definitions_ifdef( ) zephyr_library_sources_ifdef(CONFIG_NET_L2_CANBUS_RAW canbus_raw.c) -zephyr_library_sources_ifdef(CONFIG_NET_L2_CANBUS 6locan.c) diff --git a/subsys/net/l2/canbus/Kconfig b/subsys/net/l2/canbus/Kconfig index 1d17c12770e..7d168bc94d2 100644 --- a/subsys/net/l2/canbus/Kconfig +++ b/subsys/net/l2/canbus/Kconfig @@ -1,76 +1,6 @@ # Copyright (c) 2019 Alexander Wachter # SPDX-License-Identifier: Apache-2.0 -config NET_L2_CANBUS - bool "CANBUS L2 layer [EXPERIMENTAL]" - depends on CAN_NET - select NET_6LO - select EXPERIMENTAL - help - Add a CANBUS L2 layer driver. This is the layer for IPv6 over CAN - (6loCAN). It uses IPHC to compress the IP header and ISO-TP for - flow control and reassembling. - -if NET_L2_CANBUS - -config NET_L2_CANBUS_USE_FIXED_ADDR - bool "Use fixed L2 address" - help - Use a fixed L2 address for 6LoCAN instead of a random chosen one. - -config NET_L2_CANBUS_FIXED_ADDR - hex "L2 address" - depends on NET_L2_CANBUS_USE_FIXED_ADDR - range 0x00FF 0x3DEF - -config NET_L2_CANBUS_DAD_RETRIES - int "Number of DAD retries" - default 5 - help - Number of retries for Duplicate Address Detection. - Greater than one only makes sense for random link layer addresses. - -config NET_L2_CANBUS_STMIN - int "STmin" - default 0 - range 0 127 - help - Minimal separation time between frames in ms. - The timer starts when the frame is queued and the next frame is - transmitted after expiration. - STmin is chosen by the receiver and transmitted in the FC - (Flow Control) frame. See also: ISO 15765-2:2016 - -config NET_L2_CANBUS_BS - int "BS (Block Size)" - default 8 - range 0 256 - help - Number of CF (Contiguous Frame) PDUs before next FC (Flow Control) - frame is sent. Zero value means all frames are sent consecutive - without an additional FC frame. - A BS counter at the sender counts from one to BS. When BS is reached, - the sender waits for a FC frame again an BS is reset. - See also: ISO 15765-2:2016 - -config NET_L2_CANBUS_ETH_TRANSLATOR - bool "6LoCAN to Ethernet translator" - depends on NET_L2_ETHERNET - help - Enable a 6LoCAN Ethernet translator. With this translator it is - possible to connect a 6LoCAN network to a Ethernet network directly, - via a Switch or through a router. Messages that goes through the - translator have a special address and the MAC address is carried inline. - The packet is forwarded with uncompressed IPv6 header. - -module = NET_L2_CANBUS -module-dep = NET_LOG -module-str = Log level for CANbus L2 layer -module-help = Enables CANbus L2 to output debug messages. -source "subsys/net/Kconfig.template.log_config.net" - -endif # NET_L2_CANBUS - config NET_L2_CANBUS_RAW bool "CANBUS RAW l2 layer" help diff --git a/subsys/net/l2/canbus/canbus_internal.h b/subsys/net/l2/canbus/canbus_internal.h deleted file mode 100644 index 76064e07bc4..00000000000 --- a/subsys/net/l2/canbus/canbus_internal.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2019 Alexander Wachter - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_SUBSYS_NET_L2_CANBUS_INTERNAL_H_ -#define ZEPHYR_SUBSYS_NET_L2_CANBUS_INTERNAL_H_ - - -#ifdef NET_CAN_USE_CAN_FD -#define NET_CAN_DL 64 -#else -#define NET_CAN_DL 8 -#endif/*NET_CAN_USE_CAN_FD*/ - -/* Protocol control information*/ -#define NET_CAN_PCI_SF 0x00 /* Single frame*/ -#define NET_CAN_PCI_FF 0x01 /* First frame */ -#define NET_CAN_PCI_CF 0x02 /* Consecutive frame */ -#define NET_CAN_PCI_FC 0x03 /* Flow control frame */ - -#define NET_CAN_PCI_TYPE_BYTE 0 -#define NET_CAN_PCI_TYPE_POS 4 -#define NET_CAN_PCI_TYPE_MASK 0xF0 -#define NET_CAN_PCI_TYPE_SF (NET_CAN_PCI_SF << NET_CAN_PCI_TYPE_POS) -#define NET_CAN_PCI_TYPE_FF (NET_CAN_PCI_FF << NET_CAN_PCI_TYPE_POS) -#define NET_CAN_PCI_TYPE_CF (NET_CAN_PCI_CF << NET_CAN_PCI_TYPE_POS) -#define NET_CAN_PCI_TYPE_FC (NET_CAN_PCI_FC << NET_CAN_PCI_TYPE_POS) - -#define NET_CAN_PCI_SF_DL_MASK 0x0F - -#define NET_CAN_PCI_FF_DL_UPPER_BYTE 0 -#define NET_CAN_PCI_FF_DL_UPPER_MASK 0x0F -#define NET_CAN_PCI_FF_DL_LOWER_BYTE 1 - -#define NET_CAN_PCI_FS_BYTE 0 -#define NET_CAN_PCI_FS_MASK 0x0F -#define NET_CAN_PCI_BS_BYTE 1 -#define NET_CAN_PCI_ST_MIN_BYTE 2 - -#define NET_CAN_PCI_FS_CTS 0x0 -#define NET_CAN_PCI_FS_WAIT 0x1 -#define NET_CAN_PCI_FS_OVFLW 0x2 - -#define NET_CAN_PCI_SN_MASK 0x0F - -#define NET_CAN_FF_DL_MIN (NET_CAN_CAN_DL) - -#define NET_CAN_WFT_FIRST 0xFF - -#define NET_CAN_BS_TIME K_MSEC(1000) -#define NET_CAN_A_TIME K_MSEC(1000) - -#define NET_CAN_FF_CF_TIME K_MSEC(1) - -#define NET_CAN_STMIN_MAX 0xFA -#define NET_CAN_STMIN_MS_MAX 0x7F -#define NET_CAN_STMIN_US_BEGIN 0xF1 -#define NET_CAN_STMIN_US_END 0xF9 - -#ifdef __cplusplus -extern "C" { -#endif - -enum net_can_isotp_tx_state { - NET_CAN_TX_STATE_UNUSED, - NET_CAN_TX_STATE_RESET, - NET_CAN_TX_STATE_WAIT_FC, - NET_CAN_TX_STATE_SEND_CF, - NET_CAN_TX_STATE_WAIT_ST, - NET_CAN_TX_STATE_WAIT_TX_BACKLOG, - NET_CAN_TX_STATE_FIN, - NET_CAN_TX_STATE_ERR -}; - -enum net_can_isotp_rx_state { - NET_CAN_RX_STATE_UNUSED, - NET_CAN_RX_STATE_RESET, - NET_CAN_RX_STATE_FF, - NET_CAN_RX_STATE_CF, - NET_CAN_RX_STATE_FIN, - NET_CAN_RX_STATE_TIMEOUT -}; - -struct canbus_l2_ctx { - struct canbus_isotp_tx_ctx tx_ctx[CONFIG_NET_PKT_TX_COUNT]; - struct canbus_isotp_rx_ctx rx_ctx[CONFIG_NET_PKT_RX_COUNT]; - struct k_mutex tx_ctx_mtx; - struct k_mutex rx_ctx_mtx; - struct k_sem tx_sem; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_SUBSYS_NET_L2_CANBUS_INTERNAL_H_ */ diff --git a/subsys/net/l2/ethernet/ethernet.c b/subsys/net/l2/ethernet/ethernet.c index 9f3e96ae888..41a42ad68de 100644 --- a/subsys/net/l2/ethernet/ethernet.c +++ b/subsys/net/l2/ethernet/ethernet.c @@ -21,9 +21,6 @@ LOG_MODULE_REGISTER(net_ethernet, CONFIG_NET_L2_ETHERNET_LOG_LEVEL); #endif #include -#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) -#include -#endif #include "arp.h" #include "eth_stats.h" @@ -292,12 +289,6 @@ static enum net_verdict ethernet_recv(struct net_if *iface, net_pkt_lladdr_dst(pkt)); } -#if defined(CONFIG_NET_L2_CANBUS_ETH_TRANSLATOR) - if (net_canbus_translate_eth_frame(iface, pkt) == NET_OK) { - return NET_OK; - } -#endif - if (!net_eth_is_addr_broadcast((struct net_eth_addr *)lladdr->addr) && !net_eth_is_addr_multicast((struct net_eth_addr *)lladdr->addr) && !net_eth_is_addr_lldp_multicast( diff --git a/tests/net/all/prj.conf b/tests/net/all/prj.conf index 9dc78b0aa8d..c6f055ce4d8 100644 --- a/tests/net/all/prj.conf +++ b/tests/net/all/prj.conf @@ -89,7 +89,6 @@ CONFIG_NET_L2_IEEE802154_SECURITY=y CONFIG_NET_L2_IEEE802154_SECURITY_CRYPTO_DEV_NAME="CRYPTO-DEV" CONFIG_NET_L2_DUMMY=y CONFIG_NET_L2_ETHERNET=y -CONFIG_NET_L2_CANBUS=y CONFIG_NET_L2_CANBUS_RAW=y CONFIG_NET_L2_ETHERNET_MGMT=y CONFIG_NET_L2_IEEE802154_RADIO_DFLT_TX_POWER=2 @@ -370,7 +369,6 @@ CONFIG_NET_SOCKETS_TLS_MAX_CREDENTIALS=10 # Network interface defaults CONFIG_NET_DEFAULT_IF_BLUETOOTH=y -CONFIG_NET_DEFAULT_IF_CANBUS=y CONFIG_NET_DEFAULT_IF_CANBUS_RAW=y CONFIG_NET_DEFAULT_IF_DUMMY=y CONFIG_NET_DEFAULT_IF_ETHERNET=y