-
Notifications
You must be signed in to change notification settings - Fork 171
[cslip]: Add support for cslip example #891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
david-cermak
wants to merge
1
commit into
espressif:master
Choose a base branch
from
david-cermak:feat/cslip
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# The following lines of boilerplate have to be in your project's CMakeLists | ||
# in this exact order for cmake to work correctly | ||
cmake_minimum_required(VERSION 3.16) | ||
|
||
include($ENV{IDF_PATH}/tools/cmake/project.cmake) | ||
project(cslip_client) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | | ||
| ----------------- | ----- | -------- | -------- | -------- | | ||
|
||
# CSLIP device client (initial) | ||
|
||
This example mirrors the SLIP custom netif example, but prepares for CSLIP (Van Jacobson TCP/IP header compression over SLIP). In this initial version, the data path behaves like plain SLIP while exposing a minimal CSLIP-facing API and structure so compression can be added incrementally. | ||
|
||
It demonstrates creating a custom network interface and attaching it to `esp_netif` with an external component (`cslip_modem`) similar to the `slip_modem` used in the SLIP example. | ||
|
||
Notes: | ||
- Compression is not yet implemented; packets are forwarded as standard SLIP. | ||
- The structure allows later integration of VJ compression/decompression. | ||
|
||
## How to use | ||
|
||
Hardware and setup are identical to the SLIP example. You can point a Linux host to the serial port and use `slattach` with `-p slip` for initial testing. | ||
|
||
Build and flash: | ||
- idf.py set-target <chip> | ||
- idf.py menuconfig (configure Example Configuration) | ||
- idf.py -p <PORT> flash monitor | ||
|
||
Troubleshooting and behavior should match the SLIP example until compression is added. |
7 changes: 7 additions & 0 deletions
7
examples/esp_netif/cslip_custom_netif/components/cslip_modem/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# CSLIP Modem Component (initial, pass-through) | ||
|
||
idf_component_register( | ||
SRCS "library/cslip_modem.c" "library/cslip_modem_netif.c" | ||
INCLUDE_DIRS "include" | ||
REQUIRES esp_netif driver | ||
) |
72 changes: 72 additions & 0 deletions
72
examples/esp_netif/cslip_custom_netif/components/cslip_modem/include/cslip_modem.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdbool.h> | ||
#include <stdint.h> | ||
|
||
#include "esp_netif.h" | ||
#include "driver/uart.h" | ||
|
||
/** | ||
* Minimal CSLIP-facing default netif config (mirrors SLIP example) | ||
*/ | ||
#define ESP_NETIF_INHERENT_DEFAULT_CSLIP() \ | ||
{ \ | ||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(mac) \ | ||
ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(ip_info) \ | ||
.get_ip_event = 0, \ | ||
.lost_ip_event = 0, \ | ||
.if_key = "CSLP_DEF", \ | ||
.if_desc = "cslip", \ | ||
.route_prio = 16, \ | ||
.bridge_info = NULL \ | ||
} | ||
|
||
extern const esp_netif_netstack_config_t *netstack_default_cslip; | ||
|
||
typedef struct cslip_modem *cslip_modem_handle; | ||
|
||
// Optional filter for application-specific serial messages in the stream | ||
typedef bool cslip_rx_filter_cb_t(cslip_modem_handle cslip, uint8_t *data, uint32_t len); | ||
|
||
// Minimal CSLIP config stub per requirements (values currently unused) | ||
typedef struct { | ||
bool enable; // default true | ||
uint8_t vj_slots; // default 16 | ||
bool slotid_compression; // default true | ||
bool safe_mode; // default true | ||
} esp_cslip_config_t; | ||
|
||
// Configuration structure for CSLIP modem interface (extends SLIP modem config) | ||
typedef struct { | ||
uart_port_t uart_dev; /* UART device for reading/writing */ | ||
|
||
int uart_tx_pin; /* UART TX pin number */ | ||
int uart_rx_pin; /* UART RX pin number */ | ||
|
||
uint32_t uart_baud; /* UART baud rate */ | ||
|
||
uint32_t rx_buffer_len; /* RX buffer length */ | ||
|
||
cslip_rx_filter_cb_t *rx_filter; /* Optional RX filter */ | ||
esp_ip6_addr_t *ipv6_addr; /* IPv6 address */ | ||
|
||
esp_cslip_config_t cslip; /* CSLIP options (currently informational) */ | ||
} cslip_modem_config_t; | ||
|
||
// Create a CSLIP modem (initially pass-through SLIP behavior) | ||
cslip_modem_handle cslip_modem_create(esp_netif_t *cslip_netif, const cslip_modem_config_t *modem_config); | ||
|
||
// Destroy a CSLIP modem | ||
esp_err_t cslip_modem_destroy(cslip_modem_handle cslip); | ||
|
||
// Get configured IPv6 address | ||
esp_ip6_addr_t cslip_modem_get_ipv6_address(cslip_modem_handle cslip); | ||
|
||
// Raw write out the interface | ||
void cslip_modem_raw_write(cslip_modem_handle cslip, void *buffer, size_t len); |
176 changes: 176 additions & 0 deletions
176
examples/esp_netif/cslip_custom_netif/components/cslip_modem/library/cslip_modem.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <string.h> | ||
#include <inttypes.h> | ||
#include "cslip_modem.h" | ||
|
||
#include "esp_netif.h" | ||
#include "cslip_modem_netif.h" | ||
#include "esp_event.h" | ||
#include "esp_log.h" | ||
|
||
#define CSLIP_RX_TASK_PRIORITY 10 | ||
#define CSLIP_RX_TASK_STACK_SIZE (4 * 1024) | ||
|
||
static const char *TAG = "cslip-modem"; | ||
|
||
typedef struct { | ||
uart_port_t uart_dev; | ||
uint32_t uart_baud; | ||
int uart_tx_pin; | ||
int uart_rx_pin; | ||
QueueHandle_t uart_queue; | ||
TaskHandle_t uart_rx_task; | ||
} esp_cslip_uart_t; | ||
|
||
struct cslip_modem { | ||
esp_netif_driver_base_t base; | ||
esp_cslip_uart_t uart; | ||
uint8_t *buffer; | ||
uint32_t buffer_len; | ||
cslip_rx_filter_cb_t *rx_filter; | ||
bool running; | ||
esp_ip6_addr_t addr; | ||
esp_cslip_config_t cslip_cfg; // currently informational | ||
}; | ||
|
||
static void cslip_modem_uart_rx_task(void *arg); | ||
static esp_err_t cslip_modem_post_attach(esp_netif_t *esp_netif, void *args); | ||
|
||
cslip_modem_handle cslip_modem_create(esp_netif_t *cslip_netif, const cslip_modem_config_t *modem_config) | ||
{ | ||
if (cslip_netif == NULL || modem_config == NULL) { | ||
ESP_LOGE(TAG, "invalid parameters"); | ||
return NULL; | ||
} | ||
ESP_LOGI(TAG, "%s: Creating cslip modem (netif: %p)", __func__, cslip_netif); | ||
|
||
cslip_modem_handle modem = calloc(1, sizeof(struct cslip_modem)); | ||
if (!modem) { | ||
ESP_LOGE(TAG, "create netif glue failed"); | ||
return NULL; | ||
} | ||
|
||
modem->base.post_attach = cslip_modem_post_attach; | ||
modem->base.netif = cslip_netif; | ||
|
||
modem->buffer_len = modem_config->rx_buffer_len; | ||
modem->rx_filter = modem_config->rx_filter; | ||
|
||
modem->uart.uart_dev = modem_config->uart_dev; | ||
modem->uart.uart_baud = modem_config->uart_baud; | ||
modem->uart.uart_rx_pin = modem_config->uart_rx_pin; | ||
modem->uart.uart_tx_pin = modem_config->uart_tx_pin; | ||
modem->addr = *modem_config->ipv6_addr; | ||
modem->cslip_cfg = modem_config->cslip; | ||
|
||
return modem; | ||
} | ||
|
||
static esp_err_t esp_cslip_driver_start(cslip_modem_handle modem) | ||
{ | ||
if (modem->buffer == NULL) { | ||
modem->buffer = malloc(modem->buffer_len); | ||
} | ||
if (modem->buffer == NULL) { | ||
ESP_LOGE(TAG, "error allocating rx buffer"); | ||
return ESP_ERR_NO_MEM; | ||
} | ||
|
||
uart_config_t uart_config = { | ||
.baud_rate = modem->uart.uart_baud, | ||
.data_bits = UART_DATA_8_BITS, | ||
.parity = UART_PARITY_DISABLE, | ||
.stop_bits = UART_STOP_BITS_1, | ||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, | ||
}; | ||
|
||
ESP_ERROR_CHECK(uart_param_config(modem->uart.uart_dev, &uart_config)); | ||
ESP_ERROR_CHECK(uart_set_pin(modem->uart.uart_dev, modem->uart.uart_tx_pin, modem->uart.uart_rx_pin, 0, 0)); | ||
ESP_ERROR_CHECK(uart_driver_install(modem->uart.uart_dev, modem->buffer_len, modem->buffer_len, 10, &modem->uart.uart_queue, 0)); | ||
|
||
modem->running = true; | ||
xTaskCreate(cslip_modem_uart_rx_task, "cslip_modem_uart_rx_task", CSLIP_RX_TASK_STACK_SIZE, modem, CSLIP_RX_TASK_PRIORITY, &modem->uart.uart_rx_task); | ||
|
||
esp_netif_action_start(modem->base.netif, 0, 0, 0); | ||
ESP_ERROR_CHECK(cslip_modem_netif_start(modem->base.netif, &modem->addr)); | ||
return ESP_OK; | ||
} | ||
|
||
esp_err_t cslip_modem_destroy(cslip_modem_handle modem) | ||
{ | ||
if (modem != NULL) { | ||
esp_netif_action_stop(modem->base.netif, 0, 0, 0); | ||
ESP_ERROR_CHECK(cslip_modem_netif_stop(modem->base.netif)); | ||
vTaskDelete(modem->uart.uart_rx_task); | ||
uart_driver_delete(modem->uart.uart_dev); | ||
free(modem); | ||
} | ||
|
||
return ESP_OK; | ||
} | ||
|
||
static esp_err_t cslip_modem_transmit(void *driver, void *buffer, size_t len) | ||
{ | ||
cslip_modem_handle modem = (cslip_modem_handle)driver; | ||
int32_t res = uart_write_bytes(modem->uart.uart_dev, (char *)buffer, len); | ||
if (res < 0) { | ||
ESP_LOGE(TAG, "%s: uart_write_bytes error %" PRId32, __func__, res); | ||
return ESP_FAIL; | ||
} | ||
return ESP_OK; | ||
} | ||
|
||
static esp_err_t cslip_modem_post_attach(esp_netif_t *esp_netif, void *args) | ||
{ | ||
cslip_modem_handle modem = (cslip_modem_handle) args; | ||
|
||
const esp_netif_driver_ifconfig_t driver_ifconfig = { | ||
.driver_free_rx_buffer = NULL, | ||
.transmit = cslip_modem_transmit, | ||
.handle = modem, | ||
}; | ||
|
||
modem->base.netif = esp_netif; | ||
ESP_ERROR_CHECK(esp_netif_set_driver_config(esp_netif, &driver_ifconfig)); | ||
|
||
esp_cslip_driver_start(modem); | ||
return ESP_OK; | ||
} | ||
|
||
static void cslip_modem_uart_rx_task(void *arg) | ||
{ | ||
if (arg == NULL) { | ||
vTaskDelete(NULL); | ||
} | ||
cslip_modem_handle modem = (cslip_modem_handle) arg; | ||
|
||
ESP_LOGD(TAG, "Start CSLIP modem RX task (filter: %p)", modem->rx_filter); | ||
|
||
while (modem->running == true) { | ||
int len = uart_read_bytes(modem->uart.uart_dev, modem->buffer, modem->buffer_len, 1 / portTICK_PERIOD_MS); | ||
|
||
if (len > 0) { | ||
modem->buffer[len] = '\0'; | ||
if ((modem->rx_filter != NULL) && modem->rx_filter(modem, modem->buffer, len)) { | ||
continue; | ||
} | ||
esp_netif_receive(modem->base.netif, modem->buffer, len, NULL); | ||
} | ||
vTaskDelay(1 * portTICK_PERIOD_MS); | ||
} | ||
} | ||
|
||
esp_ip6_addr_t cslip_modem_get_ipv6_address(cslip_modem_handle modem) | ||
{ | ||
return modem->addr; | ||
} | ||
|
||
void cslip_modem_raw_write(cslip_modem_handle modem, void *buffer, size_t len) | ||
{ | ||
cslip_modem_netif_raw_write(modem->base.netif, buffer, len); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: UART RX Task Buffer Overflow Risk
In
cslip_modem_uart_rx_task
, writingmodem->buffer[len] = '\0'
can cause a buffer overflow. Ifuart_read_bytes
returnsmodem->buffer_len
bytes, this writes one byte past the allocated buffer boundary. Additionally, null-terminating SLIP-encoded binary data is generally not appropriate for this buffer.