Merge pull request #68 from logicog/dhcp

Add a DHCP client implementation and validate BANKS code size.
This commit is contained in:
René van Dorst
2026-01-18 11:08:17 +00:00
committed by GitHub
13 changed files with 738 additions and 105 deletions
+4 -7
View File
@@ -6,7 +6,7 @@ CONFIG_LOCATION = 458752
HTML_LOCATION = 262144 HTML_LOCATION = 262144
CC = sdcc CC = sdcc
CC_FLAGS = -mmcs51 -Ihttpd -Iuip CC_FLAGS = -mmcs51 -I. -Ihttpd -Iuip
ASM = sdas8051 ASM = sdas8051
AFLAGS= -plosgff AFLAGS= -plosgff
@@ -21,7 +21,7 @@ all: create_build_dir $(VERSION_HEADER) $(SUBDIRS) $(BUILDDIR)rtlplayground.bin
create_build_dir: create_build_dir:
mkdir -p $(BUILDDIR) mkdir -p $(BUILDDIR)
SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c machine.c SRCS = rtlplayground.c rtl837x_flash.c rtl837x_phy.c rtl837x_port.c cmd_parser.c html_data.c rtl837x_igmp.c rtl837x_stp.c dhcp.c machine.c
OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel} OBJS = ${SRCS:%.c=$(BUILDDIR)%.rel}
OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel OBJS += uip/$(BUILDDIR)/timer.rel uip/$(BUILDDIR)/uip-fw.rel uip/$(BUILDDIR)/uip-neighbor.rel uip/$(BUILDDIR)/uip-split.rel uip/$(BUILDDIR)/uip.rel uip/$(BUILDDIR)/uip_arp.rel uip/$(BUILDDIR)/uiplib.rel httpd/$(BUILDDIR)/httpd.rel httpd/$(BUILDDIR)/page_impl.rel
@@ -59,17 +59,14 @@ $(BUILDDIR)%.rel: $(BUILDDIR)%.asm
# mv -f $(addprefix $(basename $^), .lst .rel .sym) . # mv -f $(addprefix $(basename $^), .lst .rel .sym) .
$(BUILDDIR)rtlplayground.ihx: $(BUILDDIR)crtstart.rel $(OBJS) $(BUILDDIR)crc16.rel $(BUILDDIR)rtlplayground.ihx: $(BUILDDIR)crtstart.rel $(OBJS) $(BUILDDIR)crc16.rel
$(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-r -o $@ $^ $(CC) $(CC_FLAGS) -Wl-bHOME=${BOOTLOADER_ADDRESS} -Wl-bBANK1=0x14000 -Wl-bBANK2=0x24000 -Wl-r -o $@ $^
$(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx $(BUILDDIR)rtlplayground.img: $(BUILDDIR)rtlplayground.ihx
objcopy --input-target=ihex -O binary $< $@ objcopy --input-target=ihex -O binary $< $@
$(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img $(BUILDDIR)rtlplayground.bin: $(BUILDDIR)rtlplayground.img
if [ -e $@ ]; then rm $@; fi if [ -e $@ ]; then rm $@; fi
echo "0000000: 00 40" | xxd -r - $@ tools/$(BUILDDIR)imagebuilder -i $^ $@
cat $< >> $@
truncate --size=16K $@
dd if=$< skip=80 bs=1024 >>$@
tools/$(BUILDDIR)fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@ tools/$(BUILDDIR)fileadder -a $(CONFIG_LOCATION) -s $(IMAGESIZE) -d config.txt $@
tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data $@ tools/$(BUILDDIR)fileadder -a $(HTML_LOCATION) -s $(IMAGESIZE) -d html -p html_data $@
tools/$(BUILDDIR)crc_calculator -u $@ tools/$(BUILDDIR)crc_calculator -u $@
+59 -19
View File
@@ -13,6 +13,7 @@
#include "rtl837x_sfr.h" #include "rtl837x_sfr.h"
#include "rtl837x_stp.h" #include "rtl837x_stp.h"
#include "rtl837x_igmp.h" #include "rtl837x_igmp.h"
#include "dhcp.h"
#include "uip/uip.h" #include "uip/uip.h"
#include "version.h" #include "version.h"
@@ -37,6 +38,8 @@ extern __xdata struct flash_region_t flash_region;
extern __xdata char passwd[21]; extern __xdata char passwd[21];
extern __xdata struct dhcp_state dhcp_state;
__xdata uint8_t vlan_names[VLAN_NAMES_SIZE]; __xdata uint8_t vlan_names[VLAN_NAMES_SIZE];
__xdata uint16_t vlan_ptr; __xdata uint16_t vlan_ptr;
__xdata uint8_t gpio_last_value[8] = { 0 }; __xdata uint8_t gpio_last_value[8] = { 0 };
@@ -149,6 +152,7 @@ uint8_t atoi_hex(uint8_t idx)
return ((h_idx + 1) >> 1); return ((h_idx + 1) >> 1);
} }
uint8_t atoi_short(register uint16_t *vlan, register uint8_t idx) uint8_t atoi_short(register uint16_t *vlan, register uint8_t idx)
{ {
uint8_t err = 1; uint8_t err = 1;
@@ -774,28 +778,64 @@ void cmd_parser(void) __banked
} else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) { } else if (cmd_compare(0, "mtu") && cmd_words_b[1] > 0) {
parse_mtu(); parse_mtu();
} else if (cmd_compare(0, "ip")) { } else if (cmd_compare(0, "ip")) {
print_string("Got ip command: "); if (cmd_words_b[2] > 0 && cmd_compare(1, "dhcp")) {
if (!parse_ip(cmd_words_b[1])) dhcp_start();
uip_ipaddr(&uip_hostaddr, ip[0], ip[1], ip[2], ip[3]); } else if (cmd_words_b[2] < 0) {
else print_string("Current IP: ");
print_string("Invalid IP address\n"); itoa(uip_hostaddr[0]); write_char('.'); itoa(uip_hostaddr[0] >> 8); write_char('.');
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]); itoa(uip_hostaddr[1]); write_char('.'); itoa(uip_hostaddr[1] >> 8);
write_char('\n'); if (dhcp_state.state == DHCP_LEASING) {
print_string(" (dhcp, renewal in sec: ");
print_short(dhcp_state.dhcp_timer);
write_char(')');
} else {
print_string(" (static)");
}
write_char('\n');
} else {
if (dhcp_state.state)
dhcp_stop();
if (!parse_ip(cmd_words_b[1])) {
uip_ipaddr(&uip_hostaddr, ip[0], ip[1], ip[2], ip[3]);
print_string("Setting ip: ");
itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.');
itoa(ip[2]); write_char('.'); itoa(ip[3]); write_char('\n');
} else {
print_string("Invalid IP address\n");
print_string("Error: ip [<ip-address>|dhcp]\n");
print_string(" The dhcp option enables the dhcp client, calling ip without options prints the current IP\n");
print_string(" Calling with a valid IP address will stop any ongoing dhcp client and set the IP address\n");
}
}
} else if (cmd_compare(0, "gw")) { } else if (cmd_compare(0, "gw")) {
print_string("Got gw command: "); if (cmd_words_b[2] < 0) {
if (!parse_ip(cmd_words_b[1])) print_string("Current gw: ");
uip_ipaddr(&uip_draddr, ip[0], ip[1], ip[2], ip[3]); itoa(uip_draddr[0]); write_char('.'); itoa(uip_draddr[0] >> 8); write_char('.');
else itoa(uip_draddr[1]); write_char('.'); itoa(uip_draddr[1] >> 8);
print_string("Invalid IP address\n"); } else {
print_byte(ip[0]); print_byte(ip[1]); print_byte(ip[2]); print_byte(ip[3]); if (!parse_ip(cmd_words_b[1]))
uip_ipaddr(&uip_draddr, ip[0], ip[1], ip[2], ip[3]);
else
print_string("Invalid IP address\n");
print_string("Setting gw: ");
itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.');
itoa(ip[2]); write_char('.'); itoa(ip[3]);
}
write_char('\n'); write_char('\n');
} else if (cmd_compare(0, "netmask")) { } else if (cmd_compare(0, "netmask")) {
print_string("Got netmask command: "); if (cmd_words_b[2] < 0) {
if (!parse_ip(cmd_words_b[1])) print_string("Current netmask: ");
uip_ipaddr(&uip_netmask, ip[0], ip[1], ip[2], ip[3]); itoa(uip_netmask[0]); write_char('.'); itoa(uip_netmask[0] >> 8); write_char('.');
else itoa(uip_netmask[1]); write_char('.'); itoa(uip_netmask[1] >> 8);
print_string("Invalid IP address\n"); } else {
print_byte(ip[0]);print_byte(ip[1]);print_byte(ip[2]);print_byte(ip[3]); if (!parse_ip(cmd_words_b[1]))
uip_ipaddr(&uip_netmask, ip[0], ip[1], ip[2], ip[3]);
else
print_string("Invalid IP address\n");
print_string("Setting netmask: ");
itoa(ip[0]); write_char('.'); itoa(ip[1]); write_char('.');
itoa(ip[2]); write_char('.'); itoa(ip[3]);
}
write_char('\n'); write_char('\n');
} else if (cmd_compare(0, "l2")) { } else if (cmd_compare(0, "l2")) {
if (cmd_words_b[1] > 0 && cmd_compare(1, "forget")) if (cmd_words_b[1] > 0 && cmd_compare(1, "forget"))
+391
View File
@@ -0,0 +1,391 @@
/*
* This is a DHCP client implementation for the RTL837x-based switches
*/
// #define REGDBG
// #define DEBUG
#include <stdint.h>
#include "rtl837x_sfr.h"
#include "rtl837x_common.h"
#include "dhcp.h"
#include "uip.h"
#include "uip/uip.h"
extern __code struct uip_eth_addr uip_ethaddr;
__xdata struct dhcp_state dhcp_state;
__xdata uip_ipaddr_t server;
#define DHCP_HW_TYPE_ETH 1
#define DHCP_SUBNET_MASK 1
#define DHCP_SUBNET_MASK_LEN 4
#define DHCP_ROUTER 3
#define DHCP_ROUTER_LEN 4
#define DHCP_DNS 6
#define DHCP_DNS_LEN 4
#define DHCP_BROADCAST 28
#define DHCP_BROADCAST_LEN 4
#define DHCP_SERVER_ID 54
#define DHCP_SERVER_ID_LEN 4
#define DHCP_MESSAGE_TYPE 53
#define DHCP_MESSAGE_TYPE_LEN 1
#define DHCP_MESSAGE_DISCOVER 1
#define DHCP_MESSAGE_OFFER 2
#define DHCP_MESSAGE_REQUEST 3
#define DHCP_MESSAGE_ACK 5
#define DHCP_LEASE 51
#define DHCP_LEASE_LEN 4
#define DHCP_RENEWAL 58
#define DHCP_RENEWAL_LEN 4
#define DHCP_REBIND 59
#define DHCP_REBIND_LEN 4
#define DHCP_CLIENT_ID 61
#define DHCP_CLIENT_ID_LEN 7
#define DHCP_REQUEST_IP 50
#define DHCP_REQUEST_IP_LEN 4
#define DHCP_PARAMS 55
#define DHCP_PARAM_SUBNET 1
#define DHCP_PARAM_ROUTER 3
#define DHCP_PARAM_DNS 6
#define DHCP_END 255
#pragma codeseg BANK2
#pragma constseg BANK2
struct dhcp_pkt {
uint8_t type;
uint8_t hw;
uint8_t hw_len;
uint8_t hops;
uint32_t tid;
uint16_t delay;
uint16_t flags;
uint8_t client_ip[4];
uint8_t your_ip[4];
uint8_t next_server_ip[4];
uint8_t relay_ip[4];
uint8_t client_addr[6];
uint8_t client_pad[10];
uint8_t server_name[64];
uint8_t file[128];
uint8_t cookie[4];
};
/*
#define DHCP_P ((__xdata struct dhcp_pkt *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE])
#define DHCP_OPT ((__xdata uint8_t *)&uip_buf[RTL_TAG_SIZE + VLAN_TAG_SIZE + sizeof (struct dhcp_pkt)])
*/
#define DHCP_P ((__xdata struct dhcp_pkt *)uip_appdata)
#define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt))
__xdata uint32_t long_value;
void dhcp_print_ip(uint8_t *a)
{
itoa(a[0]); write_char('.');
itoa(a[1]); write_char('.');
itoa(a[2]); write_char('.');
itoa(a[3]);
}
void dhcp_prepare_request(void)
{
DHCP_P->type = 1;
DHCP_P->hw = DHCP_HW_TYPE_ETH;
DHCP_P->hw_len = 6;
DHCP_P->hops = 0;
DHCP_P->tid = HTONS(dhcp_state.transaction_id);
DHCP_P->delay = HTONS(0);
DHCP_P->flags = 0;
// Clear fields client_ip to bootp_file
memset(DHCP_P->client_ip, 0, 224);
memcpyc(DHCP_P->client_addr, uip_ethaddr.addr, 6);
DHCP_P->cookie[0] = 0x63;
DHCP_P->cookie[1] = 0x82;
DHCP_P->cookie[2] = 0x53;
DHCP_P->cookie[3] = 0x63;
}
void dhcp_addopt_client_id(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_CLIENT_ID_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_HW_TYPE_ETH;
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 6);
dhcp_state.opt_ptr += 6;
}
void dhcp_addopt_request_ip(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_REQUEST_IP_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[0];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.current_ip[3];
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
}
void dhcp_addopt_server_id(void)
{
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SERVER_ID;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_SERVER_ID_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[0];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[1];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[2];
DHCP_OPT[dhcp_state.opt_ptr++] = dhcp_state.server[3];
memcpyc(&DHCP_OPT[dhcp_state.opt_ptr], uip_ethaddr.addr, 4);
}
void dhcp_send_discover(void)
{
print_string("dhcp_send_discover called\n");
dhcp_prepare_request();
dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_DISCOVER;
dhcp_addopt_client_id();
dhcp_addopt_request_ip();
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_SUBNET;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_ROUTER;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_DNS;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
// Padding to 300 bytes
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
dhcp_state.state = DHCP_DISCOVER_SENT;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = 30; // Timeout for discover
}
void dhcp_send_request(void)
{
print_string("dhcp_send_request called\n");
dhcp_prepare_request();
dhcp_state.opt_ptr = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_REQUEST;
dhcp_addopt_client_id();
dhcp_addopt_request_ip();
dhcp_addopt_server_id();
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_SUBNET;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_ROUTER;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_DNS;
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
// Padding to 300 bytes
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
dhcp_state.state = DHCP_REQUEST_SENT;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = 30; // Timeout for request
}
void ip_opt(uint8_t * __xdata ip)
{
dhcp_state.opt_ptr++;
uint8_t len = DHCP_OPT[dhcp_state.opt_ptr++];
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
*ip++ = DHCP_OPT[dhcp_state.opt_ptr++];
// There may be more than one IP option, such as 2 DNS servers advertised
dhcp_state.opt_ptr += len - 4;
}
void long_opt(void)
{
dhcp_state.opt_ptr++;
dhcp_state.opt_ptr++;
long_value = DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
long_value <<= 8;
long_value |= DHCP_OPT[dhcp_state.opt_ptr++];
}
void parse_opts(void)
{
while (DHCP_OPT[dhcp_state.opt_ptr] && DHCP_OPT[dhcp_state.opt_ptr] != DHCP_END) {
switch(DHCP_OPT[dhcp_state.opt_ptr]) {
case DHCP_SUBNET_MASK:
ip_opt(&dhcp_state.subnet[0]);
break;
case DHCP_ROUTER:
ip_opt(&dhcp_state.router[0]);
break;
case DHCP_DNS:
ip_opt(&dhcp_state.dns[0]);
break;
case DHCP_SERVER_ID:
ip_opt(&dhcp_state.server[0]);
break;
case DHCP_BROADCAST:
ip_opt(&dhcp_state.broadcast[0]);
break;
case DHCP_LEASE:
long_opt();
dhcp_state.lease = long_value;
break;
case DHCP_REBIND:
long_opt();
dhcp_state.rebind = long_value;
break;
case DHCP_RENEWAL:
long_opt();
dhcp_state.renewal = long_value;
break;
case DHCP_END:
break;
default:
print_string("Unknown DHCP option: "); print_byte(DHCP_OPT[dhcp_state.opt_ptr]); write_char('\n');
dhcp_state.opt_ptr++;
dhcp_state.opt_ptr += DHCP_OPT[dhcp_state.opt_ptr];
dhcp_state.opt_ptr++;
}
}
}
void parse_dhcp(void)
{
if (!DHCP_P->tid == HTONS(dhcp_state.transaction_id))
return;
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
return;
dhcp_state.opt_ptr = 0;
if (DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE || DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE_LEN)
return;
if (DHCP_OPT[dhcp_state.opt_ptr] == DHCP_MESSAGE_OFFER) {
dhcp_state.opt_ptr++;
dhcp_state.current_ip[0] = DHCP_P->your_ip[0];
dhcp_state.current_ip[1] = DHCP_P->your_ip[1];
dhcp_state.current_ip[2] = DHCP_P->your_ip[2];
dhcp_state.current_ip[3] = DHCP_P->your_ip[3];
parse_opts();
print_string("DHCP offer received for IP "); dhcp_print_ip(dhcp_state.current_ip);
write_char('\n');
dhcp_send_request();
} else if (DHCP_OPT[dhcp_state.opt_ptr++] == DHCP_MESSAGE_ACK) {
parse_opts();
print_string("DHCP ACK, our IP is "); dhcp_print_ip(dhcp_state.current_ip);
write_char('\n');
print_string("DHCP netmask "); dhcp_print_ip(dhcp_state.subnet);
write_char('\n');
print_string("DHCP gateway "); dhcp_print_ip(dhcp_state.router);
write_char('\n');
print_string("DHCP lease-time ");
print_long(dhcp_state.lease);
write_char('\n');
uip_ipaddr(&uip_hostaddr, dhcp_state.current_ip[0], dhcp_state.current_ip[1], dhcp_state.current_ip[2], dhcp_state.current_ip[3]);
uip_ipaddr(&uip_draddr, dhcp_state.router[0], dhcp_state.router[1], dhcp_state.router[2], dhcp_state.router[3]);
uip_ipaddr(&uip_netmask, dhcp_state.subnet[0], dhcp_state.subnet[1], dhcp_state.subnet[2], dhcp_state.subnet[3]);
dhcp_state.state = DHCP_LEASING;
dhcp_state.ticks = SYS_TICK_HZ;
dhcp_state.dhcp_timer = dhcp_state.renewal > 0xffff ? 0xffff : dhcp_state.renewal;
}
}
void dhcp_start(void) __banked
{
uip_ipaddr(server, 255,255,255,255);
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCPC_SERVER_PORT));
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
if(dhcp_state.conn) {
uip_udp_bind(dhcp_state.conn, HTONS(DHCPC_CLIENT_PORT));
} else {
print_string("dhcp_start failed to set up socket\n");
return;
}
get_random_32();
dhcp_state.transaction_id = SFR_DATA_U32;
dhcp_state.state = DHCP_START;
print_string("dhcp_start done\n");
}
void dhcp_stop(void) __banked
{
print_string("dhcp_stop called\n");
uip_udp_remove(dhcp_state.conn);
dhcp_state.state = DHCP_OFF;
}
void dhcp_callback(void) __banked
{
if (!dhcp_state.state)
return;
if (uip_closed()) {
print_string("Closed\n");
return;
} else if (uip_newdata()) {
parse_dhcp();
} else {
if (dhcp_state.state == DHCP_START) {
dhcp_send_discover();
} else if (!--dhcp_state.ticks) {
// print_string("Timer: "); print_short(dhcp_state.ticks); write_char(' '); print_short(dhcp_state.dhcp_timer);
dhcp_state.dhcp_timer--;
dhcp_state.ticks = SYS_TICK_HZ;
}
if (!dhcp_state.dhcp_timer) {
switch (dhcp_state.state) {
case DHCP_DISCOVER_SENT:
dhcp_send_discover();
break;
case DHCP_LEASING:
case DHCP_REQUEST_SENT:
dhcp_send_request();
break;
default:
print_string("UNKNOWN STATE\n");
}
}
}
// By default we do not send anything out
uip_len = 0;
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef _DHCP_H_
#define _DHCP_H_
#include "uipopt.h"
#include <stdint.h>
#define DHCPC_SERVER_PORT 67
#define DHCPC_CLIENT_PORT 68
#define DHCP_OFF 0
#define DHCP_START 1
#define DHCP_DISCOVER_SENT 2
#define DHCP_REQUEST_SENT 3
#define DHCP_LEASING 4
void dhcp_start(void) __banked;
void dhcp_stop(void) __banked;
// void dhcp_periodic(void) __banked;
void dhcp_callback(void) __banked;
struct dhcp_state {
uint8_t state;
uint32_t transaction_id;
uint16_t dhcp_timer;
uint8_t ticks;
uint16_t opt_ptr;
uint8_t current_ip[4];
uint8_t server[4];
uint8_t router[4];
uint8_t subnet[4];
uint8_t dns[4];
uint8_t broadcast[4];
uint32_t lease;
uint32_t rebind;
uint32_t renewal;
struct uip_udp_conn *conn;
};
typedef struct dhcp_state uip_udp_appstate_t;
/* Finally we define the application function to be called by uIP. */
#ifndef UIP_UDP_APPCALL
#define UIP_UDP_APPCALL dhcp_callback
#endif /* UIP_APPCALL */
#endif
-1
View File
@@ -11,7 +11,6 @@
// #define DEBUG // #define DEBUG
#include "debug.h" #include "debug.h"
#define SESSION_ID_LENGTH 12 #define SESSION_ID_LENGTH 12
#define SESSION_TIMEOUT 200 #define SESSION_TIMEOUT 200
+3
View File
@@ -5,6 +5,8 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#define SYS_TICK_HZ 200
// SCL and SDA pin numbers for SFP cage 0 and SFP cage 1 // SCL and SDA pin numbers for SFP cage 0 and SFP cage 1
#define SCL_PIN 3 #define SCL_PIN 3
#define SDA_PIN_0 4 #define SDA_PIN_0 4
@@ -88,6 +90,7 @@ void print_string(__code char *p);
void print_long(__xdata uint32_t a); void print_long(__xdata uint32_t a);
void print_short(uint16_t a); void print_short(uint16_t a);
void print_byte(uint8_t a); void print_byte(uint8_t a);
void itoa(uint8_t v);
void print_sfr_data(void); void print_sfr_data(void);
void print_phy_data(void); void print_phy_data(void);
void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v); void phy_write_mask(uint16_t phy_mask, uint8_t dev_id, uint16_t reg, uint16_t v);
+2 -2
View File
@@ -16,8 +16,8 @@
#include "rtl837x_phy.h" #include "rtl837x_phy.h"
#include "phy.h" #include "phy.h"
#pragma codeseg BANK1 #pragma codeseg BANK2
#pragma constseg BANK1 #pragma constseg BANK2
extern __code uint16_t bit_mask[16]; extern __code uint16_t bit_mask[16];
+30
View File
@@ -12,6 +12,7 @@
#include "rtl837x_port.h" #include "rtl837x_port.h"
#include "rtl837x_stp.h" #include "rtl837x_stp.h"
#include "rtl837x_igmp.h" #include "rtl837x_igmp.h"
#include "dhcp.h"
#include "cmd_parser.h" #include "cmd_parser.h"
#include "uip/uipopt.h" #include "uip/uipopt.h"
#include "uip/uip.h" #include "uip/uip.h"
@@ -80,6 +81,7 @@ volatile __xdata uint32_t ticks;
volatile __xdata uint8_t sec_counter; volatile __xdata uint8_t sec_counter;
volatile __xdata uint16_t sleep_ticks; volatile __xdata uint16_t sleep_ticks;
__xdata uint8_t stp_clock; __xdata uint8_t stp_clock;
extern __xdata struct dhcp_state dhcp_state;
#define STP_TICK_DIVIDER 3 #define STP_TICK_DIVIDER 3
@@ -172,6 +174,22 @@ void write_char(char c)
} }
void itoa(uint8_t v)
{
uint8_t t = (v / 100);
// when print_zeros is not zero, we know that a non-zero number has printed.
// That have to print all the next numbers.
uint8_t print_zeros = t;
if (print_zeros)
write_char('0' + t);
t = (v / 10) % 10;
print_zeros |= t;
if (print_zeros)
write_char('0' + t);
write_char('0' + (v % 10));
}
void print_string(__code char *p) void print_string(__code char *p)
{ {
while (*p) while (*p)
@@ -910,6 +928,10 @@ void handle_rx(void)
uip_arp_out(); uip_arp_out();
tcpip_output(); tcpip_output();
} }
} else {
#ifdef RXTXDBG
print_string("Unknown RX on port "); print_byte(rx_headers[3] & 0xf); write_char('\n');
#endif
} }
} }
} }
@@ -927,6 +949,13 @@ void handle_tx(void)
tcpip_output(); tcpip_output();
} }
} }
for(uint8_t i = 0; i < UIP_UDP_CONNS; i++) {
uip_udp_periodic(i);
if(uip_len > 0) {
uip_arp_out();
tcpip_output();
}
}
} }
@@ -1739,6 +1768,7 @@ void bootloader(void)
{ {
ticks = 0; ticks = 0;
stp_clock = STP_TICK_DIVIDER; stp_clock = STP_TICK_DIVIDER;
dhcp_state.state = DHCP_OFF;
sbuf_ptr = 0; sbuf_ptr = 0;
CKCON = 0; // Initial Clock configuration CKCON = 0; // Initial Clock configuration
+5 -1
View File
@@ -2,7 +2,8 @@ CC = gcc
CCFLAGS = -Wall -o CCFLAGS = -Wall -o
BUILDDIR = output/ BUILDDIR = output/
all: create_build_dir $(BUILDDIR)injector $(BUILDDIR)fileadder $(BUILDDIR)httpd_sim $(BUILDDIR)crc_calculator all: create_build_dir $(BUILDDIR)injector $(BUILDDIR)fileadder $(BUILDDIR)httpd_sim\
$(BUILDDIR)crc_calculator $(BUILDDIR)imagebuilder
create_build_dir: create_build_dir:
mkdir -p $(BUILDDIR) mkdir -p $(BUILDDIR)
@@ -21,3 +22,6 @@ $(BUILDDIR)crc_calculator: crc_calculator.c
$(BUILDDIR)httpd_sim: httpd_sim.c httpd_sim.h $(BUILDDIR)httpd_sim: httpd_sim.c httpd_sim.h
gcc $< $(CCFLAGS) $@ -I/usr/include/json-c -ljson-c gcc $< $(CCFLAGS) $@ -I/usr/include/json-c -ljson-c
$(BUILDDIR)imagebuilder: imagebuilder.c
gcc $^ $(CCFLAGS) $@
+166
View File
@@ -0,0 +1,166 @@
/*
* Adds data files into specified locations of an image, optionally creates
* an index in the form of a header file
*/
#include <stdint.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <argp.h>
#include <stdbool.h>
#define OFFSET 2
#define BANK0_SIZE 0x4000
#define BANK_SIZE 0xc000
#define BANK_STRIDE 0x10000
// Use a 4MB buffer, the maximum flash rom size
#define BUFFER_SIZE 0x400000
uint8_t buffer[BUFFER_SIZE];
FILE *inptr;
int outptr;
const char *argp_program_version = "imagebuilder 0.1";
const char *argp_program_bug_address = "<git@logicog.de>";
static char doc[] = "Create an image with multiple banks for RTL837X-based switches";
static char args_doc[] = "INPUT_IMAGE";
static struct argp_option options[] = {
{ "input", 'i', "FILE", 0, "Input file"},
{ 0 }
};
struct arguments {
char *input_file;
};
static error_t parse_opt(int key, char *arg, struct argp_state *state)
{
struct arguments *arguments = state->input;
switch (key) {
case 'i':
arguments->input_file = arg;
break;
case ARGP_KEY_END:
if (state->arg_num < 1) // Expect 1 command line argument at end
argp_usage(state);
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp argp = {
options, parse_opt, args_doc, doc, 0, 0, 0
};
int main(int argc, char **argv)
{
struct arguments arguments;
int arg_index;
arguments.input_file = NULL;
argp_parse(&argp, argc, argv, 0, &arg_index, &arguments);
memset(buffer, 0, BUFFER_SIZE);
size_t filesize = 0;
inptr = fopen(arguments.input_file, "rb");
if (inptr == NULL) {
printf("Cannot open input file %s\n", arguments.input_file);
return 5;
}
fseek(inptr, 0L, SEEK_END);
filesize = ftell(inptr);
rewind(inptr);
printf("Input file size: %ld\n", filesize);
if (filesize > BUFFER_SIZE) {
printf("File too large.\n");
return 5;
}
int nbanks = (filesize - BANK0_SIZE) / BANK_STRIDE;
printf("Input file contains %d banks\n", nbanks);
/* Verify the size of banks in input file:
* Bank 0: 0x00002 - 0x04000 <- 0x00000 - 0x03ffe
* Bank 1: 0x04000 - 0x10000 <- 0x14000 - 0x20000
* Bank 2: 0x10000 - 0x1c000 <- 0x24000 - 0x33000
* [...]
* by verifying whether other than 0-bytes are found in the input
* file after these ranges.
*/
size_t bytes_read = fread(buffer, 1, filesize, inptr);
if (bytes_read != filesize) {
printf("Error reading input file.\n");
return 5;
}
for (int b = BANK0_SIZE; b < BANK_STRIDE + BANK0_SIZE; b ++) {
if (buffer[b]) {
printf("WARNING: Bank 0: code segment too large at 0x%x!\n", b);
break;
}
}
for (int bank = 1; bank <= nbanks; bank++) {
for (int b = (bank + 1) * BANK_STRIDE; b < (bank + 1) * BANK_STRIDE + BANK0_SIZE; b ++) {
if (buffer[b]) {
printf("WARNING: Bank %d: code segment too large at 0x%x!\n", bank, b);
break;
}
}
}
rewind(inptr);
memset(buffer, 0, BUFFER_SIZE);
// BANK0-Size
buffer[0] = 0x00;
buffer[1] = 0x40;
// Read bank 0
bytes_read = fread(buffer + OFFSET, 1, BANK0_SIZE, inptr);
printf("Bank 0: Bytes read: %ld\n", bytes_read);
if (bytes_read != BANK0_SIZE) {
printf("Error reading input file.\n");
return 5;
}
fseek(inptr, BANK_STRIDE, SEEK_CUR);
for (int bank = 1; bank <= nbanks; bank++) {
bytes_read = fread(buffer + (bank - 1) * BANK_SIZE + BANK0_SIZE, 1, BANK_SIZE, inptr);
printf("Bank %d: bytes read: %ld\n", bank, bytes_read);
if (bank != nbanks)
fseek(inptr, BANK0_SIZE, SEEK_CUR);
}
fclose(inptr);
outptr = creat(argv[arg_index], S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (!outptr) {
printf("Cannot open %s\n", argv[arg_index]);
return 5;
}
size_t written = write(outptr, buffer, (nbanks + 1) * BANK_STRIDE);
if (written != (nbanks + 1) * BANK_STRIDE) {
printf("Error writing output file.\n");
return 5;
}
close(outptr);
return 0;
}
+7 -2
View File
@@ -129,14 +129,18 @@ typedef unsigned short uip_stats_t;
* *
* \hideinitializer * \hideinitializer
*/ */
#define UIP_CONF_UDP 0 #define UIP_CONF_UDP 1
/** /**
* UDP checksums on or off * UDP checksums on or off
* The RTL8372/3 are able to calculate and verify all L2 and L3 checksums
* in hardware. The TX checksums are configured in the CPU-tag of outgoing
* packets, while the RTL837X_NIC_RX_CTRL register configures the verification
* of the checksum of inbound packets and subsequent possible drop.
* *
* \hideinitializer * \hideinitializer
*/ */
#define UIP_CONF_UDP_CHECKSUMS 1 #define UIP_CONF_UDP_CHECKSUMS 0
/** /**
* uIP statistics on or off * uIP statistics on or off
@@ -149,6 +153,7 @@ typedef unsigned short uip_stats_t;
our project. */ our project. */
/*#include "smtp.h"*/ /*#include "smtp.h"*/
#include "httpd.h" #include "httpd.h"
#include "dhcp.h"
/*#include "telnetd.h"*/ /*#include "telnetd.h"*/
/*#include "webserver.h" */ /*#include "webserver.h" */
/*#include "dhcpc.h"*/ /*#include "dhcpc.h"*/
+16 -14
View File
@@ -85,6 +85,7 @@
#include "uip.h" #include "uip.h"
#include "uipopt.h" #include "uipopt.h"
#include "uip_arch.h" #include "uip_arch.h"
#include <stddef.h>
#pragma codeseg BANK1 #pragma codeseg BANK1
#pragma constseg BANK1 #pragma constseg BANK1
@@ -168,8 +169,8 @@ __xdata u16_t uip_listenports[UIP_LISTENPORTS];
/* The uip_listenports list all currently /* The uip_listenports list all currently
listning ports. */ listning ports. */
#if UIP_UDP #if UIP_UDP
struct uip_udp_conn *uip_udp_conn; __xdata struct uip_udp_conn *uip_udp_conn;
struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; __xdata struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
#endif /* UIP_UDP */ #endif /* UIP_UDP */
__xdata static u16_t ipid; /* Ths ipid variable is an increasing __xdata static u16_t ipid; /* Ths ipid variable is an increasing
@@ -401,7 +402,7 @@ uip_init(void) __banked
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if UIP_ACTIVE_OPEN #if UIP_ACTIVE_OPEN
__xdata struct uip_conn * __xdata struct uip_conn *
uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport) __banked
{ {
__xdata struct uip_conn *conn, *cconn; __xdata struct uip_conn *conn, *cconn;
@@ -467,9 +468,9 @@ uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t rport)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if UIP_UDP #if UIP_UDP
struct uip_udp_conn * struct uip_udp_conn *
uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) __banked
{ {
register struct uip_udp_conn *conn; __xdata struct uip_udp_conn *conn;
/* Find an unused local port. */ /* Find an unused local port. */
again: again:
@@ -512,7 +513,7 @@ uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport)
#endif /* UIP_UDP */ #endif /* UIP_UDP */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_unlisten(u16_t port) uip_unlisten(u16_t port) __banked
{ {
for(c = 0; c < UIP_LISTENPORTS; ++c) { for(c = 0; c < UIP_LISTENPORTS; ++c) {
if(uip_listenports[c] == port) { if(uip_listenports[c] == port) {
@@ -523,7 +524,7 @@ uip_unlisten(u16_t port)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_listen(u16_t port) uip_listen(u16_t port) __banked
{ {
for(c = 0; c < UIP_LISTENPORTS; ++c) { for(c = 0; c < UIP_LISTENPORTS; ++c) {
if(uip_listenports[c] == 0) { if(uip_listenports[c] == 0) {
@@ -721,7 +722,6 @@ uip_process(u8_t flag) __banked
/* Reset the length variables. */ /* Reset the length variables. */
uip_len = 0; uip_len = 0;
uip_slen = 0; uip_slen = 0;
/* Check if the connection is in a state in which we simply wait /* Check if the connection is in a state in which we simply wait
for the connection to time out. If so, we increase the for the connection to time out. If so, we increase the
connection's timer and remove the connection if it times connection's timer and remove the connection if it times
@@ -919,12 +919,14 @@ uip_process(u8_t flag) __banked
} }
#endif /* UIP_BROADCAST */ #endif /* UIP_BROADCAST */
/* Check if the packet is destined for our IP address. */ /* Check if we have a DHCP packet, otherwise check if the packet is destined for our IP address. */
#if !UIP_CONF_IPV6 #if !UIP_CONF_IPV6
if(!uip_ipaddr_cmpx(BUF->destipaddr, uip_hostaddr)) { if(!(BUF->proto == UIP_PROTO_UDP && UDPBUF->destport == HTONS(DHCPC_CLIENT_PORT))) {
UIP_STAT(++uip_stat.ip.drop); if(!uip_ipaddr_cmpx(BUF->destipaddr, uip_hostaddr)) {
goto drop; UIP_STAT(++uip_stat.ip.drop);
} goto drop;
}
}
#else /* UIP_CONF_IPV6 */ #else /* UIP_CONF_IPV6 */
/* For IPv6, packet reception is a little trickier as we need to /* For IPv6, packet reception is a little trickier as we need to
make sure that we listen to certain multicast addresses (all make sure that we listen to certain multicast addresses (all
@@ -1901,7 +1903,7 @@ htons(u16_t val)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_send(register __xdata const void *data, register uint16_t len) uip_send(register __xdata const void *data, register uint16_t len) __banked
{ {
if(len > 0) { if(len > 0) {
uip_slen = len; uip_slen = len;
+7 -59
View File
@@ -447,7 +447,7 @@ void uip_setipid(u16_t id);
* *
* \param port A 16-bit port number in network byte order. * \param port A 16-bit port number in network byte order.
*/ */
void uip_listen(u16_t port); void uip_listen(u16_t port) __banked;
/** /**
* Stop listening to the specified port. * Stop listening to the specified port.
@@ -461,7 +461,7 @@ void uip_listen(u16_t port);
* *
* \param port A 16-bit port number in network byte order. * \param port A 16-bit port number in network byte order.
*/ */
void uip_unlisten(u16_t port); void uip_unlisten(u16_t port) __banked;
/** /**
* Connect to a remote host using TCP. * Connect to a remote host using TCP.
@@ -495,7 +495,7 @@ void uip_unlisten(u16_t port);
* or NULL if no connection could be allocated. * or NULL if no connection could be allocated.
* *
*/ */
__xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t port); __xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __xdata u16_t port) __banked;
@@ -535,7 +535,7 @@ __xdata struct uip_conn *uip_connect(register __xdata uip_ipaddr_t *ripaddr, __x
* *
* \hideinitializer * \hideinitializer
*/ */
void uip_send(register __xdata const void *data, register uint16_t len); void uip_send(register __xdata const void *data, register uint16_t len) __banked;
/** /**
* The length of any incoming data that is currently avaliable (if avaliable) * The length of any incoming data that is currently avaliable (if avaliable)
@@ -763,7 +763,7 @@ void uip_send(register __xdata const void *data, register uint16_t len);
* \return The uip_udp_conn structure for the new connection or NULL * \return The uip_udp_conn structure for the new connection or NULL
* if no connection could be allocated. * if no connection could be allocated.
*/ */
struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport); struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, u16_t rport) __banked;
/** /**
* Removed a UDP connection. * Removed a UDP connection.
@@ -1224,8 +1224,8 @@ struct uip_udp_conn {
/** /**
* The current UDP connection. * The current UDP connection.
*/ */
extern struct uip_udp_conn *uip_udp_conn; extern __xdata struct uip_udp_conn *uip_udp_conn;
extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; extern __xdata struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS];
#endif /* UIP_UDP */ #endif /* UIP_UDP */
/** /**
@@ -1538,58 +1538,6 @@ extern __xdata uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
extern __xdata uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; extern __xdata uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
#endif /* UIP_FIXEDADDR */ #endif /* UIP_FIXEDADDR */
/**
* Calculate the Internet checksum over a buffer.
*
* The Internet checksum is the one's complement of the one's
* complement sum of all 16-bit words in the buffer.
*
* See RFC1071.
*
* \param buf A pointer to the buffer over which the checksum is to be
* computed.
*
* \param len The length of the buffer over which the checksum is to
* be computed.
*
* \return The Internet checksum of the buffer.
*/
u16_t uip_chksum(u16_t *buf, u16_t len);
/**
* Calculate the IP header checksum of the packet header in uip_buf.
*
* The IP header checksum is the Internet checksum of the 20 bytes of
* the IP header.
*
* \return The IP header checksum of the IP header in the uip_buf
* buffer.
*/
u16_t uip_ipchksum(void);
/**
* Calculate the TCP checksum of the packet in uip_buf and uip_appdata.
*
* The TCP checksum is the Internet checksum of data contents of the
* TCP segment, and a pseudo-header as defined in RFC793.
*
* \return The TCP checksum of the TCP segment in uip_buf and pointed
* to by uip_appdata.
*/
u16_t uip_tcpchksum(void);
/**
* Calculate the UDP checksum of the packet in uip_buf and uip_appdata.
*
* The UDP checksum is the Internet checksum of data contents of the
* UDP segment, and a pseudo-header as defined in RFC768.
*
* \return The UDP checksum of the UDP segment in uip_buf and pointed
* to by uip_appdata.
*/
u16_t uip_udpchksum(void);
#endif /* __UIP_H__ */ #endif /* __UIP_H__ */