diff --git a/CLI_Readme_DLEP.docx b/CLI_Readme_DLEP.docx deleted file mode 100644 index f8f47fd..0000000 Binary files a/CLI_Readme_DLEP.docx and /dev/null differ diff --git a/CLI_Readme_DLEP.md b/CLI_Readme_DLEP.md new file mode 100644 index 0000000..00d38e8 --- /dev/null +++ b/CLI_Readme_DLEP.md @@ -0,0 +1,433 @@ +# RADIO CLI README + +This is a list of all the radio sim cli commands. parameters with a short description and the command directory hierarchy. + +Starting from the root: + +``` +Radio_RT-1 >ld +[show], [debug], [test] +[fuzz], start, stop +``` + +(Note: “~” is used to come back to main menu/root.) + +``` +Radio_RT-1 > start ? +start - starts the discovery process when MANUAL is defined in the config file. +``` +(Note: This is used for early versions of DLEP. In Latest Discovery Mode is enabled) + +``` +Radio_RT-1 > stop ? +``` +stop - immediately exits the simulation without sending any terminates. + +## SHOW COMMANDS: +``` +Radio_RT-1 >ld +[show], [debug], [test] +[fuzz], start, stop + +Radio_RT-1 >show + +Radio_RT-1 >ld +[system], [peer], [neighbor] + +Radio_RT-1 >system + +Radio_RT-1 >ld +system_show_timer + +Radio_RT-1 >system_show_timer ? +system_show_timer - lists timer stats +Radio_RT-1 > ~ + +Radio_RT-1 >show + +Radio_RT-1 >peer + +Radio_RT-1 >ld +peer_show_all, peer_show_fsm_history, peer_show_fsm_table + +Radio_RT-1 >peer_show_all ? +peer_show_all - lists all peers + +Radio_RT-1 >peer_show_fsm_history ? +peer_show_fsm_history - display peer state history + +Radio_RT-1 >peer_show_fsm_table ? +peer_show_fsm_table - displays peer state machine + +Radio_RT-1 > ~ + + +Radio_RT-1 >show + +Radio_RT-1 >neighbor + +Radio_RT-1 >ld +neighbor_show_mac, neighbor_show_all, neighbor_show_fsm_history +neighbor_show_fsm_table +Radio_RT-1 >neighbor_show_mac ? +neighbor_show_mac - display neighbor info for MAC address +where + - 11:22:33:44:55:66 +Radio_RT-1 >neighbor_show_all ? +neighbor_show_all - lists all client neighbors + +Radio_RT-1 >neighbor_show_fsm_history ? +neighbor_show_fsm_history - displays neighbor state history +where + - 11:22:33:44:55:66 + +Radio_RT-1 >neighbor_show_fsm_table ? +neighbor_show_fsm_table - displays neighbor state machine +where + - 11:22:33:44:55:66 + +Radio_RT-1 > ~ +``` + +## DEBUG COMMANDS: + +``` +Radio_RT-1 >ld +[show], [debug], [test] +[fuzz], start, stop + +Radio_RT-1 >debug + +Radio_RT-1 >ld +debug_show, debug_set, debug_clear +debug_enable, debug_disable + +Radio_RT-1 >debug_show ? +peer_debug_show - displays enabled debugging levels + +Radio_RT-1 >debug_set ? +debug_set [error|udp|incoming|outgoing|packet|peer|neighbor|metrics|scratch|decoder] +where + error - enables the error debug trace + udp - enables debug trace of the udp send-receive + incoming - enables debug trace of incoming packets + outgoing - enables debug trace of outgoing packets + packet - enables both incoming and outgoing packet trace + peer - enables peer specific debug trace + neighbor - enables neighbor specific debug trace + metrics - enables neighbor metrics trace + scratch - enables scratch pad trace + decoder - enables debug trace of TLV validation +Radio_RT-1 >debug_clear ? +debug_clear [error|udp|incoming|outgoing|packet|peer|neighbor|metrics|scratch|decoder] +where + error - disables the error debug trace + udp - disables debug trace for udp operations + incoming - disables debug trace of incoming packets + outgoing - disables debug trace of outgoing packets + packet - enables both incoming and outgoing packet trace + peer - disables peer specific debug trace + neighbor - disables neighbor specific debug trace + metrics - disables neighbor metrics trace + scratch - disables scratch pad trace + decoder - disables debug trace of TLV validation + +Radio_RT-1 >debug_enable ? +debug_enable - enables all debugs + +Radio_RT-1 >debug_disable ? +debug_disable - disables all debugs + +Radio_RT-1 > ~ +``` + +## TEST COMMANDS: + +``` +Radio_RT-1 >test + +Radio_RT-1 >ld +[peer], [neighbor] + +Radio_RT-1 >peer + +Radio_RT-1 >ld + +test_session_init, peer_test_terminate, peer_test_update +peer_test_offer, peer_test_init_ack, peer_test_update_res +peer_test_term_res, peer_test_heartbeat + + +Radio_RT-1 >test_session_init ? +session init enter 0 or 1 + + +Radio_RT-1 >peer_test_terminate ? +peer_test_terminate - sends a peer terminate + + +Radio_RT-1 >peer_test_update ? +peer_test_update - sends a peer update + + + +Radio_RT-1 >peer_test_offer ? +dlep_client_fsm_engine-436 normalized_event=2 p2peer=0x8d26468 peer_id=1 p2neighbor=(nil) + +OUTGOING- 0x44 0x4c 0x45 0x50 0x00 0x02 0x00 0x1e +OUTGOING- 0x00 0x04 0x00 0x0f 0x00 0x44 0x4c 0x45 +OUTGOING- 0x50 0x5f 0x52 0x61 0x64 0x69 0x6f 0x5f +OUTGOING- 0x52 0x54 0x32 0x00 0x02 0x00 0x07 0x00 +OUTGOING- 0x20 0x00 0x00 0x16 0x05 0xa7 + +Sending peer offer : + signal code=2 RFC5444_SIG_PEER_OFFER +sendto: udp failed : Invalid argument +dlep_send-806 Error: peer_id=1 send to 32.0.0.17 at port 1233 bytes=-1 + + +Radio_RT-1 >peer_test_init_ack ? +reaching here + +OUTGOING- 0x00 0x02 0x00 0x84 0x00 0x01 0x00 0x01 +OUTGOING- 0x00 0x00 0x04 0x00 0x0f 0x00 0x44 0x4c +OUTGOING- 0x45 0x50 0x5f 0x52 0x61 0x64 0x69 0x6f +OUTGOING- 0x5f 0x52 0x54 0x32 0x00 0x05 0x00 0x04 +OUTGOING- 0x00 0x00 0x13 0x88 0x00 0x0c 0x00 0x08 +OUTGOING- 0x00 0x00 0x00 0x00 0x05 0xf5 0xe1 0x00 +OUTGOING- 0x00 0x0d 0x00 0x08 0x00 0x00 0x00 0x00 +OUTGOING- 0x05 0xf5 0xe1 0x00 0x00 0x0e 0x00 0x08 +OUTGOING- 0x00 0x00 0x00 0x00 0x05 0xf5 0xe1 0x00 +OUTGOING- 0x00 0x0f 0x00 0x08 0x00 0x00 0x00 0x00 +OUTGOING- 0x05 0xf5 0xe1 0x00 0x00 0x10 0x00 0x08 +OUTGOING- 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xfa +OUTGOING- 0x00 0x12 0x00 0x01 0x64 0x00 0x13 0x00 +OUTGOING- 0x01 0x64 0x00 0x11 0x00 0x01 0x64 0x00 +OUTGOING- 0x14 0x00 0x02 0x00 0x64 0x00 0x08 0x00 +OUTGOING- 0x05 0x01 0x20 0x00 0x00 0x16 0x00 0x0a +OUTGOING- 0x00 0x06 0x01 0xff 0xff 0xff 0x00 0x18 + +Sending Session initialization response : + Message code=2 RFC5444_MSG_PEER_INIT_RES +sendto: tcp failed : Socket operation on non-socket +dlep_tcp_send-882 Error: peer_id=1 send to 32.0.0.17 at port 3333 bytes=-1 + + +Radio_RT-1 >peer_test_update_res ? + +OUTGOING- 0x00 0x04 0x00 0x05 0x00 0x01 0x00 0x01 +OUTGOING- 0x00 + +Sending session update response : + Message code=4 RFC5444_MSG_PEER_UPDATE_RES +sendto: tcp failed : Socket operation on non-socket +dlep_tcp_send-882 Error: peer_id=1 send to 32.0.0.17 at port 3333 bytes=-1 + + + + +Radio_RT-1 >peer_test_term_res ? + +OUTGOING- 0x00 0x06 0x00 0x00 + +Sending session termination message : + Message code=5 RFC5444_MSG_PEER_TERM_RES +sendto: tcp failed : Socket operation on non-socket +dlep_tcp_send-882 Error: peer_id=1 send to 32.0.0.17 at port 3333 bytes=-1 + +Radio_RT-1 >peer_test_heartbeat ? + +OUTGOING- 0x00 0x10 0x00 0x00 + +Sending heartbeat message : + Message code=16 RFC5444_MSG_PEER_HEARTBEAT +sendto: tcp failed : Socket operation on non-socket +dlep_tcp_send-882 Error: peer_id=1 send to 32.0.0.17 at port 3333 bytes=-1 + +Radio_RT-1 > + + +Radio_RT-1 >~ + +Radio_RT-1 >test + +Radio_RT-1 >ld +[peer], [neighbor] + +Radio_RT-1 >neighbor + +Radio_RT-1 >ld + +neighbor_test_up, neighbor_test_credit_up, neighbor_test_metric_up +neighbor_test_ipv4, neighbor_test_ipv6, neighbor_test_down +neighbor_test_metrics, neighbor_test_rlq, neighbor_test_resources +neighbor_test_latency, neighbor_test_cdr, neighbor_test_mdr +neighbor_test_mtu, neighbor_test_update_msg +Radio_RT-1 >neighbor_test_up ? +neighbor_test_up - generate a neighbor up with Layer 3 addresse +where + - 11:22:33:44:55:66 + - 210.123.234.102 + + +Radio_RT-1 >neighbor_test_credit_up ? +neighbor_test_up - generate a neighbor up +where + - 11:22:33:44:55:66 + + + + + + + + +Radio_RT-1 >neighbor_test_metric_up ? +neighbor_test_metric_up - generate a neighbor up w/ metrics +where + - 11:22:33:44:55:66 + ipv4 addrss + - 0 - 100 + - 0 - 100 + - 64-bit millisecond value + - 64-bit bps value + - 64-bit bps value + - 16-bit + + +Radio_RT-1 >neighbor_test_ipv4 ? +neighbor_test_ipv4 - generate a neighbor address IPv4 update +where + - 11:22:33:44:55:66 + - add | drop + - 210.123.234.102 + +Radio_RT-1 >neighbor_test_ipv6 ? +neighbor_test_ipv6 - generate a neighbor address IPv6 update +where + - 11:22:33:44:55:66 + - add | drop + - 11223344:22334455:33445566:44556677 + +Radio_RT-1 >neighbor_test_down ? +neighbor_test_down - generate a neighbor down +where + - 11:22:33:44:55:66 + +Radio_RT-1 >neighbor_test_metrics ? +neighbor_test_metrics - generate a neighbor metrics update +where + - 11:22:33:44:55:66 + - 0 - 100 + - 0 - 100 + - 0 - 100 + - 16-bit millisecond value + - 64-bit bps value + - 64-bit bps value + - 64-bit bps value + - 64-bit bps value + - 16-bit + +Radio_RT-1 >neighbor_test_rlq ? +neighbor_test_rlq - generate a neighbor metrics update with a new RLQ +where + - 11:22:33:44:55:66 + - 0 - 100 + - 0 - 100 + +Radio_RT-1 >neighbor_test_resources ? +neighbor_test_resources - generate a neighbor metrics update with a new resource +where + - 11:22:33:44:55:66 + - 0 - 100 + - 0 - 100 + +Radio_RT-1 >neighbor_test_latency ? +neighbor_test_latency -generate a neighbor metrics update with a new latency +where + - 11:22:33:44:55:66 + 64-bit millisecond value + +Radio_RT-1 >neighbor_test_cdr ? +neighbor_test_cdr - generate a neighbor metrics update with a new CDR +where + - 11:22:33:44:55:66 + 64-bit bps value + 64-bit bps value + +Radio_RT-1 >neighbor_test_mdr ? +neighbor_test_mdr - generate a neighbor metrics update with a new MDR +where + - 11:22:33:44:55:66 + 64-bit bps value + 64-bit bps value +Radio_RT-1 >neighbor_test_mtu ? +neighbor_test_mdr - generate a neighbor metrics update with a new MDR +where + - 11:22:33:44:55:66 + 64-bit bps value + 64-bit bps value + + +Radio_RT-1 >neighbor_test_update_msg +neighbor_test_update_msg - generate a neighbor up +where + - 11:22:33:44:55:66 + +Radio_RT-1 > ~ +``` + +## FUZZ COMMANDS: + +``` +Radio_RT-1 >fuzz + +Radio_RT-1 >ld +[peer], [neighbor] + +Radio_RT-1 >peer + +Radio_RT-1 >ld +peer_fuzz_terminate, peer_fuzz_heartbeat + +Radio_RT-1 >peer_fuzz_terminate ? +peer_fuzz_terminate - sends a peer terminate + +Radio_RT-1 >peer_fuzz_heartbeat ? +peer_fuzz_heartbeat - sends a peer heartbeat + +Radio_RT-1 >~ + +Radio_RT-1 >fuzz + +Radio_RT-1 >ld +[peer], [neighbor] + +Radio_RT-1 >neighbor + +Radio_RT-1 >ld +neighbor_fuzz_up, neighbor_fuzz_term, neighbor_fuzz_metrics + +Radio_RT-1 >neighbor_fuzz_up ? +neighbor_fuzz_up - generate a neighbor up +where + - 11:22:33:44:55:66 + + +Radio_RT-1 >neighbor_fuzz_term ? +neighbor_fuzz_term - generate a neighbor terminate +where + - 11:22:33:44:55:66 +Radio_RT-1 >neighbor_fuzz_metrics ? +neighbor_fuzz_metrics +where + - 11:22:33:44:55:66 + - 0 - 100 + - 0 - 100 + - 16-bit millisecond value + - 64-bit bps value + - 64-bit bps value + + +Radio_RT-1 >~ +``` diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..84ff849 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.2.2) +project(Cisco-DLEP-Radio-Simulator) +add_subdirectory(dlep_radio_ipv4) +add_subdirectory(dlep_radio_ipv6) + diff --git a/Readme_DLEP.docx b/Readme_DLEP.docx deleted file mode 100644 index 8b0fc74..0000000 Binary files a/Readme_DLEP.docx and /dev/null differ diff --git a/Readme_DLEP.md b/Readme_DLEP.md new file mode 100644 index 0000000..c2f3d2c --- /dev/null +++ b/Readme_DLEP.md @@ -0,0 +1,273 @@ +# README + +The CISCO ESR DLEP (DLEP-rfc8175) is an implementation of the Dynamic Link Exchange Protocol, an IETF standards-track protocol (https://datatracker.ietf.org/doc/rfc8175/) that specifies a radio-to-router interface. An IP network protocol runs between a radio/modem and a router over a direct (single hop) connection. Its primary purpose is to enable the modem to tell the router about destinations (other computers/networks) that the modem can reach, and to provide metrics associated with those destinations. The router can then make routing decisions based on that information. + +## OS Requirement: + +This README describes how to build and run the Dlep implementation developed at CISCO ESR Laboratory. The radio simulator can be installed in a linux machine such as +* Red Hat Enterprise Linux Server release 6.9 +* Red Hat Enterprise Linux AS release 4 +* Ubuntu 16.04.3 LTS +* Ubuntu Linux version 14.04 LTS +* CentOS 7.0 + +## Build Procedure: + +``` +cmake . +make + +``` + +## Test Binary: + +The steps involved in testing or running the binary/ simulator are as follows: + +### Step 1 + +In the source directory there will be an example configuration file with the name “uut.cfg” + +You need to change the configuration file before launching the binary. + +Basic configuration changes need to be performed in “uut.cfg” file as follows: +1. The name of the simulator/Radio can be changed with name convention as SIM NAME. +2. IPv4 address or IPv6 address of the Radio, which is mention as LOCAL_IPV4 and LOCAL_IPV6 can be changed with new IPv4 and IPv6 respectively +3. IPv4 address or IPv6 address of the Router, which is mention as ROUTER_IPV4 and ROUTER_IPV6 can be changed with new IPv4 and IPv6 respectively +4. LOCAL_UDP_PORT should be 854, it should not be changed. +5. LOCAL_TCP_PORT, ROUTER_UDP_PORT and ROUTER_TCP_PORT can be changed to any value between <1-65534>. +6. DLEP_PEER_HEARTBEAT_INTERVAL can be set with default value or can be changed with respect to Router configuration. +7. DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD can be set with default value or changed if the rate of heartbeat is high or missing of heartbeat is observed frequently. + +#### IPV4 Configuration details: + +Sample of uut.cfg file inputs are as follows: + +``` +# +# DLEP Sim Radio Config File +# +SIM_NAME Radio_RT-1 + +DEBUG_FLAGS 0xFF +#DEBUG_FLAGS 0x00 + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +MANUAL_START +DISCOVERY_START + +# String for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_RT2 + +LOCAL_UDP_PORT 854 +LOCAL_TCP_PORT 1447 +LOCAL_PORT 44444 +LOCAL_IPV4 a.b.c.d + +#Server pot values + +ROUTER_UDP_PORT 1233 +ROUTER_TCP_PORT 3333 +#ROUTER_PORT 7777 +ROUTER_IPV4 e.f.g.h + +LOCAL_ID 1015 + +### +### Add counters, timers, and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 2000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 2000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# +``` + +#### IPV6 Configuration details: + +Sample of uut.cfg file inputs are as follows: + +``` +# +# DLEP Sim Radio Config File +# +SIM_NAME ipv6_radio1 + +DEBUG_FLAGS 0xFF +#DEBUG_FLAGS 0x00 + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +MANUAL_START +#DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_Sim_1 + +LOCAL_UDP_PORT 854 +LOCAL_TCP_PORT 11115 +LOCAL_IPV6 A:B:C:D:E:F:G:H + +#Server pot values +ROUTER_UDP_PORT 11116 +ROUTER_TCP_PORT 11117 +ROUTER_IPV6 I:J:K:L:M:N:O:P + +LOCAL_ID 1111 + + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 1000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 1000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# +``` + +### Step 2 + +Configure the ip-address of radio to the hardware interface through which the actual communication happens. + +Command to configure the ip-address to hardware interface in Linux prompt is as follows: + +IPv4: ifconfig netmask up + +Example: + +``` +ifconfig eth0 a.b.c.d netmask 255.255.255.0 up +``` + +IPv6: ifconfig inet6 add up + +Example: + +``` +ifconfig eth0 inet6 add a:b:c:d:e:f:g:h/64 up +``` + +### Step 3 + +To run the binary follow the following command: + +An example for IPv4 is shown below, binary execution is same for both IPv4 and IPv6. + +``` +./dlep_radio -f uut.cfg +``` + +### Step 4 + +Upon Successful launch, the simulator will appear as follows: + +``` +sim-radio-1 DLEP Configuration from uut.cfg + local udp port=854 + local tcp port=11111 + local ipv4=10.0.0.1 + router udp port=854 + router tcp port=11114 + router ipv4=10.0.0.2 + + Type Description: DLEP_Radio_RT2 + local ID=1025 + peer_offer_tmo=5 seconds + peer_heartbeat_interval=5 seconds + peer_heartbeat_missed_threshold=2 + peer_term_ack_tmo=1000 milliseconds + peer_term_missed_ack_threshold=3 + + neighbor_up_ack_tmo=2000 milliseconds + neighbor_up_missed_ack_threshold=4 + neighbor_update_interval_tmo=2000 milliseconds + neighbor_activity_timer=10 seconds + neighbor_down_ack_tmo=2000 milliseconds + neighbor_down_missed_ack_threshold=4 + +Adding multicast group...OK. + + waiting connect from router +start on launch +``` + +### Step 5 + +The simulator for DLEP is now up and running now, you can form the session using the router. + +If you enable the debug flags in the configuration file, you can observe the session establishment debugs. + +Example: + +``` +DEBUG_FLAGS 0xFF - Enables the debugs +#DEBUG_FLAGS 0x00 - Disables the debugs +``` + +As with the modem, you should see a "Peer up" message in both windows indicating that the DLEP session initialization successfully completed. + +### Step 6 + +To stop the simulator or to terminate the session completely you need to use “stop” as command, as shown below: + +``` +Radio_RT-1 >stop +``` + +By using this command, the radio simulator will be terminated and you will return to the Linux prompt. + +To relaunch the same radio you can follow from “Step 3”. In case, any modification in the source code you need to follow from “Step 1”. + +(Note: CLI options and the commands to use DLEP simulator is given in CLI_Readme file.) + +## MORE INFORMATION: + +For more information, please refer (https://datatracker.ietf.org/doc/rfc81s75/). diff --git a/dlep-rfc8175.tar b/dlep-rfc8175.tar deleted file mode 100644 index 4ebf70e..0000000 Binary files a/dlep-rfc8175.tar and /dev/null differ diff --git a/dlep_radio_ipv4/1fuzz_dlep_cli.c b/dlep_radio_ipv4/1fuzz_dlep_cli.c new file mode 100644 index 0000000..efeebcc --- /dev/null +++ b/dlep_radio_ipv4/1fuzz_dlep_cli.c @@ -0,0 +1,406 @@ +/*------------------------------------------------------------------ + * fuzz_dlep_cli.c -- fuzz CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reerved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#include "safe_types.h" +#include "cli.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" +#include "packet_dump.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_debug_cli.h" +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" +#include "dlep_porter.h" + +#include "fuzz_message_builder.h" +#include "fuzz_packet.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "fuzz_dlep_cli.h" + + + + +/* + * directory record + */ +static cli_record_t cli_fuzz_dir; +static cli_record_t fuzz_peer_dir; +static cli_record_t fuzz_neighbor_dir; + + +/* + * test command records + */ +static cli_record_t test_peer_hbt_cmd; +static cli_record_t test_peer_term_cmd; +static cli_record_t fuzz_neighbor_up_cmd; + +static cli_record_t fuzz_neighbor_term_cmd; +static cli_record_t fuzz_neighbor_metrics_cmd; + + +/** + ** test peer commands + **/ +static void +peer_fuzz_peer_term (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_fuzz_terminate - sends a peer terminate \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + send_fuzz_peer_terminate(p2peer); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + +static void +peer_fuzz_heartbeat (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_fuzz_heartbeat - sends a peer heartbeat \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + send_fuzz_peer_heartbeat(p2peer); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + + + + +/** + ** test neighbor commands + **/ +static void +cli_fuzz_neighbor_up (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_fuzz_up - generate a neighbor up \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + /* don't send the layer 3 addresses, force router to ARP/ND */ + ipv4_zero_address(&p2neighbor->ipv4_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + + /* set the neighbor metrics */ + p2neighbor->rlq_tx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->latency = 250; + p2neighbor->cdr_tx = 100000000; + p2neighbor->mdr_tx = 100000000; + + send_fuzz_neighbor_up(p2peer, p2neighbor); + return; +} + + +static void +cli_fuzz_neighbor_metrics (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + uint8_t rlq; + uint8_t resources; + uint16_t latency; + uint64_t cdr; + uint64_t mdr; + uint32_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_fuzz_metrics " + " \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf(" - 16-bit millisecond value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq = RFC5444_100_PERCENT; + } else { + rlq = temp; + } + } else { + printf("Input error: rlq missing \n"); + return; + } + + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + resources = RFC5444_100_PERCENT; + } else { + resources = temp; + } + } else { + printf("Input error: resources missing \n"); + return; + } + + if (argv[4]) { + temp = strtoul(argv[4], NULL, 10); + if (temp > 16535) { + latency = 16535; /* 16-bit max */ + } else { + latency = temp; + } + } else { + printf("Input error: latency missing \n"); + return; + } + + cdr = 0; + if (argv[5]) { + cdr = strtoul(argv[5], NULL, 10); + } else { + printf("Input error: cdr missing \n"); + return; + } + + mdr = 0; + if (argv[6]) { + mdr = strtoul(argv[6], NULL, 10); + } else { + printf("Input error: mdr missing \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->rlq_tx = rlq; + p2neighbor->resources_tx = resources; + p2neighbor->latency = latency; + p2neighbor->cdr_tx = cdr; + p2neighbor->mdr_tx = mdr; + + send_fuzz_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: RLQ=%u Resources=%u Latency=%u \n" + " CDR=%llu MDR=%llu \n", + rlq, + resources, + latency, + cdr, + mdr); + return; +} + + +static void +cli_fuzz_neighbor_term (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_fuzz_term - generate a " + "neighbor terminate \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + send_fuzz_neighbor_down(p2peer, p2neighbor); + + //dlep_client_neighbor_fsm_engine(neighbor_term_user_req_e, + // p2peer, p2neighbor); + return; +} + + +/** + * NAME + * fuzz_dlep_cli_init + * + * SYNOPSIS + * void + * fuzz_dlep_cli_init() + * + * DESCRIPTION + * Registers the dlep fuzzing commands with the cli + * facility. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +fuzz_dlep_cli_init (void) +{ + RC_CLI_t rc; + + /* + * Create directory and commands + */ + rc = cli_mkdir("fuzz", NULL, &cli_fuzz_dir); + + rc = cli_mkdir("peer", &cli_fuzz_dir, &fuzz_peer_dir); + rc = cli_mkdir("neighbor", &cli_fuzz_dir, &fuzz_neighbor_dir); + + + /* + * test peer + */ + rc = cli_mkcmd("peer_fuzz_terminate", peer_fuzz_peer_term, + &fuzz_peer_dir, &test_peer_term_cmd); + + rc = cli_mkcmd("peer_fuzz_heartbeat", peer_fuzz_heartbeat, + &fuzz_peer_dir, &test_peer_hbt_cmd); + + /* + * test neighbor + */ + rc = cli_mkcmd("neighbor_fuzz_up", cli_fuzz_neighbor_up, + &fuzz_neighbor_dir, &fuzz_neighbor_up_cmd); + + rc = cli_mkcmd("neighbor_fuzz_term", cli_fuzz_neighbor_term, + &fuzz_neighbor_dir, &fuzz_neighbor_term_cmd); + rc = cli_mkcmd("neighbor_fuzz_metrics", cli_fuzz_neighbor_metrics, + &fuzz_neighbor_dir, &fuzz_neighbor_metrics_cmd); + + return; +} + diff --git a/dlep_radio_ipv4/1fuzz_encoder_tlv.c b/dlep_radio_ipv4/1fuzz_encoder_tlv.c new file mode 100644 index 0000000..180fa0e --- /dev/null +++ b/dlep_radio_ipv4/1fuzz_encoder_tlv.c @@ -0,0 +1,646 @@ +/*---------------------------------------------------------------------- + * fuzz_encoder_tlv.c -- routines to encode TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "network_order.h" + +#include "rfc5444_types.h" +#include "rfc5444_encoder.h" +#include "rfc5444_encoder_tlv.h" + + + +/** + * NAME + * rfc5444_mac_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_mac_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t mac_address[]) + * + * DESCRIPTION + * Call this function to insert the remote MAC address TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * mac_address - the remote router MAC address. The MAC + * is used to uniquely address all neighbor messages. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | MAC Addr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Remote Router MAC Continued (32-bit) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | MAC Addr | + * +-+-+-+-+-+-+-+-+ + * + */ + uint8_t +*fuzz_mac_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t mac_address[]) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MAC_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_MAC_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MAC_ADDRESS_LENGTH); + dest += sizeof(uint16_t); + + dest = mac_put_address(dest, mac_address); + + /*** FUZZ the pointer ***/ + p2encoder_state->buildit_ptr = dest + 1; + return (dest); +} + + +/** + * NAME + * rfc5444_ipv4_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_ipv4_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t operation, + * ipv4_address_t ipv4) + * + * DESCRIPTION + * Call this function to insert the IPv4 TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * operation - indicates the operation to be applied + * on the IPv4 address + * RFC5444_EXISTING_NEW_ADDRESS + * RFC5444_WITHDRAW_ADDRESS + * + * ipv4 - the address + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | operation | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | IPv4 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*fuzz_ipv4_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv4_address_t *ipv4) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV4_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV4_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV4_ADDRESS_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv4_put_address(dest, ipv4); + + /* NETWORK_ORDER_PUTBYTE(dest, 24); + dest += sizeof(uint8_t); */ + + /*** FUZZ the pointer to short***/ + p2encoder_state->buildit_ptr = dest - 2; + return (dest); +} + + + +/** + * NAME + * rfc5444_link_metric_mdr_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_mdr_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t mdr) + * + * DESCRIPTION + * Call this function to insert the maximum datarate TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * mdr - the maximum theoretical data rate, in bits per + * second (bps), achieved on the link. When + * metrics are reported, the maximum data rate + * MUST be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | MDR | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | MDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | MDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ + uint8_t +*fuzz_link_metric_mdr_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_MDR_METRIC_TX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_MDR_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_MDR_LENGTH); + /*** FUZZ over write length ***/ + //dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, mdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + uint8_t +*fuzz_link_metric_mdr_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_MDR_METRIC_RX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_MDR_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_MDR_LENGTH); + /*** FUZZ over write length ***/ + //dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, mdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + +/** + * NAME + * rfc5444_link_metric_cdr_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_cdr_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t cdr) + * + * DESCRIPTION + * Call this function to insert the current datarate TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * cdr - the current data rate, in bits per second + * (bps), achieved on the link. If there is no + * distinction between maximum and current + * data rate, current data rate SHOULD be set + * equal to the maximum data rate. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | CDR | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | CDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | CDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*fuzz_link_metric_cdr_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + /*** FUZZ the tlv type ***/ + //NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_CDR_METRIC_TX); + //dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_CDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, cdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*fuzz_link_metric_cdr_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + /*** FUZZ the tlv type ***/ + //NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_CDR_METRIC_RX); + //dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_CDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, cdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/** + * NAME + * rfc5444_link_metric_latency_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_latency_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t latency) + * + * DESCRIPTION + * Call this function to insert the latency TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * latency - the transmission delay that a packet + * encounters as it is transmitted over the link. + * This is reported in absolute delay, in + * milliseconds. If latency cannot be calculated, + * a value of 0 should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Latency | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Latency | + * +-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*fuzz_link_metric_latency_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_LATENCY_METRIC); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_LATENCY_FLAGS); + dest += sizeof(uint8_t); +#endif + /*** FUZZ the length***/ + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH + 2); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLONG(dest, latency); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*fuzz_link_metric_resources_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RESOURCES_METRIC); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, resources); + dest += sizeof(uint8_t); + + /*** FUZZ the pointer ***/ + p2encoder_state->buildit_ptr = dest + 1; + return (dest); +} +/** + * NAME + * rfc5444_link_metric_rlq_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_rq_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t rlq) + * + * DESCRIPTION + * Call this function to insert the RLQ TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * rlq - a non-dimensional number, 0-100, representing + * the relative link quality. A value of 100 + * represents a link of the highest quality. If + * the RLQ cannot be calculated, a value of 100 + * should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | RLQ | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*fuzz_link_metric_rlq_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RLQ_METRIC_TX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RLQ_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, rlq); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*fuzz_link_metric_rlq_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RLQ_METRIC_RX); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RLQ_LENGTH); + dest += sizeof(uint16_t); + + /*** FUZZ the rlq value ***/ + //NETWORK_ORDER_PUTBYTE(dest, rlq); + //dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/* + * MTU + */ +uint8_t +*fuzz_mtu_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint16_t mtu) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MTU); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MTU_LENGTH); + dest += sizeof(uint16_t); + + /*** FUZZ the mtu value ***/ + + //NETWORK_ORDER_PUTBYTE(dest, mtu); + //dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_status_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + * uint8_t status_code) + * + * DESCRIPTION + * Call this function to insert the peer status TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * status_code - protocol status code reflecting success + * of previous request + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Status Code | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*fuzz_status_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t status_code) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_STATUS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_STATUS_FLAGS); + dest += sizeof(uint8_t); +#endif + + /*** FUZZ the length ***/ + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_STATUS_LENGTH+2); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, status_code); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + diff --git a/dlep_radio_ipv4/1fuzz_message_builder.c b/dlep_radio_ipv4/1fuzz_message_builder.c new file mode 100644 index 0000000..0c8f3a7 --- /dev/null +++ b/dlep_radio_ipv4/1fuzz_message_builder.c @@ -0,0 +1,2383 @@ +/*---------------------------------------------------------------------- + * dlep_message_builder.c -- Routines to build the DLEP messages + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "packet_dump.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_encoder_tlv.h" +#include "rfc5444_encoder.h" + +#include "dlep_sim_options.h" +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" +#include "rfc5444_experimental_tlv.h" + +#include "dlep_message_builder.h" +#include "dlep_client_timer.h" +#include "fuzz_encoder_tlv.h" + +#include "fuzz_message_builder.h" + +extern int TCP_READY; + + +/* + * Local API to increment a sequence number. Sequence numbers + * are simply request-response correlators. They are not + * checked for 'sequencing' or lost messages. The originator + * determines the sequence number so it can correlate the + * response. + */ +static uint16_t +dlep_get_next_sequence_number (uint16_t sequence_number) +{ + sequence_number++; + if (!sequence_number) { + sequence_number++; + } + return (sequence_number); +} + + +/** + * NAME + * send_fuzz_attached_peer_discovery + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_attached_peer_discovery( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a attached peer discovery message + * from the radio to the router to initiate the discovery process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_attached_peer_discovery (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + TCP_READY = 0; +// printf("\n INSIDE send_fuzz_attached_peer_discovery "); + p2es = rfc5444_encoder_packet_start(); + + /* Adding message header */ + rfc5444_encoder_message_block_start(p2es, + RFC5444_SIG_ATT_PEER_DISCOVERY); + + packet_dump("OUTGOING-", + p2es->packet_ptr, + 1); + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_detached_peer_discovery + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_detached_peer_discovery( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a detached peer discovery message + * from the radio to the router to initiate the discovery process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_detached_peer_discovery (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + /* + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); +*/ + +// added for D5 + +rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_DET_PEER_DISCOVERY); + +/* This function call to add message lenth */ + +#if 0 +rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); +#endif +#if 0 + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +/* + // added for testing, will remove it +// rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_DET_PEER_DISCOVERY); + */ + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + p2peer->expected_peer_offer_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + +#endif + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + /* optional */ + rfc5444_peer_tlv(p2es, p2config->local_type_description); +#if 0 + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); +#if 0 + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#endif + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_peer_offer + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_offer(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer offer message + * from the router to the radio in response to the + * peer attached/detached discovery message. This + * confirms discovery. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_offer (dlep_context_peer_t *p2peer) +{ + + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + p2es = rfc5444_encoder_packet_start(); + + /* Adding Message header */ + + rfc5444_encoder_signal_block_start(p2es, + RFC5444_SIG_PEER_OFFER, + DLEP_SIGNAL_FLAGS); + + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_ipv4_connection_point_tlv(p2es, p2config->local_tcp_port, + &p2config->local_ipv4); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending peer offer : \n"); + printf(" signal code=%u RFC5444_SIG_PEER_OFFER \n", + RFC5444_SIG_PEER_OFFER); + } + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + + /* Oppening TCP socket */ +// dlep_tcp_porter_open(p2config); + + rfc5444_encoder_free(p2es); + + return; +} + + + /** + * NAME + * send_fuzz_peer_init + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_init( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer init message + * from the radio to the router to initiate the TCP synchronization process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ + void + send_fuzz_peer_init (dlep_context_peer_t *p2peer) + { + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_INIT_REQ); + + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); + + rfc5444_link_metric_mdr_rx_tlv(p2es, 100000000); + p2peer->mdr_rx=100000000; + + rfc5444_link_metric_mdr_tx_tlv(p2es, 100000000); + p2peer->mdr_tx=100000000; + + rfc5444_link_metric_cdr_rx_tlv(p2es, 100000000); + p2peer->cdr_rx=100000000; + rfc5444_link_metric_cdr_tx_tlv(p2es, 250); + p2peer->cdr_tx =250; + + rfc5444_link_metric_latency_tlv(p2es, 250); + p2peer->latency = 250; + + rfc5444_link_metric_resources_tx_tlv(p2es, 100); + p2peer->resources_tx = 100; + rfc5444_link_metric_resources_rx_tlv(p2es, 100); + p2peer->resources_rx = 100; + + rfc5444_link_metric_rlq_rx_tlv(p2es, 100); + p2peer->rlq_rx = 100; + rfc5444_link_metric_rlq_tx_tlv(p2es, 100); + p2peer->rlq_tx = 100; + + + + /* optional */ + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#if 0 + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + + + printf("\n CALLING dlep_tcp_connect"); +#endif + +#if 0 + dlep_tcp_connect(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); +#endif + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + /* Setting this flag inorder for dlep_tcp_receive to get called after tcp connect + * and first dlep_tcp_send is called inorder to avoid infinite call in loop. + */ + TCP_READY = 1; + + rfc5444_encoder_free(p2es); +// printf("\n PEER INIT REQUEST Sent"); + + return; +} + + /** + * NAME + * send_fuzz_peer_init_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_init( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer init message response + * from the radio to the router. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ + void + send_fuzz_peer_init_ack (dlep_context_peer_t *p2peer) + { + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_INIT_RES); + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); + + rfc5444_link_metric_mdr_rx_tlv(p2es, 100000000); + p2peer->mdr_rx=100000000; + + rfc5444_link_metric_mdr_tx_tlv(p2es, 100000000); + p2peer->mdr_tx=100000000; + + rfc5444_link_metric_cdr_rx_tlv(p2es, 100000000); + p2peer->cdr_rx=100000000; + + rfc5444_link_metric_cdr_tx_tlv(p2es, 250); + p2peer->cdr_tx = 100000000; + + rfc5444_link_metric_latency_tlv(p2es, 250); + p2peer->latency = 250; + + rfc5444_link_metric_rlq_rx_tlv(p2es, 100); + p2peer->rlq_rx = 100; + + rfc5444_link_metric_rlq_tx_tlv(p2es, 100); + p2peer->rlq_tx = 100; + + rfc5444_link_metric_resources_tlv(p2es, 100); + p2peer->resources = 100; + + rfc5444_mtu_tlv(p2es, 100); + p2peer->mtu = 100; + + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2config->local_ipv4); + ipv4_zero_address(&p2peer->ipv4_address); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#if 0 + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + + + printf("\n CALLING dlep_tcp_connect"); +#endif + +#if 0 + dlep_tcp_connect(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); +#endif + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Session initialization response : \n"); + printf(" Message code=%u RFC5444_MSG_PEER_INIT_RES\n",RFC5444_MSG_PEER_INIT_RES); + + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + /* Setting this flag inorder for dlep_tcp_receive to get called after tcp connect + * and first dlep_tcp_send is called inorder to avoid infinite call in loop. + */ + TCP_READY = 1; + + rfc5444_encoder_free(p2es); + + return; +} + + +/** + * NAME + * send_fuzz_peer_heartbeat + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_heartbeat( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer heartbeat to + * maintain a persistent presence with the peer. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_heartbeat (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + +// printf("\n INSIDE send_fuzz_peer_heartbeat"); + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + 18); + +#if 0 + /* + * Get a unique sequence number + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + /* rfc5444_heartbeat_interval_tlv(p2es, + p2config->peer_heartbeat_interval); */ + rfc5444_encoder_message_block_end(p2es); +#if 0 +#ifdef MULTIPLE_PEER_MESSAGES_PACKED + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_HEARTBEAT); + + /* + * Get a unique sequence number + * HB does not have an ACK, so the sequence number is not important. + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); +#endif +#endif + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + /* if (TCP_READY ) { + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + } else { // Else send with UDP socket if heartbeat sent before TCP connection. + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + } */ + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending heartbeat message : \n"); + printf(" Message code=18 RFC5444_MSG_PEER_HEARTBEAT\n"); + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_peer_update_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_update_request( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer update message + * from the router to the radio. It is used to indicate + * a new layer 3 address or the removal of a layer 3 + * address. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_update_request (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_UPDATE_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = dlep_get_next_sequence_number(p2peer->sequence); + p2peer->expected_peer_update_response_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + /* if (p2peer->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2peer->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2peer->update_ipv4_operation, + &p2peer->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2peer->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2peer->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2peer->update_ipv6_operation, + &p2peer->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } */ +#if 0 + rfc5444_encoder_tlv_block_end(p2es); +#endif + printf("Sending mdr ,cdr, latency as fuzz\n"); + fuzz_link_metric_mdr_rx_tlv(p2es, p2peer->mdr_rx); + fuzz_link_metric_mdr_tx_tlv(p2es, p2peer->mdr_tx); + fuzz_link_metric_cdr_rx_tlv(p2es, p2peer->cdr_rx); + fuzz_link_metric_cdr_tx_tlv(p2es, p2peer->cdr_tx); + fuzz_link_metric_latency_tlv(p2es, p2peer->latency); + rfc5444_link_metric_resources_tlv(p2es, p2peer->resources); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2peer->rlq_tx); + rfc5444_link_metric_rlq_rx_tlv(p2es, p2peer->rlq_rx); + rfc5444_mtu_tlv(p2es, p2peer->mtu); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session update request :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_UPDATE_REQ\n", + RFC5444_MSG_PEER_UPDATE_REQ); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + + return; +} + + +/** + * NAME + * send_fuzz_peer_update_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_update_response( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer update response message + * from the radio to the router. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_update_response (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_UPDATE_RES); +#if 0 + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session update response :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_UPDATE_RES\n", + RFC5444_MSG_PEER_UPDATE_RES); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_peer_termination + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_termination(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer termination message + * from the router to the radio or from the radio to the + * router to termiante the association. As result all + * neighbor neighbors are also terminated. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_terminate (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + printf("\n send_fuzz_peer_termination in builder.c "); + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = dlep_get_next_sequence_number( + p2peer->sequence); + p2peer->expected_peer_offer_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +// printf("\n Adding Status TLV"); + rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + rfc5444_encoder_message_block_end(p2es); +#endif +#ifdef MULTIPLE_PEER_MESSAGES_PACKED + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); + + /* + * acks will not align with incremented sequence + * + * p2peer->sequence = dlep_get_next_sequence_number( + * p2peer->sequence); + * p2peer->expected_peer_offer_sequence = p2peer->sequence; + */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + + printf("Sending fuzz status tlv\n"); + fuzz_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session termination :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_TERM_REQ\n", + RFC5444_MSG_PEER_TERM_REQ); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_peer_termination_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_termination_ack(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer termination ACK + * message from the router to the radio or from the radio + * to the router in response to the peer terminate request. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_termination_ack (dlep_context_peer_t *p2peer) +{ + + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_RES); +#if 0 + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + +// rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session terrmination message :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_TERM_REQ\n", + RFC5444_MSG_PEER_TERM_REQ); + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_up + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_up(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor up message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_up (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_REQ); + printf("Sending ip address as fuzz\n"); + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* add the IPv4 address if there is one to add */ + //if (p2neighbor->ipv4_address.v4_addr.v4_addr32) { + fuzz_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv4_address); + ipv4_zero_address(&p2neighbor->ipv4_address); + // } + + /* add the IPv6 address if there is one to add */ + if (p2neighbor->ipv6_address.v6_addr.v6_addr32[0] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[1] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[2] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[3]) { + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv6_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + + + if (!p2neighbor->CREDIT_NOT_SUPPORTED) { + rfc5444_credit_window_status_tlv(p2es, p2neighbor->mrw, p2neighbor->rrw); + } + + rfc5444_encoder_message_block_end(p2es); +#if 0 +//ifdef MULTIPLE_NEIGHBOR_MESSAGES_PACKED + /**** neighbor down ****/ + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_term_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + /**** neighbor up ****/ + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_init_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* add the IPv4 address if there is one to add */ + if (p2neighbor->ipv4_address.v4_addr.v4_addr32) { + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv4_address); + ipv4_zero_address(&p2neighbor->ipv4_address); + } + + /* add the IPv6 address if there is one to add */ + if (p2neighbor->ipv6_address.v6_addr.v6_addr32[0] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[1] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[2] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[3]) { + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv6_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + } + + rfc5444_link_metric_mdr_tlv(p2es, p2neighbor->mdr); + + rfc5444_link_metric_cdr_tlv(p2es, p2neighbor->cdr); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); +#endif + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination up:\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_UP_REQ\n", + RFC5444_MSG_NEIGHBOR_UP_REQ); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_up_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_up_ack(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor up ack message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_up_ack (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); +#if 0 + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_metrics + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_metrics(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor metrics message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context with the + * metrics data set + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_metrics (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + //if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + //p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + //p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + //} + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + printf("Sending relative link quality , resources, mtu as fuzz\n"); + + fuzz_link_metric_resources_tlv(p2es, p2neighbor->resources); + + fuzz_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + fuzz_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + + fuzz_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination update to metrics:\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_METRICS\n", + RFC5444_MSG_NEIGHBOR_METRICS); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + +void +send_fuzz_neighbor_credit_grant_req (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); + +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + +#if 0 + /* + * Get a unique sequence number */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_credit_grand_request_tlv(p2es, p2neighbor->cgr); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + + /* + * start the ack timer. Using same neighbor_up_ack_tmo Neighbor Up Time. + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_update_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_update_ack_tmr, + (void *)p2neighbor); + + return; +} + + +void +send_fuzz_neighbor_credit_reject (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); + + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_rx_tlv(p2es, p2neighbor->resources_tx); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_address_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_address_request(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a peer heartbeat. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_address_request (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_ADDRESS_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = + dlep_get_next_sequence_number(p2neighbor->sequence); + p2neighbor->expected_neighbor_address_response_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_address_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_address_response(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor address response. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_address_response (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_ADDRESS_RES); + + /* + * echo the neighbor sequence number + */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_down + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_down(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor down message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_down (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_REQ); +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_term_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + + printf("Sending mac address as fuzz\n"); + fuzz_mac_address_tlv(p2es, p2neighbor->mac_address); + +// rfc5444_status_tlv(p2es, p2neighbor->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination down :\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_DOWN_REQ\n", + RFC5444_MSG_NEIGHBOR_DOWN_REQ); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_down_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_down_ack(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor down ack message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_down_ack (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination down response :\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_DOWN_RES\n", + RFC5444_MSG_NEIGHBOR_DOWN_RES); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_link_char_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_link_char_request(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor, + * uint64_t cdr, + * uint16_t latency) + * + * DESCRIPTION + * This function is used to send a link characteristic message from + * the server to the client. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * cdr - requested data rate + * + * latency - maximum latency requested + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_link_char_request (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor, + uint64_t cdr, + uint64_t latency) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_LINK_CHAR_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = + dlep_get_next_sequence_number(p2neighbor->sequence); + p2neighbor->expected_neighbor_link_char_response_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (cdr) { + rfc5444_link_metric_cdr_tx_tlv(p2es, cdr); + rfc5444_link_metric_cdr_rx_tlv(p2es, cdr); + } + + + if (latency) { + rfc5444_link_metric_latency_tlv(p2es, latency); + } + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_link_char_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_link_char_response(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a link characteristic response from + * the client to the server. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_link_char_response (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_LINK_CHAR_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + +#if 0 + rfc5444_link_metric_resources_rx_tlv(p2es, p2neighbor->resources_tx); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination link char response :\n"); + printf(" Message code=%u FC5444_MSG_LINK_CHAR_RES\n", + RFC5444_MSG_LINK_CHAR_RES); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + diff --git a/dlep_radio_ipv4/CMakeLists.txt b/dlep_radio_ipv4/CMakeLists.txt new file mode 100644 index 0000000..25617f4 --- /dev/null +++ b/dlep_radio_ipv4/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0.0) +project (dlep_radio_ipv4) +file(GLOB SOURCES "*.c") +add_executable(dlep_radio_ipv4 ${SOURCES}) +install( + TARGETS dlep_radio_ipv4 + RUNTIME DESTINATION bin) + diff --git a/dlep_radio_ipv4/cli.c b/dlep_radio_ipv4/cli.c new file mode 100644 index 0000000..4db9b26 --- /dev/null +++ b/dlep_radio_ipv4/cli.c @@ -0,0 +1,936 @@ +/*------------------------------------------------------------------ + * cli.c -- command line interpreter + * + * Copyright (c) 2009 by B. Berry + * All rights resevered. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include "safe_types.h" + +#include "cli.h" + + +/** + * cli -- command line interpreter + * + * DESCRIPTION + * command line interpreter (cli) provides a directory + * hierarchy of commands similar in concept to the linux + * directory structure. There exists the concept of a root + * directory and subdirectory. Subdirectories can be created + * under root or under other subdirectories. Commands can + * be created under root or any subdirectory. + * + * When the user enters a command, the matching command + * structure is located from the registered commands + * and the associated call-back function is invoked to + * execute the command. + * + * When the user enters a directory name to change directories, + * the cli will change to that directory and display the + * contents. This new directory becomes the present + * working directory (pwd). + * + * User call backs are invoked with the (argc, *argv[]) parameters. + * argv[0] is the command string while argv[1,2,...,ARGC_MAX] are + * command specific parameters. + * + * There are several built-in commands for directory navigation: + * h help + * ~ moves to the top directory, root + * .. moves the directory up one level + * ld lists both commands and directories + * ! (bang) global command execution + * ls global list of commands + * + * Optional built in directories + * cli_config_dir - Commands to manage configuration. + * cli_show_dir - Commands to show internals: configuration, data, etc. + * cli_clear_dir - Commands to clear counters, runtime data, etc. + * cli_opertion_dir - Commands to manage the runtime operation. + * cli_debug_dir - Commands to facilitate debugging. + * + * PUBLIC FUNCTIONS + * cli_mkcmd - add a command to a directory + * cli_mkdir - add a subdirectory to directory + * cli_engine - command processing engine + * cli_init - initialization + * + * + */ + +/* + * #define CLI_DEBUG ( 1 ) + */ +//#define CLI_DEBUG ( 1 ) + +#ifdef CLI_DEBUG +#define DEBUG_PRINTF(myargs...) printf(myargs) +#else +#define DEBUG_PRINTF(myargs...) ((void)0) +#endif + + + +/* + * The maximum number of entries displayed on a single line + * is ENTRIES_PER_LINE. If there are more than ENTRIES_PER_LINE, + * a newline is injected to avoid line wrap. Useful for small + * screens. + */ +#define ENTRIES_PER_LINE ( 3 ) + + + + +/* + * navigation commands + */ +#define CLI_H "h" /* h => help */ +#define CLI_HELP "help" /* help */ +#define CLI_QUESTION "?" /* help */ +#define CLI_UP_ONE ".." /* move up one directory level */ +#define CLI_ROOT_DIR "~" /* move to root directory */ +#define CLI_LIST_DIR "ld" /* list the current directory */ +#define CLI_GLOBAL_BANG "!" /* global execution */ +#define CLI_GLOBAL_LIST "ls" /* global command list */ + + + +/* + * root directory structure + */ +static cli_record_t cli_root_element; + +/* + * pointer to present working directory (pwd) + */ +static cli_record_t *current_directory; + + +static struct t_nodal_record *list; + + +/* + * Public directories that applications can register with. + * Enable define for these root directories. Once defined, + * apps can register in this directory structure. If not, + * applications register to the root directory. + */ +#ifdef CLI_ROOT_DIRS +//cli_record_t cli_config_dir; +cli_record_t cli_show_dir; +//cli_record_t cli_clear_dir; +//cli_record_t cli_operation_dir; +cli_record_t cli_debug_dir; +cli_record_t cli_test_dir; +#endif + + +#define CLI_PROMPT_LEN ( 32 ) +static char cli_prompt[CLI_PROMPT_LEN]; + + + + +static void +cli_help (void) +{ + printf("\n"); + printf(" Built-in commands \n"); + printf(" h help \n"); + printf(" ~ Returns to the top or root command directory \n"); + printf(" .. Moves the from the current directory up one directory \n"); + printf(" ld current directory listing \n"); + printf(" ! (bang) global command seek and execute \n"); + printf(" ls Global list of commands \n"); + printf(" All commands followed by \n"); + + printf("\n"); + return; +} + + + +static boolean_t +str_exact (char *p1, char *p2, size_t n) +{ + while (*p1) { + if (*p1 == *p2) { + p1++; + p2++; + } else { + return (FALSE); + } + } + + if (*p1 == *p2) { + return (TRUE); + } else { + return (FALSE); + } +} + + + + +/* + * NAME + * cli_bind_entry + * + * SYNOPSIS + * #include "cli.h" + * static RC_CLI_t + * cli_bind_entry(char *name, + * cli_funcvar_t fv, + * cli_record_t *dir_rec, + * cli_record_t *cmd_rec) + * + * DESCRIPTION + * This is an internal function to add a command/directory + * into the specified chain. To add an entry into the + * root directory, specify NULL for the directory pointer. + * + * INPUT PARAMETERS + * name the name of the user command. + * + * fv a pointer to the target function to be invoked + * when the command is entered. If NULL then + * the name is considered to be a directory. + * + * dir_rec a pointer to the directory record + * + * cmd_rec a pointer to the command record to be added + * + * RETURN VALUE + * RC_CLI_OK + * error otherwise + * + */ +static RC_CLI_t +cli_bind_entry (char *name, + cli_funcvar_t fv, + cli_record_t *dir_rec, + cli_record_t *cmd_rec) +{ + cli_record_t *p2list; + cli_record_t *p2parent_directory; + + if (name == NULL) { + return (RC_CLI_NULL_NAME); + } + + if (cmd_rec == NULL) { + return (RC_CLI_NULL_CMD); + } + + if (dir_rec == NULL) { + p2list = &cli_root_element; + } else { + p2list = dir_rec; + } + + p2parent_directory = p2list; + + + /* + * can not re-use a record + */ + if (cmd_rec == p2list) { + return (RC_CLI_RECORD_CORRUPT); + } + + /* + * check if the directory is empty to add the + * first entry + */ + if (p2list->link2subdir == NULL) { + p2list->link2subdir = cmd_rec; + + DEBUG_PRINTF("\"%s\" is the First entry in directory [%s]\n", + name, p2list->name ); + + } else { + /* + * Directory is not empty, so walk the list to + * check for duplicates and append the entry. + */ + + p2list = p2list->link2subdir; + + while (p2list->next_entry != NULL) { + /* + * can not re-use a record + */ + if (cmd_rec == p2list) { + return (RC_CLI_RECORD_CORRUPT); + } + + /* + * do not allow duplicate names within the same subdirectory + */ + if (str_exact(p2list->name, name, CLI_ENTRY_LEN)) { + return (RC_CLI_DUPLICATE); + } + + p2list = p2list->next_entry; + } + + /* + * Now we can append the new entry. + */ + p2list->next_entry = cmd_rec; + + DEBUG_PRINTF("Appended \"%s\" in directory [%s]\n", + name, dir_rec->name); + } + + /* + * setup the new entry record + */ + strncpy(cmd_rec->name, name, CLI_ENTRY_LEN-1); + cmd_rec->name[CLI_ENTRY_LEN-1] = '\0'; + cmd_rec->parent_dir = p2parent_directory; + cmd_rec->next_entry = NULL; + cmd_rec->link2subdir = NULL; + cmd_rec->fv = fv; + + if (cmd_rec->fv) { + cmd_rec->cmd_list = list; + list = cmd_rec; + } + + return (RC_CLI_OK); +} + + +/** + * NAME + * cli_mkcmd + * + * SYNOPSIS + * #include "cli.h" + * RC_CLI_t + * cli_mkcmd(char *name, + * cli_funcvar_t fv, + * cli_record_t *dir_rec, + * cli_record_t *cmd_rec) + * + * DESCRIPTION + * Add the new command into the specified directory. + * To add a command into the root directory, + * specify NULL for the directory pointer. + * + * INPUT PARAMETERS + * name pointer to the command name. + * + * fv pointer to the target function to be invoked + * when the command is entered. + * + * dir_rec pointer to the directory record where the + * new command is to be added. Use NULL for root. + * + * cmd_rec pointer to the new command record. + * + * RETURN VALUE + * RC_CLI_OK + * error otherwise + * + * EXAMPLES + * The examples below add three commands to my_directory. + * + * rcode = cli_mkcmd ( "command_one", funct_one, + * &my_directory_record, &cmd_one_record ); + * rcode = cli_mkcmd ( "command_two", funct_two, + * &my_directory_record, &cmd_two_record ); + * rcode = cli_mkcmd ( "command_three", funct_three, + * &my_directory_record, &cmd_three_record ); + * + */ +RC_CLI_t +cli_mkcmd (char *name, + cli_funcvar_t fv, + cli_record_t *dir_rec, + cli_record_t *cmd_rec) +{ + RC_CLI_t rc; + + if (fv == NULL) { + return (RC_CLI_NULL_FV); + } + + /* + * bind into ROOT if directory not specified + */ + if (dir_rec == NULL) { + dir_rec = &cli_root_element; + } + + /* + * you must bind only to a directory + */ + if (dir_rec->fv != NULL) { + return (RC_CLI_DIR_INVALID); + } + + rc = cli_bind_entry(name, fv, dir_rec, cmd_rec); + return (rc); +} + + +/** + * NAME + * cli_mkdir + * + * SYNOPSIS + * #include "cli.h" + * RC_CLI_t + * cli_mkdir(char *name, cli_record_t *dir_rec, + * cli_record_t *sub_dir) + * + * DESCRIPTION + * Add a new directory into the specified directory. + * To add a new directory into the ROOT directory, + * specify NULL for the directory pointer. + * + * INPUT PARAMETERS + * name pointer to the direcory name. + * + * dir_rec pointer to the directory record where the + * new subdir is to be added. Use NULL for root. + * + * cmd_rec pointer to the new directory record. + * + * RETURN VALUE + * RC_CLI_OK + * error otherwise + * + * EXAMPLES + * The example below adds a_directory (subdirectory) to the + * root directory. This is a visible entry. + * + * rc = cli_mkdir( "a_directory", NULL, + * &a_directory_record); + * + * + * The example below adds a_sub_directory (subdirectory) to the + * previously created directory 'a_directory_record'. + * + * rc = cli_mkdir( "a_sub_directory", &a_directory_record, + * &a_subdir_record); + * + */ +RC_CLI_t +cli_mkdir (char *name, cli_record_t *dir_rec, + cli_record_t *sub_dir) +{ + RC_CLI_t rc; + + /* + * bind into ROOT if the directory is not specified + */ + if (dir_rec == NULL) { + dir_rec = &cli_root_element; + } + + /* + * must bind only to an existing directory + */ + if (dir_rec->fv != NULL) { + return (RC_CLI_DIR_INVALID); + } + + rc = cli_bind_entry(name, NULL, dir_rec, sub_dir); + return (rc); +} + + +/* + * NAME + * global_command_list + * + * SYNOPSIS + * #include "cli.h" + * static void + * global_command_list(void) + * + * DESCRIPTION + * Displays the global list of commands. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * void + * + */ +static void +global_command_list (void) +{ + uint16_t count; + cli_record_t *cmd_rec; + + count = 0; + + /* + * global list of command + */ + printf("\n"); + cmd_rec = list; + while (cmd_rec != NULL) { + if (count){ printf(", "); } + + printf("%s", cmd_rec->name); + count++; + + /* + * prevent line wrap + */ + if (count >= ENTRIES_PER_LINE) { + printf("\n"); + count = 0; + } + cmd_rec = cmd_rec->cmd_list; + } + + return; +} + + +/* + * NAME + * list_directory + * + * SYNOPSIS + * #include "cli.h" + * static void + * list_directory(void) + * + * DESCRIPTION + * Display the contents of the directory, both commands and + * subdirectories. Directories are enclosed in brackets, [..]. + * + * INPUT PARAMETERS + * none + * + * RETURN VALUE + * void + * + */ +static void +list_directory (void) +{ + uint16_t count; + cli_record_t *cmd_tmp; + + count = 0; + + /* + * first list all directoies + * list directory with brackets: [ directory ] + */ + printf("\n"); + cmd_tmp = current_directory->link2subdir; + while (cmd_tmp != NULL) { + + /* fv == NULL means it is a directory */ + if (cmd_tmp->fv == NULL) { + if (count){ printf(", "); } + + printf("[%s]", cmd_tmp->name); + count++; + + /* + * prevent line wrap + */ + if (count >= ENTRIES_PER_LINE) { + printf("\n"); + count = 0; + } + } + cmd_tmp = cmd_tmp->next_entry; + } + + /* + * list commands + */ + cmd_tmp = current_directory->link2subdir; + while (cmd_tmp != NULL) { + + if (cmd_tmp->fv != NULL) { + if (count){ printf(", "); } + + printf("%s", cmd_tmp->name); + count++; + + /* + * prevent line wrap + */ + if (count >= ENTRIES_PER_LINE) { + printf("\n"); + count = 0; + } + } + cmd_tmp = cmd_tmp->next_entry; + } + + return; +} + + +/* + * NAME + * cli_find_cmd + * + * SYNOPSIS + * #include "cli.h" + * static cli_record_t + * *cli_find_cmd(char *name) + * + * DESCRIPTION + * An internal function to scan the current directory for the + * specified entry. + * + * INPUT PARAMETERS + * name pointer to the string to look for (null terminated). + * + * RETURN VALUE + * NULL string NOT found + * ptr Pointer to entry record if a match was found + * + */ +static cli_record_t +*cli_find_cmd (char *name) +{ + cli_record_t *cmd_rec; + + DEBUG_PRINTF("\nAttempting to Find \"%s\" in directory [%s]\n", + name, current_directory->name ); + + /* + * check for global command search + */ + if (*name == '!') { + DEBUG_PRINTF("\nGlobal command search! \n"); + + name++; + cmd_rec = list; + while (cmd_rec != NULL) { + DEBUG_PRINTF("\nglobal comparing \"%s\" with entry \"%s\"\n", + name, cmd_rec->name); + + if (str_exact(cmd_rec->name, name, CLI_ENTRY_LEN)) { + DEBUG_PRINTF("\nGlobal match found for -%s- \n", name); + return (cmd_rec); + } + cmd_rec = cmd_rec->cmd_list; + } + + printf("\n*Unknown entry \"%s\"\n", name); + return (NULL); + } + + /* + * now compare to existing command and directory entries + */ + cmd_rec = current_directory->link2subdir; + while (cmd_rec != NULL) { + DEBUG_PRINTF("\ncomparing \"%s\" with entry \"%s\"\n", + name, cmd_rec->name); + + if (str_exact(cmd_rec->name, name, CLI_ENTRY_LEN)) { + DEBUG_PRINTF("\nMatch found for -%s- \n", name); + return (cmd_rec); + } + cmd_rec = cmd_rec->next_entry; + } + + /* + * check to see if the user wants to go back one directory + */ + if (str_exact(name, CLI_UP_ONE, 2)) { + DEBUG_PRINTF("\nGo up one dir level \n"); + current_directory = current_directory->parent_dir; + return (NULL); + } + + /* + * check to see if user wants to go to the root directory + */ + if (str_exact(name, CLI_ROOT_DIR, 1)) { + DEBUG_PRINTF("\nGo to root \n"); + current_directory = &cli_root_element; + return (NULL); + } + + /* + * check to see if user wants to list entries + */ + if (str_exact(name, CLI_LIST_DIR, 2)) { + DEBUG_PRINTF("\nList directory \n"); + list_directory(); + return (NULL); + } + + if (str_exact(name, CLI_GLOBAL_LIST, 2)) { + DEBUG_PRINTF("\nGlobal List \n"); + global_command_list(); + return (NULL); + } + + if (str_exact(name, CLI_H, 1) || + str_exact(name, CLI_HELP, 4) || + str_exact(name, CLI_QUESTION, 1)) { + cli_help(); + return (NULL); + } + + /* did not find a match */ + printf("\n*Unknown entry \"%s\"\n", name); + return (NULL); +} + + +/** + * NAME + * cli_engine + * + * SYNOPSIS + * #include "cli.h" + * void + * cli_engine(char *input_string) + * + * DESCRIPTION + * The CLI engine. + * + * INPUT PARAMETERS + * input_string - The string as entered by the user. The cli + * processor will use the first token to match a + * valid directory or command entry. If the + * entry matches with a directory, the current + * directory is changed to that directory. + * + * If the entry is a command, the remainder of the + * string is passed to the user function. The user + * function can then continue parsing token. + * + * RETURN VALUE + * None + * + * : + * For example, a simple CLI process. + * for(;;) { + * gets(input_string); + * cli_engine(input_string); + * } + * + */ +void +cli_engine (char *input_string) +{ + cli_record_t *next_level; + uint32_t i; + char *p2str; + + uint32_t argc; + char *argv[ARGC_MAX]; + + if ((input_string == NULL) || (*input_string == '\0')) { + DEBUG_PRINTF("\nEmpty string entered\n"); + + printf("\n%s >", cli_prompt); + fflush(stdout); + return; + } + + for (i=0; i", cli_prompt); + fflush(stdout); + return; + } + + DEBUG_PRINTF("\n0 input token \"%s\"\n", argv[0]); + + /* + * now pick off parameters. + */ + argc = 1; + for (i=1; ifv != NULL) { + /* + * call users registered function + */ + (next_level->fv)(argc, &argv[0]); + + } else { + /* + * change to the subdirectory + */ + current_directory = next_level; + } + } else { + /* Did not find a match */ + } + + printf("\n%s >", cli_prompt); + fflush(stdout); + return; +} + + + +/** + * NAME + * cli_set_prompt + * + * SYNOPSIS + * #include "cli.h" + * void + * cli_set_prompt(char *prompt) + * + * DESCRIPTION + * This function is used to set a prompt string. + * + * INPUT PARAMETERS + * prompt - pointer to the string prompt + * + * RETURN VALUE + * none + * + */ +void +cli_set_prompt (char *prompt) +{ + if (prompt) { + strncpy(cli_prompt, prompt, CLI_PROMPT_LEN); + cli_prompt[CLI_PROMPT_LEN-1] = '\0'; + } + + return; +} + + + +/** + * NAME + * cli_init + * + * SYNOPSIS + * #include "cli.h" + * RC_CLI_t + * cli_init (cli_init_data_t *init_data) + * + * DESCRIPTION + * This function initializes the CLI facility. All the + * parameters listed in init_data must be provided. + * + * INPUT PARAMETERS + * init_data pointer to initialization information + * prefix - string to be displayed at the + * root directory + * + * RETURN VALUE + * RC_CLI_OK + * error otherwise + * + */ +RC_CLI_t +cli_init (cli_init_data_t *init_data) +{ + RC_CLI_t rc; + + strncpy(cli_prompt, "prompt", CLI_PROMPT_LEN); + cli_prompt[CLI_PROMPT_LEN-1] = '\0'; + + /* + * initialize the ROOT directory + */ + strncpy(cli_root_element.name, init_data->prefix, CLI_ENTRY_LEN); + + cli_root_element.name[CLI_ENTRY_LEN-1] = '\0'; + cli_root_element.fv = NULL; + cli_root_element.parent_dir = &cli_root_element; + cli_root_element.next_entry = NULL; + cli_root_element.link2subdir = NULL; + + /* mark end of hte command list */ + list = NULL; + + +#ifdef CLI_ROOT_DIRS +// rc = cli_mkdir("config", NULL, &cli_config_dir); + rc = cli_mkdir("show", NULL, &cli_show_dir); +// rc = cli_mkdir("clear", NULL, &cli_clear_dir); +// rc = cli_mkdir("operation", NULL, &cli_operation_dir); + rc = cli_mkdir("debug", NULL, &cli_debug_dir); + rc = cli_mkdir("test", NULL, &cli_test_dir); +#endif + + current_directory = &cli_root_element; + return (RC_CLI_OK); +} + diff --git a/dlep_radio_ipv4/cli.h b/dlep_radio_ipv4/cli.h new file mode 100644 index 0000000..62ffb92 --- /dev/null +++ b/dlep_radio_ipv4/cli.h @@ -0,0 +1,148 @@ +/*------------------------------------------------------------------ + * cli.h -- embedded command line interpreter + * + * Copyright (C) 2009 by B. Berry + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __CLI_H__ +#define __CLI_H__ + +#include + +/* + * Public directories that applications can register with. + * Enable define for these root directories. Once defined, + * apps can register in this directory structure. If not, + * applications register to the root directory. + */ +#define CLI_ROOT_DIRS ( 1 ) + + +/* + * This is the maximum number of parameters that can be passed + * to the application function. The parameters are passed to + * the application in the argument count and argument value + * format. + */ +#define ARGC_MAX ( 11 ) + + +/* + * Number of characters in an entry's name, for directories + * and commands + */ +#define CLI_ENTRY_LEN ( 34 ) + + +/* + * return codes + */ +typedef enum { + RC_CLI_OK = 0, + RC_CLI_NULL_NAME, + RC_CLI_NULL_FV, + RC_CLI_DUPLICATE, + RC_CLI_RECORD_CORRUPT, + RC_CLI_NULL_CMD, + RC_CLI_DIR_INVALID, +} RC_CLI_t; + + + +/* + * type def for call back function to process user command parsers + */ +typedef void (*cli_funcvar_t)(uint32_t argc, char *argv[]); + + +/* + * The structure for a directory or command entry. + */ +typedef struct t_nodal_record { + struct t_nodal_record *cmd_list; + char name[CLI_ENTRY_LEN+1]; + cli_funcvar_t fv; + struct t_nodal_record *parent_dir; + struct t_nodal_record *next_entry; + struct t_nodal_record *link2subdir; +} cli_record_t; + + + +/* + * A few common root command directories + * if enabled. + */ +#ifdef CLI_ROOT_DIRS +extern cli_record_t cli_config_dir; +extern cli_record_t cli_show_dir; +extern cli_record_t cli_clear_dir; +//extern cli_record_t cli_operation_dir; +extern cli_record_t cli_debug_dir; +extern cli_record_t cli_test_dir; +#endif + + +/* + * The structure required to initialize the CLI facility. + * It must be initialized before use. + */ +typedef struct { + char prefix[CLI_ENTRY_LEN]; +} cli_init_data_t; + + + +/* + * prototypes + */ + +/* add a command */ +extern RC_CLI_t cli_mkcmd(char *name, + cli_funcvar_t fv, + cli_record_t *dir_rec, + cli_record_t *cmd_rec); + + +/* make a directory */ +extern RC_CLI_t cli_mkdir(char *name, + cli_record_t *dir_rec, + cli_record_t *sub_dir); + + +/* drive the cli */ +extern void cli_engine(char *input_string); + + +/* set the prompt string */ +void cli_set_prompt(char *prompt); + + +/* init function */ +extern RC_CLI_t cli_init(cli_init_data_t *init_data); + +#endif /* __CLI_H__ */ + diff --git a/dlep_radio_ipv4/config_examples/my_radio_discovery.cfg b/dlep_radio_ipv4/config_examples/my_radio_discovery.cfg new file mode 100644 index 0000000..8aaaa0a --- /dev/null +++ b/dlep_radio_ipv4/config_examples/my_radio_discovery.cfg @@ -0,0 +1,60 @@ +# +# DLEP Sim Radio Config File +# +SIM_NAME radio_2 + +#DEBUG_FLAGS 0xFF + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +#MANUAL_START +DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_Sim_2 + +LOCAL_UDP_PORT 38681 +LOCAL_TCP_PORT 38682 +LOCAL_IPV4 9.0.0.179 + +ROUTER_UDP_PORT 38677 + +ROUTER_TCP_PORT 38675 +ROUTER_IPV4 9.1.1.201 + +LOCAL_ID 2222 + + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 1000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 1000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# + diff --git a/dlep_radio_ipv4/config_examples/my_radio_discovery_2.cfg b/dlep_radio_ipv4/config_examples/my_radio_discovery_2.cfg new file mode 100644 index 0000000..f70d272 --- /dev/null +++ b/dlep_radio_ipv4/config_examples/my_radio_discovery_2.cfg @@ -0,0 +1,60 @@ +# +# DLEP Sim Radio Config File +# +SIM_NAME radio_2 + +DEBUG_FLAGS 0xFF + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +#MANUAL_START +DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_Sim_2 + +LOCAL_UDP_PORT 38700 +LOCAL_TCP_PORT 38710 +LOCAL_IPV4 20.1.1.4 + +ROUTER_UDP_PORT 38777 + +ROUTER_TCP_PORT 38775 +ROUTER_IPV4 9.1.1.202 + +LOCAL_ID 2222 + + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 1000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 1000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# + diff --git a/dlep_radio_ipv4/config_examples/uut.cfg b/dlep_radio_ipv4/config_examples/uut.cfg new file mode 100644 index 0000000..060631b --- /dev/null +++ b/dlep_radio_ipv4/config_examples/uut.cfg @@ -0,0 +1,64 @@ +# +# DLEP Sim Radio Config File +# +SIM_NAME Radio_RT-1 + +DEBUG_FLAGS 0xFF +#DEBUG_FLAGS 0x00 + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +MANUAL_START +DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_RT2 + +LOCAL_UDP_PORT 854 +LOCAL_TCP_PORT 11111 +#LOCAL_PORT 5657 +LOCAL_IPV4 17.0.0.21 + +#Server pot values + +ROUTER_UDP_PORT 11113 +ROUTER_TCP_PORT 11114 +#ROUTER_PORT 1314 +ROUTER_IPV4 17.0.0.24 + +LOCAL_ID 1025 + + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 2000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 2000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# + diff --git a/dlep_radio_ipv4/dlep_buffers.c b/dlep_radio_ipv4/dlep_buffers.c new file mode 100644 index 0000000..892a9ca --- /dev/null +++ b/dlep_radio_ipv4/dlep_buffers.c @@ -0,0 +1,141 @@ +/*---------------------------------------------------------------------- + * dlep_buffers.c -- abstracted buffer routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include + +#include "safe_types.h" +#include "dlep_debug.h" + +#include "dlep_buffers.h" + +/* + * Porting: The implementation of the functions in this file can be + * changed to platform specific buffer management APIs. + */ + + +#define MAX_BUFFER_SIZE ( 1400 ) + + +/** + * NAME + * dlep_allocate_transmit_buffer + * + * SYNOPSIS + * uint8_t + * *dlep_allocate_transmit_buffer(void) + * + * DESCRIPTION + * This function is used to allocate a buffer for transmit + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * Pointer to a buffer or NULL if no buffer is available. + * + */ +uint8_t +*dlep_allocate_transmit_buffer (void) +{ + void *ptr; + + ptr = malloc(MAX_BUFFER_SIZE); + return (ptr); +} + + +/** + * NAME + * dlep_allocate_receive_buffer + * + * SYNOPSIS + * uint8_t + * *dlep_allocate_receive_buffer(void) + * + * DESCRIPTION + * This function is used to allocate a receive buffer + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * Pointer to a buffer or NULL if no buffer is available. + * + */ +uint8_t +*dlep_allocate_receive_buffer (void) +{ + void *ptr; + + ptr = malloc(MAX_BUFFER_SIZE); + return (ptr); +} + + +/** + * NAME + * dlep_free_buffer + * + * SYNOPSIS + * void + * *dlep_free_buffer(void) + * + * DESCRIPTION + * This routine frees a previously allocated (transmit and + * receive) buffer. + * + * INPUT PARAMETERS + * ptr - This is a pointer to the buffer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_free_buffer (void *ptr) +{ + if (ptr) { + free(ptr); + } + return; +} + diff --git a/dlep_radio_ipv4/dlep_buffers.h b/dlep_radio_ipv4/dlep_buffers.h new file mode 100644 index 0000000..f868081 --- /dev/null +++ b/dlep_radio_ipv4/dlep_buffers.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------- + * dlep_buffers.h -- abstracted buffer routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_BUFFERS_H__ +#define __DLEP_BUFFERS_H__ + +#include "safe_types.h" + + +extern uint8_t +*dlep_allocate_transmit_buffer(void); + +extern uint8_t +*dlep_allocate_receive_buffer(void); + +extern void +dlep_free_buffer(void *ptr); + +#endif + diff --git a/dlep_radio_ipv4/dlep_client_message_parser.c b/dlep_radio_ipv4/dlep_client_message_parser.c new file mode 100644 index 0000000..8965ceb --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_message_parser.c @@ -0,0 +1,377 @@ +/*---------------------------------------------------------------------- + * dlep_client_message_parser.c -- client message parsing routine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" + +#include "dlep_client_message_parser.h" + +void +rfc5444_show_signal_scratch_pad ( + rfc5444_message_scratch_pad_t *msg_scratch_pad) +{ + char *p2text; + + if (!msg_scratch_pad) { + return; + } + + switch (msg_scratch_pad->message_code) { + case RFC5444_SIG_ATT_PEER_DISCOVERY: + p2text = "RFC5444_SIG_ATT_PEER_DISCOVERY"; + break; + + case RFC5444_SIG_PEER_OFFER: + p2text = "RFC5444_SIG_PEER_OFFER"; + break; + } + + + printf("Signal Scratch Pad \n"); + + printf(" signal code=%u %s \n", + msg_scratch_pad->message_code, + p2text); +} + +/** + * NAME + * dlep_client_message_parser + * + * SYNOPSIS + * void + * dlep_client_message_parser(uint16_t message_code, + * uint16_t sequence_number, + * void *context_ptr) + * + * DESCRIPTION + * This function is used by the client application to handle the + * initial parse of a DLEP message. Only the valid set of DLEP + * messages expected by the client are processed. + * + * INPUT PARAMETERS + * message_code - This is the message code representing the + * message to be parsed. + * + * sequence_number - The sequence number of the message + * + * context_ptr - The pointer to the message scratch pad + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_client_message_parser (uint16_t message_code, + uint16_t sequence_number, + void *context_ptr, int signal) +{ + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *scratch_pad; + dlep_context_neighbor_t *p2neighbor; + + p2peer = context_ptr; + if (!p2peer) { + return; + } + + p2peer->status_code = RFC5444_SUCCESS; + + scratch_pad = &p2peer->message_scratch_pad; + + scratch_pad->message_code = message_code; + + scratch_pad->sequence = sequence_number; + scratch_pad->sequence_present = TRUE; + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + if (signal) { + rfc5444_show_signal_scratch_pad(scratch_pad); + } else { + rfc5444_show_message_scratch_pad(scratch_pad); + } + } + + /* + * now drive the state machine by the message type + */ + + if (signal) { + switch (message_code) { + + case RFC5444_SIG_ATT_PEER_DISCOVERY: + dlep_client_fsm_engine(peer_att_discovery_e, p2peer, NULL); + break; + /* this signal client does not receive */ + case RFC5444_SIG_PEER_OFFER: + dlep_client_fsm_engine(peer_offer_e, p2peer, NULL); + DLEP_DEBUG("%s-%u DLEP unexpected signal, signal_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + break; + default: + DLEP_DEBUG("%s-%u DLEP unknown signal, signal_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + break; + } + } + else { + switch (message_code) { + + case RFC5444_MSG_PEER_INIT_REQ: + dlep_client_fsm_engine(peer_init_request_e, p2peer, NULL); + break; + + case RFC5444_MSG_PEER_HEARTBEAT: + dlep_client_fsm_engine(peer_heartbeat_e, p2peer, NULL); + break; + + case RFC5444_MSG_PEER_UPDATE_REQ: + dlep_client_fsm_engine(peer_update_request_e, p2peer, NULL); + break; + + case RFC5444_MSG_PEER_UPDATE_RES: + dlep_client_fsm_engine(peer_update_response_e,p2peer, NULL); + break; + + case RFC5444_MSG_PEER_TERM_REQ: + dlep_client_fsm_engine(peer_term_request_e, p2peer, NULL); + break; + + case RFC5444_MSG_PEER_TERM_RES: + dlep_client_fsm_engine(peer_term_response_e, p2peer, NULL); + break; + + case RFC5444_MSG_NEIGHBOR_UP_RES: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_init_ack_e, + p2peer, p2neighbor); + } + break; + + case RFC5444_MSG_NEIGHBOR_METRICS: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + printf("\nRFC5444_MSG_NEIGHBOR_METRICS: Received with ERROR"); + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + printf("\nRFC5444_MSG_NEIGHBOR_METRICS: Received "); + dlep_client_neighbor_fsm_engine(neighbor_update_ack_e, + p2peer, p2neighbor); + } + break; + + case RFC5444_MSG_NEIGHBOR_ADDRESS_RES: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_update_addr_res_e, + p2peer, p2neighbor); + } + break; + + case RFC5444_MSG_NEIGHBOR_DOWN_REQ: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_term_e, + p2peer, p2neighbor); + } + break; + + case RFC5444_MSG_NEIGHBOR_DOWN_RES: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_term_ack_e, + p2peer, p2neighbor); + } + break; + + + case RFC5444_MSG_LINK_CHAR_REQ: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_link_char_req_e, + p2peer, p2neighbor); + } + break; + + + /* messages that the client peer can not receive */ + case RFC5444_MSG_PEER_INIT_RES: + DLEP_DEBUG("%s-%u DLEP unexpected message, msg_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + printf("\nUnexpected message sending termination message\n"); + p2peer->status_code = RFC5444_MSG_UNEXPECTED; + send_dlep_peer_termination(p2peer); + break; + case RFC5444_MSG_NEIGHBOR_UP_REQ: + DLEP_DEBUG("%s-%u DLEP unexpected message, msg_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + printf("\nUnexpected message sending termination message\n"); + p2peer->status_code = RFC5444_MSG_UNEXPECTED; + send_dlep_peer_termination(p2peer); + break; + case RFC5444_MSG_LINK_CHAR_RES: + DLEP_DEBUG("%s-%u DLEP unexpected message, msg_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + printf("\nUnexpected message sending termination message\n"); + p2peer->status_code = RFC5444_MSG_UNEXPECTED; + send_dlep_peer_termination(p2peer); + break; + + default: + DLEP_DEBUG("%s-%u DLEP unknown message, msg_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + printf("\nUnknown message sending termination message\n"); + p2peer->status_code = RFC5444_MSG_UNKNOWN; + send_dlep_peer_termination(p2peer); + break; + } + + } + rfc5444_scrub_message_scratch_pad(scratch_pad); + + return; +} + diff --git a/dlep_radio_ipv4/dlep_client_message_parser.h b/dlep_radio_ipv4/dlep_client_message_parser.h new file mode 100644 index 0000000..e3580f8 --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_message_parser.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------- + * dlep_client_message_parser.h -- Message parsing routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_MESSAGE_PARSER_H__ +#define __DLEP_CLIENT_MESSAGE_PARSER_H__ + +#include "safe_types.h" +#include "dlep_context_peer.h" + + +extern void +dlep_client_message_parser(uint16_t message_code, + uint16_t sequence_number, + void *context_ptr,int signal); + +#endif + diff --git a/dlep_radio_ipv4/dlep_client_metrics.c b/dlep_radio_ipv4/dlep_client_metrics.c new file mode 100644 index 0000000..366b7aa --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_metrics.c @@ -0,0 +1,206 @@ +/*---------------------------------------------------------------------- + * dlep_client_metrics.c -- dynamic client metrics + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "safe_types.h" +#include "dlep_context_neighbor.h" + + +static int32_t metric_index = 0; +static int32_t metric_direction = 1; + + +/** + * NAME + * dlep_client_metrics + * + * SYNOPSIS + * void + * dlep_client_metrics(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to insert a dynamic nature to the + * metrics for test. + * + * INPUT PARAMETERS + * p2neighbor - pointer to the neighbor + * + * OUTPUT PARAMETERS + * p2neighbor - neighbor metrics updated + * + * RETURN VALUE + * none + * + */ +void +dlep_client_metrics (dlep_context_neighbor_t *p2neighbor) +{ + if (!p2neighbor) { + return; + } + + /* + * could be more creative with file inputs + * or radio models. + */ + switch (metric_index) { + case 0: + p2neighbor->rlq_rx = 100; + p2neighbor->rlq_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_rx = 0; + p2neighbor->cdr_tx = 0; + p2neighbor->mdr_rx = 110000000; + p2neighbor->mdr_tx = 110000000; + break; + + case 1: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 11000000; + p2neighbor->cdr_rx = 11000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 2: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 22000000; + p2neighbor->cdr_rx = 22000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 3: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 33000000; + p2neighbor->cdr_rx = 33000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 4: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 44000000; + p2neighbor->cdr_rx = 44000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_tx = 110000000; + break; + + case 5: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 55000000; + p2neighbor->cdr_rx = 55000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 6: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 66000000; + p2neighbor->cdr_rx = 66000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 7: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 77000000; + p2neighbor->cdr_rx = 77000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 8: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 88000000; + p2neighbor->cdr_rx = 88000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 9: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 99000000; + p2neighbor->cdr_rx = 99000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + } + + if (metric_index >= 9) { + metric_direction = -1; + } else if (metric_index == 0) { + metric_direction = 1; + } + + metric_index += metric_direction; + return; +} + diff --git a/dlep_radio_ipv4/dlep_client_metrics.h b/dlep_radio_ipv4/dlep_client_metrics.h new file mode 100644 index 0000000..7efc8da --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_metrics.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------- + * dlep_client_metrics.h -- dynamic client metrics + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_METRICS_H__ +#define __DLEP_CLIENT_METRICS_H__ + +#include "safe_types.h" + + +extern void +dlep_client_metrics(dlep_context_neighbor_t *p2neighbor); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_client_neighbor_event_handlers.c b/dlep_radio_ipv4/dlep_client_neighbor_event_handlers.c new file mode 100644 index 0000000..14ab8f6 --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_neighbor_event_handlers.c @@ -0,0 +1,1114 @@ +/*---------------------------------------------------------------------- + * dlep_client_neighbor_event_handlers.c -- client neighbor event handlers + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "safe_types.h" +#include "time_units.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_sim_options.h" +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_config.h" +#include "dlep_message_builder.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_timer.h" +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" + +#include "dlep_client_metrics.h" + +#include "dlep_client_neighbor_event_handlers.h" + + + +/** + * NAME + * initializing_neighbor_up_ack + * + * SYNOPSIS + * RC_FSM_t + * initializing_neighbor_up_ack(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor up ack message + * is received during the initializing state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +initializing_neighbor_up_ack (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (msg_scratch_pad->status_code_present) { + if (msg_scratch_pad->status_code == 0) { + //send_dlep_neighbor_up_ack(p2peer,p2neighbor); + //printf("\n SENT DLEP NEIGHBOR ACK \n"); + printf("success dest ack received\n"); + /* 0 is a success code */ + } else { + printf("Status code is not success\n"); + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u return code %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + msg_scratch_pad->status_code); + } + } + } + else { + printf("status tlv is mandatory , is not present \n"); + } + + +#if 0 + if (p2neighbor->expected_neighbor_init_ack_sequence != + msg_scratch_pad->sequence) { + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "unexpected neighbor up ack \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor up ack rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + stw_system_timer_stop(&p2neighbor->neighbor_init_ack_tmr); + + /* + * conditionally start the periodic timer to generate metrics + */ + /* if (p2peer->neighbor_update_interval_tmo) { + (void)stw_system_timer_start(&p2neighbor->neighbor_update_interval_tmr, + p2peer->neighbor_update_interval_tmo, + p2peer->neighbor_update_interval_tmo, + &dlep_neighbor_metrics_interval_tmr, + (void *)p2neighbor); + } */ + + return (RC_FSM_OK); +} + + +/** + * NAME + * initializing_neighbor_up_ack_tmo + * + * SYNOPSIS + * RC_FSM_t + * initializing_neighbor_up_ack_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor up ack + * message was not received within the guard timer during + * the initializing state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESING + * + */ +RC_FSM_t +initializing_neighbor_up_ack_tmo (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } +// printf("\n INSIDE START initializing_neighbor_up_ack_tmo"); + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor->neighbor_up_ack_tmo_count++; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor up ack missed, count=%u threshold=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5], + p2neighbor->neighbor_up_ack_tmo_count, + p2peer->neighbor_up_missed_ack_threshold); + } + + if (p2neighbor->neighbor_up_ack_tmo_count >= + p2peer->neighbor_up_missed_ack_threshold) { +// printf("\n INSIDE neighbor_up_missed_ack_threshold "); + /* stop timers and clear context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + return (RC_FSM_STOP_PROCESSING); + } +// printf("\n EXIT initializing_neighbor_up_ack_tmo "); + //send_dlep_neighbor_up(p2peer, p2neighbor); + return (RC_FSM_OK); +} + + + +RC_FSM_t +initializing_neighbor_update_ack (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (msg_scratch_pad->cws_present) { + msg_scratch_pad->cws_present = FALSE; + p2neighbor->mrw = msg_scratch_pad->mrw; + printf("\n DLEP NEIGHBOR ACK : Credit Accepted " + "Client MRW %llu , Router MRW %llu \n", + p2neighbor->mrw, msg_scratch_pad->mrw); + // printf("\n DLEP NEIGHBOR ACK : Credit Not Matches : " + // "Client MRW %llu , Router MRW %llu \n", + // p2neighbor->mrw, msg_scratch_pad->mrw); + stw_system_timer_stop(&p2neighbor->neighbor_update_ack_tmr); + } else if (msg_scratch_pad->credit_req_present) { + msg_scratch_pad->credit_req_present = FALSE; + if (p2neighbor->CREDIT_NOT_SUPPORTED) { + send_dlep_neighbor_credit_reject(p2peer, p2neighbor); + } else { + p2neighbor->cgr = 65534; + send_dlep_neighbor_credit_grant_req(p2peer, p2neighbor); + } + } else if (msg_scratch_pad->status_code_present) { + msg_scratch_pad->status_code_present = FALSE; + if (msg_scratch_pad->status_code == 0) { + printf("\n DLEP NEIGHBOR ACK : Credit Not Supported \n"); + /* 0 is a success code */ + } else { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u return code %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + msg_scratch_pad->status_code); + } + } + stw_system_timer_stop(&p2neighbor->neighbor_update_ack_tmr); + } else { + printf("\n DLEP NEIGHBOR ACK : Unknown TLV received \n"); + } + + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor up ack rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + +// stw_system_timer_stop(&p2neighbor->neighbor_update_ack_tmr); + + + return (RC_FSM_OK); +} + + +/** + * NAME + * initializing_neighbor_update_ack_tmo + * + * SYNOPSIS + * RC_FSM_t + * initializing_neighbor_update_ack_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor update ack + * message was not received within the guard timer during + * the update state. This is currently used only for Credit Grant + * Request. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESING + * + */ +RC_FSM_t +initializing_neighbor_update_ack_tmo (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } +// printf("\n INSIDE START initializing_neighbor_up_ack_tmo"); + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor->neighbor_update_ack_tmo_count++; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor up ack missed, count=%u threshold=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5], + p2neighbor->neighbor_update_ack_tmo_count, + p2peer->neighbor_up_missed_ack_threshold); + } + + /* Leveraging the same threshold of Neighbor up */ + if (p2neighbor->neighbor_update_ack_tmo_count >= + p2peer->neighbor_up_missed_ack_threshold) { +// printf("\n INSIDE neighbor_up_missed_ack_threshold "); + /* stop timers and clear context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + return (RC_FSM_STOP_PROCESSING); + } +// printf("\n EXIT initializing_neighbor_up_ack_tmo "); + send_dlep_neighbor_credit_grant_req(p2peer, p2neighbor); + return (RC_FSM_OK); +} + + +/** + * NAME + * update_neighbor_update_interval + * + * SYNOPSIS + * RC_FSM_t + * update_neighbor_update_interval(void *p2event, void *p2parm) + * + * DESCRIPTION + * The event handler is invoked when the neighbor update interval + * timer has expired indicating that it is time to send + * neighbor metrics. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + */ +RC_FSM_t +update_neighbor_update_interval (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + /* dynamically tweak metrics for testing */ +#ifdef DYNAMIC_METRICS_ENABLED + dlep_client_metrics(p2neighbor); +#endif + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + return (RC_FSM_OK); +} + + +/** + * NAME + * update_neighbor_update_address_response + * + * SYNOPSIS + * RC_FSM_t + * update_neighbor_update_address_response(void *p2event, void *p2parm) + * + * DESCRIPTION + * The event handler is invoked when the neighbor update address + * response was received. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + */ +RC_FSM_t +update_neighbor_update_address_response (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor address response rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + return (RC_FSM_OK); +} + + +/** + * NAME + * update_neighbor_down_request + * + * SYNOPSIS + * RC_FSM_t + * update_neighbor_down_request(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked upon user or system request to + * terminate the neighbor. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +update_neighbor_down_request (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " user-system neighbor down request \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + stw_system_timer_stop(&p2neighbor->neighbor_update_interval_tmr); + + send_dlep_neighbor_down(p2peer, p2neighbor); + + /* + * conditionally start the periodic timer to guard against + * lost term acks + */ + if (p2peer->neighbor_down_ack_tmo) { + (void)stw_system_timer_start(&p2neighbor->neighbor_term_ack_tmr, + p2peer->neighbor_down_ack_tmo, + p2peer->neighbor_down_ack_tmo, + &dlep_neighbor_term_ack_tmr, + (void *)p2neighbor); + } + + return (RC_FSM_OK); +} + + +/** + * NAME + * update_neighbor_down + * + * SYNOPSIS + * RC_FSM_t + * update_neighbor_down(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor down + * message is received during the synchronized state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_STOP_PROCESING + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +update_neighbor_down (void *p2event, void *p2parm) +{ + RC_FSM_t rc_fsm; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor down rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + send_dlep_neighbor_down_ack(p2peer, p2neighbor); + + /* stop timers and clear context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + rc_fsm = RC_FSM_STOP_PROCESSING; + return (rc_fsm); +} + + +/** + * NAME + * update_link_char_request + * + * SYNOPSIS + * RC_FSM_t + * update_link_char_request(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the link characteristic + * request is received during the synchronized state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * p2neighbor->cdr = msg_scratch_pad->cdr; + * p2neighbor->latency = msg_scratch_pad->latency; + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_STOP_PROCESING + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +update_link_char_request (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " link char request \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + p2neighbor->cdr_tx = msg_scratch_pad->cdr_tx; + + p2neighbor->latency = msg_scratch_pad->latency; + + send_dlep_neighbor_link_char_response(p2peer, p2neighbor); + + return (RC_FSM_OK); +} + + + +/** + * NAME + * terminating_neighbor_down_ack + * + * SYNOPSIS + * RC_FSM_t + * terminating_neighbor_down_ack(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor down + * ack is received during the terminating state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_STOP_PROCESSING + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +terminating_neighbor_down_ack (void *p2event, void *p2parm) +{ + RC_FSM_t rc_fsm; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + if (p2neighbor->expected_neighbor_link_char_response_sequence != + msg_scratch_pad->sequence) { + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " unexpected neighbor down ack \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor down ack \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + /* stop timers and clear context */ + stw_system_timer_stop(&p2neighbor->neighbor_term_ack_tmr); + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + rc_fsm = RC_FSM_STOP_PROCESSING; + return (rc_fsm); +} + + +/** + * NAME + * terminating_neighbor_down_ack_tmo + * + * SYNOPSIS + * RC_FSM_t + * terminating_neighbor_down_ack_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor down + * ack was not received within the guard timer during the + * terminating state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESSING + * + */ +RC_FSM_t +terminating_neighbor_down_ack_tmo (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor->neighbor_down_ack_tmo_count++; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor down ack missed, count=%u threshold=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5], + p2neighbor->neighbor_down_ack_tmo_count, + p2peer->neighbor_down_missed_ack_threshold); + } + + if (p2neighbor->neighbor_down_ack_tmo_count >= + p2peer->neighbor_down_missed_ack_threshold) { + /* stop timers and clear context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + return (RC_FSM_STOP_PROCESSING); + } + + //send_dlep_neighbor_down(p2peer, p2neighbor); + return (RC_FSM_OK); +} + + diff --git a/dlep_radio_ipv4/dlep_client_neighbor_event_handlers.h b/dlep_radio_ipv4/dlep_client_neighbor_event_handlers.h new file mode 100644 index 0000000..678509b --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_neighbor_event_handlers.h @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------- + * dlep_client_neighbor_event_handlers.h -- client neighbor state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reseved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_SESSION_EVENT_HANDLERS_H__ +#define __DLEP_CLIENT_SESSION_EVENT_HANDLERS_H__ + +#include "safe_types.h" +#include "fsm.h" + + + +extern RC_FSM_t +initializing_neighbor_up_ack(void *p2event, void *p2parm); + +extern RC_FSM_t +initializing_neighbor_up_ack_tmo(void *p2event, void *p2parm); + +extern RC_FSM_t +initializing_neighbor_update_ack(void *p2event, void *p2parm); + +extern RC_FSM_t +initializing_neighbor_update_ack_tmo(void *p2event, void *p2parm); + +extern RC_FSM_t +update_neighbor_update_interval(void *p2event, void *p2parm); + +extern RC_FSM_t +update_neighbor_update_address_response(void *p2event, void *p2parm); + +extern RC_FSM_t +update_neighbor_down_request(void *p2event, void *p2parm); + +extern RC_FSM_t +update_neighbor_down(void *p2event, void *p2parm); + +extern RC_FSM_t +update_link_char_request(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_neighbor_down_ack(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_neighbor_down_ack_tmo(void *p2event, void *p2parm); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_client_neighbor_fsm.c b/dlep_radio_ipv4/dlep_client_neighbor_fsm.c new file mode 100644 index 0000000..b0d1969 --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_neighbor_fsm.c @@ -0,0 +1,491 @@ +/*---------------------------------------------------------------------- + * dlep_client_neighbor_fsm.c -- client neighbor state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "fsm.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_neighbor_event_handlers.h" +#include "dlep_client_timer.h" + +#include "dlep_client_neighbor_fsm.h" + + + +/* + * normalized client neighbor event description + */ +static event_description_t normalized_event_table[] = + {{neighbor_init_ack_e, "Neighbor Up ACK Event"}, + {neighbor_up_ack_tmo_e, "Neighbor Up ACK TMO Event"}, + {neighbor_update_metrics_interval_e, "Internal Metrics Event"}, + {neighbor_update_ack_e, "Neighbor Update ACK Event"}, + {neighbor_update_ack_tmo_e, "Neighbor Update ACK TMO Event"}, + {neighbor_update_addr_res_e, "Neighbor Update Address Response Event"}, + {neighbor_term_user_req_e, "Neighbor Down User Request Event"}, + {neighbor_term_e, "Neighbor Down Recieved Event"}, + {neighbor_term_ack_e, "Neighbor Down ACK Event"}, + {neighbor_down_ack_tmo_e, "Neighbor Down ACK TMO Event"}, + {neighbor_link_char_req_e, "Neighbor Link Char Request Event"}, + {FSM_NULL_EVENT_ID, NULL} }; + + +/* + * normalized neighbor state description + */ +static state_description_t normalized_state_table[] = + {{neighbor_initializing_s, "Initializing` State"}, + {neighbor_update_s, "Update State"}, + {neighbor_terminating_s, "Terminating State"}, + {FSM_NULL_STATE_ID, NULL} }; + + +/* + * catch-all to ignore events + */ +static RC_FSM_t event_ignore (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + p2peer = p2event; + + if (p2peer) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u event ignored \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + } else { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u event ignored! \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + } + return (RC_FSM_IGNORE_EVENT); +} + + +/* + * State event tables + */ +static event_tuple_t state_initializing_events[] = + {{neighbor_init_ack_e, + initializing_neighbor_up_ack, neighbor_update_s}, + {neighbor_up_ack_tmo_e, + initializing_neighbor_up_ack_tmo, neighbor_initializing_s}, + {neighbor_update_metrics_interval_e, + event_ignore, neighbor_initializing_s}, + {neighbor_update_ack_e, + event_ignore, neighbor_initializing_s}, + {neighbor_update_ack_tmo_e, + event_ignore, neighbor_initializing_s}, + {neighbor_update_addr_res_e, + event_ignore, neighbor_initializing_s}, + {neighbor_term_user_req_e, + event_ignore, neighbor_initializing_s}, + {neighbor_term_e, + event_ignore, neighbor_initializing_s}, + {neighbor_term_ack_e, + event_ignore, neighbor_initializing_s}, + {neighbor_down_ack_tmo_e, + event_ignore, neighbor_initializing_s}, + {neighbor_link_char_req_e, + event_ignore, neighbor_initializing_s}}; + + +static event_tuple_t state_update_events[] = + {{neighbor_init_ack_e, + event_ignore, neighbor_update_s}, + {neighbor_up_ack_tmo_e, + event_ignore, neighbor_update_s}, + {neighbor_update_metrics_interval_e, + update_neighbor_update_interval, neighbor_update_s}, + {neighbor_update_ack_e, + initializing_neighbor_update_ack, neighbor_update_s}, + {neighbor_update_ack_tmo_e, + initializing_neighbor_update_ack_tmo, neighbor_update_s}, + {neighbor_update_addr_res_e, + update_neighbor_update_address_response, neighbor_update_s}, + {neighbor_term_user_req_e, + update_neighbor_down_request, neighbor_terminating_s}, + {neighbor_term_e, + update_neighbor_down, neighbor_terminating_s}, + {neighbor_term_ack_e, + event_ignore, neighbor_update_s}, + {neighbor_down_ack_tmo_e, + event_ignore, neighbor_update_s}, + {neighbor_link_char_req_e, + update_link_char_request, neighbor_update_s}}; + + +static event_tuple_t state_terminating_events[] = + {{neighbor_init_ack_e, + event_ignore, neighbor_terminating_s}, + {neighbor_up_ack_tmo_e, + event_ignore, neighbor_terminating_s}, + {neighbor_update_metrics_interval_e, + event_ignore, neighbor_terminating_s}, + {neighbor_update_ack_e, + event_ignore, neighbor_terminating_s}, + {neighbor_update_ack_tmo_e, + event_ignore, neighbor_terminating_s}, + {neighbor_update_addr_res_e, + event_ignore, neighbor_terminating_s}, + {neighbor_term_user_req_e, + event_ignore, neighbor_terminating_s}, + {neighbor_term_e, + event_ignore, neighbor_terminating_s}, + {neighbor_term_ack_e, + terminating_neighbor_down_ack, neighbor_terminating_s}, + {neighbor_down_ack_tmo_e, + terminating_neighbor_down_ack_tmo, neighbor_terminating_s}, + {neighbor_link_char_req_e, + event_ignore, neighbor_terminating_s}}; + + + +/* + * neighbor state table + */ +static state_tuple_t dlep_neighbor_state_table[] = + {{neighbor_initializing_s, state_initializing_events}, + {neighbor_update_s, state_update_events}, + {neighbor_terminating_s, state_terminating_events}, + {FSM_NULL_STATE_ID, NULL} }; + + +/** + * NAME + * dlep_client_neighbor_fsm_get_state + * + * SYNOPSIS + * uint32_t + * dlep_client_neighbor_fsm_get_state( + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to return the current state + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * current state + * FSM_NULL_STATE_ID if there is an error. + * + */ +uint32_t +dlep_client_neighbor_fsm_get_state (dlep_context_neighbor_t *p2neighbor) +{ + uint32_t state; + + state = FSM_NULL_STATE_ID; + + if (p2neighbor) { + fsm_get_state(p2neighbor->neighbor_fsm_handle, &state); + } else { + /* ignore */ + } + return (state); +} + + +/** + * NAME + * dlep_client_neighbor_fsm_show_state_table + * + * SYNOPSIS + * void + * dlep_client_neighbor_fsm_show_state_table( + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to display the state machine table + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_client_neighbor_fsm_show_state_table ( + dlep_context_neighbor_t *p2neighbor) +{ + if (p2neighbor) { + fsm_display_table(p2neighbor->neighbor_fsm_handle); + } else { + /* ignore */ + } + return; +} + + +/** + * NAME + * dlep_client_neighbor_fsm_show_history + * + * SYNOPSIS + * void + * dlep_client_neighbor_fsm_show_history( + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to display the state machine history + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_client_neighbor_fsm_show_history (dlep_context_neighbor_t *p2neighbor) +{ + if (p2neighbor) { + fsm_show_history(p2neighbor->neighbor_fsm_handle); + } else { + /* ignore */ + } + return; +} + + +/** + * NAME + * dlep_client_neighbor_fsm_engine + * + * SYNOPSIS + * void + * dlep_client_neighbor_fsm_engine(uint32_t normalized_event, + * dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to process the state machine normalized + * events. + * + * INPUT PARAMETERS + * normalized_event - This is the state machine event to process. + * + * p2peer - This is a pointer to the peer context. + * + * p2neighbor - This is a pointer to the neighbor context. This is + * NULL for peer specific events. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESSING This indicates that the state machine + * is to be terminated and resources released. + * error otherwise + * + */ +void +dlep_client_neighbor_fsm_engine (uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + RC_FSM_t rc; + +// printf("\n INSIDE dlep_client_neighbor_fsm_engine "); + if (!p2peer) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer context is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return; + } + + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: neighbor context is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return; + } + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u normalized_event=%u peer_id=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + normalized_event, + p2peer->peer_id); + } + + rc = fsm_engine(p2neighbor->neighbor_fsm_handle, + normalized_event, + p2peer, + p2neighbor); + + if (rc == RC_FSM_STOP_PROCESSING) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u stopped \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + /* cancel all neighbor timers and context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + + } else if (rc == RC_FSM_IGNORE_EVENT) { + /* do nothing */ + } else if (rc != RC_FSM_OK) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u state machine rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + return; +} + + +/** + * NAME + * dlep_neighbor_fsm_destroy + * + * SYNOPSIS + * void + * dlep_neighbor_fsm_destroy(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to destroy the neighbor state machine. + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * p2neighbor - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_fsm_destroy (dlep_context_neighbor_t *p2neighbor) +{ + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: neighbor context is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + } else { + /* fsm_handle is nulled */ + fsm_destroy((fsm_t **)&p2neighbor->neighbor_fsm_handle); + } + return; +} + + +/** + * NAME + * dlep_neighbor_fsm_create + * + * SYNOPSIS + * void + * dlep_neighbor_fsm_create(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to create the neighbor state machine. + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * p2neighbor - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_fsm_create (dlep_context_neighbor_t *p2neighbor) +{ + RC_FSM_t rc; + + if (!p2neighbor) { + return; + } + + p2neighbor->neighbor_fsm_handle = NULL; + rc = fsm_create((fsm_t **)&p2neighbor->neighbor_fsm_handle, + "Session State Machine", + neighbor_initializing_s, + normalized_state_table, + normalized_event_table, + dlep_neighbor_state_table); + if (rc != RC_FSM_OK) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: neighbor local_id=%u state " + "machine rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2neighbor->local_id, + rc); + } + } + + return; +} + + diff --git a/dlep_radio_ipv4/dlep_client_neighbor_fsm.h b/dlep_radio_ipv4/dlep_client_neighbor_fsm.h new file mode 100644 index 0000000..e075c7a --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_neighbor_fsm.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------- + * dlep_client_neighbor_fsm.h -- client neighbor state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_SESSION_FSM_H__ +#define __DLEP_CLIENT_SESSION_FSM_H__ + +#include "safe_types.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_peer.h" + +/* + * normalized client events + */ +typedef enum { + neighbor_init_ack_e = 0, + neighbor_up_ack_tmo_e, + neighbor_update_metrics_interval_e, + neighbor_update_ack_e, + neighbor_update_ack_tmo_e, + neighbor_update_addr_res_e, + neighbor_term_user_req_e, + neighbor_term_e, + neighbor_term_ack_e, + neighbor_down_ack_tmo_e, + neighbor_link_char_req_e, +} dlep_client_neighbor_events_e; + + +/* + * normalized client states + */ +typedef enum { + neighbor_initializing_s = 0, + neighbor_update_s, + neighbor_terminating_s, +} dlep_client_neighbor_states_e; + + + + +extern uint32_t +dlep_client_neighbor_fsm_get_state( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_client_neighbor_fsm_show_counter( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_client_neighbor_fsm_show_state_table( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_client_neighbor_fsm_show_history( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_client_neighbor_fsm_engine(uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +dlep_neighbor_fsm_destroy(dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_neighbor_fsm_create(dlep_context_neighbor_t *p2neighbor); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_client_peer_event_handlers.c b/dlep_radio_ipv4/dlep_client_peer_event_handlers.c new file mode 100644 index 0000000..925319c --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_peer_event_handlers.c @@ -0,0 +1,1634 @@ +/*---------------------------------------------------------------------- + * dlep_client_peer_event_handlers.c -- client peer state event handlers + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include + +#include "safe_types.h" +#include "time_units.h" + +#include "rfc5444_utils.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_config.h" +#include "dlep_message_builder.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_timer.h" +#include "dlep_client_peer_fsm.h" + +#include "dlep_client_peer_event_handlers.h" + +extern int TCP_READY; +extern int init; +/** + * NAME + * discovery_start_init + * + * SYNOPSIS + * RC_FSM_t + * discovery_start_init(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the start event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTNPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +discovery_start_init (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; +#if 0 + send_dlep_attached_peer_discovery(p2peer); + + /*** start the peer offer guard timer ***/ + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); +#endif + return (RC_FSM_OK); +} + +/** + * NAME + * discovery_peer_attached_rcvd + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_attached_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer discovery event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +discovery_peer_attached_rcvd (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + p2peer = p2event; + dlep_config_t *p2config; + + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + msg_scratch_pad = &p2peer->message_scratch_pad; + + p2config = p2peer->p2config; + + /* To avoid discovery message from unconfigured router */ + if (p2config->router_udp_port != htons(p2config->client_udp.sin_port)) { + return (RC_FSM_IGNORE_EVENT); + } + + + /* + * optional: peer type string was null terminated in scratch + */ + strcpy(p2peer->peer_type_description, + msg_scratch_pad->peer_type_description); + + dlep_client_fsm_engine(peer_offer_e, p2peer, NULL); + return (RC_FSM_OK); +} + +#if 0 +/** + * NAME + * discovery_peer_offer_rcvd + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_offer_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer offer event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +discovery_peer_offer_rcvd (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } +// printf("\n PEER OFFER RECEIVED"); + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; +#if 0 + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + /* + * verify that this is the expected response + */ + if (msg_scratch_pad->sequence != + p2peer->expected_peer_offer_sequence) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sequence number miss-match, " + "expected %u-%u rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->expected_peer_offer_sequence, + msg_scratch_pad->sequence); + } + return (RC_FSM_IGNORE_EVENT); + } + + + /* optional */ + if (msg_scratch_pad->status_code_present) { + if (msg_scratch_pad->status_code == 0) { + /* 0 is a success code */ + } else { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u return code %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + msg_scratch_pad->status_code); + } + return (RC_FSM_IGNORE_EVENT); + } + } + + stw_system_timer_stop(&p2peer->peer_offer_tmr); + + /* save the router ID */ + p2peer->router_id = pkt_scratch_pad->router_id; + + + /* + * optional: peer type string was null terminated in scratch + */ + strcpy(p2peer->peer_type_description, + msg_scratch_pad->peer_type_description); + + /* start the peer hb timer if non-zero */ + if (p2peer->peer_heartbeat_interval) { + + printf("\n start peer_heartbeat timer"); + stw_system_timer_start(&p2peer->peer_heartbeat_tmr, + (p2peer->peer_heartbeat_interval), + (p2peer->peer_heartbeat_interval), + &dlep_peer_heartbeat_tmr, + (void *)p2peer->peer_id); + } + printf("\n calling peer_init"); + dlep_client_fsm_engine(peer_init_request_e, p2peer, NULL); + + return (RC_FSM_OK); +} + +#endif + +/** + * NAME + * discovery_peer_offer_tmo + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_offer_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer offer message + * was not received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +discovery_peer_offer_tmo (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2peer->peer_offer_timeout_count++; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u peer offer timer expiration " + "count %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->peer_offer_timeout_count); + } +// send_dlep_attached_peer_discovery(p2peer); + + /* reset the state */ + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + return (RC_FSM_OK); +} + + + +/** + * NAME + * discovery_peer_offer_start + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_init_start(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the start event is + * received during the discovery state. + * + * INPUT PARAMETERS + * NAME + * discovery_peer_offer_start + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_init_start(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the start event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTNPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +discovery_peer_offer_start (void *p2event, void *p2parm) +{ +// dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + +// p2config = p2peer->p2config; + +// send_dlep_peer_init(p2peer); + + send_dlep_peer_offer(p2peer); + return (RC_FSM_OK); +} + + +#if 0 +/** + * NAME + * discovery_peer_init_start + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_init_start(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the start event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTNPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +discovery_peer_init_start (void *p2event, void *p2parm) +{ +// dlep_config_t *p2config; + dlep_context_peer_t *p2peer; +// printf("\n SENDING send_dlep_peer_init "); + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + +// p2config = p2peer->p2config; + + send_dlep_peer_init(p2peer); + + + return (RC_FSM_OK); +} + +#endif + + + + + +/** + * NAME + * discovery_peer_init_ack_rcvd + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_init_ack_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer initialization + * response event is received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +discovery_peer_init_ack_rcvd (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +// printf("\n INSIDE discovery_peer_init_ack_rcvd"); +#if 0 + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + /* + * verify that this is the expected response + */ +#if 0 + if (msg_scratch_pad->sequence != + p2peer->expected_peer_offer_sequence) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sequence number miss-match, " + "expected %u-%u rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->expected_peer_offer_sequence, + msg_scratch_pad->sequence); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + /* mandatory */ + if (msg_scratch_pad->status_code_present) { + if (msg_scratch_pad->status_code == 0) { + /* 0 is a success code */ +// printf("\n PEER INIT ACK Received SUCCESS"); + } else { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u return code %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + msg_scratch_pad->status_code); + } + return (RC_FSM_IGNORE_EVENT); + } + } + + /* save the router ID */ + p2peer->router_id = pkt_scratch_pad->router_id; + + + /* + * optional: peer type string was null terminated in scratch + */ + strcpy(p2peer->peer_type_description, + msg_scratch_pad->peer_type_description); + + /* start the peer hb timer if non-zero */ + + if (p2peer->peer_heartbeat_interval) { + stw_system_timer_start(&p2peer->peer_heartbeat_tmr, + (p2peer->peer_heartbeat_interval), + (p2peer->peer_heartbeat_interval), + &dlep_peer_heartbeat_tmr, + (void *)p2peer->peer_id); + } + + return (RC_FSM_OK); +} + + + + + + +/* + * peer_init_rcvd + * + * SYNOPSIS + * RC_FSM_t + * initialization_peer_init_ack_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer initialization + * request event is received during the initialization state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +initialization_peer_init_rcvd (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + /* + * verify that this is the expected response + */ +#if 0 + if (msg_scratch_pad->sequence != + p2peer->expected_peer_offer_sequence) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sequence number miss-match, " + "expected %u-%u rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->expected_peer_offer_sequence, + msg_scratch_pad->sequence); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + p2peer->peer_heartbeat_interval = msg_scratch_pad->hbt; // ASL__ change + + strcpy(p2peer->peer_type_description, + msg_scratch_pad->peer_type_description); + + if (msg_scratch_pad->ipv4_address_present) { + p2peer->update_ipv4_operation = msg_scratch_pad->ipv4_operation; + p2peer->ipv4_address = msg_scratch_pad->ipv4_address; + p2peer->ipv4_attached_subnet = msg_scratch_pad->ipv4_attached_subnet; + } + + /* start the peer hb timer if non-zero */ + + if (p2peer->peer_heartbeat_interval) { + p2peer->peer_heartbeat_timeout_count = 0; + stw_system_timer_start(&p2peer->peer_heartbeat_tmr, + (p2peer->peer_heartbeat_interval), + (p2peer->peer_heartbeat_interval), + &dlep_peer_heartbeat_tmr, + (void *)p2peer->peer_id); + } + + if(init == 1) { + stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + + dlep_neighbor_deallocate_all(p2peer); + TCP_READY = 0; + + p2peer->peer_heartbeat_timeout_count = 0; + + send_dlep_peer_init_ack(p2peer); + + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + return (RC_FSM_OK); + } + + dlep_client_fsm_engine(peer_init_response_e, p2peer, NULL); + return (RC_FSM_OK); +} + + + /* NAME + * initialization_peer_init_ack_start + * + * SYNOPSIS + * RC_FSM_t + * initialization_peer_init_ack_start (void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked as response to the peer initialization + * request received in initialization state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +initialization_peer_init_ack_start (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + /* clear count */ + +// printf(" resting time out count"); + // p2peer->peer_heartbeat_timeout_count = 0; + + p2peer->status_code = RFC5444_SUCCESS; + send_dlep_peer_init_ack(p2peer); + rc = RC_FSM_OK; + +// send_peer_init_ack(p2peer); + return (rc); +} + + + + /* NAME + * in_session_peer_heartbeat_rcvd + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_heartbeat_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer heartbeat message + * is received during the in_session state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +in_session_peer_heartbeat_rcvd (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + printf("\n EXIT BEFOR clear counter in_session_peer_heartbeat_rcvd"); + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + /* clear count */ + +// printf(" resting time out count"); + p2peer->peer_heartbeat_timeout_count = 0; + return (RC_FSM_OK); +} + + +/** + * NAME + * in_session_peer_heartbeat_tmo + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_heartbeat_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer heartbeat message + * was not received within the guard timer during the in_session + * state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESSING + * + */ +RC_FSM_t +in_session_peer_heartbeat_tmo (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } + +#endif + p2peer->peer_heartbeat_timeout_count++; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u missed heartbeats %u " + "threshold=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->peer_heartbeat_timeout_count, + p2peer->peer_heartbeat_missed_threshold); + } + + if (p2peer->peer_heartbeat_timeout_count > + p2peer->peer_heartbeat_missed_threshold) { + stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + + dlep_neighbor_deallocate_all(p2peer); + TCP_READY = 0; + + p2peer->peer_heartbeat_timeout_count = 0; + send_dlep_peer_termination(p2peer); + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + rc = RC_FSM_OK; + + /* p2peer->status_code = RFC5444_MSG_TIMEOUT; + dlep_client_fsm_engine(user_peer_term_request_e, p2peer, NULL); + rc = RC_FSM_OK; */ + + } else { + send_dlep_peer_heartbeat(p2peer); + rc = RC_FSM_OK; + } + return (rc); +} + +/** + * NAME + * in_session_peer_update_request_rcvd + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_update_request_rcvd(void *p2event, + * void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer update request + * message is received during the in_session state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +in_session_peer_update_request_rcvd (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + if (msg_scratch_pad->ipv4_address_present) { + p2peer->update_ipv4_operation = msg_scratch_pad->ipv4_operation; + p2peer->ipv4_address = msg_scratch_pad->ipv4_address; + p2peer->ipv4_attached_subnet = msg_scratch_pad->ipv4_attached_subnet; + } + + /* Reseting time out count */ + p2peer->peer_heartbeat_timeout_count = 0; + + send_dlep_peer_update_response(p2peer); + return (RC_FSM_OK); +} + + +/** + * NAME + * synchronized_peer_update_response_rcvd + * + * SYNOPSIS + * RC_FSM_t + * synchronized_peer_update_response_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * The event handler is invoked when the peer update response + * message has been received during the synchronized state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +in_session_peer_update_response_rcvd (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u peer update rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + p2peer->status_code = msg_scratch_pad->status_code; + return (RC_FSM_OK); +} + + +/** + * NAME + * in_session_peer_term_request + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_term_request(void *p2event, void *p2parm) + * + * DESCRIPTION + * The event handler is invoked when the user or system issues + * a request to terminate the peer and all neighbors associated + * with the peer. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is + * set prior to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +in_session_peer_term_request (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + //printf("\n in_session_peer_term_request calling send_peer_ter "); + dlep_neighbor_deallocate_all(p2peer); + + //p2peer->status_code = RFC5444_SUCCESS; + send_dlep_peer_termination(p2peer); + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + + /* start the peer term timer */ + stw_system_timer_start(&p2peer->peer_term_ack_tmr, + (4*p2peer->peer_heartbeat_interval), + (4*p2peer->peer_heartbeat_interval), + &dlep_peer_term_ack_tmr, + (void *)p2peer->peer_id); + + return (RC_FSM_OK); +} + +/** + * NAME + * in_session_peer_term_rcvd + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_term_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer terminate message + * is received during the in_session state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_STOP_PROCESSING + * + */ +RC_FSM_t +in_session_peer_term_rcvd (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + p2peer->status_code = msg_scratch_pad->status_code; + + send_dlep_peer_termination_ack(p2peer); + + /* Reset the state *\ + fsm_set_exception_state(p2peer->fsm_handle, reset_s); + + /* cancel all timers and clear context */ + dlep_neighbor_deallocate_all(p2peer); + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + rc = stw_system_timer_stop(&p2peer->peer_term_ack_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + +#if 0 + /*** start the router offer guard timer ***/ + + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); +#endif + /* reset the state */ + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + + return (RC_FSM_OK); +} + + +/** + * NAME + * terminating_peer_term_ack_rcvd + * + * SYNOPSIS + * RC_FSM_t + * terminating_peer_term_ack_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer terminate + * ack is received during the terminating state. The neighbor + * are all terminated and cleaned and the peer state machine + * is stopped and removed. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_IGNORE_EVENT + * RC_FSM_STOP_PROCESSING which removes the state machine + * + */ +RC_FSM_t +terminating_peer_term_ack_rcvd (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + printf("\n peer_term ack rcvd \n"); + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->expected_peer_term_ack_sequence != + msg_scratch_pad->sequence) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u unexpected term ack \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + return (RC_FSM_IGNORE_EVENT); + } + } +#endif + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term ack rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + /* cancel all timers and clear context */ + dlep_neighbor_deallocate_all(p2peer); +// close(p2config->dlep_udp_sockfd); +// close(p2config->dlep_tcp_sockfd); + TCP_READY = 0; + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + rc = stw_system_timer_stop(&p2peer->peer_term_ack_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } +#if 0 + /*** start the router offer guard timer ***/ + + if (p2config->start_on_discovery) { + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); + } +// dlep_porter_open(p2config); +#endif + /* reset the state */ + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + + return (RC_FSM_OK); +} + + +/** + * NAME + * terminating_peer_term_ack_tmo + * + * SYNOPSIS + * RC_FSM_t + * terminating_peer_term_ack_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer terminate + * ack is not received dnd the guard timer expires. The neighbor + * are all terminated and cleaned and the peer state machine + * is stopped and removed. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_STOP_PROCESSING which removes the state machine + * + */ +RC_FSM_t +terminating_peer_term_ack_tmo (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + + printf("\n terminating_peer_term_ack_tmo "); + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term ack timeout \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + + /* ignoring retry timers, just restart discovery */ + + /* cancel all timers and clear context */ + dlep_neighbor_deallocate_all(p2peer); +// close(p2config->dlep_udp_sockfd); +// close(p2config->dlep_tcp_sockfd); + TCP_READY = 0; +#if 0 + /*** start the router offer guard timer ***/ + if (p2config->start_on_discovery) { + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); + } +#endif + /* reset the state */ +// dlep_porter_open(p2config); + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + + return (RC_FSM_OK); +} + + +/** + * NAME + * terminating_peer_term_rcvd + * + * SYNOPSIS + * RC_FSM_t + * terminating_peer_term_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer terminate + * message is received during the terminating state. The neighbors + * are all terminated and the peer state machine + * is stopped and removed. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_STOP_PROCESSING which removes the state machine + * + */ +RC_FSM_t +terminating_peer_term_rcvd (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + printf("\n terminating_peer_term_rcvd "); + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + + send_dlep_peer_termination_ack(p2peer); + + /* Reset the state */ + fsm_set_exception_state(p2peer->fsm_handle, reset_s); + + +// close(p2config->dlep_udp_sockfd); +// close(p2config->dlep_tcp_sockfd); + TCP_READY = 0; + +#if 0 + /*** start the router offer guard timer ***/ + if (p2config->start_on_discovery) { + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); + + } +#endif + /* reset the state */ +// dlep_porter_open(p2config); + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + + return (RC_FSM_OK); +} + + diff --git a/dlep_radio_ipv4/dlep_client_peer_event_handlers.h b/dlep_radio_ipv4/dlep_client_peer_event_handlers.h new file mode 100644 index 0000000..023b33f --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_peer_event_handlers.h @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------- + * dlep_client_peer_event_handlers.h -- client peer state event handlers + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_PEER_EVENT_HANDLERS_H__ +#define __DLEP_CLIENT_PEER_EVENT_HANDLERS_H__ + +#include "fsm.h" + + +extern RC_FSM_t +discovery_start_init(void *p2event, void *p2parm); + +extern RC_FSM_t +discovery_peer_attached_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +discovery_peer_offer_start(void *p2event, void *p2parm); + +/* extern RC_FSM_t +discovery_peer_offer_rcvd(void *p2event, void *p2parm); */ + +extern RC_FSM_t +initialization_peer_init_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +initialization_peer_init_ack_start(void *p2event, void *p2parm); +/* extern RC_FSM_t +discovery_peer_offer_tmo(void *p2event, void *p2parm); */ + +/* extern RC_FSM_t +discovery_peer_init_start(void *p2event, void *p2parm); */ + +/* extern RC_FSM_t +discovery_peer_init_ack_rcvd(void *p2event, void *p2parm); */ + +extern RC_FSM_t +in_session_peer_heartbeat_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +in_session_peer_heartbeat_tmo(void *p2event, void *p2parm); + +/* extern RC_FSM_t +in_session_peer_update_rcvd(void *p2event, void *p2parm); */ + + +extern RC_FSM_t +in_session_peer_update_request_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +in_session_peer_update_response_rcvd(void *p2event, void *p2parm); + + +extern RC_FSM_t +in_session_peer_term_request(void *p2event, void *p2parm); + +extern RC_FSM_t +in_session_peer_term_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_peer_term_ack_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_peer_term_ack_tmo(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_peer_term_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +out_of_state_rom_rcvd(void *p2event, void *p2parm); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_client_peer_fsm.c b/dlep_radio_ipv4/dlep_client_peer_fsm.c new file mode 100644 index 0000000..f732212 --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_peer_fsm.c @@ -0,0 +1,568 @@ +/*---------------------------------------------------------------------- + * dlep_client_fsm.c -- DLEP Client state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "fsm.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_neighbor_event_handlers.h" +#include "dlep_client_peer_event_handlers.h" +#include "dlep_client_timer.h" +#include "dlep_client_peer_fsm.h" + +/* + * normalized client peer event description + */ +static event_description_t normalized_event_table[] = + {{start_init_e, "Start Event"}, + {peer_att_discovery_e, "Attached Discovery Event"}, + {peer_offer_e, "Peer Offer Event"}, + {peer_offer_tmo_e, "Peer Offer TMO Event"}, + {peer_init_request_e, "Peer Initialization Request Event"}, + {peer_init_response_e, "Peer Initialization Response Event"}, + {peer_heartbeat_e, "Peer Heartbeat Event"}, + {peer_heartbeat_tmo_e, "Peer Heartbeat TMO Event"}, + {peer_update_request_e, "Peer Update Request Event"}, + {peer_update_response_e, "Peer Update Response Event"}, + {user_peer_term_request_e, "User Node Term Request Event"}, + {peer_term_request_e, "Peer Term Event"}, + {peer_term_response_e, "Peer Term Response Event"}, + {peer_term_response_tmo_e, "Peer Term Response TMO Event"}, + {FSM_NULL_EVENT_ID, NULL} }; + + +/* + * normalized peer state description + */ +static state_description_t normalized_state_table[] = + {{discovery_s, "Idle State"}, + {initialization_s, "Initialized State"}, + {in_session_s, "Established State"}, + {terminating_s, "Terminating State"}, + {reset_s, "Resetting state"}, + {FSM_NULL_STATE_ID, NULL} }; + + +/* + * catch-all to ignore events + */ +static RC_FSM_t event_ignore (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + + p2peer = p2event; + + if (p2peer) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u event ignored: p2peer=%p peer_id=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer, + p2peer->peer_id); + } + } else { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u event ignored! \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + } + return (RC_FSM_OK); // IGNORE_EVENT); +} + + +/* + _ State event tables + */ +static event_tuple_t state_discovery_events[] = + {{start_init_e, + discovery_start_init, discovery_s}, + {peer_att_discovery_e, + discovery_peer_attached_rcvd, initialization_s}, + {peer_offer_e, + discovery_peer_offer_start, initialization_s}, + {peer_offer_tmo_e, + event_ignore, discovery_s}, + {peer_init_request_e, + initialization_peer_init_rcvd, in_session_s}, + {peer_init_response_e, + initialization_peer_init_ack_start, in_session_s}, + {peer_heartbeat_e, + event_ignore, discovery_s}, + {peer_heartbeat_tmo_e, + event_ignore, discovery_s}, + {peer_update_request_e, + event_ignore, discovery_s}, + {peer_update_response_e, + event_ignore, discovery_s}, + {user_peer_term_request_e, + event_ignore, discovery_s}, + {peer_term_request_e, + event_ignore, discovery_s}, + {peer_term_response_e, + event_ignore, discovery_s}, + {peer_term_response_tmo_e, + event_ignore, discovery_s}}; + +static event_tuple_t state_initialization_events[] = + {{start_init_e, + event_ignore, initialization_s}, + {peer_att_discovery_e, + event_ignore, initialization_s}, + {peer_offer_e, + event_ignore, initialization_s}, + {peer_offer_tmo_e, + event_ignore, initialization_s}, + {peer_init_request_e, + initialization_peer_init_rcvd, in_session_s}, + {peer_init_response_e, + initialization_peer_init_ack_start, in_session_s}, + {peer_heartbeat_e, + event_ignore, initialization_s}, + {peer_heartbeat_tmo_e, + event_ignore, initialization_s}, + {peer_update_request_e, + event_ignore, initialization_s}, + {peer_update_response_e, + event_ignore, initialization_s}, + {user_peer_term_request_e, + event_ignore, initialization_s}, + {peer_term_request_e, + event_ignore, initialization_s}, + {peer_term_response_e, + event_ignore, initialization_s}, + {peer_term_response_tmo_e, + event_ignore, initialization_s}}; + + + +static event_tuple_t state_in_session_events[] = + { {start_init_e, + event_ignore, in_session_s}, + {peer_att_discovery_e, + event_ignore, in_session_s}, + {peer_offer_e, + event_ignore, in_session_s}, + {peer_offer_tmo_e, + event_ignore, in_session_s}, + {peer_init_request_e, + event_ignore, in_session_s}, + {peer_init_response_e, + event_ignore, in_session_s}, + {peer_heartbeat_e, + in_session_peer_heartbeat_rcvd, in_session_s}, + {peer_heartbeat_tmo_e, + in_session_peer_heartbeat_tmo, in_session_s}, + {peer_update_request_e, + in_session_peer_update_request_rcvd, in_session_s}, + {peer_update_response_e, + in_session_peer_update_response_rcvd, in_session_s}, + {user_peer_term_request_e, + in_session_peer_term_request, terminating_s}, + {peer_term_request_e, + in_session_peer_term_rcvd, terminating_s}, + {peer_term_response_e, + event_ignore, in_session_s}, + {peer_term_response_tmo_e, + event_ignore, in_session_s}}; + + +static event_tuple_t state_terminating_events[] = + { {start_init_e, + event_ignore, terminating_s}, + {peer_att_discovery_e, + event_ignore, terminating_s}, + {peer_offer_e, + event_ignore, terminating_s}, + {peer_offer_tmo_e, + event_ignore, terminating_s}, + {peer_init_request_e, + event_ignore, terminating_s}, + {peer_init_response_e, + event_ignore, terminating_s}, + {peer_heartbeat_e, + event_ignore, terminating_s}, + {peer_heartbeat_tmo_e, + event_ignore, terminating_s}, + {peer_update_request_e, + event_ignore, terminating_s}, + {peer_update_response_e, + event_ignore, terminating_s}, + {user_peer_term_request_e, + event_ignore, terminating_s}, + {peer_term_request_e, + terminating_peer_term_rcvd, terminating_s}, + {peer_term_response_e, + terminating_peer_term_ack_rcvd, reset_s}, + {peer_term_response_tmo_e, + terminating_peer_term_ack_tmo, reset_s}}; + +static event_tuple_t state_reset_events[] = + {{start_init_e, + event_ignore, reset_s}, + {peer_att_discovery_e, + event_ignore, reset_s}, + {peer_offer_e, + event_ignore, reset_s}, + {peer_offer_tmo_e, + event_ignore, reset_s}, + {peer_init_request_e, + event_ignore, reset_s}, + {peer_init_response_e, + event_ignore, reset_s}, + {peer_heartbeat_e, + event_ignore, reset_s}, + {peer_heartbeat_tmo_e, + event_ignore, reset_s}, + {peer_update_request_e, + event_ignore, reset_s}, + {peer_update_response_e, + event_ignore, reset_s}, + {user_peer_term_request_e, + event_ignore, reset_s}, + {peer_term_request_e, + event_ignore, reset_s}, + {peer_term_response_e, + event_ignore, reset_s}, + {peer_term_response_tmo_e, + event_ignore, reset_s}}; + + +/* + * State table + */ +static state_tuple_t dlep_client_state_table[] = + + { {discovery_s, state_discovery_events}, + {initialization_s, state_initialization_events}, + {in_session_s, state_in_session_events}, + {terminating_s, state_terminating_events}, + {reset_s,state_reset_events}, + {FSM_NULL_STATE_ID, NULL} }; + + +/** + * NAME + * dlep_client_fsm_get_state + * + * SYNOPSIS + * uint32_t + * dlep_client_fsm_get_state(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to return the current state + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * current state + * FSM_NULL_STATE_ID if there is an error. + * + */ +uint32_t +dlep_client_fsm_get_state (dlep_context_peer_t *p2peer) +{ + uint32_t state; + + state = FSM_NULL_STATE_ID; + + if (p2peer) { + fsm_get_state(p2peer->fsm_handle, &state); + } else { + /* ignore */ + } + return (state); +} + + +/** + * NAME + * dlep_client_fsm_show_state_table + * + * SYNOPSIS + * void + * dlep_client_fsm_show_state_table(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to display the state machine counters + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_client_fsm_show_state_table (dlep_context_peer_t *p2peer) +{ + if (p2peer) { + fsm_display_table(p2peer->fsm_handle); + } else { + /* ignore */ + } + return; +} + + +/** + * NAME + * dlep_client_fsm_show_history + * + * SYNOPSIS + * void + * dlep_client_fsm_show_history(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to display the state machine history + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_client_fsm_show_history (dlep_context_peer_t *p2peer) +{ + if (p2peer) { + fsm_show_history(p2peer->fsm_handle); + } else { + /* ignore */ + } + return; +} + + +/** + * NAME + * dlep_client_fsm_engine + * + * SYNOPSIS + * void + * dlep_client_fsm_engine(uint32_t normalized_event, + * dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to process the state machine normalized + * events. + * + * INPUT PARAMETERS + * normalized_event - This is the state machine event to process. + * + * p2peer - This is a pointer to the peer context. + * + * p2neighbor - This is a pointer to the neighbor context. This is + * NULL for peer specific events. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESSING This indicates that the state machine + * is to be terminated and resources released. + * error otherwise + * + */ +void +dlep_client_fsm_engine (uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + RC_FSM_t rc; + + if (!p2peer) { + DLEP_DEBUG("%s-%u Error: peer is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return; + } + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u normalized_event=%u p2peer=%p " + "peer_id=%u p2neighbor=%p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + normalized_event, + p2peer, + p2peer->peer_id, + p2neighbor); + } + + rc = fsm_engine(p2peer->fsm_handle, + normalized_event, + p2peer, + p2neighbor); + + if (rc == RC_FSM_STOP_PROCESSING) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u p2peer=%p peer_id=%u stopped \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer, + p2peer->peer_id); + } + + /* cancel all timers and clear context */ + dlep_neighbor_deallocate_all(p2peer); + + /* stop peer timers */ + dlep_peer_clear(p2peer); + dlep_peer_remove(&p2peer); + + } else if (rc != RC_FSM_OK) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u radio state " + "machine rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + return; +} + + +/** + * NAME + * dlep_fsm_destroy + * + * SYNOPSIS + * void + * dlep_fsm_destroy(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to destroy the client state machine. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * p2peer - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_fsm_destroy (dlep_context_peer_t *p2peer) +{ + if (!p2peer) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + } else { + /* fsm_handle is nulled */ + fsm_destroy((fsm_t **)&p2peer->fsm_handle); + } + return; +} + + +/** + * NAME + * dlep_fsm_create + * + * SYNOPSIS + * void + * dlep_fsm_create(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to create the client state machine. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * p2peer - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_fsm_create (dlep_context_peer_t *p2peer) +{ + RC_FSM_t rc; + + if (!p2peer) { + return; + } + + p2peer->fsm_handle = NULL; + rc = fsm_create((fsm_t **)&p2peer->fsm_handle, + "DLEP State Machine", + discovery_s, + normalized_state_table, + normalized_event_table, + dlep_client_state_table); + if (rc != RC_FSM_OK) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u radio state " + "machine rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + + return; +} + + diff --git a/dlep_radio_ipv4/dlep_client_peer_fsm.h b/dlep_radio_ipv4/dlep_client_peer_fsm.h new file mode 100644 index 0000000..8334007 --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_peer_fsm.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------- + * dlep_client_fsm.h -- DLEP Client state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reseved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_FSM_H__ +#define __DLEP_CLIENT_FSM_H__ + +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" + +/* + * normalized client events + */ +typedef enum { + start_init_e = 0, + peer_att_discovery_e, + peer_offer_e, + peer_offer_tmo_e, + peer_init_request_e, + peer_init_response_e, + peer_heartbeat_e, + peer_heartbeat_tmo_e, + peer_update_request_e, + peer_update_response_e, + user_peer_term_request_e, + peer_term_request_e, + peer_term_response_e, + peer_term_response_tmo_e, +} dlep_client_events_e; + + +/* + * normalized client states + */ +typedef enum { + discovery_s = 0, + initialization_s, + in_session_s, + terminating_s, + reset_s, +} dlep_client_states_e; + + + + +extern uint32_t +dlep_client_fsm_get_state(dlep_context_peer_t *p2peer); + + +extern void +dlep_client_fsm_show_counter(dlep_context_peer_t *p2peer); + + +extern void +dlep_client_fsm_show_state_table(dlep_context_peer_t *p2peer); + + +extern void +dlep_client_fsm_show_history(dlep_context_peer_t *p2peer); + + +extern void +dlep_client_fsm_engine(uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +dlep_fsm_destroy(dlep_context_peer_t *p2peer); + + +extern void +dlep_fsm_create(dlep_context_peer_t *p2peer); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_client_timer.c b/dlep_radio_ipv4/dlep_client_timer.c new file mode 100644 index 0000000..342fa66 --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_timer.c @@ -0,0 +1,294 @@ +/*---------------------------------------------------------------------- + * dlep_client_timer.c -- Client state machine guard timers + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "dlep_context_peer_management.h" +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" +#include "dlep_client_timer.h" + + + +/** + * NAME + * dlep_peer_offer_tmr + * + * SYNOPSIS + * void + * dlep_peer_offer_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that the peer offer + * response expected by the peer has not been received. + * + * INPUT PARAMETERS + * tmr - This is the timer handle + * + * p2arm - This is the local peer id that was set when the timer + * was started. + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_offer_tmr (stw_tmr_t *tmr, void *parm) +{ + uint32_t peer_id; + dlep_context_peer_t *p2peer; + + peer_id = (uint32_t)parm; + p2peer = dlep_get_peer_by_peer_id(peer_id); + + printf("\n peer offer time out"); + dlep_client_fsm_engine(peer_offer_tmo_e, p2peer, NULL); + return; +} + + +/** + * NAME + * dlep_peer_heartbeat_tmr + * + * SYNOPSIS + * void + * dlep_peer_heartbeat_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that it is time to + * for the peer send another peer heartbeat. + * + * INPUT PARAMETERS + * tmr - This is the timer handle + * + * p2arm - This is the local peer id that was set when + * the timer was started. + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_heartbeat_tmr (stw_tmr_t *tmr, void *parm) +{ + uint32_t peer_id; + dlep_context_peer_t *p2peer; + + peer_id = (uint32_t)parm; + p2peer = dlep_get_peer_by_peer_id(peer_id); + + dlep_client_fsm_engine(peer_heartbeat_tmo_e, p2peer, NULL); + return; +} + + +/** + * NAME + * dlep_peer_term_ack_tmr + * + * SYNOPSIS + * void + * dlep_peer_term_ack_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that the term ACK + * expected by the peer was not received. + * + * INPUT PARAMETERS + * tmr - This is the timer handle + * + * p2arm - This is the local peer id that was set when + * the timer was started. + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_term_ack_tmr (stw_tmr_t *tmr, void *parm) +{ + uint32_t peer_id; + dlep_context_peer_t *p2peer; + + peer_id = (uint32_t)parm; + p2peer = dlep_get_peer_by_peer_id(peer_id); + + printf("\n Peer term ack tmr out "); + dlep_client_fsm_engine(peer_term_response_tmo_e, p2peer, NULL); + return; +} + + +/** + * NAME + * dlep_neighbor_init_ack_tmr + * + * SYNOPSIS + * void + * dlep_neighbor_init_ack_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that the neighbor + * neighbor up ack was not received. The neighbor up may the + * be retransmitted. + * + * INPUT PARAMETERS + * p2arm + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_init_ack_tmr (stw_tmr_t *tmr, void *parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2neighbor = parm; + p2peer = p2neighbor->p2peer; + + dlep_client_neighbor_fsm_engine(neighbor_up_ack_tmo_e, + p2peer, p2neighbor); + return; +} + + +/** + * NAME + * dlep_neighbor_update_ack_tmr + * + * SYNOPSIS + * void + * dlep_neighbor_update_ack_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that the neighbor + * update ack was not received. The neighbor update may the + * be retransmitted. + * + * INPUT PARAMETERS + * p2arm + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_update_ack_tmr (stw_tmr_t *tmr, void *parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2neighbor = parm; + p2peer = p2neighbor->p2peer; + + dlep_client_neighbor_fsm_engine(neighbor_update_ack_tmo_e, + p2peer, p2neighbor); + return; +} + + + +/** + * NAME + * dlep_neighbor_metrics_interval_tmr + * + * SYNOPSIS + * void + * dlep_neighbor_metrics_interval_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer is used to periodically + * generate the periodic neighbor metrics message. + * + * INPUT PARAMETERS + * tmr - This is a handle to the timer + * + * p2arm - This is a pointer to the neighbor context that + * was set when the timer was started. + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_metrics_interval_tmr (stw_tmr_t *tmr, void *parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2neighbor = parm; + p2peer = p2neighbor->p2peer; + + dlep_client_neighbor_fsm_engine(neighbor_update_metrics_interval_e, + p2peer, p2neighbor); + return; +} + + +/** + * NAME + * dlep_neighbor_term_ack_tmr + * + * SYNOPSIS + * void + * dlep_neighbor_term_ack_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that theneighbor + * neighbor down was not received. The neighbor down may the + * be retransmitted. + * + * INPUT PARAMETERS + * p2arm + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_term_ack_tmr (stw_tmr_t *tmr, void *parm) +{ + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2neighbor = parm; + p2peer = p2neighbor->p2peer; + + dlep_client_neighbor_fsm_engine(neighbor_down_ack_tmo_e, + p2peer, p2neighbor); + return; +} + diff --git a/dlep_radio_ipv4/dlep_client_timer.h b/dlep_radio_ipv4/dlep_client_timer.h new file mode 100644 index 0000000..c133dc6 --- /dev/null +++ b/dlep_radio_ipv4/dlep_client_timer.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------- + * dlep_client_timer.h + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_TIMER_H__ +#define __DLEP_CLIENT_TIMER_H__ + +#include "stw_system_timer.h" + + +extern void +dlep_peer_offer_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_peer_heartbeat_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_peer_term_ack_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_neighbor_init_ack_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_neighbor_update_ack_tmr(stw_tmr_t *tmr, void *parm); + +//exter n void +//d lep_n ei ghbor_met rics_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_neighbor_metrics_interval_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_neighbor_term_ack_tmr(stw_tmr_t *tmr, void *parm); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_config.c b/dlep_radio_ipv4/dlep_config.c new file mode 100644 index 0000000..acac5ba --- /dev/null +++ b/dlep_radio_ipv4/dlep_config.c @@ -0,0 +1,596 @@ +/*---------------------------------------------------------------------- + * dlep_config.c -- Routine to parse the configuration file + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" + + +static dlep_config_t dlep_config; + + +/** + * NAME + * dlep_get_config_ptr + * + * SYNOPSIS + * dlep_config_t *dlep_get_config_ptr(void) + * + * DESCRIPTION + * This function can be used to get the pointer to the + * configuration structure. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * The configuration structure pointer. + * + */ +dlep_config_t *dlep_get_config_ptr (void) +{ + return (&dlep_config); +} + + +/** + * NAME + * dlep_default_config + * + * SYNOPSIS + * void + * dlep_default_config(void) + * + * DESCRIPTION + * This function sets the configuration data to default values, where + * default values apply. + * + * INPUT PARAMETERS + * p2config Pointer to the config structure + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_default_config (void) +{ + dlep_config_t *p2config; + + p2config = &dlep_config; + + strcpy(p2config->filename, "dlep_sim.cfg"); + + strcpy(p2config->sim_name, "dlep"); + + p2config->local_udp_port = 0; + p2config->local_tcp_port = 0; + + p2config->local_ipv4_dot[0] = '\0'; + ipv4_zero_address(&p2config->local_ipv4); + + p2config->router_udp_port = 0; + p2config->router_tcp_port = 0; + + p2config->router_ipv4_dot[0] = '\0'; + ipv4_zero_address(&p2config->router_ipv4); + + p2config->start_on_launch = TRUE; + + strcpy(p2config->local_type_description, "no type description"); + + + p2config->local_id = 0; + + p2config->peer_offer_interval = + DLEP_PEER_OFFER_INTERVAL_DEFAULT; + + p2config->peer_heartbeat_interval = + DLEP_PEER_HEARTBEAT_INTERVAL_DEFAULT; + p2config->peer_heartbeat_missed_threshold = + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_DEFAULT; + + p2config->peer_term_ack_tmo = + DLEP_PEER_TERM_ACK_TMO_DEFAULT; + p2config->peer_term_missed_ack_threshold = + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_DEFAULT; + + p2config->neighbor_up_ack_tmo = + DLEP_NEIGHBOR_UP_ACK_TMO_DEFAULT; + p2config->neighbor_up_missed_ack_threshold = + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_DEFAULT; + + p2config->neighbor_update_interval_tmo = + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_DEFAULT; + + p2config->neighbor_activity_timer = + DLEP_NEIGHBOR_ACTIVITY_TIMER_DEFAULT; + + p2config->neighbor_down_ack_tmo = + DLEP_NEIGHBOR_DOWN_ACK_TMO_DEFAULT; + p2config->neighbor_down_missed_ack_threshold = + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_DEFAULT; + + return; +} + + +/** + * NAME + * dlep_display_config + * + * SYNOPSIS + * void + * dlep_display_config(dlep_config_t *p2config) + * + * DESCRIPTION + * This function displays the configuration data to the console. + * + * INPUT PARAMETERS + * p2config Pointer to the config structure + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_display_config (dlep_config_t *p2config) +{ + if (!p2config) { + return; + } + + printf("\n%s DLEP Configuration from %s \n", + p2config->sim_name, + p2config->filename); + + printf(" local udp port=%u \n", + p2config->local_udp_port); + printf(" local tcp port=%u \n", + p2config->local_tcp_port); + printf(" local ipv4=%s \n", + p2config->local_ipv4_dot); + + if (p2config->router_udp_port) { + printf(" router udp port=%u \n", + p2config->router_udp_port); + } + + if (p2config->router_tcp_port) { + printf(" router tcp port=%u \n", + p2config->router_tcp_port); + } + + if (p2config->router_udp_port && p2config->router_tcp_port) { + printf(" router ipv4=%s \n", + p2config->router_ipv4_dot); + } + + printf("\n"); + + printf(" Type Description: %s \n", + p2config->local_type_description); + + printf(" local ID=%u \n", + p2config->local_id); + + printf(" peer_offer_tmo=%u seconds \n", + p2config->peer_offer_interval); + + printf(" peer_heartbeat_interval=%u seconds \n", + p2config->peer_heartbeat_interval); + + printf(" peer_heartbeat_missed_threshold=%u \n", + p2config->peer_heartbeat_missed_threshold); + + printf(" peer_term_ack_tmo=%u milliseconds \n", + p2config->peer_term_ack_tmo); + + printf(" peer_term_missed_ack_threshold=%u \n", + p2config->peer_term_missed_ack_threshold); + + printf("\n"); + + printf(" neighbor_up_ack_tmo=%u milliseconds \n", + p2config->neighbor_up_ack_tmo); + + printf(" neighbor_up_missed_ack_threshold=%u \n", + p2config->neighbor_up_missed_ack_threshold); + + printf(" neighbor_update_interval_tmo=%u milliseconds \n", + p2config->neighbor_update_interval_tmo); + + printf(" neighbor_activity_timer=%u seconds \n", + p2config->neighbor_activity_timer); + + printf(" neighbor_down_ack_tmo=%u milliseconds \n", + p2config->neighbor_down_ack_tmo); + + printf(" neighbor_down_missed_ack_threshold=%u \n", + p2config->neighbor_down_missed_ack_threshold); + + printf("\n"); + return; +} + + +/** + * NAME + * dlep_read_config_file + * + * SYNOPSIS + * void + * dlep_read_config_file(dlep_config_t *p2config) + * + * DESCRIPTION + * This function parses the configuration file and assigns + * the appropriate parameters in the config struct. + * + * INPUT PARAMETERS + * p2config - This is a pointer to the DLEP configuration data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_read_config_file (dlep_config_t *p2config) +{ + int i, line_count; + uint32_t temp; + + FILE *fp; + +#define MAX_INPUT_LENGTH ( 512 ) + char input_string[MAX_INPUT_LENGTH]; + +#define ARGC_MAX ( 5 ) + uint32_t argc; + char *argv[ARGC_MAX]; + + fp = fopen(p2config->filename, "r"); + if (!fp) { + printf("Error: problem opening config file: %s\n", + p2config->filename); + return; + } + + line_count = 0; + while (fgets(input_string, MAX_INPUT_LENGTH, fp)) { + + if (input_string[0] == '\0') { + continue; + } else if (input_string[0] == '#') { + continue; + } + + argv[0] = strtok(input_string, " \t\n"); + argc = 1; + + for (i=1; isim_name, argv[1], DLEP_SIM_NAME_LEN); + } + + /* peer debug flags */ + else if (strncmp(argv[0], "DEBUG_FLAGS", + strlen("DEBUG_FLAGS")) == 0) { + if (dlep_debug_flags) { + /* cli debug flag sticks */ + } else { + dlep_debug_flags = strtoul(argv[1], NULL, 16); + } + } + + else if (strncmp(argv[0], "MANUAL_START", + strlen("MANUAL_START")) == 0) { + p2config->start_on_launch = FALSE; + } + + else if (strncmp(argv[0], "DISCOVERY_START", + strlen("DISCOVERY_START")) == 0) { + p2config->start_on_discovery = TRUE; + } + + else if (strncmp(argv[0], "LOCAL_UDP_PORT", + strlen("LOCAL_UDP_PORT")) == 0) { + p2config->local_udp_port = strtoul(argv[1], NULL, 10); + } + + else if (strncmp(argv[0], "LOCAL_TCP_PORT", + strlen("LOCAL_TCP_PORT")) == 0) { + p2config->local_tcp_port = strtoul(argv[1], NULL, 10); + } + + else if (strncmp(argv[0], "LOCAL_IPV4", + strlen("LOCAL_IPV4")) == 0) { + strcpy(p2config->local_ipv4_dot, argv[1]); + + ipv4_dot_decimal2digits(&p2config->local_ipv4, argv[1]); + } + + else if (strncmp(argv[0], "ROUTER_UDP_PORT", + strlen("ROUTER_UDP_PORT")) == 0) { + p2config->router_udp_port = strtoul(argv[1], NULL, 10); + } + + else if (strncmp(argv[0], "ROUTER_TCP_PORT", + strlen("ROUTER_TCP_PORT")) == 0) { + p2config->router_tcp_port = strtoul(argv[1], NULL, 10); + } + + else if (strncmp(argv[0], "ROUTER_IPV4", + strlen("ROUTER_IPV4")) == 0) { + strcpy(p2config->router_ipv4_dot, argv[1]); + + ipv4_dot_decimal2digits(&p2config->router_ipv4, argv[1]); + p2config->router_ipv4.v4_addr.v4_addr32 = + htonl(p2config->router_ipv4.v4_addr.v4_addr32); + } + + else if (strncmp(argv[0], "TYPE_DESCRIPTION", + strlen("TYPE_DESCRIPTION")) == 0) { + strncpy(p2config->local_type_description, + argv[1], RFC5444_TLV_PEER_TYPE_MAX_LENGTH); + + p2config->local_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH] = '\0'; + } + + else if (strncmp(argv[0], "LOCAL_ID", + strlen("LOCAL_ID")) == 0) { + temp = strtoul(argv[1], NULL, 10); + p2config->local_id = temp; + } + + else if (strncmp(argv[0], "DLEP_PEER_HEARTBEAT_INTERVAL", + strlen("DLEP_PEER_HEARTBEAT_INTERVAL")) == 0) { + p2config->peer_heartbeat_interval = strtoul(argv[1], NULL, 10); + + if (p2config->peer_heartbeat_interval < + DLEP_PEER_HEARTBEAT_INTERVAL_MIN) { + p2config->peer_heartbeat_interval = + DLEP_PEER_HEARTBEAT_INTERVAL_MIN; + } + + if (p2config->peer_heartbeat_interval > + DLEP_PEER_HEARTBEAT_INTERVAL_MAX) { + p2config->peer_heartbeat_interval = + DLEP_PEER_HEARTBEAT_INTERVAL_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD", + strlen("DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD")) == 0) { + p2config->peer_heartbeat_missed_threshold = + strtoul(argv[1], NULL, 10); + + if (p2config->peer_heartbeat_missed_threshold < + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MIN) { + p2config->peer_heartbeat_missed_threshold = + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MIN; + } + + if (p2config->peer_heartbeat_missed_threshold > + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MAX) { + p2config->peer_heartbeat_missed_threshold = + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_PEER_TERM_ACK_TMO", + strlen("DLEP_PEER_TERM_ACK_TMO")) == 0) { + p2config->peer_term_ack_tmo = strtoul(argv[1], NULL, 10); + + if (p2config->peer_term_ack_tmo < + DLEP_PEER_TERM_ACK_TMO_MIN) { + p2config->peer_term_ack_tmo = + DLEP_PEER_TERM_ACK_TMO_MIN; + } + + if (p2config->peer_term_ack_tmo > + DLEP_PEER_TERM_ACK_TMO_MAX) { + p2config->peer_term_ack_tmo = + DLEP_PEER_TERM_ACK_TMO_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_PEER_TERM_MISSED_ACK_THRESHOLD", + strlen("DLEP_PEER_TERM_MISSED_ACK_THRESHOLD")) == 0) { + p2config->peer_term_missed_ack_threshold = + strtoul(argv[1], NULL, 10); + + if (p2config->peer_term_missed_ack_threshold < + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MIN) { + p2config->peer_term_missed_ack_threshold = + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MIN; + } + + if (p2config->peer_term_missed_ack_threshold > + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MAX) { + p2config->peer_term_missed_ack_threshold = + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_UP_ACK_TMO", + strlen("DLEP_NEIGHBOR_UP_ACK_TMO")) == 0) { + p2config->neighbor_up_ack_tmo = strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_up_ack_tmo < + DLEP_NEIGHBOR_UP_ACK_TMO_MIN) { + p2config->neighbor_up_ack_tmo = + DLEP_NEIGHBOR_UP_ACK_TMO_MIN; + } + + if (p2config->neighbor_up_ack_tmo > + DLEP_NEIGHBOR_UP_ACK_TMO_MAX) { + p2config->neighbor_up_ack_tmo = + DLEP_NEIGHBOR_UP_ACK_TMO_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD", + strlen("DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD")) == 0) { + p2config->neighbor_up_missed_ack_threshold = + strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_up_missed_ack_threshold < + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MIN) { + p2config->neighbor_up_missed_ack_threshold = + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MIN; + } + + if (p2config->neighbor_up_missed_ack_threshold > + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MAX) { + p2config->neighbor_up_missed_ack_threshold = + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO", + strlen("DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO")) == 0) { + p2config->neighbor_update_interval_tmo = + strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_update_interval_tmo > 0) { + if (p2config->neighbor_update_interval_tmo < + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MIN) { + p2config->neighbor_update_interval_tmo = + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MIN; + } + + if (p2config->neighbor_update_interval_tmo > + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MAX) { + p2config->neighbor_update_interval_tmo = + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MAX; + } + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_ACTIVITY_TIMER", + strlen("DLEP_NEIGHBOR_ACTIVITY_TIMER")) == 0) { + p2config->neighbor_activity_timer = strtoul(argv[1], NULL, 10); + + if (!p2config->neighbor_activity_timer) { + if (p2config->neighbor_activity_timer < + DLEP_NEIGHBOR_ACTIVITY_TIMER_MIN) { + p2config->neighbor_activity_timer = + DLEP_NEIGHBOR_ACTIVITY_TIMER_MIN; + } + + if (p2config->neighbor_activity_timer > + DLEP_NEIGHBOR_ACTIVITY_TIMER_MAX) { + p2config->neighbor_activity_timer = + DLEP_NEIGHBOR_ACTIVITY_TIMER_MAX; + } + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_DOWN_ACK_TMO", + strlen("DLEP_NEIGHBOR_DOWN_ACK_TMO")) == 0) { + p2config->neighbor_down_ack_tmo = strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_down_ack_tmo < + DLEP_NEIGHBOR_DOWN_ACK_TMO_MIN) { + p2config->neighbor_down_ack_tmo = + DLEP_NEIGHBOR_DOWN_ACK_TMO_MIN; + } + + if (p2config->neighbor_down_ack_tmo > + DLEP_NEIGHBOR_DOWN_ACK_TMO_MAX) { + p2config->neighbor_down_ack_tmo = + DLEP_NEIGHBOR_DOWN_ACK_TMO_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD", + strlen("DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD")) == 0) { + p2config->neighbor_down_missed_ack_threshold = + strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_down_missed_ack_threshold < + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MIN) { + p2config->neighbor_down_missed_ack_threshold = + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MIN; + } + + if (p2config->neighbor_down_missed_ack_threshold > + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MAX) { + p2config->neighbor_down_missed_ack_threshold = + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MAX; + } + } + + else { + printf("%s-%u Unknown config file option -%s-\n", + __FUNCTION__, + __LINE__, + argv[0]); + } + } + + fclose(fp); + return; +} + diff --git a/dlep_radio_ipv4/dlep_config.h b/dlep_radio_ipv4/dlep_config.h new file mode 100644 index 0000000..7f2c156 --- /dev/null +++ b/dlep_radio_ipv4/dlep_config.h @@ -0,0 +1,267 @@ +/*---------------------------------------------------------------------- + * dlep_config.h - routines to parse the config file + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONFIG_H__ +#define __DLEP_CONFIG_H__ + +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" + +#include "rfc5444_types.h" + + + + +#define ROUTER_DEFAULT_PORT ( 5000 ) +#define RADIO_DEFAULT_PORT ( 5001 ) + + +/* + * The configuration range for the router offer timeout + * in seconds. The MIM is retransmitted if the ROM is + * not received. + */ +#define DLEP_PEER_OFFER_INTERVAL_MIN ( 1 ) +#define DLEP_PEER_OFFER_INTERVAL_MAX ( 60 ) +#define DLEP_PEER_OFFER_INTERVAL_DEFAULT ( 5 ) + +/* + * The configuration range for the peer heartbeat timeout. + * This is the time that each node, server and client, + * expects to receive the peer heartbeat. 0 disables. + * Time units are in seconds. + */ +#define DLEP_PEER_HEARTBEAT_INTERVAL_MIN ( 1 ) +#define DLEP_PEER_HEARTBEAT_INTERVAL_MAX ( 60 ) +#define DLEP_PEER_HEARTBEAT_INTERVAL_DEFAULT ( 5 ) + +/* + * The number of consecutive missed HBs that result in + * a failure. + */ +#define DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MIN ( 2 ) +#define DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MAX ( 8 ) +#define DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_DEFAULT ( 3 ) + + +/* + * The configuration range for the peer terminate ack timeout. + * This is the time the client waits for the peer term ack. + * Time units are milliseconds. + */ +#define DLEP_PEER_TERM_ACK_TMO_MIN ( 100 ) +#define DLEP_PEER_TERM_ACK_TMO_MAX ( 5000 ) +#define DLEP_PEER_TERM_ACK_TMO_DEFAULT ( 1000 ) + +/* + * The max number of peer term ack timeouts that are tolerated. + */ +#define DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MIN ( 1 ) +#define DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MAX ( 5 ) +#define DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_DEFAULT ( 3 ) + + +/* + * The configuration range for the neighbor up ack timeout. + * This is the time the client waits for the neighbor up ack. + * Time units are milliseconds. + */ +#define DLEP_NEIGHBOR_UP_ACK_TMO_MIN ( 100 ) +#define DLEP_NEIGHBOR_UP_ACK_TMO_MAX ( 40000 ) +#define DLEP_NEIGHBOR_UP_ACK_TMO_DEFAULT ( 1000 ) + +/* + * The configuration range for the retransmission threshold for + * the neighbor up. + */ +#define DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MIN ( 1 ) +#define DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MAX ( 5 ) +#define DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_DEFAULT ( 3 ) + + +/* + * The configuration range the for the periodic neighbor update + * timer. The client sends neighbor updates at this interval. + * Time units are milliseconds. + */ +#define DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MIN ( 100 ) +#define DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MAX ( 5000 ) +#define DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_DEFAULT ( 400 ) + +/* + * The configuration range the for the neighbor activity + * timer. The server expects to see traffic on a neighbor + * session during this interval. Time units are seconds. + * 0 disables. + */ +#define DLEP_NEIGHBOR_ACTIVITY_TIMER_MIN ( 0 ) +#define DLEP_NEIGHBOR_ACTIVITY_TIMER_MAX ( 5 ) +#define DLEP_NEIGHBOR_ACTIVITY_TIMER_DEFAULT ( 10 ) + + +/* + * The configuration range the neighbor down ack timeout. + * This is the time the client waits for the neighbor down ack. + * Time units are milliseconds. + */ +#define DLEP_NEIGHBOR_DOWN_ACK_TMO_MIN ( 100 ) +#define DLEP_NEIGHBOR_DOWN_ACK_TMO_MAX ( 5000 ) +#define DLEP_NEIGHBOR_DOWN_ACK_TMO_DEFAULT ( 1000 ) + +/* + * The max number of neighbor down ack timeouts that are tolerated. + * Once the threshold is reached, neighbor downs are stopped + * and the neighbor cleaned up. + */ +#define DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MIN ( 1 ) +#define DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MAX ( 5 ) +#define DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_DEFAULT ( 3 ) + + +#define DLEP_FILENAME_LEN ( 128 ) +#define ROOT_PATH_LEN ( 512 ) +#define DLEP_SIM_NAME_LEN ( 32 ) + + +/* + * Defines the data used to manage config data + * and stateless data + */ +typedef struct { + char filename[DLEP_FILENAME_LEN]; + + char sim_name[DLEP_SIM_NAME_LEN]; + + /* port for the local udp and tcp */ + uint16_t local_udp_port; + uint16_t local_tcp_port; + + /* ipv4 for the local*/ + char local_ipv4_dot[IPV4_ADDR_STRING_LEN]; + ipv4_address_t local_ipv4; + + /* port for the client */ + uint16_t router_udp_port; + uint16_t router_tcp_port; + boolean_t router_port_present; + + /* The router IPv4 address info */ + char router_ipv4_dot[IPV4_ADDR_STRING_LEN]; + ipv4_address_t router_ipv4; + boolean_t router_ipv4_present; + + /* Used by radio discovery */ + char dlep_multicast_ipv4_dot[IPV4_ADDR_STRING_LEN]; + ipv4_address_t dlep_multicast_ipv4; + + + /* + * Configuration data + */ + char local_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH+1]; + + + uint16_t flow_control; + uint16_t auth_type; + + boolean_t start_on_launch; + boolean_t start_on_discovery; + + uint32_t local_id; + + //FIX -- uint8_t heartbeat_interval; + + uint32_t peer_offer_interval; + + /* 0-60 seconds. 0-disables. Must match the peer's interval */ + uint32_t peer_heartbeat_interval; + + /* missed HBs that indicate failure */ + uint32_t peer_heartbeat_missed_threshold; + + uint32_t peer_term_ack_tmo; + uint32_t peer_term_missed_ack_threshold; + + uint32_t neighbor_up_ack_tmo; + uint32_t neighbor_up_missed_ack_threshold; + + /* to drive periodic updates in milliseconds, 400 default */ + uint32_t neighbor_update_interval_tmo; + + uint32_t neighbor_activity_timer; + + uint32_t neighbor_down_ack_tmo; + uint32_t neighbor_down_missed_ack_threshold; + + int dlep_udp_sockfd; + int dlep_tcp_sockfd; + int dlep_tcp_client_sockfd; + + struct sockaddr_in dlep_addr; + struct sockaddr_in client; + struct sockaddr_in client_udp; + + struct ip_mreq group; + int reuse; + + int client_lenght; + socklen_t dlep_sock_len; + + struct sockaddr_in msg_addr; + socklen_t msg_sock_len; + +} dlep_config_t; + + + + +extern +dlep_config_t *dlep_get_config_ptr(void); + +extern void +dlep_default_config(void); + +extern void +dlep_display_config(dlep_config_t *p2config); + +extern void +dlep_read_config_file(dlep_config_t *p2config); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_context_neighbor.c b/dlep_radio_ipv4/dlep_context_neighbor.c new file mode 100644 index 0000000..54b0969 --- /dev/null +++ b/dlep_radio_ipv4/dlep_context_neighbor.c @@ -0,0 +1,293 @@ +/*---------------------------------------------------------------------- + * dlep_context_neighbor.c -- neighbor context management routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include + +#include "stw_system_timer.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_server_neighbor_fsm.h" +#include "dlep_context_neighbor.h" + + +static uint16_t sid = 0; + + +static uint16_t sid_alloc (void) +{ + sid++; + return (sid); +} + + +/** + * NAME + * dlep_get_next_neighbor_id + * + * SYNOPSIS + * #include "dlep_context_neighbor.h" + * uint16_t + * dlep_get_next_neighbor_id(void) + * + * DESCRIPTION + * This function returns the next neighbor ID. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * Next neighbor ID + * + */ +uint16_t +dlep_get_next_neighbor_id (void) +{ + return (sid_alloc()); +} + + +/** + * NAME + * dlep_neighbor_init + * + * SYNOPSIS + * #include "dlep_context_neighbor.h" + * void + * dlep_neighbor_init(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function initializes the neighbor context data after the + * neighbor has been allocated. + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context + * + * OUTPUT PARAMETERS + * p2neighbor - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_init (dlep_context_neighbor_t *p2neighbor) +{ + if (!p2neighbor) { + return; + } + + p2neighbor->p2next_neighbor = NULL; + + p2neighbor->local_id = 0; + + /* The global neighbor id to be assigned by the server */ + p2neighbor->sequence = 0; + + p2neighbor->status_code = RFC5444_SUCCESS; + + /* + * Saved sequence number to match the neighbor init + * ACK from the router. + */ + p2neighbor->expected_neighbor_init_ack_sequence = 0; + p2neighbor->expected_neighbor_term_ack_sequence = 0; + p2neighbor->expected_neighbor_address_response_sequence = 0; + p2neighbor->expected_neighbor_link_char_response_sequence = 0; + + /* + * RF metrics + */ + p2neighbor->rlq_tx = 100; + p2neighbor->resources = 100; + p2neighbor->latency = 10; + p2neighbor->cdr_tx = 1000000000; + p2neighbor->mdr_tx = 1000000000; + p2neighbor->mtu = 1500; + + /* + * This is the number of times the init ACK timer has + * expired waiting on the init ACK. + */ + p2neighbor->neighbor_up_ack_tmo_count = 0; + + /* + * This is the number of times the update ACK timer has + * expired waiting on the update ACK. + */ + p2neighbor->neighbor_update_ack_tmo_count = 0; + + /* + * used by the activity tmr to track messages on the neighbor neighbor + * TRUE == active + */ + p2neighbor->neighbor_activity_flag = 0; + + /* + * default activity timer duration, seconds + */ + p2neighbor->neighbor_activity_duration = 5; + + /* Initialize IPv4/IPv6 addresses */ + ipv4_zero_address(&p2neighbor->ipv4_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + + p2neighbor->ipv6_subnet_prefix = 0; + p2neighbor->update_ipv6_operation = RFC5444_NO_ADDRESS; + + /* + * This is the number of times the terminate ACK timer has + * expired waiting on the terminate ACK. + */ + p2neighbor->neighbor_down_ack_tmo_count = 0; + + p2neighbor->neighbor_fsm_handle = NULL; + dlep_neighbor_fsm_create(p2neighbor); + + stw_system_timer_prepare(&p2neighbor->neighbor_init_ack_tmr); + stw_system_timer_prepare(&p2neighbor->neighbor_update_ack_tmr); + stw_system_timer_prepare(&p2neighbor->neighbor_activity_tmr); + stw_system_timer_prepare(&p2neighbor->neighbor_update_interval_tmr); + stw_system_timer_prepare(&p2neighbor->neighbor_term_ack_tmr); + + return; +} + + +/** + * NAME + * dlep_neighbor_clear + * + * SYNOPSIS + * #include "dlep_context_neighbor.h" + * void + * dlep_neighbor_clear(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function should be called as part of the work needed to + * tear down a neighbor. All activity is stopped and neighbor + * internal resources are released. + * + * The context block itself is not released. + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context + * + * OUTPUT PARAMETERS + * p2neighbor - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_clear (dlep_context_neighbor_t *p2neighbor) +{ + if (!p2neighbor) { + return; + } + + p2neighbor->local_id = 0; + + mac_zero_address(p2neighbor->mac_address); + + stw_system_timer_stop(&p2neighbor->neighbor_init_ack_tmr); + stw_system_timer_stop(&p2neighbor->neighbor_update_ack_tmr); + stw_system_timer_stop(&p2neighbor->neighbor_activity_tmr); + stw_system_timer_stop(&p2neighbor->neighbor_update_interval_tmr); + stw_system_timer_stop(&p2neighbor->neighbor_term_ack_tmr); + return; +} + + +/** + * NAME + * dlep_neighbor_display + * + * SYNOPSIS + * #include "dlep_context_neighbor.h" + * void + * dlep_neighbor_display(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function displays the neighbor context data + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_neighbor_display (dlep_context_neighbor_t *p2neighbor) +{ + ipv4_address_t addr; + if (!p2neighbor) { + return; + } + + mac_print_address (" Neighbor MAC=", p2neighbor->mac_address); + + addr.v4_addr.v4_addr32 = p2neighbor->ipv4_address.v4_addr.v4_addr32; + ipv4_print_address(" Neighbor IPv4=", &addr); + + /* ipv4_print_address(" Neighbor IPv4=",&p2neighbor->ipv4_address); + ipv4_print_address(NULL,&p2neighbor->ipv4_address); */ + + printf(" activity timer=%u milliseconds \n", + p2neighbor->neighbor_activity_duration); + + printf(" Metrics:\n"); + printf(" RLQ TX=%u <0-100>", p2neighbor->rlq_tx); + printf(" RLQ RX=%u <0-100> \n", p2neighbor->rlq_rx); + printf(" Resources =%u <0-100> \n", p2neighbor->resources); + printf(" Latency=%llu milliseconds \n", p2neighbor->latency); + printf(" CDR TX=%llu bps ", p2neighbor->cdr_tx); + printf(" CDR RX=%llu bps \n", p2neighbor->cdr_rx); + printf(" MDR TX=%llu bps ", p2neighbor->mdr_tx); + printf(" MDR RX=%llu bps \n", p2neighbor->mdr_rx); + printf(" MTU=%u \n",p2neighbor->mtu); + + return; +} + + diff --git a/dlep_radio_ipv4/dlep_context_neighbor.h b/dlep_radio_ipv4/dlep_context_neighbor.h new file mode 100644 index 0000000..993a501 --- /dev/null +++ b/dlep_radio_ipv4/dlep_context_neighbor.h @@ -0,0 +1,151 @@ +/*---------------------------------------------------------------------- + * dlep_context_neighbor.h -- Session context definitions + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONTEXT_NEIGHBOR_H__ +#define __DLEP_CONTEXT_NEIGHBOR_H__ + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" + +#include "rfc5444_types.h" + + + +/* + * Defines the data used to manage a neighbor + * and its stateful data + */ +typedef struct context_neighbor_t_ { + struct context_neighbor_t_ *p2next_neighbor; + + /* pointer back to the peer context */ + void *p2peer; + + /* used to track responses */ + uint16_t sequence; + + /* a locally metered neighbor ID for user I/F */ + uint32_t local_id; + + /* Set the status code from the last neighbor operation + * or as required to sending a neighbor message. + */ + uint16_t status_code; + + /* squirrel away the sequence number to track responses */ + uint16_t expected_neighbor_init_ack_sequence; + uint16_t expected_neighbor_term_ack_sequence; + uint16_t expected_neighbor_address_response_sequence; + uint16_t expected_neighbor_link_char_response_sequence; + + uint8_t mac_address[MAC_ADDR_LEN_IN_BYTES]; + ipv4_address_t ipv4_address; + ipv6_address_t ipv6_address; + + /* + * neighbor_update_address layer 3 addresses + * update layer 3 addresses for the sim + */ + uint8_t update_ipv4_operation; + ipv4_address_t update_ipv4_address; + + uint8_t update_ipv6_operation; + uint8_t ipv6_subnet_prefix; + ipv6_address_t update_ipv6_address; + ipv6_address_t update_ipv6_subnet_address; + + /* + * RF metrics + */ +#if 0 + uint8_t rlq; /* 0-poor, 100-good */ + uint8_t resources; /* 0-100% */ + uint16_t latency; /* millisec */ + uint64_t cdr; /* kbps */ + uint64_t mdr; /* kbps */ +#endif + uint8_t rlq_rx; /* 0-poor, 100-good */ + uint8_t rlq_tx; /* 0-poor, 100-good */ + uint8_t resources_rx; /* 0 -100% */ + uint8_t resources_tx; /* 0 -100% */ + uint64_t latency; /* millisec */ + uint8_t resources; /* 0 -100% */ + uint16_t mtu; + uint64_t cdr_rx; /* bps */ + uint64_t cdr_tx; /* bps */ + uint64_t mdr_tx; /* bps */ + uint64_t mdr_rx; /* bps */ + uint64_t mrw; /* credits */ + uint64_t rrw; /* credits */ + uint64_t cgr; /* credits */ + uint32_t eft; /* millisec */ + + boolean_t CREDIT_NOT_SUPPORTED; /* credits */ + /* neighbor state machine handle */ + void *neighbor_fsm_handle; + + /* state machine working variables */ + uint32_t neighbor_up_ack_tmo_count; + uint32_t neighbor_update_ack_tmo_count; + uint32_t neighbor_down_ack_tmo_count; + + uint32_t neighbor_activity_duration; + boolean_t neighbor_activity_flag; + + stw_tmr_t neighbor_init_ack_tmr; + stw_tmr_t neighbor_update_ack_tmr; + stw_tmr_t neighbor_activity_tmr; + stw_tmr_t neighbor_update_interval_tmr; + stw_tmr_t neighbor_term_ack_tmr; + +} dlep_context_neighbor_t; + + + + +extern uint16_t +dlep_get_next_neighbor_id(void); + +extern void +dlep_neighbor_init(dlep_context_neighbor_t *p2neighbor); + +extern void +dlep_neighbor_clear(dlep_context_neighbor_t *p2neighbor); + +extern void +dlep_neighbor_display(dlep_context_neighbor_t *p2neighbor); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_context_neighbor_management.c b/dlep_radio_ipv4/dlep_context_neighbor_management.c new file mode 100644 index 0000000..54f64c6 --- /dev/null +++ b/dlep_radio_ipv4/dlep_context_neighbor_management.c @@ -0,0 +1,470 @@ +/*---------------------------------------------------------------------- + * dlep_context_neighbor_management.c + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" + + +static uint32_t local_id = 5000; + + +/* + * Porting: The implementation of the functions in this file can be + * changed to platform specific resource management APIs, such as + * AVL or RB trees. + */ + + +/* + * function to meter a local id + */ +static uint32_t +dlep_get_next_local_id (void) +{ + local_id++; + if (!local_id) { + local_id++; + } + return (local_id); +} + + +/** + * NAME + * dlep_allocate_session + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * dlep_context_neighbor_t + * *dlep_neighbor_allocate(dlep_context_peer_t *p2peer, + * uint8_t *mac_address) + * + * DESCRIPTION + * Allocates a neighbor context block for a new neighbor. The + * neighbor context is set to defaults and put in the database. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * mac_address - This is a pointer the MAC address assigned + * to the neighbor. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * A pointer to the newly allocated neighbor context. + * NULL is returned if the allocation failed. + * + */ +dlep_context_neighbor_t +*dlep_neighbor_allocate (dlep_context_peer_t *p2peer, + uint8_t *mac_address) +{ + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + return (NULL); + } + + if (!mac_address) { + return (NULL); + } + + p2ctx = NULL; + p2ctx = malloc(sizeof(dlep_context_neighbor_t)); + if (!p2ctx) { + DLEP_DEBUG("%s-%u Error: No resource for new neighbor block \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return (NULL); + } + + dlep_neighbor_init(p2ctx); + + p2ctx->p2peer = p2peer; + + p2ctx->local_id = dlep_get_next_local_id(); + + /* The sequence number must be used to correlate the + * ACKs with the original request. + */ + p2ctx->sequence = 0; + + mac_copy_address(p2ctx->mac_address, mac_address); + + /* + * insert the new context in the list + */ + p2ctx->p2next_neighbor = p2peer->neighbor_list; + p2peer->neighbor_list = p2ctx; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Allocated local id=%u neighbor %p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->local_id, + p2ctx); + } + + return (p2ctx); +} + + +/** + * NAME + * dlep_neighbor_remove + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * void + * dlep_neighbor_remove(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t **p2neighbor) + * + * DESCRIPTION + * This function removes the neighbor context block from + * the nodes database. Dynamically allocated memory + * must be freed prior to removing a neighbor. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * p2neighbor - A pointer to the neighbor context block pointer + * + * OUTPUT PARAMETERS + * p2neighbor - updated. + * + * RETURN VALUE + * none + * + */ +void +dlep_neighbor_remove (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t **p2neighbor) +{ + dlep_context_neighbor_t *p2previous; + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + DLEP_DEBUG("%s-%u peer context null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return; + } + + p2ctx = p2peer->neighbor_list; + + if (!p2ctx) { + DLEP_DEBUG("%s-%u Empty neighbor list \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return; + } + + if (p2ctx == *p2neighbor) { + p2peer->neighbor_list = p2ctx->p2next_neighbor; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u deallocating local id=%u %p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->local_id, + p2ctx); + } + + /* now free the block */ + free(p2ctx); + + *p2neighbor = NULL; + return; + } + + p2previous = p2peer->neighbor_list; + p2ctx = p2previous->p2next_neighbor; + + while (p2ctx) { + + if (p2ctx == *p2neighbor) { + p2previous->p2next_neighbor = p2ctx->p2next_neighbor; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u deallocating local id=%u %p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->local_id, + p2ctx); + } + + free(p2ctx); + + *p2neighbor = NULL; + break; + + } else { + /* walk the list */ + p2previous = p2ctx; + p2ctx = p2ctx->p2next_neighbor; + } + } + return; +} + + +/** + * NAME + * dlep_get_neighbor_by_local_id + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * dlep_context_neighbor_t + * *dlep_get_neighbor_by_local_id(dlep_context_peer_t *p2peer, + * uint32_t local_id) + * + * DESCRIPTION + * This function searches the database for the specified local ID + * and returns the neighbor context pointer. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context + * + * local_id - The local ID to locate + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * A pointer to the neighbor context. + * NULL is returned if the neighbor was not found. + * + */ +dlep_context_neighbor_t +*dlep_get_neighbor_by_local_id (dlep_context_peer_t *p2peer, + uint32_t local_id) +{ + dlep_context_neighbor_t *result; + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + DLEP_DEBUG("%s-%u null peer context \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return (NULL); + } + + result = NULL; + + p2ctx = p2peer->neighbor_list; + while (p2ctx) { + + if (p2ctx->local_id == local_id) { + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_neighbor; + } + } + return (result); +} + + +/** + * NAME + * dlep_get_neighbor_by_mac_address + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * dlep_context_neighbor_t + * *dlep_get_neighbor_by_mac_address(dlep_context_peer_t *p2peer, + * uint8_t *p2mac_address) + * + * DESCRIPTION + * This function searches the database for the specified MAC address + * and returns the neighbor context pointer. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context + * + * p2mac_address - the MAC to locate + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * A pointer to the neighbor context. + * NULL is returned if the neighbor was not found. + * + */ +dlep_context_neighbor_t +*dlep_get_neighbor_by_mac_address (dlep_context_peer_t *p2peer, + uint8_t *p2mac_address) +{ + dlep_context_neighbor_t *result; + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + return (NULL); + } + + result = NULL; + + p2ctx = p2peer->neighbor_list; + while (p2ctx) { + + if (mac_compare_address(p2ctx->mac_address, p2mac_address)) { +// printf("\n Checking MAC in the MAC LIST"); + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_neighbor; + } + } +// printf("\n Not preset MAC in the MAC list"); + return (result); +} + + +/** + * NAME + * dlep_neighbor_deallocate_all + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * void + * dlep_neighbor_deallocate_all(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function removes and frees all neighbor context blocks + * tied to this node. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_neighbor_deallocate_all (dlep_context_peer_t *p2peer) + +{ + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + return; + } + + /* + * Now free each block + */ + while (p2peer->neighbor_list) { + p2ctx = p2peer->neighbor_list; + + /* clear and stop processing */ + dlep_neighbor_clear(p2ctx); + + p2peer->neighbor_list = p2ctx->p2next_neighbor; + free(p2ctx); + } + + /* + * Nullify the node's neighbor list + */ + p2peer->neighbor_list = NULL; + return; +} + + +/** + * NAME + * dlep_neighbor_list_all + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * void + * dlep_neighbor_list_all(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function displays all established neighbors on + * the peer to stdout. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_neighbor_list_all (dlep_context_peer_t *p2peer) +{ + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + return; + } + + p2ctx = p2peer->neighbor_list; + while (p2ctx) { + dlep_neighbor_display(p2ctx); + p2ctx = p2ctx->p2next_neighbor; + } + printf("\n"); + return; +} + + diff --git a/dlep_radio_ipv4/dlep_context_neighbor_management.h b/dlep_radio_ipv4/dlep_context_neighbor_management.h new file mode 100644 index 0000000..200121a --- /dev/null +++ b/dlep_radio_ipv4/dlep_context_neighbor_management.h @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------- + * dlep_context_neighbor_management.h + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONTEXT_SESSION_MANAGEMENT_H__ +#define __DLEP_CONTEXT_SESSION_MANAGEMENT_H__ + +#include "dlep_context_neighbor.h" +#include "dlep_context_peer.h" + + +extern dlep_context_neighbor_t +*dlep_neighbor_allocate(dlep_context_peer_t *p2peer, + uint8_t *mac_address); + +extern void +dlep_neighbor_remove(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t **p2context); + +extern dlep_context_neighbor_t +*dlep_get_neighbor_by_local_id(dlep_context_peer_t *p2peer, + uint32_t local_id); + +extern dlep_context_neighbor_t +*dlep_get_neighbor_by_mac_address(dlep_context_peer_t *p2peer, + uint8_t *mac_address); + +extern void +dlep_neighbor_deallocate_all(dlep_context_peer_t *p2peer); + +extern void +dlep_neighbor_list_all(dlep_context_peer_t *p2peer); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_context_peer.c b/dlep_radio_ipv4/dlep_context_peer.c new file mode 100644 index 0000000..4035fe5 --- /dev/null +++ b/dlep_radio_ipv4/dlep_context_peer.c @@ -0,0 +1,476 @@ +/*---------------------------------------------------------------------- + * dlep_context_peer.c -- Routines to manage the peer context data + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "stw_system_timer.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_peer.h" + + +extern void +dlep_fsm_destroy(dlep_context_peer_t *p2peer); + +extern void +dlep_fsm_create(dlep_context_peer_t *p2peer); + + + +/* Meters a locally unique ID for nodes */ +static uint32_t peer_id_meter = 0; + + +/* + * API to increment seq ID + */ +uint16_t +get_next_sequence_number (dlep_context_peer_t *p2peer) +{ + if (!p2peer) { + return (0); + } + + p2peer->sequence++; + if (!p2peer->sequence) { + p2peer->sequence++; + } + return (p2peer->sequence); +} + + + +/* + * Local API to meter peer IDs + */ +static uint32_t +get_next_peer_id (void) +{ + peer_id_meter++; + if (!peer_id_meter) { + peer_id_meter++; + } + return (peer_id_meter); +} + +/* Below two init functions are added for DLEPv7 */ + +/* + * init optional signal data + */ +static uint32_t init_optional_signal(void) { + + uint32_t opt_signal = 0; + + opt_signal |= (~(~0 << (RFC5444_MAX_MESSAGE_CODE - 1))); + + opt_signal &= (~(1 << (RFC5444_MSG_PEER_UPDATE_RES -1))); + opt_signal &= (~(1 << (RFC5444_MSG_PEER_UPDATE_REQ -1))); + opt_signal &= (~(1 << (RFC5444_MSG_LINK_CHAR_RES -1))); + opt_signal &= (~(1 << (RFC5444_MSG_LINK_CHAR_REQ -1))); + + return opt_signal; +} + +/* + * init optional data item + */ +static uint32_t init_optional_data_item(void) { + + uint32_t opt_data = 0; + + opt_data |= (~(~0 << (RFC5444_MAX_DATA_ITEM - 1))); + + + opt_data &= (~(1 << (RFC5444_TLV_LINK_RESOURCES_METRIC_RX - 1))); + opt_data &= (~(1 << (RFC5444_TLV_LINK_RESOURCES_METRIC_TX - 1))); + opt_data &= (~(1 << (RFC5444_TLV_LINK_RLQ_METRIC_TX -1))); + opt_data &= (~(1 << (RFC5444_TLV_LINK_RLQ_METRIC_RX -1))); + opt_data &= (~(1 << (RFC5444_TLV_CREDIT_WINDOW_STATUS -1))); + opt_data &= (~(1 << (RFC5444_TLV_CREDIT_GRANT -1))); + opt_data &= (~(1 << (RFC5444_TLV_CREDIT_REQUEST -1))); + opt_data &= (~(1 << (RFC5444_TLV_VENDOR_EXTENSION -1))); + opt_data &= (~(1 << (RFC5444_TLV_IPV4_ATTACHED_SUBNET -1))); + opt_data &= (~(1 << (RFC5444_TLV_IPV6_ATTACHED_SUBNET -1))); + + return opt_data; +} + +/** + * NAME + * dlep_peer_init + * + * SYNOPSIS + * #include "dlep_context_peer.h" + * void + * dlep_peer_init(dlep_config_t *p2config, + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function initializes the peer context data after the + * peer has been allocated. The function copies the configuration + * parameters to the peer context. This prevents changes to + * configuration parameters occuring while the protocol is + * active. + * + * INPUT PARAMETERS + * p2config - A pointer to the configuration data + * + * p2peer - A pointer to the peer context + * + * OUTPUT PARAMETERS + * p2peer - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_init (dlep_config_t *p2config, dlep_context_peer_t *p2peer) +{ + if (!p2config || !p2peer) { + return; + } + + p2peer->p2config = p2config; + + /* + * The next_node pointer and the IPv4:Port are already present + */ + p2peer->peer_id = get_next_peer_id(); + + p2peer->sequence = 0; + p2peer->router_id = 0; + p2peer->client_id = 0; + + p2peer->expected_peer_offer_sequence = 0; + p2peer->expected_peer_term_ack_sequence = 0; + p2peer->expected_peer_update_response_sequence = 0; + + p2peer->status_code = RFC5444_SUCCESS; + + strcpy(p2peer->peer_type_description, "no peer description"); + p2peer->peer_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH] = '\0'; + + + p2peer->peer_term_ack_tmo = + p2config->peer_term_ack_tmo; + p2peer->peer_term_missed_ack_threshold = + p2config->peer_term_missed_ack_threshold; + + p2peer->peer_heartbeat_interval = + p2config->peer_heartbeat_interval; + p2peer->peer_heartbeat_missed_threshold = + p2config->peer_heartbeat_missed_threshold; + + p2peer->neighbor_up_ack_tmo = + p2config->neighbor_up_ack_tmo; + p2peer->neighbor_up_missed_ack_threshold = + p2config->neighbor_up_missed_ack_threshold; + + p2peer->neighbor_update_interval_tmo = + p2config->neighbor_update_interval_tmo; + + p2peer->neighbor_activity_timer = + p2config->neighbor_activity_timer; + + p2peer->neighbor_down_ack_tmo = + p2config->neighbor_down_ack_tmo; + p2peer->neighbor_down_missed_ack_threshold = + p2config->neighbor_down_missed_ack_threshold; + + + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + ipv4_zero_address(&p2peer->update_ipv4_address); + + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + ipv6_zero_address(&p2peer->update_ipv6_address); + + + /* + * This is the number of times the timer has + * expired waiting on the ack msg. + */ + p2peer->peer_offer_timeout_count = 0; + p2peer->peer_heartbeat_timeout_count = 0; + p2peer->peer_term_ack_timeout_count = 0; + + /* + * pointer to a single linked list of neighbors associated + * with this node. + */ + p2peer->neighbor_list = NULL; + + p2peer->fsm_handle = NULL; + dlep_fsm_create(p2peer); + + /* + * init optional data and signal item + */ + p2peer->optional_signal = init_optional_signal(); + p2peer->optional_data_item = init_optional_data_item(); + + stw_system_timer_prepare(&p2peer->peer_offer_tmr); + stw_system_timer_prepare(&p2peer->peer_heartbeat_tmr); + stw_system_timer_prepare(&p2peer->peer_term_ack_tmr); + + return; +} + + +/** + * NAME + * dlep_peer_clear + * + * SYNOPSIS + * #include "dlep_context_peer.h" + * void + * dlep_peer_clear(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function should be called as part of the work + * needed to tear down a node. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer data + * structure to be freed. + * + * OUTPUT PARAMETERS + * p2peer - cleared + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_clear (dlep_context_peer_t *p2peer) +{ + RC_STW_t rc; + + if (!p2peer) { + printf("%s-%u peer pointer null \n", + DEBUG_FUNCTION, DEBUG_LINE); + return; + } + + rc = stw_system_timer_stop(&p2peer->peer_offer_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + rc = stw_system_timer_stop(&p2peer->peer_term_ack_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + p2peer->peer_id = 0; + p2peer->peer_udp_port = 0; + p2peer->peer_tcp_port = 0; + + dlep_fsm_destroy(p2peer); + return; +} + + +/** + * NAME + * dlep_peer_display + * + * SYNOPSIS + * #include "dlep_context_peer.h" + * void + * dlep_peer_display(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function displays the peer node data + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_short_display (dlep_context_peer_t *p2peer) +{ + if (!p2peer) { + return; + } + + printf("\nDLEP Local Client %u \n", + p2peer->peer_id); + + /* printf(" Client ID=%u \n", + p2peer->client_id); + + printf(" Router ID=%u \n", + p2peer->router_id); */ + + printf(" Peer Description=%s \n", + p2peer->peer_type_description); + + printf(" Peer UDP port=%u \n", + p2peer->peer_udp_port); + + printf(" Peer TCP port=%u \n", + p2peer->peer_tcp_port); + + ipv4_print_address(" Peer IPv4", + &p2peer->peer_ipv4); + + return; +} + + +/** + * NAME + * dlep_peer_display + * + * SYNOPSIS + * #include "dlep_context_peer.h" + * void + * dlep_peer_display(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function displays the peer node data + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer data + * structure to be freed. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_display (dlep_context_peer_t *p2peer) +{ + if (!p2peer) { + return; + } + + printf("\nDLEP Local Client %u \n", + p2peer->peer_id); + + /* printf(" Client ID=%u \n", + p2peer->client_id); + + printf(" Router ID=%u \n", + p2peer->router_id); */ + + printf(" Peer Description=%s \n", + p2peer->peer_type_description); + + printf(" Peer UDP port=%u \n", + p2peer->peer_udp_port); + + printf(" Peer TCP port=%u \n", + p2peer->peer_tcp_port); + + ipv4_print_address(" Peer IPv4", + &p2peer->peer_ipv4); + + /* printf(" router offer timeout count=%u \n", + p2peer->peer_offer_timeout_count); */ + + printf(" peer heartbeat missed count=%u \n", + p2peer->peer_heartbeat_timeout_count); + + /* printf(" peer term ack missed count=%u \n", + p2peer->peer_term_ack_timeout_count); */ + + printf(" peer term ack missed threshold=%u \n", + p2peer->peer_term_missed_ack_threshold); + + printf(" neighbor_up_ack_tmo=%u milliseconds \n", + p2peer->neighbor_up_ack_tmo); + + printf(" neighbor_up_missed_ack_threshold=%u \n", + p2peer->neighbor_up_missed_ack_threshold); + + printf(" neighbor_update_interval_tmo=%u milliseconds \n", + p2peer->neighbor_update_interval_tmo); + + printf(" neighbor_activity_timer=%u \n", + p2peer->neighbor_activity_timer); + + printf(" neighbor_down_ack_tmo=%u milliseconds \n", + p2peer->neighbor_down_ack_tmo); + + printf(" neighbor_down_missed_ack_threshold=%u \n", + p2peer->neighbor_down_missed_ack_threshold); + + printf(" Metrics:\n"); + printf(" RLQ TX=%u <0-100>", p2peer->rlq_tx); + printf(" RLQ RX=%u <0-100> \n", p2peer->rlq_rx); + printf(" Resources =%u <0-100>", p2peer->resources); + printf(" Latency=%llu milliseconds \n", p2peer->latency); + printf(" CDR TX=%llu bps ", p2peer->cdr_tx); + printf(" CDR RX=%llu bps \n", p2peer->cdr_rx); + printf(" MDR TX=%llu bps ", p2peer->mdr_tx); + printf(" MDR RX=%llu bps \n", p2peer->mdr_rx); + printf(" MTU=%u \n",p2peer->mtu); + + return; +} + + diff --git a/dlep_radio_ipv4/dlep_context_peer.h b/dlep_radio_ipv4/dlep_context_peer.h new file mode 100644 index 0000000..274cb0b --- /dev/null +++ b/dlep_radio_ipv4/dlep_context_peer.h @@ -0,0 +1,228 @@ +/*---------------------------------------------------------------------- + * dlep_context_peer.h -- routines to manage the peer context data + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONTEXT_PEER_H__ +#define __DLEP_CONTEXT_PEER_H__ + +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" + +#include "rfc5444_scratch_pad.h" + +#include "dlep_config.h" +#include "dlep_context_neighbor.h" + + +#define ERROR_STRING_LENGTH ( 32 ) + + + +/* + * Defines the data used to manage a node + */ +typedef struct context_peer_t_ { + struct context_peer_t_ *p2next_peer; + + /* a locally unique ID for display and user I/F */ + uint32_t peer_id; + + /* DLEP IDs */ + uint32_t router_id; + uint32_t client_id; + + /* link to the configuration data */ + dlep_config_t *p2config; + + /* + * incremented with each peer and neighbor message + * transmitted + */ + uint16_t sequence; + + /* expected seq set when the modem init is sent */ + uint16_t expected_peer_offer_sequence; + + /* expected seq set when the peer term is sent */ + uint16_t expected_peer_term_ack_sequence; + + /* expected seq set when the peer update is sent */ + uint16_t expected_peer_update_response_sequence; + + /* + * If the return code is non-zero, an error occurred + * and the Return Status TLV will be inserted when a + * response is built. + */ + uint16_t status_code; + + char peer_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH+1]; + + /* + * peer ip address info to uniquely discriminate nodes + */ +#if 0 + uint16_t peer_port; +#endif + uint16_t peer_udp_port; + uint16_t peer_tcp_port; + ipv4_address_t peer_ipv4; + + struct sockaddr_in msg_addr; + + socklen_t msg_sock_len; + + ipv4_address_t ipv4_address; + ipv6_address_t ipv6_address; + + + ipv4_address_t ipv4_attached_subnet; + ipv6_address_t ipv6_attached_subnet; + + uint32_t peer_term_ack_tmo; + uint32_t peer_term_missed_ack_threshold; + + uint32_t peer_heartbeat_interval; + uint32_t peer_heartbeat_missed_threshold; + + /* + * peer_update addresses + * update layer 3 addresses for the sim + */ + uint8_t update_ipv4_operation; + ipv4_address_t update_ipv4_address; + + uint8_t update_ipv6_operation; + ipv6_address_t update_ipv6_address; + + + uint32_t neighbor_up_ack_tmo; + uint32_t neighbor_up_missed_ack_threshold; + + /* + * used by the client to drive periodic updates + * in milliseconds + */ + uint32_t neighbor_update_interval_tmo; + + uint32_t neighbor_activity_timer; + + uint32_t neighbor_down_ack_tmo; + uint32_t neighbor_down_missed_ack_threshold; + + + /* + * Peer Link-wide RF metrics + */ + uint16_t peer_supported_metrics; + + uint8_t rlq_rx; /* 0-poor, 100-good */ + uint8_t rlq_tx; /* 0-poor, 100-good */ + uint8_t resources_rx; /* 0 -100% */ + uint8_t resources_tx; /* 0 -100% */ + uint8_t resources; /* added for v27 */ + uint64_t latency; /* millisec */ + uint64_t cdr_rx; /* bps */ + uint64_t cdr_tx; /* bps */ + uint64_t mdr_tx; /* bps */ + uint64_t mdr_rx; /* bps */ + uint32_t eft; /* millisec */ + uint16_t mtu; /* added for v27 */ + /* + * Adding optional and data signal + */ + uint32_t optional_signal; + uint32_t optional_data_item; + + /* + * A few peer state working variables + */ + uint32_t peer_offer_timeout_count; + uint32_t peer_heartbeat_timeout_count; + uint32_t peer_term_ack_timeout_count; + + /* + * The list of neighbors associated with this node. + * For simplicity, this is a linked list. If the + * number of neighbors per peer is small, this is + * not a problem. If the numbers increase we can + * go to a hasher. + */ + dlep_context_neighbor_t *neighbor_list; + + /* + * peer state machine handle + */ + void *fsm_handle; + + stw_tmr_t peer_offer_tmr; + stw_tmr_t peer_heartbeat_tmr; + stw_tmr_t peer_term_ack_tmr; + + /* + * When a received message is parsed, its contents are + * parsed here. The data is then passed to the state + * machine where it is processed relative to the + * state for correctness. + */ + rfc5444_packet_scratch_pad_t packet_scratch_pad; + rfc5444_message_scratch_pad_t message_scratch_pad; + + uint32_t ttl; + +} dlep_context_peer_t; + + + +extern uint16_t +get_next_sequence_number(dlep_context_peer_t *p2peer); + +extern void +dlep_peer_init(dlep_config_t *p2config, dlep_context_peer_t *p2peer); + +extern void +dlep_peer_clear(dlep_context_peer_t *p2peer); + +extern void +dlep_peer_short_display(dlep_context_peer_t *p2peer); + +extern void +dlep_peer_display(dlep_context_peer_t *p2peer); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_context_peer_management.c b/dlep_radio_ipv4/dlep_context_peer_management.c new file mode 100644 index 0000000..dc959e6 --- /dev/null +++ b/dlep_radio_ipv4/dlep_context_peer_management.c @@ -0,0 +1,465 @@ +/*---------------------------------------------------------------------- + * dlep_context_node_management.c + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include + +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + + +/* + * List anchor for the local nodes + */ +static dlep_context_peer_t *p2peer_list = NULL; + + +/** + * NAME + * dlep_allocate_node + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * dlep_context_peer_t + * *dlep_peer_allocate(ipv4_address_t *p2ipv4, uint16_t udp_port, tcp_port) + * + * DESCRIPTION + * Allocates a context block for a new node. The context + * block is set to defaults and put on the list. The IPv4 + * address and the port uniquely discriminate the node. + * + * INPUT PARAMETERS + * p2ipv4 - This is a pointer to the IPv4 address structure. + * + * udp_port - This is the udp port for the node. + * + * tcp_port - This is the tcp port for the node. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * A pointer to the newly allocated nod context. + * NULL is returned if the block could not be allocated. + * + */ +dlep_context_peer_t +*dlep_peer_allocate (ipv4_address_t *p2ipv4, uint16_t udp_port, uint16_t tcp_port) +{ + dlep_context_peer_t *p2ctx; + + p2ctx = NULL; + p2ctx = malloc(sizeof(dlep_context_peer_t)); + if (!p2ctx) { + DLEP_DEBUG("%s-%u Error: No resources for new peer context block \n", + DEBUG_FUNCTION, + DEBUG_LINE); + + return (NULL); + } + + ipv4_copy_address(&p2ctx->peer_ipv4, p2ipv4); + p2ctx->peer_udp_port = udp_port; + p2ctx->peer_tcp_port = tcp_port; + + /* + * jam the new peer context in the list + */ + p2ctx->p2next_peer = p2peer_list; + p2peer_list = p2ctx; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Allocated peer block %p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx); + } + + return (p2ctx); +} + + +/** + * NAME + * dlep_peer_remove + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_remove(dlep_context_peer_t **p2peer) + * + * DESCRIPTION + * This function removes a peer context block from the database. + * All dynamically allocate resources must be freed prior to + * removing a node. + * + * INPUT PARAMETERS + * p2peer - A pointer to the peer context block pointer + * + * OUTPUT PARAMETERS + * p2peer - nulled + * + * RETURN VALUE + * No return code + * The callers pointer is NULLed. If there was a problem, the + * callers peer context pointer is not updated. + * + */ +void +dlep_peer_remove (dlep_context_peer_t **p2peer) +{ + dlep_context_peer_t *p2previous; + dlep_context_peer_t *p2ctx; + + if (!p2peer_list) { + return; + } + + p2ctx = p2peer_list; + if (p2ctx == *p2peer) { + p2peer_list = p2ctx->p2next_peer; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u deallocating \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->peer_id); + } + + /* now free the block and update the caller's pointer */ + free(p2ctx); + *p2peer = NULL; + return; + } + + p2previous = p2peer_list; + p2ctx = p2previous->p2next_peer; + + while (p2ctx) { + if (p2ctx == *p2peer) { + p2previous->p2next_peer = p2ctx->p2next_peer; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u deallocating \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->peer_id); + } + + /* now free the block and update the caller's pointer */ + free(p2ctx); + *p2peer = NULL; + break; + + } else { + /* walk the list */ + p2previous = p2ctx; + p2ctx = p2ctx->p2next_peer; + } + } + return; +} + + +/** + * NAME + * dlep_get_peer_by_peer_id + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * dlep_context_peer_t + * *dlep_get_peer_by_peer_id(uint16_t peer_id) + * + * DESCRIPTION + * This function searches the database for the specified peer ID + * and returns the context block pointer. + * + * INPUT PARAMETERS + * peer_id - The locally unique peer ID to look up + * + * RETURN VALUE + * A pointer to the peer context block. + * NULL is returned if the peer was not found. + * + */ +dlep_context_peer_t +*dlep_get_peer_by_peer_id (uint16_t peer_id) +{ + dlep_context_peer_t *result; + dlep_context_peer_t *p2ctx; + + result = NULL; + p2ctx = p2peer_list; + while (p2ctx) { + + if (p2ctx->peer_id == peer_id) { + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_peer; + } + } + return (result); +} + + +/** + * NAME + * dlep_peer_get_by_ipv4 + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * dlep_context_peer_t + * *dlep_peer_get_by_ipv4(ipv4_address_t *p2ipv4, + * uint16_t port) + * + * DESCRIPTION + * This function returns the pointer to the peer context block. + * + * INPUT PARAMETERS + * p2ipv4 - This is a pointer to the IPv4 address to locate + * + * port - This is the port used by the peer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * The pointer to the peer context block. + * NULL is returned if the peer context is not located. + * + */ +dlep_context_peer_t +*dlep_peer_get_by_ipv4 (ipv4_address_t *p2ipv4, uint16_t udp_port, uint16_t tcp_port) +{ + dlep_context_peer_t *result; + dlep_context_peer_t *p2ctx; + + if (!p2ipv4) { + return (NULL); + } + + result = NULL; + p2ctx = p2peer_list; + while (p2ctx) { + + if (ipv4_compare_address(&p2ctx->peer_ipv4, p2ipv4) && + p2ctx->peer_udp_port == udp_port && + p2ctx->peer_tcp_port == tcp_port) { + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_peer; + } + } + return (result); +} + + +/** + * NAME + * dlep_peer_deallocate_all + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_deallocate_all(void) + * + * DESCRIPTION + * This function removes and frees all peer context blocks. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_deallocate_all (void) +{ + dlep_context_peer_t *p2ctx; + dlep_context_peer_t *p2free; + + p2ctx = p2peer_list; + while (p2ctx) { + p2free = p2ctx; + + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->peer_id); + } + + /* walk the list */ + p2ctx = p2ctx->p2next_peer; + free(p2free); + } + p2peer_list = NULL; + return; +} + +/** + * NAME + * dlep_peer_short_list_all + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_short_list_all(void) + * + * DESCRIPTION + * This function generates a short list of all peers. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_short_list_all (void) +{ + dlep_context_peer_t *p2ctx; + + p2ctx = p2peer_list; + while (p2ctx) { + dlep_peer_short_display(p2ctx); + p2ctx = p2ctx->p2next_peer; + } + printf("\n"); + return; +} + + +/** + * NAME + * dlep_peer_list_all + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_list_all(void) + * + * DESCRIPTION + * This function generates a list of all peers. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_list_all (void) +{ + dlep_context_peer_t *p2ctx; + + p2ctx = p2peer_list; + while (p2ctx) { + dlep_peer_display(p2ctx); + p2ctx = p2ctx->p2next_peer; + } + printf("\n"); + return; +} + + +/** + * NAME + * dlep_peer_neighbor_list_all + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_neighbor_list_all(void) + * + * DESCRIPTION + * This function generates a list of all neighbors associated + * with each node + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_neighbor_list_all (void) +{ + dlep_context_peer_t *p2ctx; + + p2ctx = p2peer_list; + while (p2ctx) { + dlep_peer_short_display(p2ctx); + + dlep_neighbor_list_all(p2ctx); + p2ctx = p2ctx->p2next_peer; + } + printf("\n"); + return; +} + + diff --git a/dlep_radio_ipv4/dlep_context_peer_management.h b/dlep_radio_ipv4/dlep_context_peer_management.h new file mode 100644 index 0000000..cbbc5c7 --- /dev/null +++ b/dlep_radio_ipv4/dlep_context_peer_management.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------- + * dlep_context_peer_management.h + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONTEXT_PEER_MANAGEMENT_H__ +#define __DLEP_CONTEXT_PEER_MANAGEMENT_H__ + +#include "dlep_context_peer.h" + + +extern dlep_context_peer_t +*dlep_peer_allocate(ipv4_address_t *p2ipv4, uint16_t udp_port, uint16_t tcp_port); + +extern void +dlep_peer_remove(dlep_context_peer_t **p2peer); + +extern dlep_context_peer_t +*dlep_peer_get_by_ipv4(ipv4_address_t *p2ipv4, uint16_t udp_port, uint16_t tcp_port); + +extern dlep_context_peer_t +*dlep_get_peer_by_peer_id(uint16_t peer_id); + +extern void +dlep_peer_short_list_all(void); + +extern void +dlep_peer_list_all(void); + +extern void +dlep_peer_neighbor_list_all(void); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_debug.c b/dlep_radio_ipv4/dlep_debug.c new file mode 100644 index 0000000..44cf032 --- /dev/null +++ b/dlep_radio_ipv4/dlep_debug.c @@ -0,0 +1,255 @@ +/*------------------------------------------------------------------ + * dlep_debug.c -- debug flag support for DLEP + * + * August 2010, Bo Berry + * + * Copyright (c) 2008, 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *----------------------------------------------------------------- + */ + +#include "dlep_debug.h" + +/* + * debug flags + */ +uint32_t dlep_debug_flags = 0; + + +/** + * NAME + * dlep_debug_set_flag + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_set_flag(uint32_t *p2debug_flags, uint32_t mask) + * + * DESCRIPTION + * Sets specific debug flags + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to component debug flags. + * + * mask - bit mask indicating which flags to set. + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + * NOTES + * If p2debug_flags is null, no operation takes place. + * If mask is (-1), all flags will be set. + * If mask is 0, no operation takes place. + * + */ +void +dlep_debug_set_flag (uint32_t *p2debug_flags, uint32_t mask) +{ + if (p2debug_flags) { + if (mask) { + *p2debug_flags |= mask; + } + } + return; +} + + +/** + * NAME + * dlep_debug_clear_flag + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_clear_flag(uint32_t *p2debug_flags, uint32_t mask) + * + * DESCRIPTION + * Clears specific debug flag(s) + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to the component debug flags. + * + * mask - bit mask indicating which flags to clear. + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + * NOTES + * If p2debug_flags is null, no operation takes place. + * If mask is (-1), all flags will be cleared. + * If mask is 0, no operation takes place. + * + */ +void +dlep_debug_clear_flag (uint32_t *p2debug_flags, uint32_t mask) +{ + if (p2debug_flags) { + if (mask) { + *p2debug_flags &= ~mask; + } + } + return; +} + + +/** + * NAME + * dlep_debug_is_flag_set + * + * SYNOPSIS + * #include "dlep_debug.h" + * boolean_t + * dlep_debug_is_flag_set(uint32_t debug_flags, uint32_t mask) + * + * DESCRIPTION + * Returns the status of debug flag(s) + * + * INPUT PARAMETERS + * debug_flags - Component debugs. + * + * mask - debug flag(s). + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE flag(s) set + * FALSE flag(s) clear + * + * EXAMPLES + * dlep_debug_is_flag_set(&component_flags, SOME_DEBUG) + * + * dlep_debug_is_flag_set(&component_flags, (SOME_DEBUG | ANOTHER_DEBUG) ) + * + */ +boolean_t +dlep_debug_is_flag_set (uint32_t debug_flags, uint32_t flag) +{ + return ( ((debug_flags & flag) ? TRUE : FALSE) ); +} + + +/** + * NAME + * dlep_debug_set_all + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_set_all(uint32_t *p2debug_flags) + * + * DESCRIPTION + * This function should be used to set all debugs. + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to component debug flags. + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + */ +void +dlep_debug_set_all (uint32_t *p2debug_flags) +{ + if (p2debug_flags) { + *p2debug_flags = DLEP_DEBUG_ALL_FLAGS; + } + return; +} + +/** + * NAME + * dlep_debug_clear_all + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_clear_all(uint32_t *p2debug_flags) + * + * DESCRIPTION + * This function should be used to clear all debugs. + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to component debug flags. + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + */ +void +dlep_debug_clear_all (uint32_t *p2debug_flags) +{ + if (p2debug_flags) { + *p2debug_flags = 0; + } + return; +} + + +/** + * NAME + * dlep_debug_init + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_int(uint32_t *p2debug_flags, uint32_t initial_mask) + * + * DESCRIPTION + * Init the debug flagss. + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to component debug flags. + * + * initial_mask + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + */ +void +dlep_debug_init (uint32_t *p2debug_flags, uint32_t initial_mask) +{ + if (p2debug_flags) { + *p2debug_flags = initial_mask; + } + return; +} + + diff --git a/dlep_radio_ipv4/dlep_debug.h b/dlep_radio_ipv4/dlep_debug.h new file mode 100644 index 0000000..3262893 --- /dev/null +++ b/dlep_radio_ipv4/dlep_debug.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------- + * dlep_debug.h -- Debug flags and supporting macros + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_DEBUG_H__ +#define __DLEP_DEBUG_H__ + +#include "safe_types.h" + +extern uint32_t dlep_debug_flags; + + + +/* + * Use these macros to abstract the preprocessor + * so internal information is not displayed in + * debugs. + */ +#define ENABLE_FUNCTION_AND_LINE + +#ifdef ENABLE_FUNCTION_AND_LINE +#define DEBUG_FILE __FILE__ +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ +#define DEBUG_DATE __DATE__ +#define DEBUG_TIME __TIME__ +#else +#define DEBUG_FILE " " +#define DEBUG_FUNCTION " " +#define DEBUG_LINE 0 +#define DEBUG_DATE " " +#define DEBUG_TIME " " +#endif + + +/* + * abstracted for porting + */ +#define DLEP_DEBUG printf + + +/* + * surgical debug flags for DLEP. + */ +#define DLEP_DEBUG_ALL_FLAGS ( -1 ) + +#define DLEP_ERROR_TRACE_FLAG ( 0x01 ) +#define DLEP_UDP_TRACE_FLAG ( 0x02 ) + +#define DLEP_INCOMING_TRACE_FLAG ( 0x04 ) +#define DLEP_OUTGOING_TRACE_FLAG ( 0x08 ) + +#define DLEP_PEER_TRACE_FLAG ( 0x10 ) +#define DLEP_NEIGHBOR_TRACE_FLAG ( 0x20 ) + +#define DLEP_METRICS_TRACE_FLAG ( 0x40 ) +#define DLEP_SCRATCH_TRACE_FLAG ( 0x80 ) +#define DLEP_DECODER_TRACE_FLAG ( 0x100 ) + + + +extern void dlep_debug_set_flag(uint32_t *p2debug_flags, uint32_t mask); + +extern void dlep_debug_clear_flag(uint32_t *p2debug_flags, uint32_t mask); + +extern boolean_t dlep_debug_is_flag_set(uint32_t debug_flags, uint32_t mask); + +extern void dlep_debug_set_all(uint32_t *p2debug_flags); + +extern void dlep_debug_clear_all(uint32_t *p2debug_flags); + +extern void dlep_debug_init(uint32_t *p2debug_flags, uint32_t mask); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_debug_cli.c b/dlep_radio_ipv4/dlep_debug_cli.c new file mode 100644 index 0000000..402b9f2 --- /dev/null +++ b/dlep_radio_ipv4/dlep_debug_cli.c @@ -0,0 +1,334 @@ +/*------------------------------------------------------------------ + * dlep_debug_cli.c -- DLEP debug CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "safe_types.h" +#include "cli.h" + +#include "rfc5444_types.h" + +#include "dlep_debug.h" +#include "dlep_debug_cli.h" + + +/* + * directory record + * + * static cli_record_t debug_dir; + */ + +/* + * allocate command records + */ +static cli_record_t debug_show_mask_cmd; +static cli_record_t debug_set_mask_cmd; +static cli_record_t debug_clear_mask_cmd; +static cli_record_t debug_enable_all_cmd; +static cli_record_t debug_disable_all_cmd; + + + + +/** + ** debug commands + **/ +static void +cli_debug_show_mask (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("peer_debug_show - displays enabled debugging levels \n"); + printf("\n"); + return; + } + + printf(" error - %s \n", + ((dlep_debug_flags&DLEP_ERROR_TRACE_FLAG)?"On":"Off")); + + printf(" udp - %s \n", + ((dlep_debug_flags&DLEP_UDP_TRACE_FLAG)?"On":"Off")); + + printf(" incoming - %s \n", + ((dlep_debug_flags&DLEP_INCOMING_TRACE_FLAG)?"On":"Off")); + + printf(" outgoing - %s \n", + ((dlep_debug_flags&DLEP_OUTGOING_TRACE_FLAG)?"On":"Off")); + + printf(" peer - %s \n", + ((dlep_debug_flags&DLEP_PEER_TRACE_FLAG)?"On":"Off")); + + printf(" neighbor - %s \n", + ((dlep_debug_flags&DLEP_NEIGHBOR_TRACE_FLAG)?"On":"Off")); + + printf(" metrics - %s \n", + ((dlep_debug_flags&DLEP_METRICS_TRACE_FLAG)?"On":"Off")); + + printf(" scratch - %s \n", + ((dlep_debug_flags&DLEP_SCRATCH_TRACE_FLAG)?"On":"Off")); + + printf(" decoder - %s \n", + ((dlep_debug_flags&DLEP_DECODER_TRACE_FLAG)?"On":"Off")); + + printf("\n"); + return; +} + + + +static void +cli_debug_set_mask (uint32_t argc, char *argv[]) +{ + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("debug_set [error|udp|incoming|outgoing|packet|peer|" + "neighbor|metrics|scratch|decoder] \n"); + printf("where \n"); + printf(" error - enables the error debug trace \n"); + printf(" udp - enables debug trace of the udp send-receive \n"); + + printf(" incoming - enables debug trace of incoming packets \n"); + printf(" outgoing - enables debug trace of outgoing packets \n"); + printf(" packet - enables both incoming and outgoing packet " + "trace \n"); + + printf(" peer - enables peer specific debug trace \n"); + printf(" neighbor - enables neighbor specific debug trace \n"); + + printf(" metrics - enables neighbor metrics trace \n"); + printf(" scratch - enables scratch pad trace \n"); + printf(" decoder - enables debug trace of TLV validation \n"); + + printf("\n"); + return; + } + + if (!strcmp(argv[1], "error")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_ERROR_TRACE_FLAG); + + } else if (!strcmp(argv[1], "udp")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_UDP_TRACE_FLAG); + + } else if (!strcmp(argv[1], "incoming")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_INCOMING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "outgoing")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_OUTGOING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "packet")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_INCOMING_TRACE_FLAG); + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_OUTGOING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "peer")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_PEER_TRACE_FLAG); + + } else if (!strcmp(argv[1], "neighbor")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_NEIGHBOR_TRACE_FLAG); + + } else if (!strcmp(argv[1], "metrics")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_METRICS_TRACE_FLAG); + + } else if (!strcmp(argv[1], "scratch")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_SCRATCH_TRACE_FLAG); + + } else if (!strcmp(argv[1], "decoder")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_DECODER_TRACE_FLAG); + } else { + printf("Invalid debug flag, <%s> \n", argv[1]); + } + return; +} + + +static void +cli_debug_clear_mask (uint32_t argc, char *argv[]) +{ + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + + printf("debug_clear [error|udp|incoming|outgoing|packet|peer|neighbor|" + "metrics|scratch|decoder] \n"); + printf("where \n"); + printf(" error - disables the error debug trace \n"); + printf(" udp - disables debug trace for udp operations \n"); + + printf(" incoming - disables debug trace of incoming packets \n"); + printf(" outgoing - disables debug trace of outgoing packets \n"); + printf(" packet - enables both incoming and outgoing packet " + "trace \n"); + + printf(" peer - disables peer specific debug trace \n"); + printf(" neighbor - disables neighbor specific debug trace \n"); + + printf(" metrics - disables neighbor metrics trace \n"); + printf(" scratch - disables scratch pad trace \n"); + printf(" decoder - disables debug trace of TLV validation \n"); + + printf("\n"); + return; + } + + if (!strcmp(argv[1], "error")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_ERROR_TRACE_FLAG); + + } else if (!strcmp(argv[1], "udp")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_UDP_TRACE_FLAG); + + } else if (!strcmp(argv[1], "incoming")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_INCOMING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "outgoing")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_OUTGOING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "packet")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_INCOMING_TRACE_FLAG); + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_OUTGOING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "peer")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_PEER_TRACE_FLAG); + + } else if (!strcmp(argv[1], "neighbor")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_NEIGHBOR_TRACE_FLAG); + + } else if (!strcmp(argv[1], "metrics")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_METRICS_TRACE_FLAG); + + } else if (!strcmp(argv[1], "scratch")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_SCRATCH_TRACE_FLAG); + + } else if (!strcmp(argv[1], "decoder")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_DECODER_TRACE_FLAG); + } + return; +} + + +static void +cli_debug_enable_all (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("debug_enable - enables all debugs \n"); + printf("\n"); + return; + } + dlep_debug_flags = (-1); + printf(" all peer debugs enabled \n"); + return; +} + + +static void +cli_debug_disable_all (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("debug_disable - disables all debugs \n"); + printf("\n"); + return; + } + dlep_debug_flags = (0); + printf(" all peer debugs disabled \n"); + return; +} + + +/** + * NAME + * dlep_debug_cli_init + * + * SYNOPSIS + * void + * dlep_debug_cli_init() + * + * DESCRIPTION + * Registers the dlep debug commands with the cli + * facility. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_debug_cli_init (void) +{ + RC_CLI_t rc; + + /* + * Create directory and commands + **rc = cli_mkdir("peer", &cli_debug_dir, &debug_dir); + */ + + /* debug commands */ + rc = cli_mkcmd("debug_show", cli_debug_show_mask, + &cli_debug_dir, &debug_show_mask_cmd); + + rc = cli_mkcmd("debug_set", cli_debug_set_mask, + &cli_debug_dir, &debug_set_mask_cmd); + + rc = cli_mkcmd("debug_clear", cli_debug_clear_mask, + &cli_debug_dir, &debug_clear_mask_cmd); + + rc = cli_mkcmd("debug_enable", cli_debug_enable_all, + &cli_debug_dir, &debug_enable_all_cmd); + + rc = cli_mkcmd("debug_disable", cli_debug_disable_all, + &cli_debug_dir, &debug_disable_all_cmd); + + return; +} + + diff --git a/dlep_radio_ipv4/dlep_debug_cli.h b/dlep_radio_ipv4/dlep_debug_cli.h new file mode 100644 index 0000000..1245a9b --- /dev/null +++ b/dlep_radio_ipv4/dlep_debug_cli.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------- + * dlep_debug_cli.h -- debug cli prototypes for DLEP + * + * October 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_DEBUG_CLI_H__ +#define __DLEP_DEBUG_CLI_H__ + + +extern void +dlep_debug_cli_init(void); + +#endif + diff --git a/dlep_radio_ipv4/dlep_message_builder.c b/dlep_radio_ipv4/dlep_message_builder.c new file mode 100644 index 0000000..ed7f356 --- /dev/null +++ b/dlep_radio_ipv4/dlep_message_builder.c @@ -0,0 +1,2373 @@ +/*---------------------------------------------------------------------- + * dlep_message_builder.c -- Routines to build the DLEP messages + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "packet_dump.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_encoder_tlv.h" +#include "rfc5444_encoder.h" + +#include "dlep_sim_options.h" +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" +#include "rfc5444_experimental_tlv.h" + +#include "dlep_message_builder.h" +#include "dlep_client_timer.h" + +extern int TCP_READY; +extern int init; + +/* + * Local API to increment a sequence number. Sequence numbers + * are simply request-response correlators. They are not + * checked for 'sequencing' or lost messages. The originator + * determines the sequence number so it can correlate the + * response. + */ +static uint16_t +dlep_get_next_sequence_number (uint16_t sequence_number) +{ + sequence_number++; + if (!sequence_number) { + sequence_number++; + } + return (sequence_number); +} + + +/** + * NAME + * send_dlep_attached_peer_discovery + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_attached_peer_discovery( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a attached peer discovery message + * from the radio to the router to initiate the discovery process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_attached_peer_discovery (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + TCP_READY = 0; +// printf("\n INSIDE send_dlep_attached_peer_discovery "); + p2es = rfc5444_encoder_packet_start(); + + /* Adding message header */ + rfc5444_encoder_message_block_start(p2es, + RFC5444_SIG_ATT_PEER_DISCOVERY); + + packet_dump("OUTGOING-", + p2es->packet_ptr, + 1); + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_detached_peer_discovery + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_detached_peer_discovery( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a detached peer discovery message + * from the radio to the router to initiate the discovery process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_detached_peer_discovery (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + /* + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); +*/ + +// added for D5 + +rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_DET_PEER_DISCOVERY); + +/* This function call to add message lenth */ + +#if 0 +rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); +#endif +#if 0 + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +/* + // added for testing, will remove it +// rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_DET_PEER_DISCOVERY); + */ + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + p2peer->expected_peer_offer_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + +#endif + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + /* optional */ + rfc5444_peer_tlv(p2es, p2config->local_type_description); +#if 0 + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); +#if 0 + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#endif + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_peer_offer + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_offer(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer offer message + * from the router to the radio in response to the + * peer attached/detached discovery message. This + * confirms discovery. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_offer (dlep_context_peer_t *p2peer) +{ + + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + p2es = rfc5444_encoder_packet_start(); + + /* Adding Message header */ + + rfc5444_encoder_signal_block_start(p2es, + RFC5444_SIG_PEER_OFFER, + DLEP_SIGNAL_FLAGS); + + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_ipv4_connection_point_tlv(p2es, p2config->local_tcp_port, + &p2config->local_ipv4); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending peer offer : \n"); + printf(" signal code=%u RFC5444_SIG_PEER_OFFER \n", + RFC5444_SIG_PEER_OFFER); + } + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + + /* Oppening TCP socket */ +// dlep_tcp_porter_open(p2config); + + rfc5444_encoder_free(p2es); + + return; +} + + + /** + * NAME + * send_dlep_peer_init + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_init( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer init message + * from the radio to the router to initiate the TCP synchronization process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ + void + send_dlep_peer_init (dlep_context_peer_t *p2peer) + { + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_INIT_REQ); + + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); + + rfc5444_link_metric_mdr_rx_tlv(p2es, 100000000); + p2peer->mdr_rx=100000000; + + rfc5444_link_metric_mdr_tx_tlv(p2es, 100000000); + p2peer->mdr_tx=100000000; + + rfc5444_link_metric_cdr_rx_tlv(p2es, 100000000); + p2peer->cdr_rx=100000000; + rfc5444_link_metric_cdr_tx_tlv(p2es, 250); + p2peer->cdr_tx =250; + + rfc5444_link_metric_latency_tlv1(p2es, 250); + p2peer->latency = 250; + + rfc5444_link_metric_resources_tx_tlv(p2es, 100); + p2peer->resources_tx = 100; + rfc5444_link_metric_resources_rx_tlv(p2es, 100); + p2peer->resources_rx = 100; + + rfc5444_link_metric_rlq_rx_tlv(p2es, 100); + p2peer->rlq_rx = 100; + rfc5444_link_metric_rlq_tx_tlv(p2es, 100); + p2peer->rlq_tx = 100; + + + + /* optional */ + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#if 0 + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + + + printf("\n CALLING dlep_tcp_connect"); +#endif + +#if 0 + dlep_tcp_connect(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); +#endif + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + /* Setting this flag inorder for dlep_tcp_receive to get called after tcp connect + * and first dlep_tcp_send is called inorder to avoid infinite call in loop. + */ + TCP_READY = 1; + + rfc5444_encoder_free(p2es); +// printf("\n PEER INIT REQUEST Sent"); + + return; +} + + /** + * NAME + * send_dlep_peer_init_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_init( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer init message response + * from the radio to the router. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ + void + send_dlep_peer_init_ack (dlep_context_peer_t *p2peer) + { + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_INIT_RES); + if(init == 1) { + p2peer->status_code = RFC5444_REQUEST_DENIED; + } + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); + + rfc5444_link_metric_mdr_rx_tlv(p2es, 100000000); + p2peer->mdr_rx=100000000; + + rfc5444_link_metric_mdr_tx_tlv(p2es, 100000000); + p2peer->mdr_tx=100000000; + + rfc5444_link_metric_cdr_rx_tlv(p2es, 100000000); + p2peer->cdr_rx=100000000; + + rfc5444_link_metric_cdr_tx_tlv(p2es, 100000000); + p2peer->cdr_tx = 100000000; + + rfc5444_link_metric_latency_tlv1(p2es, 250); + p2peer->latency = 250; + + /* rfc5444_link_metric_latency_tlv(p2es, 250); + p2peer->latency = 250; */ + + rfc5444_link_metric_rlq_rx_tlv(p2es, 100); + p2peer->rlq_rx = 100; + + rfc5444_link_metric_rlq_tx_tlv(p2es, 100); + p2peer->rlq_tx = 100; + + rfc5444_link_metric_resources_tlv(p2es, 100); + p2peer->resources = 100; + + rfc5444_mtu_tlv(p2es, 100); + p2peer->mtu = 100; + + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2config->local_ipv4); + ipv4_zero_address(&p2peer->ipv4_address); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#if 0 + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + + + printf("\n CALLING dlep_tcp_connect"); +#endif + +#if 0 + dlep_tcp_connect(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); +#endif + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Session initialization response : \n"); + printf(" Message code=%u RFC5444_MSG_PEER_INIT_RES\n",RFC5444_MSG_PEER_INIT_RES); + + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + /* Setting this flag inorder for dlep_tcp_receive to get called after tcp connect + * and first dlep_tcp_send is called inorder to avoid infinite call in loop. + */ + TCP_READY = 1; + + rfc5444_encoder_free(p2es); + + return; +} + + +/** + * NAME + * send_dlep_peer_heartbeat + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_heartbeat( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer heartbeat to + * maintain a persistent presence with the peer. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_heartbeat (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + +// printf("\n INSIDE send_dlep_peer_heartbeat"); + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_HEARTBEAT); + +#if 0 + /* + * Get a unique sequence number + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); +#if 0 +#ifdef MULTIPLE_PEER_MESSAGES_PACKED + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_HEARTBEAT); + + /* + * Get a unique sequence number + * HB does not have an ACK, so the sequence number is not important. + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); +#endif +#endif + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + /* if (TCP_READY ) { + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + } else { // Else send with UDP socket if heartbeat sent before TCP connection. + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + } */ + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending heartbeat message : \n"); + printf(" Message code=%u RFC5444_MSG_PEER_HEARTBEAT\n", + RFC5444_MSG_PEER_HEARTBEAT); + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_peer_update_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_update_request( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer update message + * from the router to the radio. It is used to indicate + * a new layer 3 address or the removal of a layer 3 + * address. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_update_request (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_UPDATE_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = dlep_get_next_sequence_number(p2peer->sequence); + p2peer->expected_peer_update_response_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + /* if (p2peer->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2peer->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2peer->update_ipv4_operation, + &p2peer->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2peer->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2peer->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2peer->update_ipv6_operation, + &p2peer->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } */ +#if 0 + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_link_metric_mdr_rx_tlv(p2es, p2peer->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2peer->mdr_tx); + rfc5444_link_metric_cdr_rx_tlv(p2es, p2peer->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2peer->cdr_tx); + rfc5444_link_metric_latency_tlv1(p2es, p2peer->latency); + rfc5444_link_metric_resources_tlv(p2es, p2peer->resources); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2peer->rlq_tx); + rfc5444_link_metric_rlq_rx_tlv(p2es, p2peer->rlq_rx); + rfc5444_mtu_tlv(p2es, p2peer->mtu); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session update request :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_UPDATE_REQ\n", + RFC5444_MSG_PEER_UPDATE_REQ); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + + return; +} + + +/** + * NAME + * send_dlep_peer_update_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_update_response( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer update response message + * from the radio to the router. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_update_response (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_UPDATE_RES); +#if 0 + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session update response :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_UPDATE_RES\n", + RFC5444_MSG_PEER_UPDATE_RES); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_peer_termination + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_termination(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer termination message + * from the router to the radio or from the radio to the + * router to termiante the association. As result all + * neighbor neighbors are also terminated. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_termination (dlep_context_peer_t *p2peer) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = dlep_get_next_sequence_number( + p2peer->sequence); + p2peer->expected_peer_offer_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +// printf("\n Adding Status TLV"); + rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + rfc5444_encoder_message_block_end(p2es); +#endif +#ifdef MULTIPLE_PEER_MESSAGES_PACKED + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); + + /* + * acks will not align with incremented sequence + * + * p2peer->sequence = dlep_get_next_sequence_number( + * p2peer->sequence); + * p2peer->expected_peer_offer_sequence = p2peer->sequence; + */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session termination :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_TERM_REQ\n", + RFC5444_MSG_PEER_TERM_REQ); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_peer_termination_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_termination_ack(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer termination ACK + * message from the router to the radio or from the radio + * to the router in response to the peer terminate request. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_termination_ack (dlep_context_peer_t *p2peer) +{ + + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_RES); +#if 0 + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + +// rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session termination message :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_TERM_RES\n", + RFC5444_MSG_PEER_TERM_REQ); + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_up + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_up(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor up message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_up (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + printf("sending nei up\n"); + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_REQ); + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* add the IPv4 address if there is one to add */ + //if (p2neighbor->ipv4_address.v4_addr.v4_addr32) { + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv4_address); + ipv4_zero_address(&p2neighbor->ipv4_address); + //} + + /* add the IPv6 address if there is one to add + if (p2neighbor->ipv6_address.v6_addr.v6_addr32[0] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[1] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[2] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[3]) { + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv6_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + } */ + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + //rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + + + rfc5444_encoder_message_block_end(p2es); +#if 0 +//ifdef MULTIPLE_NEIGHBOR_MESSAGES_PACKED + /**** neighbor down ****/ + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_term_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + /**** neighbor up ****/ + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_init_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* add the IPv4 address if there is one to add */ + if (p2neighbor->ipv4_address.v4_addr.v4_addr32) { + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv4_address); + ipv4_zero_address(&p2neighbor->ipv4_address); + } + + /* add the IPv6 address if there is one to add */ + if (p2neighbor->ipv6_address.v6_addr.v6_addr32[0] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[1] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[2] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[3]) { + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv6_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + } + + rfc5444_link_metric_mdr_tlv(p2es, p2neighbor->mdr); + + rfc5444_link_metric_cdr_tlv(p2es, p2neighbor->cdr); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); +#endif + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination up:\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_UP_REQ\n", + RFC5444_MSG_NEIGHBOR_UP_REQ); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_up_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_up_ack(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor up ack message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_up_ack (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); +#if 0 + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_metrics + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_metrics(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor metrics message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context with the + * metrics data set + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_metrics (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + } */ + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + rfc5444_ipv6_subnet_tlv(p2es, + p2neighbor->update_ipv6_operation, p2neighbor->ipv6_subnet_prefix,&p2neighbor->update_ipv6_subnet_address); + p2neighbor->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination update to metrics:\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_METRICS\n", + RFC5444_MSG_NEIGHBOR_METRICS); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + +void +send_dlep_neighbor_credit_grant_req (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); + +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + +#if 0 + /* + * Get a unique sequence number */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_credit_grand_request_tlv(p2es, p2neighbor->cgr); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + + /* + * start the ack timer. Using same neighbor_up_ack_tmo Neighbor Up Time. + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_update_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_update_ack_tmr, + (void *)p2neighbor); + + return; +} + + +void +send_dlep_neighbor_credit_reject (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); + + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_rx_tlv(p2es, p2neighbor->resources_tx); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_address_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_address_request(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a peer heartbeat. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_address_request (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_ADDRESS_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = + dlep_get_next_sequence_number(p2neighbor->sequence); + p2neighbor->expected_neighbor_address_response_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_address_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_address_response(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor address response. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_address_response (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_ADDRESS_RES); + + /* + * echo the neighbor sequence number + */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_down + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_down(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor down message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_down (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_REQ); +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_term_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + +// rfc5444_status_tlv(p2es, p2neighbor->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination down :\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_DOWN_REQ\n", + RFC5444_MSG_NEIGHBOR_DOWN_REQ); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_down_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_down_ack(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor down ack message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_down_ack (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination down response :\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_DOWN_RES\n", + RFC5444_MSG_NEIGHBOR_DOWN_RES); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_link_char_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_link_char_request(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor, + * uint64_t cdr, + * uint16_t latency) + * + * DESCRIPTION + * This function is used to send a link characteristic message from + * the server to the client. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * cdr - requested data rate + * + * latency - maximum latency requested + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_link_char_request (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor, + uint64_t cdr, + uint64_t latency) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_LINK_CHAR_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = + dlep_get_next_sequence_number(p2neighbor->sequence); + p2neighbor->expected_neighbor_link_char_response_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (cdr) { + rfc5444_link_metric_cdr_tx_tlv(p2es, cdr); + rfc5444_link_metric_cdr_rx_tlv(p2es, cdr); + } + + + if (latency) { + rfc5444_link_metric_latency_tlv1(p2es, latency); + } + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_link_char_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_link_char_response(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a link characteristic response from + * the client to the server. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_link_char_response (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_LINK_CHAR_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + +#if 0 + rfc5444_link_metric_resources_rx_tlv(p2es, p2neighbor->resources_tx); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination link char response :\n"); + printf(" Message code=%u FC5444_MSG_LINK_CHAR_RES\n", + RFC5444_MSG_LINK_CHAR_RES); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + diff --git a/dlep_radio_ipv4/dlep_message_builder.h b/dlep_radio_ipv4/dlep_message_builder.h new file mode 100644 index 0000000..faa037b --- /dev/null +++ b/dlep_radio_ipv4/dlep_message_builder.h @@ -0,0 +1,133 @@ +/*---------------------------------------------------------------------- + * dlep_message_builder.h -- Routines to build the DLEP messages + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_MESSAGE_BUILDER_H__ +#define __DLEP_MESSAGE_BUILDER_H__ + +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" + + + +/* + * Router-Radio Level Mesages + */ + +extern void +send_dlep_attached_peer_discovery(dlep_context_peer_t *p2peer); + +extern void +send_dlep_detached_peer_discovery(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_offer(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_init(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_init_ack(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_heartbeat(dlep_context_peer_t *p2peer); + + +extern void +send_dlep_peer_update_request(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_update_response(dlep_context_peer_t *p2peer); + + +extern void +send_dlep_peer_termination(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_termination_ack(dlep_context_peer_t *p2peer); + + +/* + * Neighbor Level Mesages + */ + +extern void +send_dlep_neighbor_up(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_up_ack(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_metrics(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_credit_grant_req(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_credit_reject(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_address_request(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_address_response(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + +extern void +send_dlep_neighbor_down(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_down_ack(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_link_char_request(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor, + uint64_t cdr, + uint64_t latency); + + +extern void +send_dlep_neighbor_link_char_response(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + + + +#endif + diff --git a/dlep_radio_ipv4/dlep_porter.c b/dlep_radio_ipv4/dlep_porter.c new file mode 100644 index 0000000..6a71587 --- /dev/null +++ b/dlep_radio_ipv4/dlep_porter.c @@ -0,0 +1,913 @@ +/*---------------------------------------------------------------------- + * dlep_porter.c -- APIs for UDP socket use + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "safe_types.h" +#include "dlep_debug.h" +#include "dlep_config.h" +#include "dlep_context_peer.h" +#include "dlep_porter.h" + +// ADDED FOR DEBUG +// #include + +#define MSG_MIN_LEN ( 4 ) +#define MSG_MAX_LEN ( 1400 ) + +extern int TCP_READY; + +extern int TCP_CLIENT_READY; +extern int errno; + +/** + * NAME + * dlep_porter_init + * + * SYNOPSIS + * void + * dlep_porter_init(dlep_config_t *p2config) + * + * DESCRIPTION + * This function is used to initialize the transport data prior + * to allocating resources. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * None. + * + */ +void +dlep_porter_init (dlep_config_t *p2config) +{ + if (!p2config) { + return; + } + + return; +} + + +void +dlep_tcp_porter_open(dlep_config_t *p2config) + +{ + int status; + + if (!p2config) { + return; + } + + /* At this stage open tcp socket alone in order to use in + * select system call later. */ + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Opening the tcp socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + p2config->dlep_tcp_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); +// added for debug +// fcntl(p2config->dlep_tcp_sockfd, F_SETFL, O_NONBLOCK); + if (p2config->dlep_tcp_sockfd < 0) { + DLEP_DEBUG("%s-%u Error: not able to open TCP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + exit (0); + } + + + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Binding the tcp socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + memset(&p2config->dlep_addr, 0, sizeof(struct sockaddr_in)); + p2config->dlep_addr.sin_family = AF_INET; + p2config->dlep_addr.sin_port = htons(p2config->local_tcp_port); + p2config->dlep_addr.sin_addr.s_addr = INADDR_ANY; + + status = bind(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2config->dlep_addr, + sizeof(struct sockaddr_in)); + + if (status < 0) { + + printf("\n not able to bind"); + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: not able to bind TCP " + "socket to port %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2config->local_tcp_port); + } + exit (0); + } + printf("\n waiting connect from router\n"); + status = listen(p2config->dlep_tcp_sockfd,5); + if (status) { + perror("ERROR on listen"); + exit(2); + } +/* + p2config->client_lenght = sizeof(p2config->client); + p2config->dlep_tcp_client_sockfd = accept(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2config->client, &p2config->client_lenght); + + if (p2config->dlep_tcp_client_sockfd < 0) { + perror("ERROR on accept"); + exit(1); + } + + + printf(" dlep_tcp_sockfd after accept =%d",p2config->dlep_tcp_client_sockfd); + + TCP_READY = 1; +*/ + +#if 0 + int sockfd, newsockfd, portno, clilen; + char buffer[256]; + struct sockaddr_in serv_addr, cli_addr; + int n; + + /* First call to socket() function */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) + { + perror("ERROR opening socket"); + exit(1); + } + + /* Initialize socket structure */ + bzero((char *) &serv_addr, sizeof(serv_addr)); + portno = 5001; + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(portno); + + /* Now bind the host address using bind() call.*/ + if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + //perror("ERROR on binding"); + exit(1); + } + + /* Now start listening for the clients, here process will + * go in sleep mode and will wait for the incoming connection + */ + + listen(sockfd,5); + clilen = sizeof(cli_addr); + + /* Accept actual connection from the client */ + newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); + if (newsockfd < 0) + { + perror("ERROR on accept"); + exit(1); + } + + /* If connection is established then start communicating */ + bzero(buffer,256); + // n = read( newsockfd,buffer,255 ); + + if (n < 0) + { + perror("ERROR reading from socket"); + exit(1); + } + + printf("Here is the message: %s\n",buffer); + + /* Write a response to the client */ +// n = write(newsockfd,"I got your message",18); + + if (n < 0) + { + perror("ERROR writing to socket"); + exit(1); + } + + return 0; +#endif + return; + +} + + +/** + * NAME + * dlep_porter_open + * + * SYNOPSIS + * void + * dlep_porter_open(dlep_config_t *p2config) + * + * DESCRIPTION + * This function is used to open and bind to a local + * socket fd. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * None. + * + */ +void +dlep_porter_open (dlep_config_t *p2config) +{ + int status; + + if (!p2config) { + return; + } + p2config->reuse = 1; + +// if (p2config->start_on_discovery) { + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Opening the UDP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + p2config->dlep_udp_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (p2config->dlep_udp_sockfd < 0) { + DLEP_DEBUG("%s-%u Error: not able to open UDP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + exit (0); + } + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Binding the udp socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + if(setsockopt(p2config->dlep_udp_sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&p2config->reuse, sizeof(p2config->reuse)) < 0) + { + //perror("Setting SO_REUSEADDR error"); + close(p2config->dlep_udp_sockfd); + exit(1); + } + + memset(&p2config->dlep_addr, 0, sizeof(struct sockaddr_in)); + p2config->dlep_addr.sin_family = AF_INET; + p2config->dlep_addr.sin_port = htons(p2config->local_udp_port); + p2config->dlep_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + status = bind(p2config->dlep_udp_sockfd, + (struct sockaddr *)&p2config->dlep_addr, + sizeof(struct sockaddr_in)); + if (status < 0) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: not able to bind UDP " + "socket to port %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2config->local_udp_port); + } + exit (0); + } + + p2config->group.imr_multiaddr.s_addr = inet_addr("224.0.0.117"); +// p2config->group.imr_interface.s_addr = INADDR_ANY; +// p2config->group.imr_interface.s_addr = inet_addr("20.1.1.4"); + p2config->group.imr_interface.s_addr = inet_addr(p2config->local_ipv4_dot); + + if(setsockopt(p2config->dlep_udp_sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char *)&p2config->group, sizeof(p2config->group)) < 0) + { + //perror("Adding multicast group error"); + close(p2config->dlep_udp_sockfd); + exit(1); + } else { + printf("Adding multicast group...OK.\n"); + } + + +// listen(32, p2config->dlep_udp_sockfd); +// } + +#if 0 + /* At this stage open tcp socket alone in order to use in + * select system call later. */ + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Opening the tcp socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + p2config->dlep_tcp_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); +// added for debug +// fcntl(p2config->dlep_tcp_sockfd, F_SETFL, O_NONBLOCK); + if (p2config->dlep_tcp_sockfd < 0) { + DLEP_DEBUG("%s-%u Error: not able to open TCP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + exit (0); + } + + + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Binding the tcp socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + memset(&p2config->dlep_addr, 0, sizeof(struct sockaddr_in)); + p2config->dlep_addr.sin_family = AF_INET; + p2config->dlep_addr.sin_port = htons(p2config->local_tcp_port); + p2config->dlep_addr.sin_addr.s_addr = inet_addr("224.0.0.109"); + +// changing for multicast support +// p2config->dlep_addr.sin_addr.s_addr = htonl(INADDR_ANY); + +#endif //changed for d7 +#if 0 + status = bind(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2config->dlep_addr, + sizeof(struct sockaddr_in)); + if (status < 0) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: not able to bind TCP " + "socket to port %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2config->local_tcp_port); + } + exit (0); + } +#endif //not d7 changes +// listen(32, p2config->dlep_tcp_sockfd); + + + return; +} + + +void +dlep_tcp_connect (dlep_config_t *p2config, + dlep_context_peer_t *p2peer, + void *msg, + uint32_t length) +{ + int status; + + if (!p2config) { + return; + } + + + memset(&p2peer->msg_addr, 0, sizeof(struct sockaddr_in)); + + p2peer->msg_addr.sin_family = AF_INET; + + p2peer->msg_addr.sin_port = htons(p2peer->peer_tcp_port); + + //p2peer->msg_addr.sin_addr.s_addr = htonl(p2peer->peer_ipv4.v4_addr.v4_addr32); + p2peer->msg_addr.sin_addr.s_addr = p2peer->peer_ipv4.v4_addr.v4_addr32; + + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Connecting the TCP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + + status = connect(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2peer->msg_addr, + sizeof(struct sockaddr_in)); + if (status < 0) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: not able to connect to TCP " + "socket to port %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_tcp_port); + } +// exit (0); + printf("\n Do Manual start once server ready "); + } + + + +// listen(32, p2config->dlep_sockfd); + return; +} + + +/** + * NAME + * dlep_udp_receive + * + * SYNOPSIS + * int + * dlep_udp_receive(dlep_config_t *p2config, + * struct sockaddr_in *rcvd_msg_addr, + * socklen_t *rcvd_msg_socket_length, + * void *msg, + * uint32_t length) + * + * DESCRIPTION + * This function is used to receive a UDP message. + * This is a blocking call. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * rcvd_msg_addr - pointer to the receive socket data + * + * rcvd_socket_length - pointer to the receive socket length + * + * msg - pointer to the message buffer to receive the data + * + * length - Maximum number of bytes to receive, that + * the buffer can hold. + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * number of bytes read + * <= 0 error condition + * + */ +int +dlep_udp_receive (dlep_config_t *p2config, + struct sockaddr_in *rcvd_msg_addr, + socklen_t *rcvd_socket_length, + void *msg, + uint32_t length) +{ + int num_bytes; + + if (!p2config) { + return (0); + } + + if (!msg) { + return (0); + } + + if (length < MSG_MIN_LEN || length > MSG_MAX_LEN) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: msg length invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (0); + } + + /* + * Since we use the sig_alarm, we must handle + * interrupting the recv_from. + */ + *rcvd_socket_length = sizeof(struct sockaddr); + num_bytes = -1; + while (num_bytes < 0) { + num_bytes = recvfrom(p2config->dlep_udp_sockfd, + msg, + length, + MSG_WAITALL, + (struct sockaddr *)rcvd_msg_addr, + rcvd_socket_length); + + if (num_bytes < 0) { + if (errno == EINTR) { + continue; + } + + perror("recvfrom: udp failed "); + memset(msg, 0 , 128); + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: recv_from error = %d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + num_bytes); + } + + } else { + rcvd_msg_addr->sin_port = htons(rcvd_msg_addr->sin_port); + + p2config->client_udp.sin_port = htons(rcvd_msg_addr->sin_port); + p2config->client_udp.sin_addr = rcvd_msg_addr->sin_addr; + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Received from !!!!!!%s at port %u %u bytes \n", + DEBUG_FUNCTION, + DEBUG_LINE, + //inet_ntoa(rcvd_msg_addr->sin_addr), + inet_ntoa(p2config->client_udp.sin_addr), + //rcvd_msg_addr->sin_port, + htons(p2config->client_udp.sin_port), + num_bytes); + } + break; + } + } + + return (num_bytes); +} + + + + +/** + * NAME + * dlep_tcp_receive + * + * SYNOPSIS + * int + * dlep_tcp_receive(dlep_config_t *p2config, + * struct sockaddr_in *rcvd_msg_addr, + * socklen_t *rcvd_msg_socket_length, + * void *msg, + * uint32_t length) + * + * DESCRIPTION + * This function is used to receive a TCP message. + * This is a blocking call. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * rcvd_msg_addr - pointer to the receive socket data + * + * rcvd_socket_length - pointer to the receive socket length + * + * msg - pointer to the message buffer to receive the data + * + * length - Maximum number of bytes to receive, that + * the buffer can hold. + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * number of bytes read + * <= 0 error condition + * + */ +int +dlep_tcp_receive (dlep_config_t *p2config, + struct sockaddr_in *rcvd_msg_addr, + socklen_t *rcvd_socket_length, + void *msg, + uint32_t length) +{ + int num_bytes; + //static int count; + int bytes_read ,bytes_left, fd; + unsigned short msg_len = 0; + char msg_hdr[4]; + char *buf_ptr; + + bytes_read = bytes_left = 0; + buf_ptr = msg_hdr; + + if (!p2config) { + + printf("\n INNN config"); + return (0); + } + fd = p2config->dlep_tcp_client_sockfd; + + + if (!msg) { + return (0); + } + + if (length < MSG_MIN_LEN || length > MSG_MAX_LEN) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: msg length invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (0); + } + + /* + * Since we use the sig_alarm, we must handle + * interrupting the recv_from. + */ + //*rcvd_socket_length = sizeof(struct sockaddr); + //num_bytes = -1; +#if 0 + while (num_bytes < 0) { + num_bytes = recvfrom(p2config->dlep_tcp_client_sockfd, + msg, + length, + MSG_WAITALL, + (struct sockaddr *)rcvd_msg_addr, + rcvd_socket_length); + + if (num_bytes < 0) { + if (errno == EINTR) { + continue; + } + count++; + if (count < 6) + perror("recvfrom: tcp failed "); + memset(msg, 0 , 128); + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: recv_from error = %d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + num_bytes); + } + + } else { + // rcvd_msg_addr->sin_port = htons(rcvd_msg_addr->sin_port); + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Received from %s at port %u %u bytes \n", + DEBUG_FUNCTION, + DEBUG_LINE, + inet_ntoa(rcvd_msg_addr->sin_addr), + rcvd_msg_addr->sin_port, + num_bytes); + } + break; + } + } +#endif +#define MSG_HDR_SIZE 4 + bytes_read = recv(fd, msg_hdr, MSG_HDR_SIZE, MSG_PEEK); + /* fall through case where bytes_read == MSG_HDR_SIZE */ + buf_ptr++; + buf_ptr++; + +#define GETSHORT(ptr) ((unsigned char *)ptr)[0] << 8 | ((unsigned char *)ptr)[1] +// #define GETSHORT(ptr) (*((unsigned short *) (ptr))) + msg_len = GETSHORT(buf_ptr); + + /* Read the full message */ + msg_len += MSG_HDR_SIZE; + bytes_left = msg_len; + + + while (bytes_left > 0) { + bytes_read = recv(fd, msg, bytes_left, 0); + if (bytes_read == 0) { + close(p2config->dlep_tcp_client_sockfd); + TCP_CLIENT_READY = 0; + } +/* + uint8_t *ptr = msg; + int len = bytes_read; + for(;len!=0; --len) { + printf("%x",*ptr); + } +*/ + if(bytes_read < 0) { + return (-1); + } + + //*length += bytes_read; + msg += bytes_read; + bytes_left -= bytes_read; + } + num_bytes = msg_len - bytes_left; + +// return (MANET_INFRA_SUCCESS); + return (num_bytes); +} + + + + +/** + * NAME + * dlep_udp_send + * + * SYNOPSIS + * void + * dlep_send(dlep_config_t *p2config, + * dlep_context_peer_t *p2peer, + * void *msg, + * uint32_t length) + * + * DESCRIPTION + * This function is used to send a UDP mesage. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * p2peer - pointer to the peer context + * + * msg - Pointer to the message to be sent + * + * length - Number of bytes in mesage to send + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * None. + * + */ +void +dlep_send (dlep_config_t *p2config, + dlep_context_peer_t *p2peer, + void *msg, + uint32_t length) +{ + int send_bytes; + + if (!p2peer) { + return; + } + + if (!msg) { + return; + } + +// perror("send: udp "); + + memset(&p2peer->msg_addr, 0, sizeof(struct sockaddr_in)); + + p2peer->msg_addr.sin_family = AF_INET; +// Debug + + p2peer->msg_addr.sin_port = htons(p2peer->peer_udp_port); + + //p2peer->msg_addr.sin_addr.s_addr = htonl(p2peer->peer_ipv4.v4_addr.v4_addr32); + p2peer->msg_addr.sin_addr.s_addr = p2peer->peer_ipv4.v4_addr.v4_addr32; + + send_bytes = sendto(p2config->dlep_udp_sockfd, + msg, + length, + 0, + //(struct sockaddr *)&p2peer->msg_addr, + (struct sockaddr *)&p2config->client_udp, + sizeof(struct sockaddr_in)); + if (send_bytes < 0) { + perror("sendto: udp failed "); + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u send to %s at " + "port %d bytes=%d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + inet_ntoa(p2peer->msg_addr.sin_addr), + p2peer->peer_udp_port, + send_bytes); + } + } else { + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sent iiiii to %s at " + "port %d bytes=%d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + //inet_ntoa(p2peer->msg_addr.sin_addr), + inet_ntoa(p2config->client_udp.sin_addr), + //p2peer->peer_udp_port, + htons(p2config->client_udp.sin_port), + send_bytes); + } + } + + return; +} + + + + +void +dlep_tcp_send (dlep_config_t *p2config, + dlep_context_peer_t *p2peer, + void *msg, + uint32_t length) +{ + int send_bytes; + uint32_t ttl=255; + + if (!p2peer) { + return; + } + + if (!msg) { + return; + } + + + //perror("send: tcp "); + memset(&p2peer->msg_addr, 0, sizeof(struct sockaddr_in)); + + p2peer->msg_addr.sin_family = AF_INET; + + p2peer->msg_addr.sin_port = htons(p2peer->peer_tcp_port); + + //p2peer->msg_addr.sin_addr.s_addr = htonl(p2peer->peer_ipv4.v4_addr.v4_addr32); + p2peer->msg_addr.sin_addr.s_addr = p2peer->peer_ipv4.v4_addr.v4_addr32; + if (p2peer->ttl) { + if(setsockopt(p2config->dlep_tcp_client_sockfd, IPPROTO_IP, IP_TTL, + (char *)&p2peer->ttl, sizeof(p2peer->ttl)) < 0) { + // perror("setsockopt failed 1"); + close(p2config->dlep_tcp_client_sockfd); + exit(1); + } + } + + send_bytes = sendto(p2config->dlep_tcp_client_sockfd, + msg, + length, + 0, + // (struct sockaddr *)&p2peer->msg_addr, + (struct sockaddr *)&p2config->client, + sizeof(struct sockaddr_in)); + if (send_bytes < 0) { + perror("sendto: tcp failed "); + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u send to %s at " + "port %d bytes=%d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + inet_ntoa(p2peer->msg_addr.sin_addr), + p2peer->peer_tcp_port, + send_bytes); + } + } else { + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sent to %s at " + "port %d bytes=%d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + // inet_ntoa(p2peer->msg_addr.sin_addr), + inet_ntoa(p2config->client.sin_addr), + // p2peer->peer_tcp_port, + htons(p2config->client.sin_port), + send_bytes); + } + } + if (p2peer->ttl) { + p2peer->ttl = 0; + if(setsockopt(p2config->dlep_tcp_client_sockfd, IPPROTO_IP, IP_TTL, + (char *)&ttl, sizeof(ttl)) < 0) { + // perror("setsockopt failed 2"); + close(p2config->dlep_tcp_client_sockfd); + exit(1); + } + } + + return; +} diff --git a/dlep_radio_ipv4/dlep_porter.h b/dlep_radio_ipv4/dlep_porter.h new file mode 100644 index 0000000..8a3180a --- /dev/null +++ b/dlep_radio_ipv4/dlep_porter.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------- + * dlep_porter.h -- APIs for UDP socket use + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_PORTER_H__ +#define __DLEP_PORTER_H__ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "safe_types.h" +#include "dlep_config.h" + +#include "dlep_context_peer.h" + + +extern void +dlep_porter_init(dlep_config_t *p2config); + + +extern void +dlep_porter_open(dlep_config_t *p2config); + +extern void +dlep_tcp_porter_open(dlep_config_t *p2config); + + +extern void +dlep_tcp_open(dlep_config_t *p2config); + + +extern void +dlep_tcp_connect(dlep_config_t *p2config, + dlep_context_peer_t *p2ctx, + void *msg, + uint32_t length); + + +extern int +dlep_udp_receive(dlep_config_t *p2config, + struct sockaddr_in *rcvd_msg_addr, + socklen_t *rcvd_msg_socket_length, + void *msg, + uint32_t length); + +extern int +dlep_tcp_receive(dlep_config_t *p2config, + struct sockaddr_in *rcvd_msg_addr, + socklen_t *rcvd_msg_socket_length, + void *msg, + uint32_t length); + + +extern void +dlep_send(dlep_config_t *p2config, + dlep_context_peer_t *p2ctx, + void *msg, + uint32_t length); + +extern void +dlep_tcp_send(dlep_config_t *p2config, + dlep_context_peer_t *p2ctx, + void *msg, + uint32_t length); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_radio b/dlep_radio_ipv4/dlep_radio new file mode 100644 index 0000000..6c90125 Binary files /dev/null and b/dlep_radio_ipv4/dlep_radio differ diff --git a/dlep_radio_ipv4/dlep_radio_sub b/dlep_radio_ipv4/dlep_radio_sub new file mode 100644 index 0000000..6bd24d6 Binary files /dev/null and b/dlep_radio_ipv4/dlep_radio_sub differ diff --git a/dlep_radio_ipv4/dlep_server_neighbor_fsm.h b/dlep_radio_ipv4/dlep_server_neighbor_fsm.h new file mode 100644 index 0000000..a0faed7 --- /dev/null +++ b/dlep_radio_ipv4/dlep_server_neighbor_fsm.h @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------- + * dlep_server_neighbor_fsm.h -- server neighbor state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_SERVER_SESSION_FSM_H__ +#define __DLEP_SERVER_SESSION_FSM_H__ + +#include "safe_types.h" +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" + + +/* + * normalized server events for neighbors + */ +typedef enum { + neighbor_init_e = 0, + neighbor_update_metrics_e, + neighbor_update_addr_req_e, + neighbor_term_user_req_e, + neighbor_term_e, + neighbor_term_ack_e, + neighbor_down_ack_tmo_e, + neighbor_link_char_res_e, +} dlep_server_neighbor_events_e; + + +/* + * normalized server states + */ +typedef enum { + neighbor_initializing_s = 0, + neighbor_update_s, + neighbor_terminating_s, +} dlep_server_neighbor_states_e; + + + + +extern uint32_t +dlep_server_neighbor_fsm_get_state( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_server_neighbor_fsm_show_counter( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_server_neighbor_fsm_show_state_table( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_server_neighbor_fsm_show_history( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_server_neighbor_fsm_engine(uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_neighbor_fsm_destroy(dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_neighbor_fsm_create(dlep_context_neighbor_t *p2neighbor); + + +#endif + diff --git a/dlep_radio_ipv4/dlep_sim_options.h b/dlep_radio_ipv4/dlep_sim_options.h new file mode 100644 index 0000000..4d6cf73 --- /dev/null +++ b/dlep_radio_ipv4/dlep_sim_options.h @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------- + * dlep_sim_options.h -- Sim build options + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_SIM_OPTIONS_H__ +#define __DLEP_SIM_OPTIONS_H__ + +/* + * This file defines several build #defines that can be used to + * change the behavior of the simulator code for testing, etc. + */ + + +/** + ** Enable the definition of this macro to pack multiple + ** peer messages in a packet. + ** + ** #define MULTIPLE_PEER_MESSAGES_PACKED ( 1 ) + **/ +// #define MULTIPLE_PEER_MESSAGES_PACKED ( 1 ) + + +/** + ** Enable the definition of this macro to pack multiple + ** neighbor messages in a packet. + ** + ** #define MULTIPLE_NEIGHBOR_MESSAGES_PACKED ( 1 ) + **/ +//#define MULTIPLE_NEIGHBOR_MESSAGES_PACKED ( 1 ) + + +/** + ** Enable the insertion of the experimental TLVs for testing + ** + ** #define EXPERIMENTAL_TLVS ( 1 ) + **/ +// #define EXPERIMENTAL_TLVS ( 1 ) + + +/* + * defintion of this macro will enable dynamic + * metrics during periodic updates for testing. + * + * #define DYNAMIC_METRICS_ENABLED + */ +//#define DYNAMIC_METRICS_ENABLED + + + + +#endif + diff --git a/dlep_radio_ipv4/dlep_source_cli.c b/dlep_radio_ipv4/dlep_source_cli.c new file mode 100644 index 0000000..fb745a1 --- /dev/null +++ b/dlep_radio_ipv4/dlep_source_cli.c @@ -0,0 +1,143 @@ +/*------------------------------------------------------------------ + * dlep_source_cli.c -- source CLI commands + * + * October 2011, Bo Berry + * + * Copyright (c) 2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#include "cli.h" + +#include "dlep_source_cli.h" +//SENDIL +#include "sim_dlep_radio_cli.h" + + + +/* + * directory record + */ +cli_record_t cli_source_dir; + + +/* + * allocate command records + */ +static cli_record_t source_command_cmd; + + + +/** + ** source commands + **/ + +static void +source_commands (uint32_t argc, char *argv[]) +{ + FILE *fp; + +#define MAX_INPUT_LENGTH ( 512 ) + char input_string[MAX_INPUT_LENGTH]; + + + if (argv[1] && *argv[1] == '?') { + printf("source_commands - source commands from the file\n"); + printf("\n"); + printf(" - the file that contains commands being sourced \n"); + printf("\n"); + return; + } + + printf("sourcing file %s \n", argv[1]); + + fp = fopen(argv[1], "r"); + if (!fp) { + printf("Error: problem opening source file: %s\n", + argv[1]); + return; + } + + while (fgets(input_string, MAX_INPUT_LENGTH, fp)) { + if (input_string[0] == '\0') { + continue; + } else if (input_string[0] == '#') { + continue; + } + + dlep_cli_engine(input_string); + } + + return; +} + + + +/** + * NAME + * dlep_source_cli_init + * + * SYNOPSIS + * void + * dlep_source_cli_init() + * + * DESCRIPTION + * Registers the dlep source command with the cli + * facility. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_source_cli_init (void) +{ + RC_CLI_t rc; + + /* + * Create directory and commands + */ + rc = cli_mkdir("source", NULL, &cli_source_dir); + + + rc = cli_mkcmd("source_commands", + source_commands, + &cli_source_dir, + &source_command_cmd); + + return; +} + diff --git a/dlep_radio_ipv4/dlep_source_cli.h b/dlep_radio_ipv4/dlep_source_cli.h new file mode 100644 index 0000000..99bf642 --- /dev/null +++ b/dlep_radio_ipv4/dlep_source_cli.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------- + * dlep_source_cli.h -- source cli commands + * + * August 2011, Bo Berry + * + * Copyright (c) 2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_SOURCE_CLI_H__ +#define __DLEP_SOURCE_CLI_H__ + + +extern void +dlep_source_cli_init(void); + +#endif + diff --git a/dlep_radio_ipv4/dlep_tcp_sockfd b/dlep_radio_ipv4/dlep_tcp_sockfd new file mode 100644 index 0000000..18605ff --- /dev/null +++ b/dlep_radio_ipv4/dlep_tcp_sockfd @@ -0,0 +1,259 @@ +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: close(p2config->dlep_udp_sockfd); +dlep_client_peer_event_handlers.c: close(p2config->dlep_tcp_sockfd); +dlep_client_peer_event_handlers.c: if (p2config->start_on_discovery) { +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: close(p2config->dlep_udp_sockfd); +dlep_client_peer_event_handlers.c: close(p2config->dlep_tcp_sockfd); +dlep_client_peer_event_handlers.c: if (p2config->start_on_discovery) { +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: close(p2config->dlep_udp_sockfd); +dlep_client_peer_event_handlers.c: close(p2config->dlep_tcp_sockfd); +dlep_client_peer_event_handlers.c: if (p2config->start_on_discovery) { +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: close(p2config->dlep_udp_sockfd); +dlep_client_peer_event_handlers.c: close(p2config->dlep_tcp_sockfd); +dlep_client_peer_event_handlers.c: if (p2config->start_on_discovery) { +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_client_peer_event_handlers.c: secs_to_milliseconds(p2config->peer_offer_interval), +dlep_config.c: strcpy(p2config->filename, "dlep_sim.cfg"); +dlep_config.c: strcpy(p2config->sim_name, "dlep"); +dlep_config.c: p2config->local_udp_port = 0; +dlep_config.c: p2config->local_tcp_port = 0; +dlep_config.c: p2config->local_ipv4_dot[0] = '\0'; +dlep_config.c: ipv4_zero_address(&p2config->local_ipv4); +dlep_config.c: p2config->router_udp_port = 0; +dlep_config.c: p2config->router_tcp_port = 0; +dlep_config.c: p2config->router_ipv4_dot[0] = '\0'; +dlep_config.c: ipv4_zero_address(&p2config->router_ipv4); +dlep_config.c: p2config->start_on_launch = TRUE; +dlep_config.c: strcpy(p2config->local_type_description, "no type description"); +dlep_config.c: p2config->local_id = 0; +dlep_config.c: p2config->peer_offer_interval = +dlep_config.c: p2config->peer_heartbeat_interval = +dlep_config.c: p2config->peer_heartbeat_missed_threshold = +dlep_config.c: p2config->peer_term_ack_tmo = +dlep_config.c: p2config->peer_term_missed_ack_threshold = +dlep_config.c: p2config->neighbor_up_ack_tmo = +dlep_config.c: p2config->neighbor_up_missed_ack_threshold = +dlep_config.c: p2config->neighbor_update_interval_tmo = +dlep_config.c: p2config->neighbor_activity_timer = +dlep_config.c: p2config->neighbor_down_ack_tmo = +dlep_config.c: p2config->neighbor_down_missed_ack_threshold = +dlep_config.c: p2config->sim_name, +dlep_config.c: p2config->filename); +dlep_config.c: p2config->local_udp_port); +dlep_config.c: p2config->local_tcp_port); +dlep_config.c: p2config->local_ipv4_dot); +dlep_config.c: if (p2config->router_udp_port) { +dlep_config.c: p2config->router_udp_port); +dlep_config.c: if (p2config->router_tcp_port) { +dlep_config.c: p2config->router_tcp_port); +dlep_config.c: if (p2config->router_udp_port && p2config->router_tcp_port) { +dlep_config.c: p2config->router_ipv4_dot); +dlep_config.c: p2config->local_type_description); +dlep_config.c: p2config->local_id); +dlep_config.c: p2config->peer_offer_interval); +dlep_config.c: p2config->peer_heartbeat_interval); +dlep_config.c: p2config->peer_heartbeat_missed_threshold); +dlep_config.c: p2config->peer_term_ack_tmo); +dlep_config.c: p2config->peer_term_missed_ack_threshold); +dlep_config.c: p2config->neighbor_up_ack_tmo); +dlep_config.c: p2config->neighbor_up_missed_ack_threshold); +dlep_config.c: p2config->neighbor_update_interval_tmo); +dlep_config.c: p2config->neighbor_activity_timer); +dlep_config.c: p2config->neighbor_down_ack_tmo); +dlep_config.c: p2config->neighbor_down_missed_ack_threshold); +dlep_config.c: fp = fopen(p2config->filename, "r"); +dlep_config.c: p2config->filename); +dlep_config.c: strncpy(p2config->sim_name, argv[1], DLEP_SIM_NAME_LEN); +dlep_config.c: p2config->start_on_launch = FALSE; +dlep_config.c: p2config->start_on_discovery = TRUE; +dlep_config.c: p2config->local_udp_port = strtoul(argv[1], NULL, 10); +dlep_config.c: p2config->local_tcp_port = strtoul(argv[1], NULL, 10); +dlep_config.c: strcpy(p2config->local_ipv4_dot, argv[1]); +dlep_config.c: ipv4_dot_decimal2digits(&p2config->local_ipv4, argv[1]); +dlep_config.c: p2config->router_udp_port = strtoul(argv[1], NULL, 10); +dlep_config.c: p2config->router_tcp_port = strtoul(argv[1], NULL, 10); +dlep_config.c: strcpy(p2config->router_ipv4_dot, argv[1]); +dlep_config.c: ipv4_dot_decimal2digits(&p2config->router_ipv4, argv[1]); +dlep_config.c: p2config->router_ipv4.v4_addr.v4_addr32 = +dlep_config.c: htonl(p2config->router_ipv4.v4_addr.v4_addr32); +dlep_config.c: strncpy(p2config->local_type_description, +dlep_config.c: p2config->local_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH] = '\0'; +dlep_config.c: p2config->local_id = temp; +dlep_config.c: p2config->peer_heartbeat_interval = strtoul(argv[1], NULL, 10); +dlep_config.c: if (p2config->peer_heartbeat_interval < +dlep_config.c: p2config->peer_heartbeat_interval = +dlep_config.c: if (p2config->peer_heartbeat_interval > +dlep_config.c: p2config->peer_heartbeat_interval = +dlep_config.c: p2config->peer_heartbeat_missed_threshold = +dlep_config.c: if (p2config->peer_heartbeat_missed_threshold < +dlep_config.c: p2config->peer_heartbeat_missed_threshold = +dlep_config.c: if (p2config->peer_heartbeat_missed_threshold > +dlep_config.c: p2config->peer_heartbeat_missed_threshold = +dlep_config.c: p2config->peer_term_ack_tmo = strtoul(argv[1], NULL, 10); +dlep_config.c: if (p2config->peer_term_ack_tmo < +dlep_config.c: p2config->peer_term_ack_tmo = +dlep_config.c: if (p2config->peer_term_ack_tmo > +dlep_config.c: p2config->peer_term_ack_tmo = +dlep_config.c: p2config->peer_term_missed_ack_threshold = +dlep_config.c: if (p2config->peer_term_missed_ack_threshold < +dlep_config.c: p2config->peer_term_missed_ack_threshold = +dlep_config.c: if (p2config->peer_term_missed_ack_threshold > +dlep_config.c: p2config->peer_term_missed_ack_threshold = +dlep_config.c: p2config->neighbor_up_ack_tmo = strtoul(argv[1], NULL, 10); +dlep_config.c: if (p2config->neighbor_up_ack_tmo < +dlep_config.c: p2config->neighbor_up_ack_tmo = +dlep_config.c: if (p2config->neighbor_up_ack_tmo > +dlep_config.c: p2config->neighbor_up_ack_tmo = +dlep_config.c: p2config->neighbor_up_missed_ack_threshold = +dlep_config.c: if (p2config->neighbor_up_missed_ack_threshold < +dlep_config.c: p2config->neighbor_up_missed_ack_threshold = +dlep_config.c: if (p2config->neighbor_up_missed_ack_threshold > +dlep_config.c: p2config->neighbor_up_missed_ack_threshold = +dlep_config.c: p2config->neighbor_update_interval_tmo = +dlep_config.c: if (p2config->neighbor_update_interval_tmo > 0) { +dlep_config.c: if (p2config->neighbor_update_interval_tmo < +dlep_config.c: p2config->neighbor_update_interval_tmo = +dlep_config.c: if (p2config->neighbor_update_interval_tmo > +dlep_config.c: p2config->neighbor_update_interval_tmo = +dlep_config.c: p2config->neighbor_activity_timer = strtoul(argv[1], NULL, 10); +dlep_config.c: if (!p2config->neighbor_activity_timer) { +dlep_config.c: if (p2config->neighbor_activity_timer < +dlep_config.c: p2config->neighbor_activity_timer = +dlep_config.c: if (p2config->neighbor_activity_timer > +dlep_config.c: p2config->neighbor_activity_timer = +dlep_config.c: p2config->neighbor_down_ack_tmo = strtoul(argv[1], NULL, 10); +dlep_config.c: if (p2config->neighbor_down_ack_tmo < +dlep_config.c: p2config->neighbor_down_ack_tmo = +dlep_config.c: if (p2config->neighbor_down_ack_tmo > +dlep_config.c: p2config->neighbor_down_ack_tmo = +dlep_config.c: p2config->neighbor_down_missed_ack_threshold = +dlep_config.c: if (p2config->neighbor_down_missed_ack_threshold < +dlep_config.c: p2config->neighbor_down_missed_ack_threshold = +dlep_config.c: if (p2config->neighbor_down_missed_ack_threshold > +dlep_config.c: p2config->neighbor_down_missed_ack_threshold = +dlep_context_peer.c: p2config->peer_term_ack_tmo; +dlep_context_peer.c: p2config->peer_term_missed_ack_threshold; +dlep_context_peer.c: p2config->peer_heartbeat_interval; +dlep_context_peer.c: p2config->peer_heartbeat_missed_threshold; +dlep_context_peer.c: p2config->neighbor_up_ack_tmo; +dlep_context_peer.c: p2config->neighbor_up_missed_ack_threshold; +dlep_context_peer.c: p2config->neighbor_update_interval_tmo; +dlep_context_peer.c: p2config->neighbor_activity_timer; +dlep_context_peer.c: p2config->neighbor_down_ack_tmo; +dlep_context_peer.c: p2config->neighbor_down_missed_ack_threshold; +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: rfc5444_peer_tlv(p2es, p2config->local_type_description); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: rfc5444_peer_tlv(p2es, p2config->local_type_description); +dlep_message_builder.c: rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); +dlep_message_builder.c: rfc5444_peer_tlv(p2es, p2config->local_type_description); +dlep_message_builder.c: rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); +dlep_message_builder.c: rfc5444_peer_tlv(p2es, p2config->local_type_description); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_message_builder.c: p2config->peer_heartbeat_interval); +dlep_porter.c: p2config->dlep_tcp_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); +dlep_porter.c:// fcntl(p2config->dlep_tcp_sockfd, F_SETFL, O_NONBLOCK); +dlep_porter.c: memset(&p2config->dlep_addr, 0, sizeof(struct sockaddr_in)); +dlep_porter.c: p2config->dlep_addr.sin_family = AF_INET; +dlep_porter.c: p2config->dlep_addr.sin_port = htons(p2config->local_tcp_port); +dlep_porter.c: p2config->dlep_addr.sin_addr.s_addr = INADDR_ANY; +dlep_porter.c: status = bind(p2config->dlep_tcp_sockfd, +dlep_porter.c: (struct sockaddr *)&p2config->dlep_addr, +dlep_porter.c: p2config->local_tcp_port); +dlep_porter.c: status = listen(p2config->dlep_tcp_sockfd,5); +dlep_porter.c: p2config->client_lenght = sizeof(p2config->client); +dlep_porter.c: p2config->dlep_tcp_client_sockfd= accept(p2config->dlep_tcp_sockfd, +dlep_porter.c: (struct sockaddr *)&p2config->client, &p2config->client_lenght); +dlep_porter.c: if (p2config->dlep_tcp_client_sockfd < 0) { +dlep_porter.c: printf(" dlep_tcp_sockfd after accept =%d",p2config->dlep_tcp_client_sockfd); +dlep_porter.c:// if (p2config->start_on_discovery) { +dlep_porter.c: p2config->dlep_udp_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); +dlep_porter.c: if (p2config->dlep_udp_sockfd < 0) { +dlep_porter.c: memset(&p2config->dlep_addr, 0, sizeof(struct sockaddr_in)); +dlep_porter.c: p2config->dlep_addr.sin_family = AF_INET; +dlep_porter.c: p2config->dlep_addr.sin_port = htons(p2config->local_udp_port); +dlep_porter.c: p2config->dlep_addr.sin_addr.s_addr = htonl(INADDR_ANY); +dlep_porter.c: status = bind(p2config->dlep_udp_sockfd, +dlep_porter.c: (struct sockaddr *)&p2config->dlep_addr, +dlep_porter.c: p2config->local_udp_port); +dlep_porter.c:// listen(32, p2config->dlep_udp_sockfd); +dlep_porter.c: p2config->dlep_tcp_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); +dlep_porter.c:// fcntl(p2config->dlep_tcp_sockfd, F_SETFL, O_NONBLOCK); +dlep_porter.c: if (p2config->dlep_tcp_sockfd < 0) { +dlep_porter.c: memset(&p2config->dlep_addr, 0, sizeof(struct sockaddr_in)); +dlep_porter.c: p2config->dlep_addr.sin_family = AF_INET; +dlep_porter.c: p2config->dlep_addr.sin_port = htons(p2config->local_tcp_port); +dlep_porter.c: p2config->dlep_addr.sin_addr.s_addr = htonl(INADDR_ANY); +dlep_porter.c: status = bind(p2config->dlep_tcp_sockfd, +dlep_porter.c: (struct sockaddr *)&p2config->dlep_addr, +dlep_porter.c: p2config->local_tcp_port); +dlep_porter.c: listen(32, p2config->dlep_tcp_sockfd); +dlep_porter.c: status = connect(p2config->dlep_tcp_sockfd, +dlep_porter.c:// listen(32, p2config->dlep_sockfd); +dlep_porter.c: num_bytes = recvfrom(p2config->dlep_udp_sockfd, +dlep_porter.c: num_bytes = recvfrom(p2config->dlep_tcp_sockfd, +dlep_porter.c: send_bytes = sendto(p2config->dlep_udp_sockfd, +dlep_porter.c: send_bytes = sendto(p2config->dlep_tcp_sockfd, +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: rfc5444_peer_tlv(p2es, p2config->local_type_description); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: rfc5444_peer_tlv(p2es, p2config->local_type_description); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: rfc5444_peer_tlv(p2es, p2config->local_type_description); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +fuzz_message_builder.c: p2config->peer_heartbeat_interval); +sim_dlep_radio.c: strcpy(p2config->filename, args); +sim_dlep_radio.c: printf(" Config file = %s \n", p2config->filename); +sim_dlep_radio.c: p2peer = dlep_peer_allocate(&p2config->local_ipv4, +sim_dlep_radio.c: p2config->local_udp_port, +sim_dlep_radio.c: p2config->local_tcp_port); +sim_dlep_radio.c: p2peer->peer_udp_port = p2config->router_udp_port; +sim_dlep_radio.c:// if (!p2config->start_on_discovery) { +sim_dlep_radio.c: p2peer->peer_tcp_port = p2config->router_tcp_port; +sim_dlep_radio.c: p2config->router_ipv4.v4_addr.v4_addr32; +sim_dlep_radio.c: p2peer->client_id = p2config->local_id; +sim_dlep_radio.c: if (p2config->start_on_launch) { +sim_dlep_radio.c: if (p2config->start_on_discovery) { +sim_dlep_radio.c: cli_set_prompt(p2config->sim_name); +sim_dlep_radio.c: FD_SET(p2config->dlep_udp_sockfd, &readfds); +sim_dlep_radio.c: FD_SET(p2config->dlep_tcp_sockfd, &readfds); +sim_dlep_radio.c:// highsock = p2config->dlep_udp_sockfd + 1; +sim_dlep_radio.c: highsock = p2config->dlep_tcp_sockfd + 1; +sim_dlep_radio.c:// printf("\n UDP sock %d, TCP sock %d",p2config->dlep_udp_sockfd,p2config->dlep_tcp_sockfd); +sim_dlep_radio.c: if (FD_ISSET(p2config->dlep_udp_sockfd, &readfds)) { +sim_dlep_radio.c: if (FD_ISSET(p2config->dlep_tcp_sockfd, &readfds)&& TCP_READY) { +sim_dlep_radio.c: printf(" INSIDE tcp socket set tsock %d",p2config->dlep_tcp_sockfd); +sim_dlep_radio_cli.c:/* if (p2config->start_on_discovery) { diff --git a/dlep_radio_ipv4/fsm.c b/dlep_radio_ipv4/fsm.c new file mode 100644 index 0000000..a26961a --- /dev/null +++ b/dlep_radio_ipv4/fsm.c @@ -0,0 +1,788 @@ +/*------------------------------------------------------------------ + * fsm.c -- Finite State Machine + * + * February 2005, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "fsm.h" + + +/* + * These are the maximum states and events that fsm uses + * for sizing during create. + */ +#define FSM_MAX_STATES ( 64 ) +#define FSM_MAX_EVENTS ( 64 ) + + + +/** + * NAME + * fsm_display_table + * + * SYNOPSIS + * #include "fsm.h" + * void + * fsm_display_table(fsm_t *fsm) + * + * DESCRIPTION + * Displays the designated state machine table to console. + * + * INPUT PARAMETERS + * fsm - handle to fsm + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +fsm_display_table (fsm_t *fsm) +{ + uint32_t i; + uint32_t j; + state_tuple_t *state_ptr; + event_tuple_t *event_ptr; + + state_description_t *p2state_description; + event_description_t *p2event_description; + + if (fsm == NULL) { + return; + } + + if (fsm->tag != FSM_TAG) { + return; + } + + p2state_description = fsm->state_description_table; + p2event_description = fsm->event_description_table; + + printf("\nFSM: %s \n", fsm->fsm_name); + printf(" number_states = %d\n", fsm->number_states); + printf(" number_events = %d\n", fsm->number_events); + printf(" curr_state = %s\n", + p2state_description[fsm->curr_state].description ); + printf("\n"); + + /* + * For the normalized state table, list the normalized + * events and state transitions. + */ + for (i=0; inumber_states; i++) { + + state_ptr = &fsm->state_table[i]; + + printf(" State: %s \n", + p2state_description[state_ptr->state_id].description); + printf(" Event / Next State \n"); + printf("----------------------------\n"); + + for (j=0; jnumber_events; j++) { + + event_ptr = &state_ptr->p2event_tuple[j]; + + /* + * Display the name of the state associated with the next state. + */ + printf(" %u-%s / %s \n", + j, + p2event_description[j].description, + p2state_description[event_ptr->next_state].description); + } + printf("\n"); + } + printf("\n"); + return; +} + + +/** + * NAME + * fsm_show_history + * + * SYNOPSIS + * #include "fsm.h' + * void + * fsm_show_history(fsm_t *fsm) + * + * DESCRIPTION + * Displays history of the state transitions. + * + * INPUT PARAMETERS + * *fsm - handle of the state machine + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +fsm_show_history (fsm_t *fsm) +{ + uint32_t i, j; + fsm_history_t *history_ptr; + + state_description_t *p2state_description; + event_description_t *p2event_description; + + if (fsm == NULL) { + return; + } + + if (fsm->tag != FSM_TAG) { + return; + } + + p2state_description = fsm->state_description_table; + p2event_description = fsm->event_description_table; + + printf("\nFSM: %s History \n", fsm->fsm_name); + printf("Current State / Event / New State / rc \n"); + printf("------------------------------------------------\n"); + + j = fsm->history_index; + for (i=0; ihistory[i]; + + if (history_ptr->stateID == FSM_NULL_STATE_ID) { + continue; + } + + printf(" %u-%s / %u-%s / %u-%s / %u\n", + history_ptr->prevStateID, + p2state_description[history_ptr->prevStateID].description, + history_ptr->eventID, + p2event_description[history_ptr->eventID].description, + history_ptr->stateID, + p2state_description[history_ptr->stateID].description, + history_ptr->handler_rc); + + if (j==0) { + j=FSM_HISTORY; + } + j--; + } + + printf("\n"); + return; +} + + +/** + * NAME + * fsm_get_state + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_get_state(fsm_t *fsm, uint32_t*p2state) + * + * DESCRIPTION + * Function to return the current state. + * + * INPUT PARAMETERS + * *fsm - state machine handle + * + * p2state - Pointer to a state variable to be updated. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_get_state (fsm_t *fsm, uint32_t *p2state) +{ + if (fsm == NULL) { + return (RC_FSM_NULL); + } + + if (fsm->tag != FSM_TAG) { + return (RC_FSM_INVALID_HANDLE); + } + + *p2state = fsm->curr_state; + return (RC_FSM_OK); +} + + +/** + * NAME + * fsm_set_exception_state + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_set_exception_state(fsm_t *fsm, + * uint32_t exception_state) + * + * DESCRIPTION + * To be called from an event handler to alter + * the next state from the event table when an + * exception has been detected + * + * INPUT PARAMETERS + * *fsm - state machine handle + * + * exception_state - New state to be transitioned + * when the event handler returns. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_set_exception_state (fsm_t *fsm, uint32_t exception_state) +{ + if (fsm == NULL) { + return (RC_FSM_NULL); + } + + if (fsm->tag != FSM_TAG) { + return (RC_FSM_INVALID_HANDLE); + } + + /* + * Change the state of this FSM to the requested state. + */ + if (exception_state > fsm->number_states-1) { + return (RC_FSM_INVALID_STATE); + } + + fsm->exception_state = exception_state; + fsm->exception_state_indicator = TRUE; + return (RC_FSM_OK); +} + + +/** + * NAME + * fsm_destroy + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_destroy(fsm_t **fsm) + * + * DESCRIPTION + * Destroys the specified state machine. + * + * INPUT PARAMETERS + * fsm - pointer to fsm handle + * + * OUTPUT PARAMETERS + * fsm - is nulled + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_destroy (fsm_t **fsm) +{ + fsm_t *p2fsm; + + if (fsm == NULL) { + return (RC_FSM_NULL); + } + + p2fsm = *fsm; + if (p2fsm->tag != FSM_TAG) { + return (RC_FSM_INVALID_HANDLE); + } + + free(p2fsm->history); + *fsm = NULL; + free(p2fsm); + return (RC_FSM_OK); +} + + +/** + * NAME + * fsm_create + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_create(fsm_t **fsm, + * char *name, + * uint32_t initial_state, + * state_description_t *state_description_table, + * event_description_t *event_description_table, + * state_tuple_t *state_table) + * + * DESCRIPTION + * Creates and initializes a state machine. The + * initial state is specified by the user. + * + * INPUT PARAMETERS + * fsm pointer to fsm handle to be returned + * once created + * + * name pointer to fsm name + * + * initial_state Initial start state + * + * state_description_table + * Pointer to the user table which + * provides a description of each state. + * The table is used when displaying + * state info to the console. + * + * event_description_table + * Pointer to the user table which + * provides a description of each event. + * The table is used when displaying + * state info to the console. + * + * state_table Pointer to user defined state + * table. The state table is indexed + * by the normalized state ID, 0, 1, ... + * Each state table tuple must reference + * an event table. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_create (fsm_t **fsm, + char *name, + uint32_t initial_state, + state_description_t *state_description_table, + event_description_t *event_description_table, + state_tuple_t *state_table) +{ + fsm_t *temp_fsm; + uint32_t i; + uint32_t j; + state_tuple_t *state_ptr; + event_tuple_t *event_ptr; + + if (fsm == NULL) { + return (RC_FSM_NULL); + } + + if (state_description_table == NULL) { + printf("\n Description table == NULL"); + return (RC_FSM_INVALID_STATE_TABLE); + } + + if (event_description_table == NULL) { + + printf("\n event table == NULL"); + return (RC_FSM_INVALID_EVENT_TABLE); + } + + if (state_table == NULL) { + + printf("\n state_table == NULL"); + return (RC_FSM_INVALID_STATE_TABLE); + } + + + /* + * allocate memory to manage state machine + */ + temp_fsm = (fsm_t *)malloc( sizeof(fsm_t) ); + if (temp_fsm == NULL) { + printf("ME1\n"); + return (RC_FSM_NO_RESOURCES); + } + + /* + * default a name if needed + */ + if (name) { + strncpy(temp_fsm->fsm_name, name, FSM_NAME_LEN); + } else { + strncpy(temp_fsm->fsm_name, "State Machine", FSM_NAME_LEN); + } + + /* + * initialize fsm config parms + */ + temp_fsm->tag = FSM_TAG; /* for sanity cchecks */ + + temp_fsm->curr_state = initial_state; + temp_fsm->next_state = initial_state; + temp_fsm->exception_state_indicator = FALSE; + + /* save the event description table */ + temp_fsm->state_description_table = state_description_table; + temp_fsm->event_description_table = event_description_table; + + /* save the pointer to the state table */ + temp_fsm->state_table = state_table; + + /* + * Find the size of the state table + */ + temp_fsm->number_states = 0; + for (i=0; inumber_states++; + } else { + free(temp_fsm); + + printf("\n IN FSM invalied state tABLE"); + return (RC_FSM_INVALID_STATE_TABLE); + } + } else { + break; + } + } + if (temp_fsm->number_states < 1 || + temp_fsm->number_states > FSM_MAX_STATES-1) { + free(temp_fsm); + printf("ME2\n"); + return (RC_FSM_INVALID_STATE_TABLE); + } +#if 0 + printf("number states=%u \n", temp_fsm->number_states); +#endif + + /* + * check zero based range for state + */ + if (initial_state > temp_fsm->number_states-1) { + free(temp_fsm); + printf("ME3\n"); + return (RC_FSM_INVALID_STATE); + } + + + /* + * Find the size of the event table + */ + temp_fsm->number_events = 0; + for (i=0; inumber_events++; + } + if (temp_fsm->number_events < 1 || + temp_fsm->number_events > FSM_MAX_EVENTS-1) { + free(temp_fsm); + printf("ME5\n"); + return (RC_FSM_INVALID_EVENT_TABLE); + } +#if 0 + printf("number events=%u \n", temp_fsm->number_events); +#endif + + /* + * Now verify the state table - event table relationships and + * that the IDs are normalized. + */ + for (i=0; inumber_states; i++) { + state_ptr = &temp_fsm->state_table[i]; + + event_ptr = state_ptr->p2event_tuple; + + for (j=0; jnumber_events; j++) { +#if 0 + printf(" %u eventID=%u \n", + j, + event_ptr[j].eventID); +#endif + if (j != event_ptr[j].eventID) { + free(temp_fsm); + printf("ME6\n"); + return (RC_FSM_INVALID_EVENT_TABLE); + } + } + } + + /* + * allocate memory for history + */ + temp_fsm->history = malloc(FSM_HISTORY * sizeof(fsm_history_t)); + if (temp_fsm->history == NULL) { + free(temp_fsm); + printf("ME7\n"); + return (RC_FSM_NO_RESOURCES); + } + + /* + * initialize history buffer + */ + temp_fsm->history_index = 0; + for (i=0; ihistory[i].prevStateID = FSM_NULL_STATE_ID; + temp_fsm->history[i].stateID = FSM_NULL_STATE_ID; + temp_fsm->history[i].eventID = FSM_NULL_EVENT_ID; + temp_fsm->history[i].handler_rc = RC_FSM_NULL; + } + + /* return handle to the user */ + *fsm = temp_fsm; + return (RC_FSM_OK); +} + + +/* + * internal routine to record a state transition history + */ +static void +fsm_record_history (fsm_t *fsm, + uint32_t normalized_event, + uint32_t nextState, + RC_FSM_t handler_rc) +{ + fsm_history_t *history_ptr; + + /* + * get next index to record a little history + */ + fsm->history_index = (fsm->history_index+1)%FSM_HISTORY; + + /* + * Get a local pointer to the history buffer to populate + */ + history_ptr = &fsm->history[fsm->history_index]; + + history_ptr->prevStateID = fsm->curr_state; + history_ptr->stateID = nextState; + history_ptr->eventID = normalized_event; + history_ptr->handler_rc = handler_rc; + return; +} + + +/** + * NAME + * fsm_engine + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_engine(fsm_t *fsm, + * uint32_t normalized_event, + * void *p2event_buffer, + * void *p2parm) + * + * DESCRIPTION + * Drives a state machine defined by normalized event + * and a states. + * + * INPUT PARAMETERS + * *fsm state machine handle + * + * normalized_event the event id to process + * + * *p2event pointer to the raw event which + * is driving the event. This is + * passed through to the handler. + * + * *p2parm pointer parameter that is simply + * passed through to each event + * handler. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_engine (fsm_t *fsm, + uint32_t normalized_event, + void *p2event_buffer, + void *p2parm) +{ + event_tuple_t *event_ptr; + event_cb_t event_handler; + RC_FSM_t rc; + + /* + * verify pointers & handles are valid + */ + + if (fsm == NULL) { + + printf("\n RETURN 2 DEBUG "); + return (RC_FSM_NULL); + } + + if (fsm->tag != FSM_TAG) { + + printf("\n RETURN 3 DEBUG "); + return (RC_FSM_INVALID_HANDLE); + } + + /* + * verify that "event id" is valid: [0-(number_events-1)] + */ + if (normalized_event > fsm->number_events-1) { + fsm_record_history(fsm, normalized_event, + fsm->curr_state, RC_FSM_INVALID_EVENT); + printf("\n RETURN 4 DEBUG "); + return (RC_FSM_INVALID_EVENT); + } + + /* + * Index into the state table to get to the event table + * so we can get the next state and the event handler. + */ + event_ptr = + &fsm->state_table[fsm->curr_state].p2event_tuple[normalized_event]; + + /* + * If the handler was NULL then we have a quiet event , + * no processing possible. + */ + event_handler = event_ptr->event_handler; + if (event_handler == NULL) { + fsm_record_history(fsm, + normalized_event, + event_ptr->next_state, + RC_FSM_INVALID_EVENT_HANDLER); + printf("\n RETURN 5 DEBUG "); + return (RC_FSM_OK); + } + + printf(" "); + rc = (*event_handler)(p2event_buffer, p2parm); + + /* + * Event handler wants to stop processing events. There is no access + * to the fsm data structure in case the state machine has ended. + */ + if (rc == RC_FSM_STOP_PROCESSING) { + printf("\n RETURN 6 DEBUG "); + return (rc); + } + + /* + * If the return code is not OK, simply record the + * result without a state change. + */ + if (rc != RC_FSM_OK) { + fsm_record_history(fsm, normalized_event, + event_ptr->next_state, rc); + return (rc); + } + + /* + * If the exception state indicator is set, use the exception + * state provided by the event handler. This is an unexpected + * state transition. Else use the event table next state. + */ + if (fsm->exception_state_indicator) { + /* + * event handler detected an exception to the state transition + */ + fsm->exception_state_indicator = FALSE; + fsm->next_state = fsm->exception_state; + + } else { + /* + * we have a valid event table transition + */ + fsm->next_state = event_ptr->next_state; + } + + /* + * Validate the next state from the event table + * knowing that the event id is 0,1,2,... + * Then use the event id to directly index into the state + * table to set the next state. + */ + if (fsm->next_state > (fsm->number_states-1)) { + fsm_record_history(fsm, + normalized_event, + fsm->next_state, + RC_FSM_INVALID_STATE); + rc = RC_FSM_INVALID_STATE; + + } else { + + /* record a bit of history. */ + fsm_record_history(fsm, + normalized_event, + fsm->next_state, + rc); + + /* + * and update the current state completing the transition + */ + fsm->curr_state = fsm->next_state; + } + return (rc); +} + diff --git a/dlep_radio_ipv4/fsm.h b/dlep_radio_ipv4/fsm.h new file mode 100644 index 0000000..59f2c9a --- /dev/null +++ b/dlep_radio_ipv4/fsm.h @@ -0,0 +1,340 @@ +/*------------------------------------------------------------------ + * fsm.h - Finite State Machine definitions + * + * February 2005, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __FSM_H__ +#define __FSM_H__ + +#include "safe_types.h" + + +/* + * return codes utilized by the fsm APIs and + * user event handlers + */ +typedef enum { + /* indicates success - state change */ + RC_FSM_OK = 0, + + /* indicates that the fsm handle was NULL */ + RC_FSM_NULL, + + /* indicates that the fsm handle pointed to somethinf else! */ + RC_FSM_INVALID_HANDLE, + + RC_FSM_INVALID_EVENT_HANDLER, + + /* indicates that an error was found in the state table */ + RC_FSM_INVALID_STATE_TABLE, + + /* indicates that the next state was out of bounds */ + RC_FSM_INVALID_STATE, + + /* indicates that an error was found in the event table */ + RC_FSM_INVALID_EVENT_TABLE, + + /* indicates that the next event was out of bounds */ + RC_FSM_INVALID_EVENT, + + /* indicates that there was no memory available */ + RC_FSM_NO_RESOURCES, + + /* event handler indicating that the event can be + * ignored, no transition + */ + RC_FSM_IGNORE_EVENT, + + /* event handler indicating that the state machine is + * being deallocated and no further access to the fsm + * strucutre should be made - history + */ + RC_FSM_STOP_PROCESSING, +} RC_FSM_t; + + + +#define FSM_NULL_STATE_ID ( -1 ) +#define FSM_NULL_EVENT_ID ( -1 ) + + +/* + * typedef RC_FSM_t (*event_cb_t)(void *p2event, void *p2parm) + * + * DESCRIPTION + * Provides typedef for the event handler functions. + * + * Once the state's normalized event ID and index has been + * determined, the associated event call-back is invoked + * to effect the state processing and transition. + * + * INPUT PARAMETERS + * p2event pointer to the raw event to be processed + * by the event handler. + * + * p2parm pointer parameter that is simply + * passed through from fsm_engine to each + * event handler. + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + */ +typedef RC_FSM_t (*event_cb_t)(void *p2event, void *p2parm); + + +/* + * User provided Normalized Event Description Table. + * + * An Example + * typedef enum { + * start_init_e = 0, + * init_rcvd_e, + * init_tmo_e, + * init_ack_e, + * start_term_e, + * term_rcvd_e, + * term_ack_e, + * } session_events_e; + * + * static event_description_t normalized_event_table[] = + * {{start_init_e, "Start Session Init"}, + * {init_rcvd_e, "Session Init"}, + * {init_tmo_e, "Session Init ACK TMO"}, + * {init_ack_e, "Session Init ACK"}, + * {start_term_e, "Start Session Termination"}, + * {term_rcvd_e, "Session Terminate"}, + * {term_ack_e, "Session Terminate ACK"}, + * {FSM_NULL_EVENT_ID, NULL}}; / required to end table / + * + */ +typedef struct { + uint32_t event_id; + char *description; +} event_description_t; + + +/* + * User provided Normalized State DESCRIPTION Table. + * + * An example + * typedef enum { + * idle_s = 0, + * wait_for_init_ack_s, + * established_s, + * wait_for_term_ack_s, + * } demo_states_e; + * + * static state_description_t normalized_state_table[] = + * {{start_init_e, "Start Session Init"}, + * {idle_s, Idle State"}, + * {wait_for_init_ack_s, "Wait for Init Ack State"}, + * {established_s, "Established State"}, + * {wait_for_term_ack_s, "Wait for Terminate Ack State"}, + * {FSM_NULL_STATE_ID, NULL}}; / required to end table / + * + */ +typedef struct { + uint32_t state_id; + char *description; +} state_description_t; + + + +/* + * User provided Event Table - one table per state is + * required. The table must have an entry for each + * normalized event, ordered from 0 - n. + * + * event_id is the normalized value. + * + * event_handler is the user provided call-back function that is + * invoked to handle the event and effect the state transition. + * If the event_handler is NULL, no processing is + * associated with the event - no state transition. + * + * next_state is the next state as result of the event. It is + * possible that a state transition associated with an event + * remain in the current state. + * + * An example: + * static event_tuple_t state_wait_for_init_ack_events[] = + * {{start_init_e, event_ignore, wait_for_init_ack_s}, + * {init_rcvd_e, event_ignore, wait_for_init_ack_s}, + * {init_tmo_e, event_init_ack_tmo, wait_for_init_ack_s}, + * {init_ack_e, event_init_ack_rcvd, established_s}, + * {start_term_e, event_term_rcvd, wait_for_term_ack_s}, + * {term_rcvd_e, event_term_rcvd, idle_s}, + * {term_ack_e, event_ignore, wait_for_term_ack_s}}; + */ +typedef struct { + uint32_t eventID; /* normalized event id */ + event_cb_t event_handler; /* if NULL==no transaction processing */ + uint32_t next_state; /* normalized next state - can be + * the same state */ +} event_tuple_t; + + +/* + * User provided Normalized State Table. This table represents all + * the states and the event table associated with each state. + * + * An example: + * static state_tuple_t demo_state_table[] = + * {{idle_s, state_idle_events}, + * {wait_for_init_ack_s, state_wait_for_init_ack_events}, + * {established_s, state_established_events}, + * {wait_for_term_ack_s, state_wait_for_term_ack_events}, + * {FSM_NULL_STATE_ID, NULL}}; / requied to end table / + */ +typedef struct { + uint32_t state_id; + event_tuple_t *p2event_tuple; +} state_tuple_t; + + +/* + * Historical record of state changes + */ +typedef struct { + uint32_t number; + uint32_t prevStateID; + uint32_t stateID; + uint32_t eventID; + RC_FSM_t handler_rc; +} fsm_history_t; + + +#define FSM_HISTORY ( 64 ) + +/* + * Finite State Machine structure + * + */ +#define FSM_TAG ( 0xba5eba11 ) +#define FSM_NAME_LEN ( 32 ) + +typedef struct { + /* for fsm validation */ + uint32_t tag; + + uint32_t curr_state; + uint32_t next_state; + + /* + * This is set by an event handle to cover an excpetion + * state transition that is different from the event + * table next state transition. + */ + uint32_t exception_state; + boolean_t exception_state_indicator; + + char fsm_name[FSM_NAME_LEN]; + + /* number states in table */ + uint32_t number_states; + + /* number events in each state-event table */ + uint32_t number_events; + + /* debug and trace flags*/ + uint32_t flags; + + /* pointer to the state table */ + state_tuple_t *state_table; + + /* description of normalized states and events */ + state_description_t *state_description_table; + event_description_t *event_description_table; + + /* starts at 0 and wraps */ + uint32_t history_index; + /* memory is malloc'ed to record history */ + fsm_history_t *history; +} fsm_t; + + +/* + * show state machine table + */ +extern void +fsm_display_table(fsm_t *fsm); + + +/* + * shows state machine history + */ +extern void +fsm_show_history(fsm_t *fsm); + + +/* get state */ +extern RC_FSM_t +fsm_get_state(fsm_t *fsm, uint32_t *p2state); + + +/* + * allows event handler to update the next state based upon + * an unexpected condition when processing the event. + */ +extern RC_FSM_t +fsm_set_exception_state(fsm_t *fsm, uint32_t exception_state); + + +/* + * destroy a state machine + */ +extern RC_FSM_t +fsm_destroy(fsm_t **fsm); + + +/* + * create and config a state machine + */ +extern RC_FSM_t +fsm_create(fsm_t **fsm, + char *fsm_name, + uint32_t initial_state, + state_description_t *state_description_table, + event_description_t *event_description_table, + state_tuple_t *state_table); + + +/* + * API to drive a state machine + */ +extern RC_FSM_t +fsm_engine(fsm_t *fsm, + uint32_t normalized_event, + void *p2event_bufer, + void *p2parm); + + +#endif /* __FSM_H__ */ + diff --git a/dlep_radio_ipv4/fuzz_dlep_cli.h b/dlep_radio_ipv4/fuzz_dlep_cli.h new file mode 100644 index 0000000..1da0faf --- /dev/null +++ b/dlep_radio_ipv4/fuzz_dlep_cli.h @@ -0,0 +1,40 @@ +/*------------------------------------------------------------------ + * fuzz_dlep_cli.h -- fuzz CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __FUZZ_DLEP_CLI_H__ +#define __FUZZ_DLEP_CLI_H__ + + +extern +void fuzz_dlep_cli_init(void); + +#endif + diff --git a/dlep_radio_ipv4/fuzz_encoder_tlv.h b/dlep_radio_ipv4/fuzz_encoder_tlv.h new file mode 100644 index 0000000..d5d462b --- /dev/null +++ b/dlep_radio_ipv4/fuzz_encoder_tlv.h @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------- + * fuzz_encoder_tlv.h -- routine prototypes to encode TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __FUZZ_ENCODER_TLV_H__ +#define __FUZZ_ENCODER_TLV_H__ + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_encoder.h" + + + +extern uint8_t +*fuzz_identification_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t router_id, + uint32_t client_id, + uint8_t heartbeat_interval); + +extern uint8_t +*fuzz_version_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t version_major, + uint16_t version_minor); + + +extern uint8_t +*fuzz_peer_tlv(rfc5444_encoder_state_t *p2encoder_state, + char *peer_type_string); + + +extern uint8_t +*fuzz_mac_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t mac_address[]); + + +extern uint8_t +*fuzz_ipv4_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv4_address_t *ipv4); + +extern uint8_t +*fuzz_ipv6_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv6_address_t *ipv6_dest_addr); + + +extern uint8_t +*fuzz_link_metric_mdr_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr); + +extern uint8_t +*fuzz_link_metric_cdr_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr); + +extern uint8_t +*fuzz_link_metric_latency_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t latency); + +extern uint8_t +*fuzz_link_metric_resources_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources); + +extern uint8_t +*fuzz_link_metric_rlq_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq); + +extern uint8_t +*fuzz_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t termination_code); + + +extern uint8_t +*fuzz_datarate_request_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t requested_cdr); + + +extern uint8_t +*fuzz_datarate_request_ack_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t requested_cdr, + uint32_t granted_cdr); + +#endif + + diff --git a/dlep_radio_ipv4/fuzz_message_builder.h b/dlep_radio_ipv4/fuzz_message_builder.h new file mode 100644 index 0000000..db76512 --- /dev/null +++ b/dlep_radio_ipv4/fuzz_message_builder.h @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------- + * fuzz_message_builder.h -- Routines to build fuzzed DLEP messages + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __FUZZ_MESSAGE_BUILDER_H__ +#define __FUZZ_MESSAGE_BUILDER_H__ + +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" + + + +/* + * Router-Radio Level Mesages + */ + +extern void +send_fuzz_attached_peer_discovery(dlep_context_peer_t *p2peer); + +extern void +send_fuzz_detached_peer_discovery(dlep_context_peer_t *p2peer); + +extern void +send_fuzz_peer_offer(dlep_context_peer_t *p2peer); + + +extern void +send_fuzz_peer_heartbeat(dlep_context_peer_t *p2peer); + + +extern void +send_fuzz_peer_update_request(dlep_context_peer_t *p2peer); + +extern void +send_fuzz_peer_update_response(dlep_context_peer_t *p2peer); + + +extern void +send_fuzz_peer_terminate(dlep_context_peer_t *p2peer); + +extern void +send_fuzz_peer_terminate_ack(dlep_context_peer_t *p2peer); + + +/* + * Neighbor Level Mesages + */ + +extern void +send_fuzz_neighbor_up(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_up_ack(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_metrics(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_address_request(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_address_response(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + +extern void +send_fuzz_neighbor_down(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_down_ack(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_link_char_request(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor, + uint64_t cdr, + uint64_t latency); + + +extern void +send_fuzz_neighbor_link_char_response(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + + +#endif + diff --git a/dlep_radio_ipv4/fuzz_packet.c b/dlep_radio_ipv4/fuzz_packet.c new file mode 100644 index 0000000..352b899 --- /dev/null +++ b/dlep_radio_ipv4/fuzz_packet.c @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------- + * fuzz_packet.c -- Routines to read a fuzzed packet file + * + * October 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "safe_types.h" +#include "fuzz_packet.h" + + +#define FUZZ_PACKET_LENGTH ( 2048 ) + + +/** + * NAME + * fuzz_packet_load + * + * DESCRIPTION + * This function reads the designated file that contains + * a fuzzed DLEP packet. The fuzzed packet is used for testing. + * + * INPUT PARAMETERS + * + * OUTPUT PARAMETERS + * + * RETURN VALUE + * length - number of bytes in packet + * + */ +uint32_t +fuzz_packet_load (char *fuzzy_filename, uint8_t *p2packet) +{ + uint32_t i; + uint32_t key_index; + uint32_t line_count; + + FILE *fp; + + +#define MAX_INPUT_LENGTH ( 512 ) + char directed_filename[MAX_INPUT_LENGTH]; + char input_string[MAX_INPUT_LENGTH]; + +#define ARGC_MAX ( 8 ) + uint32_t argc; + char *argv[ARGC_MAX]; + + + if (!fuzzy_filename || !p2packet) { + return (0); + } + + strcpy(directed_filename, "fuzzy_dir/"); + strcat(directed_filename, fuzzy_filename); + + fp = fopen(directed_filename, "r"); + if (!fp) { + printf("Error: problem opening fuzzed file: %s\n", + directed_filename); + return (0); + } + + key_index = 0; + line_count = 0; + while (fgets(input_string, MAX_INPUT_LENGTH, fp)) { + line_count++; + + if (input_string[0] == '\0') { + continue; + } else if (input_string[0] == '#') { + continue; + } + + argv[0] = strtok(input_string, " ,\t\n"); + /* empty line */ + if (argv[0] == NULL) { + continue; + } + p2packet[key_index] = strtoul(argv[0], NULL, 16); + key_index++; + + argc = 1; + for (i=1; i +#include + +#include "ipv4_address.h" + + +/** + * NAME + * ipv4_print_address + * + * SYNOPSIS + * #include "man_ipv4_address.h" + * void + * ipv4_print_address(char *p2label, + * ipv4_address_t *ipv4_src_addr) + * + * DESCRIPTION + * Use this function to printf an IPv4 address in dot-decimal + * notation. + * + * INPUT PARAMETERS + * p2label - label to be printed + * ipv4_src_addr - pointer to the IPv4 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +ipv4_print_address (char *p2label, ipv4_address_t *ipv4_src_addr) +{ + if (!ipv4_src_addr) { + return; + } + + if (p2label) { + printf("%s %d.%d.%d.%d \n", + p2label, + ipv4_src_addr->v4_addr.v4_addr8[3], + ipv4_src_addr->v4_addr.v4_addr8[2], + ipv4_src_addr->v4_addr.v4_addr8[1], + ipv4_src_addr->v4_addr.v4_addr8[0]); + + } else { + printf("IPv4: %d.%d.%d.%d \n", + ipv4_src_addr->v4_addr.v4_addr8[3], + ipv4_src_addr->v4_addr.v4_addr8[2], + ipv4_src_addr->v4_addr.v4_addr8[1], + ipv4_src_addr->v4_addr.v4_addr8[0]); + } + + return; +} + + +/** + * NAME + * ipv4_dot_decimal2digits + * + * SYNOPSIS + * #include "man_ipv4_address.h" + * void + * ipv4_dot_decimal2digits(ipv4_address_t *ipv4_dest_addr, + * char *input) + * + * DESCRIPTION + * This function converts an IPv4 dot-decimal notation, + * such as 192.168.1.1, into binary. + * + * INPUT PARAMETERS + * ipv4_dest_addr - pointer to the IPv4 address + * + * input - pointer to the Ascii IPv4 string + * + * OUTPUT PARAMETERS + * ipv4_dest_addr - updated with the IPv4 address + * + * RETURN VALUE + * None + * + * EXAMPLES + * ipv4_dest_addr->v4_addr.v4_addr8[3] = 192; + * ipv4_dest_addr->v4_addr.v4_addr8[2] = 168; + * ipv4_dest_addr->v4_addr.v4_addr8[1] = 1; + * ipv4_dest_addr->v4_addr.v4_addr8[0] = 1; + * + * If there is an error, the remaining ipv4[i] are 0. + * + */ +void +ipv4_dot_decimal2digits (ipv4_address_t *ipv4_dest_addr, char *input) +{ + char *ptr; + + if (!ipv4_dest_addr) { + return; + } + + ipv4_zero_address(ipv4_dest_addr); + + if (!input) { + return; + } + + /* most significant */ + ipv4_dest_addr->v4_addr.v4_addr8[3] = strtoul(input, &ptr, 10); + if (*ptr != '.') { + return; + } + ptr++; + ipv4_dest_addr->v4_addr.v4_addr8[2] = strtoul(ptr, &ptr, 10); + if (*ptr != '.') { + return; + } + ptr++; + ipv4_dest_addr->v4_addr.v4_addr8[1] = strtoul(ptr, &ptr, 10); + if (*ptr != '.') { + return; + } + ptr++; + ipv4_dest_addr->v4_addr.v4_addr8[0] = strtoul(ptr, NULL, 10); + + return; +} + + diff --git a/dlep_radio_ipv4/ipv4_address.h b/dlep_radio_ipv4/ipv4_address.h new file mode 100644 index 0000000..2532b42 --- /dev/null +++ b/dlep_radio_ipv4/ipv4_address.h @@ -0,0 +1,398 @@ +/*------------------------------------------------------------------ + * ipv4_address.h -- Miscellaneous IPv4 Address Support Routines + * + * July 2008, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __IPV4_ADDRESS_H__ +#define __IPV4_ADDRESS_H__ + +#include "safe_types.h" +#include "network_order.h" + + + +/* + * IPv4 Address Notations + * + * Dot Decimal: 192.0.2.235 + * + * Hexidecimal: 0xC00002EB + * + * + * Classless Inter-Domain Routing (CIDR) + * + * CIDR ranges for private networks: + * + * Number of Classful Largest + * NAME Address range addresses DESCRIPTION CIDR block + *--------------------------------------------------------------------- + * 24-bit 10.0.0.0 – + * 10.255.255.255 16,777,216 Single Class A 10.0.0.0/8 + * 20-bit 172.16.0.0 – + * 172.31.255.255 1,048,576 16 contiguous Class + * B blocks 172.16.0.0/12 + * 16-bit 192.168.0.0 – + * 192.168.255.255 65,536 Contiguous range of + * 256 class C blocks 192.168.0.0/16 + * + * Link-local addressing + * Address block edfined in RFC3330 for the special use in + * link-local addressing. These addresses are only valid on the link, + * such as a local network segment or point-to-point connection, that + * a host is connected to. + * Range: 169.254.0.0/16 + * + * Local-host (local loopback) + * Addresses within this range are internal to the lost and should + * never appear outside the host computer. Packets sent to this + * address are returned as incoming packets on the same virtual + * network device. + * Range: 127.0.0.0 – 127.255.255.255 (127.0.0.0/8 in CIDR notation) + * + */ + + + +/* + * IPv4 Multicast Addresses: 224.0.0.0 thru 239.255.255.255 + * The multicast addresses from 224.0.0.0 to 224.0.0.255 are reserved for + * multicast routing information. Application programs should use multicast + * addresses outside this range. + */ +#define IPV4_MULTICAST_LOW ( 0xE0000000 ) +#define IPV4_MULTICAST_HIGH ( 0xEF000000 ) + + + +/* + * IPv4 length values + */ +#define IPV4_ADDR_STRING_LEN ( 16 ) +#define IPV4_ADDR_LEN_IN_BITS ( 32 ) +#define IPV4_ADDR_LEN_IN_BYTES ( 4 ) +#define IPV4_ADDR_LEN_IN_LONGS ( 1 ) + + +/* + * IPv4 Address Type (32 bits) + */ +typedef struct ipv4_address_ { + union { + uint8_t v4_addr8[IPV4_ADDR_LEN_IN_BYTES]; + uint32_t v4_addr32; + } v4_addr; +} ipv4_address_t; + + + + +/** + * NAME + * ipv4_put_address + * + * SYNOPSIS + * static inline uint8_t + * *ipv4_put_address(uint8_t *mp, ipv4_address_t *ipv4_src_addr) + * + * DESCRIPTION + * Use this function to copy the source IPv4 address to the + * destination pointer mp. + * + * INPUT PARAMETERS + * mp - destination buffer pointer + * + * ipv4_src_addr - pointer to the source address + * + * OUTPUT PARAMETERS + * mp - updated + * + * RETURN VALUE + * Pointer to the next byte in the destination space, mp + * + */ +static inline uint8_t +*ipv4_put_address (uint8_t *mp, ipv4_address_t *ipv4_src_addr) +{ + if (!ipv4_src_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_PUTLONG(mp, ipv4_src_addr->v4_addr.v4_addr32); + mp = mp + sizeof(ipv4_address_t); + + return (mp); +} + + +/** + * NAME + * ipv4_get_address + * + * SYNOPSIS + * static inline uint8_t + * *ipv4_get_address(ipv4_address_t *ipv4_dest_addr, uint8_t *mp) + * + * DESCRIPTION + * Use this function to copy an IPv4 address from the buffer + * pointer mp to the destination ipv4_dest_addr. + * + * INPUT PARAMETERS + * ipv4_dest_addr - destination pointer to receive the IPv4 address + * + * mp - source pointer to copy from + * + * OUTPUT PARAMETERS + * ipv4_dest_addr - updated + * + * RETURN VALUE + * Pointer to the next byte in the source space, mp + * + */ +static inline uint8_t +*ipv4_get_address (ipv4_address_t *ipv4_dest_addr, uint8_t *mp) +{ + if (!ipv4_dest_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_GETLONG(mp, ipv4_dest_addr->v4_addr.v4_addr32); + mp = mp + sizeof(ipv4_address_t); + + return (mp); +} + + +/** + * NAME + * ipv4_address_is_multicast + * + * SYNOPSIS + * static inline boolean_t + * ipv4_address_is_multicast(ipv4_address_t *ipv4_addr) + * + * DESCRIPTION + * Use this function determine if the IPv4 address is multicast. + * + * INPUT PARAMETERS + * ipv4_addr pointer to the IPv4 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes, it is a multicast address + * FALSE - nope! + * + */ +static inline boolean_t +ipv4_address_is_multicast (ipv4_address_t *ipv4_addr) +{ + ipv4_address_t ipv4_multicast; + + if (!ipv4_addr) { + return (FALSE); + } + + ipv4_multicast.v4_addr.v4_addr32 = + ipv4_addr->v4_addr.v4_addr32 & 0xFF000000; + + if (ipv4_multicast.v4_addr.v4_addr32 >= IPV4_MULTICAST_LOW && + ipv4_multicast.v4_addr.v4_addr32 <= IPV4_MULTICAST_HIGH) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * ipv4_address_to_broadcast + * + * SYNOPSIS + * static inline ipv4_address_t + * ipv4_address_to_broadcast(ipv4_address_t *ipv4_addr) + * ipv4_address_t *ipv4_subnet, + * ipv4_address_t *ipv4_broadcast) + * + * DESCRIPTION + * This function returns a broadcast address given an + * IPv4 address and its subnet. + * + * INPUT PARAMETERS + * ipv4_addr - pointer to the IPv4 address + * + * ipv4_subnet - pointer to the IPv4 subnet mask + * + * ipv4_broadcast - pointer to the IPv4 subnet mask + * + * OUTPUT PARAMETERS + * ipv4_broadcast - updated + * + * RETURN VALUE + * IPv4 broadcast address + * + */ +static inline boolean_t +ipv4_address_to_broadcast (ipv4_address_t *ipv4_addr, + ipv4_address_t *ipv4_subnet, + ipv4_address_t *ipv4_broadcast) +{ + if (!ipv4_addr || !ipv4_subnet || ipv4_broadcast) { + return (FALSE); + } + + ipv4_broadcast->v4_addr.v4_addr32 = + (ipv4_addr->v4_addr.v4_addr32 | + (~ipv4_subnet->v4_addr.v4_addr32)); + return (TRUE); +} + + +/** + * NAME + * ipv4_zero_address + * + * SYNOPSIS + * static inline void + * ipv4_zero_address(ipv4_address_t *ipv4_addr) + * + * DESCRIPTION + * This function can be used to zero an IPv4 address. + * + * INPUT PARAMETERS + * ipv4_addr - pointer to the IPV4 address + * + * OUTPUT PARAMETERS + * ipv4_addr - zeroed + * + * RETURN VALUE + * none + * + */ +static inline void +ipv4_zero_address (ipv4_address_t *ipv4_addr) +{ + if (!ipv4_addr) { + return; + } + + ipv4_addr->v4_addr.v4_addr32 = 0; + return; +} + + +/** + * NAME + * ipv4_compare_address + * + * SYNOPSIS + * static inline boolean_t + * ipv4_compare_address(ipv4_address_t ipv4_dest_addr, + * ipv4_address_t ipv4_src_addr) + * + * DESCRIPTION + * This function can be used to compare two IPv4 addresses. + * + * INPUT PARAMETERS + * ipv4_dest_addr - pointer to the destination IPV4 address + * + * ipv4_src_addr - pointer to the source IPV4 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE == equal + * FALSE == not equal + * + */ +static inline boolean_t +ipv4_compare_address (ipv4_address_t *ipv4_dest_addr, + ipv4_address_t *ipv4_src_addr) +{ + if (ipv4_dest_addr->v4_addr.v4_addr32 == + ipv4_src_addr->v4_addr.v4_addr32) { + return (TRUE); + } else { + return (FALSE); + } +} + + + +/** + * NAME + * ipv4_copy_address + * + * SYNOPSIS + * static inline void + * ipv4_copy_address(ipv4_address_t *ipv4_dest_addr, + * ipv4_address_t *ipv4_src_addr) + * + * DESCRIPTION + * Use this function to compare two IPv4 addresses + * + * INPUT PARAMETERS + * ipv4_dest_addr - pointer to the destination IPv4 address + * + * ipv4_src_addr - pointer to the src IPv4 address + * + * OUTPUT PARAMETERS + * ipv4_dest_addr - updated + * + * RETURN VALUE + * none + * + */ +static inline void +ipv4_copy_address (ipv4_address_t *ipv4_dest_addr, + ipv4_address_t *ipv4_src_addr) +{ + if (!ipv4_dest_addr || !ipv4_src_addr) { + return; + } + + ipv4_dest_addr->v4_addr.v4_addr32 = ipv4_src_addr->v4_addr.v4_addr32; + return; +} + + + +extern void +ipv4_print_address(char *p2label, ipv4_address_t *ipv4_src_addr); + +extern void +ipv4_dot_decimal2digits(ipv4_address_t *ipv4_dest_addr, char *input); + +extern void +ipv4_dot_hex2digits(ipv4_address_t *ipv4_dest_addr, char *input); + +#endif + diff --git a/dlep_radio_ipv4/ipv6_address.c b/dlep_radio_ipv4/ipv6_address.c new file mode 100644 index 0000000..34751cd --- /dev/null +++ b/dlep_radio_ipv4/ipv6_address.c @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------- + * ipv6_address.c -- Miscellaneous IPv6 Address Support Routines + * + * June 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include + +#include "ipv6_address.h" + + +/** + * NAME + * ipv6_print_address + * + * SYNOPSIS + * #include "man_ipv6_address.h" + * void + * ipv6_print_address(char *p2label, + * ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to print an IPv6 address + * + * INPUT PARAMETERS + * p2label - label to be printed + * + * ipv6_src_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +ipv6_print_address (char *p2label, ipv6_address_t *ipv6_src_addr) +{ + if (!ipv6_src_addr) { + return; + } + + if (p2label) { + printf("%s %08x:%08x:%08x:%08x \n", + p2label, + ipv6_src_addr->v6_addr.v6_addr32[0], + ipv6_src_addr->v6_addr.v6_addr32[1], + ipv6_src_addr->v6_addr.v6_addr32[2], + ipv6_src_addr->v6_addr.v6_addr32[3]); + + } else { + printf("IPv6: %08x:%08x:%08x:%08x \n", + ipv6_src_addr->v6_addr.v6_addr32[0], + ipv6_src_addr->v6_addr.v6_addr32[1], + ipv6_src_addr->v6_addr.v6_addr32[2], + ipv6_src_addr->v6_addr.v6_addr32[3]); + } + return; +} + + +/** + * NAME + * ipv6_ascii2digits + * + * SYNOPSIS + * #include "man_ipv6_address.h" + * void + * ipv6_ascii2digits(ipv6_address_t *ipv6_dest_addr, + * char *input) + * + * DESCRIPTION + * This function converts an ascii notation, + * 11111111:22222222:33333333:44444444 + * IPv6 address into binary. + * + * INPUT PARAMETERS + * ipv6_dest_addr - pointer to the IPv6 address + * + * input - pointer to the string + * + * OUTPUT PARAMETERS + * ipv6_dest_addr - updated + * + * RETURN VALUE + * none + * + * EXAMPLES + * ipv6_dest_addr->v6_addr.v6_addr32[0] = 11111111; + * ipv6_dest_addr->v6_addr.v6_addr32[1] = 22222222; + * ipv6_dest_addr->v6_addr.v6_addr32[2] = 33333333; + * ipv6_dest_addr->v6_addr.v6_addr32[3] = 44444444; + * + * If there is an error, the remaining ipv6[i] are 0. + * + */ +void +ipv6_ascii2digits (ipv6_address_t *ipv6_dest_addr, char *input) +{ + uint32_t i; + char *ptr; + + if (!ipv6_dest_addr) { + return; + } + + /* zero the users ipv6 */ + ipv6_zero_address(ipv6_dest_addr); + + if (!input) { + return; + } + + ipv6_dest_addr->v6_addr.v6_addr32[0] = strtoul(input, &ptr, 16); + if (*ptr != ':') { + return; + } + ptr++; + + for (i=1; i<7; i++) { + ipv6_dest_addr->v6_addr.v6_addr32[i] = strtoul(ptr, &ptr, 16); + if (*ptr != ':') { + return; + } + ptr++; + } + ipv6_dest_addr->v6_addr.v6_addr32[7] = strtoul(ptr, NULL, 16); + + return; +} + diff --git a/dlep_radio_ipv4/ipv6_address.h b/dlep_radio_ipv4/ipv6_address.h new file mode 100644 index 0000000..8630574 --- /dev/null +++ b/dlep_radio_ipv4/ipv6_address.h @@ -0,0 +1,426 @@ +/*------------------------------------------------------------------ + * ipv6_address.h -- Miscellaneous IPv6 Address Support Routines + * + * July 2008, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __IPV6_ADDRESS_H__ +#define __IPV6_ADDRESS_H__ + +#include "safe_types.h" +#include "network_order.h" + + +/* + * (few) IPv6 Address Definition + * + * 2001:0db8:3c4d:0015:0000:0000:abcd:ef12 + * ______________|____|___________________ + * global prefix subnet Interface ID + * + * IPv6 Address Ranges + * IPv6 Prefix Allocation + * -------------------------------------- + * 0000::/8 Reserved by IETF + * 2000::/3 Global Unicast + * FC00::/7 Unique Local Unicast + * FE80::/10 Link Local Unicast + * FF00::/8 Multicast + */ + + +/* defined for 32-bit overlay */ +#define IPV6_GLOBAL_PREFIX ( 0x20000000 ) /* 2000::/3 */ +#define IPV6_MULTICAST_PREFIX ( 0xFF000000 ) /* ff00::/8 */ +#define IPV6_UNIQUE_LOCAL_PREFIX ( 0xFC000000 ) /* fc00::/7 */ +#define IPV6_LINK_LOCAL_PREFIX ( 0xFE800000 ) /* fe80::/1 */ +#define IPV6_LINK_LOCAL_LOOPBACK_SUFFIX ( 0x0001 ) /* ::1/128 */ + + +/* + * IPv6 length values and prefixes + * + * http://www.iana.org/assignments/ipv6-multicast-addresses/ + * http://en.wikipedia.org/wiki/IPv6 + */ +#define IPV6_ADDR_STRING_LEN ( 42 ) +#define IPV6_ADDR_LEN_IN_BITS ( 128 ) +#define IPV6_ADDR_LEN_IN_BYTES ( 16 ) +#define IPV6_ADDR_LEN_IN_SHORTS ( 8 ) +#define IPV6_ADDR_LEN_IN_LONGS ( 4 ) + + + +/* + * IPv6 Address Type (128 bits) + */ +typedef struct ipv6_address_ { + union { + uint16_t v6_addr16[IPV6_ADDR_LEN_IN_SHORTS]; + uint32_t v6_addr32[IPV6_ADDR_LEN_IN_LONGS]; + } v6_addr; +} ipv6_address_t; + + + +/** + * NAME + * ipv6_put_address + * + * SYNOPSIS + * static inline uint8_t + * *ipv6_put_address(uint8_t *mp, ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to copy the source IPv6 address to the + * destination pointer mp. + * + * INPUT PARAMETERS + * mp - destination buffer pointer + * + * ipv6_src_addr - ponter to the source IPv6 address + * + * OUTPUT PARAMETERS + * mp - updated + * + * RETURN VALUE + * Pointer to the next byte in the destination space, mp + * + */ +static inline uint8_t +*ipv6_put_address (uint8_t *mp, ipv6_address_t *ipv6_src_addr) +{ + if (!ipv6_src_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_PUTLONG(mp, ipv6_src_addr->v6_addr.v6_addr32[0]); + mp = mp + sizeof(uint32_t); + + NETWORK_ORDER_PUTLONG(mp, ipv6_src_addr->v6_addr.v6_addr32[1]); + mp = mp + sizeof(uint32_t); + + NETWORK_ORDER_PUTLONG(mp, ipv6_src_addr->v6_addr.v6_addr32[2]); + mp = mp + sizeof(uint32_t); + + NETWORK_ORDER_PUTLONG(mp, ipv6_src_addr->v6_addr.v6_addr32[3]); + mp = mp + sizeof(uint32_t); + + return (mp); +} + + +/** + * NAME + * ipv6_get_address + * + * SYNOPSIS + * static inline uint8_t + * *ipv6_get_address(ipv6_address_t *ipv6_dest_addr, uint8_t *mp) + * + * DESCRIPTION + * Use this function to copy an IPv6 address from the buffer + * pointer mp to the destination ipv6_dest_addr. + * + * INPUT PARAMETERS + * ipv6_dest_addr - destination pointer to receive the IPv6 address + * + * mp - source pointer to copy from + * + * OUTPUT PARAMETERS + * ipv6_dest_addr - updated + * + * RETURN VALUE + * Pointer to the next byte in the source space, mp + * + */ +static inline uint8_t +*ipv6_get_address (ipv6_address_t *ipv6_dest_addr, uint8_t *mp) +{ + if (!ipv6_dest_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr32[0]); + mp = mp + sizeof(uint32_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr32[1]); + mp = mp + sizeof(uint32_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr32[2]); + mp = mp + sizeof(uint32_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr32[3]); + mp = mp + sizeof(uint32_t); + + return (mp); +} + +/** + * NAME + * ipv6_zero_address + * + * SYNOPSIS + * static inline void + * ipv6_zero_address(ipv6_address_t *ipv6_dest_addr) + * + * DESCRIPTION + * Use this function to zero an IPv6 address + * A zero address is reserved by the IETF. + * + * INPUT PARAMETERS + * ipv6_dest_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * ipv6_dest_addr - zeroed + * + * RETURN VALUE + * none + * + */ +static inline void +ipv6_zero_address (ipv6_address_t *ipv6_dest_addr) +{ + if (!ipv6_dest_addr) { + return; + } + + ipv6_dest_addr->v6_addr.v6_addr32[0] = 0; + ipv6_dest_addr->v6_addr.v6_addr32[1] = 0; + ipv6_dest_addr->v6_addr.v6_addr32[2] = 0; + ipv6_dest_addr->v6_addr.v6_addr32[3] = 0; + return; +} + + +/** + * NAME + * ipv6_address_is_global + * + * SYNOPSIS + * static inline boolean_t + * ipv6_address_is_global(ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to determine if the IPv6 address is global. + * 2000::/3 Global Unicast + * + * INPUT PARAMETERS + * ipv6_src_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes + * FALSE - nope! + * + */ +static inline boolean_t +ipv6_address_is_global (ipv6_address_t *ipv6_src_addr) +{ + + if (IPV6_GLOBAL_PREFIX == + (ipv6_src_addr->v6_addr.v6_addr32[0] & IPV6_GLOBAL_PREFIX)) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * ipv6_address_is_multicast + * + * SYNOPSIS + * static inline boolean_t + * ipv6_address_is_multicast(ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to determine if the IPv6 address is multicast. + * FF00::/8 Multicast + * + * INPUT PARAMETERS + * ipv6_src_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes + * FALSE - nope! + * + */ +static inline boolean_t +ipv6_address_is_multicast (ipv6_address_t *ipv6_src_addr) +{ + + if (IPV6_MULTICAST_PREFIX == + (ipv6_src_addr->v6_addr.v6_addr32[0] & IPV6_MULTICAST_PREFIX)) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * ipv6_address_is_linklocal + * + * SYNOPSIS + * static inline boolean_t + * ipv6_address_is_linklocal(ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to determine if the IPv6 address is link local. + * FE80::/10 Link Local Unicast + * + * INPUT PARAMETERS + * ipv6_src_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes + * FALSE - nope! + * + */ +static inline boolean_t +ipv6_address_is_linklocal (ipv6_address_t *ipv6_src_addr) +{ + if (IPV6_LINK_LOCAL_PREFIX == + (ipv6_src_addr->v6_addr.v6_addr32[0] & IPV6_LINK_LOCAL_PREFIX)) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * static inline boolean_t + * ipv6_compare_address(ipv6_address_t *ipv6_dest_addr, + * ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to compare two IPv6 addresses + * + * INPUT PARAMETERS + * ipv6_dest_addr - pointer to the destination IPv6 address + * + * ipv6_src_addr - pointer to the src IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - addresses equal + * FALSE - not equal + * + */ +static inline boolean_t +ipv6_compare_address (ipv6_address_t *ipv6_dest_addr, + ipv6_address_t *ipv6_src_addr) +{ + if (!ipv6_dest_addr || !ipv6_src_addr) { + return (FALSE); + } + + if (ipv6_dest_addr->v6_addr.v6_addr32[0] == + ipv6_src_addr->v6_addr.v6_addr32[0] && + ipv6_dest_addr->v6_addr.v6_addr32[1] == + ipv6_src_addr->v6_addr.v6_addr32[1] && + ipv6_dest_addr->v6_addr.v6_addr32[2] == + ipv6_src_addr->v6_addr.v6_addr32[2] && + ipv6_dest_addr->v6_addr.v6_addr32[3] == + ipv6_src_addr->v6_addr.v6_addr32[3]) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * ipv6_copy_address + * + * SYNOPSIS + * static inline void + * ipv6_copy_address(ipv6_address_t *ipv6_dest_addr, + * ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to compare two IPv6 addresses + * + * INPUT PARAMETERS + * ipv6_dest_addr - pointer to the destination IPv6 address + * + * ipv6_src_addr - pointer to the src IPv6 address + * + * OUTPUT PARAMETERS + * ipv6_dest_addr - updated + * + * RETURN VALUE + * none + * + */ +static inline void +ipv6_copy_address (ipv6_address_t *ipv6_dest_addr, + ipv6_address_t *ipv6_src_addr) +{ + if (!ipv6_dest_addr || !ipv6_src_addr) { + return; + } + + ipv6_dest_addr->v6_addr.v6_addr32[0] = + ipv6_src_addr->v6_addr.v6_addr32[0]; + ipv6_dest_addr->v6_addr.v6_addr32[1] = + ipv6_src_addr->v6_addr.v6_addr32[1]; + ipv6_dest_addr->v6_addr.v6_addr32[2] = + ipv6_src_addr->v6_addr.v6_addr32[2]; + ipv6_dest_addr->v6_addr.v6_addr32[3] = + ipv6_src_addr->v6_addr.v6_addr32[3]; + + return; +} + + + +extern void +ipv6_print_address(char *p2label, ipv6_address_t *ipv6_src_addr); + +extern void +ipv6_ascii2digits(ipv6_address_t *ipv6_dest_addr, char *input); + +#endif + diff --git a/dlep_radio_ipv4/mac_address.c b/dlep_radio_ipv4/mac_address.c new file mode 100644 index 0000000..f6fab64 --- /dev/null +++ b/dlep_radio_ipv4/mac_address.c @@ -0,0 +1,169 @@ +/*---------------------------------------------------------------------- + * mac_address.c -- MAC Address Support Routines + * + * January 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "mac_address.h" + + +/** + * NAME + * mac_print_address + * + * SYNOPSIS + * #include "man_mac_address.h" + * void + * mac_print_address (char *p2label, uint8_t mac[]) + * + * DESCRIPTION + * This function can be used to print the MAC address. If + * the p2label is non-NULL, the label prefixes the MAC. + * + * INPUT PARAMETERS + * p2label - Pointer to the label + * + * mac - Pointer to the mac address array + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +mac_print_address (char *p2label, uint8_t mac[]) +{ + if (p2label) { + printf("%s %02x:%02x:%02x:%02x:%02x:%02x \n", + p2label, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + } else { + printf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x \n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + return; +} + + +/** + * NAME + * mac_ascii2digits + * + * SYNOPSIS + * #include "man_mac_address.h" + * void + * mac_ascii2digits(uint8_t mac_dest_addr[], char *input) + * + * DESCRIPTION + * This function converts an ascii notation, 12:34:56:78:90:ab + * MAC address into an array. + * + * INPUT PARAMETERS + * mac_dest_addr - Pointer to the mac address array + * + * input - pointer the string + * + * OUTPUT PARAMETERS + * mac_dest_addr - updated + * + * RETURN VALUE + * none + * + * EXAMPLES + * mac_dest_addr[0] = 12; + * mac_dest_addr[1] = 34; + * mac_dest_addr[2] = 56; + * mac_dest_addr[3] = 78; + * mac_dest_addr[4] = 90; + * mac_dest_addr[5] = ab; + * + * If there is an error, the remaining mac[i] are 0. + * + */ +void +mac_ascii2digits (uint8_t mac_dest_addr[], char *input) +{ + uint32_t i; + uint8_t digit; + uint32_t maci; + + if (!mac_dest_addr) { + return; + } + + /* zero the users mac array */ + for (i=0; i= '0' && input[i] <='9') { + digit = (input[i] - '0') * (16); + } else if (input[i] >= 'a' && input[i] <='f') { + digit = (input[i] - 'a' + 10) * (16); + } else if (input[i] >= 'A' && input[i] <='F') { + digit = (input[i] - 'A' + 10) * (16); + } else { + return; + } + + i++; + if (input[i] >= '0' && input[i] <='9') { + digit += (input[i] - '0'); + } else if (input[i] >= 'a' && input[i] <='f') { + digit += (input[i] - 'a' + 10); + } else if (input[i] >= 'A' && input[i] <='F') { + digit += (input[i] - 'A' + 10); + } else { + return; + } + + mac_dest_addr[maci] = digit; + + i++; + if (input[i] != ':') { + return; + } + + maci++; + } + + return; +} + diff --git a/dlep_radio_ipv4/mac_address.h b/dlep_radio_ipv4/mac_address.h new file mode 100644 index 0000000..92e2f38 --- /dev/null +++ b/dlep_radio_ipv4/mac_address.h @@ -0,0 +1,361 @@ +/*---------------------------------------------------------------------- + * mac_address.h + * + * January 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __MAC_ADDRESS_H__ +#define __MAC_ADDRESS_H__ + +#include "safe_types.h" +#include "network_order.h" + + +/* + * MAC in string Dot Notation: 11:22:33:44:55:66 + */ +#define MAC_DOT_LEN_IN_BYTES ( 18 ) + +/* + * MAC in byte array[] + */ +#define MAC_ADDR_LEN_IN_BYTES ( 6 ) + + + +/** + * NAME + * mac_put_address + * + * SYNOPSIS + * static inline uint8_t + * *mac_put_address(uint8_t *mp, uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to copy the source MAC address to + * the destination pointer mp, in network order. + * + * INPUT PARAMETERS + * mp - destination buffer pointer + * + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTNPUT PARAMETERS + * mp - updated + * + * RETURN VALUE + * Pointer to the next byte in the destination space, mp + * + */ +static inline uint8_t +*mac_put_address (uint8_t *mp, uint8_t *mac_src_addr) +{ + if (!mac_src_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[0]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[1]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[2]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[3]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[4]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[5]); + mp++; + + return (mp); +} + + +/** + * NAME + * mac_get_address + * + * SYNOPSIS + * static inline uint8_t + * *mac_get_address(uint8_t *mac_dest_addr, uint8_t *mp) + * + * DESCRIPTION + * Use this function to copy a network ordered MAC address from + * the pointer mp to the destination array mac_dest_addr[]. + * + * INPUT PARAMETERS + * mac_dest_addr - pointer to the destination mac address, 6-bytes + * + * mp - source pointer to copy from + * + * OUTPUT PARAMETERS + * mac_dest_addr - updated + * + * RETURN VALUE + * Pointer to the next byte in the source space, mp + * + */ +static inline uint8_t +*mac_get_address (uint8_t *mac_dest_addr, uint8_t *mp) +{ + if (!mac_dest_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[0]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[1]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[2]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[3]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[4]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[5]); + mp++; + + return (mp); +} + + +/** + * NAME + * mac_zero_address + * + * SYNOPSIS + * static inline void + * mac_zero_address(uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to zero a MAC address. + * + * INPUT PARAMETERS + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTPUT PARAMETERS + * mac_src_addr - updated + * + * RETURN VALUE + * None + * + */ +static inline void +mac_zero_address (uint8_t *mac_src_addr) +{ + if (!mac_src_addr) { + return; + } + + mac_src_addr[0] = 0; + mac_src_addr[1] = 0; + mac_src_addr[2] = 0; + mac_src_addr[3] = 0; + mac_src_addr[4] = 0; + mac_src_addr[5] = 0; + return; +} + + +/** + * NAME + * mac_set_to_broadcast + * + * SYNOPSIS + * static inline void + * mac_set_to_broadcast(uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to set the MAC address to the broadcast address. + * + * INPUT PARAMETERS + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTPUT PARAMETERS + * mac_src_addr - updated + * + * RETURN VALUE + * None + * + */ +static inline void +mac_set_to_broadcast (uint8_t *mac_src_addr) +{ + if (!mac_src_addr) { + return; + } + + mac_src_addr[0] = 0xFF; + mac_src_addr[1] = 0xFF; + mac_src_addr[2] = 0xFF; + mac_src_addr[3] = 0xFF; + mac_src_addr[4] = 0xFF; + mac_src_addr[5] = 0xFF; + return; +} + + +/** + * NAME + * mac_is_broadcast + * + * SYNOPSIS + * static inline boolean_t + * mac_is_broadcast(uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to determine if this is a broadcast MAC address + * + * INPUT PARAMETERS + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes + * FALSE - no + * + */ +static inline boolean_t +mac_is_broadcast (uint8_t *mac_src_addr) +{ + if (!mac_src_addr) { + return (FALSE); + } + + if (mac_src_addr[0] == 0xFF && + mac_src_addr[1] == 0xFF && + mac_src_addr[2] == 0xFF && + mac_src_addr[3] == 0xFF && + mac_src_addr[4] == 0xFF && + mac_src_addr[5] == 0xFF) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * mac_compare_address + * + * SYNOPSIS + * static inline boolean_t + * mac_compare_address(uint8_t *mac_dest_addr, + * uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to compare two MAC addresses + * + * INPUT PARAMETERS + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * mac_dest_addr - pointer to the destination mac address, 6-bytes + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - addresses equal + * FALSE - not equal + * + */ +static inline boolean_t +mac_compare_address (uint8_t *mac_dest_addr, + uint8_t *mac_src_addr) +{ + if (!mac_dest_addr || !mac_src_addr) { + return (FALSE); + } + + if (mac_dest_addr[0] == mac_src_addr[0] && + mac_dest_addr[1] == mac_src_addr[1] && + mac_dest_addr[2] == mac_src_addr[2] && + mac_dest_addr[3] == mac_src_addr[3] && + mac_dest_addr[4] == mac_src_addr[4] && + mac_dest_addr[5] == mac_src_addr[5]) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * mac_copy_address + * + * SYNOPSIS + * static inline void + * mac_copy_address(uint8_t *mac_dest_addr, + * uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to copy a MAC address + * + * INPUT PARAMETERS + * mac_dest_addr - pointer to the destination mac address, 6-bytes + * + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTPUT PARAMETERS + * mac_dest_addr - updated + * + * RETURN VALUE + * none + * + */ +static inline void +mac_copy_address (uint8_t *mac_dest_addr, + uint8_t *mac_src_addr) +{ + if (!mac_dest_addr || !mac_src_addr) { + return; + } + + mac_dest_addr[0] = mac_src_addr[0]; + mac_dest_addr[1] = mac_src_addr[1]; + mac_dest_addr[2] = mac_src_addr[2]; + mac_dest_addr[3] = mac_src_addr[3]; + mac_dest_addr[4] = mac_src_addr[4]; + mac_dest_addr[5] = mac_src_addr[5]; + return; +} + + + +extern void +mac_print_address(char *p2label, uint8_t mac[]); + +extern void +mac_ascii2digits(uint8_t mac_dest_addr[], char *input); + +#endif + diff --git a/dlep_radio_ipv4/mdr_present b/dlep_radio_ipv4/mdr_present new file mode 100644 index 0000000..da98363 --- /dev/null +++ b/dlep_radio_ipv4/mdr_present @@ -0,0 +1,43 @@ +rfc5444_decoder_tlv.c: message_scratch_pad->major_version = major_version; +rfc5444_decoder_tlv.c: message_scratch_pad->major_version_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->minor_version = minor_version; +rfc5444_decoder_tlv.c: message_scratch_pad->minor_version_present = TRUE; +rfc5444_decoder_tlv.c: desc = message_scratch_pad->peer_type_description; +rfc5444_decoder_tlv.c: mac_copy_address(message_scratch_pad->mac_address, mac_addr); +rfc5444_decoder_tlv.c: message_scratch_pad->mac_address_present = TRUE; +rfc5444_decoder_tlv.c: ipv4_copy_address(&message_scratch_pad->ipv4_address, &ipv4_addr); +rfc5444_decoder_tlv.c: message_scratch_pad->ipv4_address_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->ipv4_operation = operation; +rfc5444_decoder_tlv.c: message_scratch_pad->ipv6_address_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->ipv6_operation = operation; +rfc5444_decoder_tlv.c: ipv6_copy_address(&message_scratch_pad->ipv6_address, &ipv6_addr); +rfc5444_decoder_tlv.c: message_scratch_pad->mdr_tx = mdr; +rfc5444_decoder_tlv.c: message_scratch_pad->mdr_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->mdr_rx = mdr; +rfc5444_decoder_tlv.c: message_scratch_pad->mdr_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->cdr_tx = cdr; +rfc5444_decoder_tlv.c: message_scratch_pad->cdr_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->cdr_rx = cdr; +rfc5444_decoder_tlv.c: message_scratch_pad->cdr_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->latency = latency; +rfc5444_decoder_tlv.c: message_scratch_pad->latency_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->resources_tx = resources; +rfc5444_decoder_tlv.c: message_scratch_pad->resources_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->resources_rx = resources; +rfc5444_decoder_tlv.c: message_scratch_pad->resources_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->rlq_tx = rlq; +rfc5444_decoder_tlv.c: message_scratch_pad->rlq_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->rlq_rx = rlq; +rfc5444_decoder_tlv.c: message_scratch_pad->rlq_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->status_code = status_code; +rfc5444_decoder_tlv.c: message_scratch_pad->status_code_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->eft = eft; +rfc5444_decoder_tlv.c: message_scratch_pad->port = port; +rfc5444_decoder_tlv.c: message_scratch_pad->mrw = mrw; +rfc5444_decoder_tlv.c: message_scratch_pad->rrw = rrw; +rfc5444_decoder_tlv.c: message_scratch_pad->cws_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->cgr = cgr; +rfc5444_decoder_tlv.c: message_scratch_pad->credit_req_present = TRUE; +rfc5444_decoder_tlv.c: message_scratch_pad->hbt = hbt; +rfc5444_decoder_tlv.c: message_scratch_pad->dlepv7_optional_signal |= (1 << opt_signals); +rfc5444_decoder_tlv.c: message_scratch_pad->dlepv7_optional_data_item |= (1 << opt_data_item ); diff --git a/dlep_radio_ipv4/network_order.h b/dlep_radio_ipv4/network_order.h new file mode 100644 index 0000000..a18c1ef --- /dev/null +++ b/dlep_radio_ipv4/network_order.h @@ -0,0 +1,234 @@ +/*---------------------------------------------------------------------- + * network_order.h -- macros to deal with byte order + * + * January 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __NETWORK_ORDER_H__ +#define __NETWORK_ORDER_H__ + +#include + + +/* + * Network Order is the transmission of the most significant byte first, + * or big-endian. + * http://en.wikipedia.org/wiki/Endianness + * + * Little-Endian architectures, the low-order byte of a word is stored + * in the lowest address in memory. + * + * Big-Endian architectures, the high-order byte of a word is stored + * in the lowest address in memory. + * + * Porting, it may be necessary to modify these functions based upon your + * platform. + * + * 16-bits + * LSB ----------------> MSB Big Endian + * | Byte1 | Byte0 | + * MSB <---------------- LSB Little Endian + * + * 32-bits + * LSB --------------------------------> MSB Big Endian + * | Byte3 | Byte2 | Byte1 | Byte0 | + * MSB <-------------------------------- LSB Little Endian + * + */ + +/* + * Define the macro for processor order to network order + * + * PowerPC, 680x0 + * #define __BIG_ENDIAN__ + * #define __BIG_ENDIAN_TO_FROM_NETWORK__ + * + * x86, x64 + * Note: MAC gcc defines the __LITTLE_ENDIAN__ macro + * #define __LITTLE_ENDIAN__ + * #define __LITTLE_ENDIAN_TO_FROM_NETWORK__ + */ + +#define __LITTLE_ENDIAN_TO_FROM_NETWORK__ + + +/* 8-bit moves */ +#undef NETWORK_ORDER_GETCHAR +#define NETWORK_ORDER_GETCHAR(ptr, value) { \ + (value) = *((char *)ptr); \ +} + +#undef NETWORK_ORDER_PUTCHAR +#define NETWORK_ORDER_PUTCHAR(ptr, value) { \ + *((char *)ptr) = (char)(value); \ +} + + +/* unsigned 8-bit moves */ +#undef NETWORK_ORDER_GETBYTE +#define NETWORK_ORDER_GETBYTE(ptr, value) { \ + (value) = *((uint8_t *)ptr); \ +} + +#undef NETWORK_ORDER_PUTBYTE +#define NETWORK_ORDER_PUTBYTE(ptr, value) { \ + *((uint8_t *)ptr) = (uint8_t)(value); \ +} + + +#if defined __LITTLE_ENDIAN_TO_FROM_NETWORK__ + +/* 16-bit moves */ +#undef NETWORK_ORDER_GETSHORT +#define NETWORK_ORDER_GETSHORT(ptr, value) { \ + (value) = *((uint8_t *)ptr + 0); \ + (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); \ +} + + +#undef NETWORK_ORDER_PUTSHORT +#define NETWORK_ORDER_PUTSHORT(ptr, value) { \ + *((uint8_t *)ptr + 0) = (uint8_t)((value) >> 8); \ + *((uint8_t *)ptr + 1) = (uint8_t)(value); \ +} + + +/* 32-bit moves */ +#undef NETWORK_ORDER_GETLONG +#define NETWORK_ORDER_GETLONG(ptr, value) { \ + (value) = *((uint8_t *)ptr + 0); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 2); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 3); \ +} + +#undef NETWORK_ORDER_PUTLONG +#define NETWORK_ORDER_PUTLONG(ptr, value) { \ + *((uint8_t *)ptr + 0) = (uint8_t) ((value) >> 24); \ + *((uint8_t *)ptr + 1) = (uint8_t) ((value) >> 16); \ + *((uint8_t *)ptr + 2) = (uint8_t) ((value) >> 8); \ + *((uint8_t *)ptr + 3) = (uint8_t) (value); \ +} + + +/* 64-bit moves */ +#undef NETWORK_ORDER_GETLLONG +#define NETWORK_ORDER_GETLLONG(ptr, value) { \ + (value) = *((uint8_t *)ptr + 0); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 2); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 3); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 4); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 5); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 6); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 7); \ +} + +#undef NETWORK_ORDER_PUTLLONG +#define NETWORK_ORDER_PUTLLONG(ptr, value) { \ + *((uint8_t *)ptr + 0) = (uint8_t) ((value) >> 56); \ + *((uint8_t *)ptr + 1) = (uint8_t) ((value) >> 48); \ + *((uint8_t *)ptr + 2) = (uint8_t) ((value) >> 40); \ + *((uint8_t *)ptr + 3) = (uint8_t) ((value) >> 32); \ + *((uint8_t *)ptr + 4) = (uint8_t) ((value) >> 24); \ + *((uint8_t *)ptr + 5) = (uint8_t) ((value) >> 16); \ + *((uint8_t *)ptr + 6) = (uint8_t) ((value) >> 8); \ + *((uint8_t *)ptr + 7) = (uint8_t) (value); \ +} + + +#elif defined __BIG_ENDIAN_TO_FROM_NETWORK__ + +/* 16-bit moves */ +#undef NETWORK_ORDER_GETSHORT +#define NETWORK_ORDER_GETSHORT(ptr, value) { \ + (value) = *((uint8_t *)ptr + 1); \ + (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 0); \ +} + + +#undef NETWORK_ORDER_PUTSHORT +#define NETWORK_ORDER_PUTSHORT(ptr, value) { \ + *((uint8_t *)ptr + 1) = (uint8_t)((value) >> 8); \ + *((uint8_t *)ptr + 0) = (uint8_t)(value); \ +} + + +/* 32-bit moves */ +#undef NETWORK_ORDER_GETLONG +#define NETWORK_ORDER_GETLONG(ptr, value) { \ + (value) = *((uint8_t *)ptr + 3); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 2); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 0); \ +} + +#undef NETWORK_ORDER_PUTLONG +#define NETWORK_ORDER_PUTLONG(ptr, value) { \ + *((uint8_t *)ptr + 3) = (uint8_t) ((value) >> 24); \ + *((uint8_t *)ptr + 2) = (uint8_t) ((value) >> 16); \ + *((uint8_t *)ptr + 1) = (uint8_t) ((value) >> 8); \ + *((uint8_t *)ptr + 0) = (uint8_t) (value); \ +} + + +/* 64-bit moves */ +#undef NETWORK_ORDER_GETLLONG +#define NETWORK_ORDER_GETLLONG(ptr, value) { \ + (value) = *((uint8_t *)ptr + 7); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 6); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 5); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 4); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 3); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 2); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 0); \ +} + +#undef NETWORK_ORDER_PUTLLONG +#define NETWORK_ORDER_PUTLLONG(ptr, value) { \ + *((uint8_t *)ptr + 7) = (uint8_t) ((value) >> 56); \ + *((uint8_t *)ptr + 6) = (uint8_t) ((value) >> 48); \ + *((uint8_t *)ptr + 5) = (uint8_t) ((value) >> 40); \ + *((uint8_t *)ptr + 4) = (uint8_t) ((value) >> 32); \ + *((uint8_t *)ptr + 3) = (uint8_t) ((value) >> 24); \ + *((uint8_t *)ptr + 2) = (uint8_t) ((value) >> 16); \ + *((uint8_t *)ptr + 1) = (uint8_t) ((value) >> 8); \ + *((uint8_t *)ptr + 0) = (uint8_t) (value); \ +} + + +#else +#error CPU endianness not defined. +#endif + +#endif + + diff --git a/dlep_radio_ipv4/packet_dump.c b/dlep_radio_ipv4/packet_dump.c new file mode 100644 index 0000000..3e29ca1 --- /dev/null +++ b/dlep_radio_ipv4/packet_dump.c @@ -0,0 +1,125 @@ +/*------------------------------------------------------------------ + * packet_dump.c -- hex display of packet data + * + * Copyright (c) 2009, 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *----------------------------------------------------------------- + */ + +#include + +#include "packet_dump.h" + + +/** + * NAME + * packet_dump + * + * SYNOPSIS + * #include "packet_dump.h" + * void + * packet_dump(char *p2label, + * void *ptr, + * uint32_t number_bytes) + * + * DESCRIPTION + * This function displays a packet to facilitate + * debug and integration. + * + * INPUT PARAMETERS + * p2label - Pointer to a string label, such as IN or OUT + * + * ptr - Pointer to the message + * + * number_bytes - Number of bytes to display + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + * EXAMPLE + * OUTGOING- 0x04 0x00 0x0c 0x01 0x10 0x09 0x0a 0x00 + * OUTGOING- 0x00 0x03 0xe8 0x00 0x00 0x04 0x57 0x0a + * OUTGOING- 0x13 0x00 0x15 0x00 0x03 0x00 0x0d 0x04 + * OUTGOING- 0x10 0x06 0x11 0x22 0x33 0x44 0x55 0x66 + * OUTGOING- 0x0c 0x10 0x01 0x00 + * + * + */ +void +packet_dump (char *p2label, + void *ptr, + uint32_t number_bytes) +{ + uint8_t *p; + uint32_t i; + + if (ptr == NULL) { + return; + } + +/* + * no minimum balance required to open an account! + */ +#if 0 +#define MIN_NUMBER_OF_BYTES ( 16 ) + if (number_bytes < MIN_NUMBER_OF_BYTES) { + return; + } +#endif + +/* + * put a limit on it + */ +#define MAX_NUMBER_OF_BYTES ( 512 ) + if (number_bytes > MAX_NUMBER_OF_BYTES) { + number_bytes = MAX_NUMBER_OF_BYTES; + } + + /* + * Loop across the data, displaying in lines. + */ +#define MAX_BYTES_PER_LINE ( 8 ) + + p = (uint8_t *)ptr; + for (i=0; i +#include +#include + +#include "safe_types.h" +#include "network_order.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_packet_header.h" + +#include "rfc5444_decoder.h" +#include "dlep_client_peer_fsm.h" + +#define RFC5444_DEBUG printf +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ + + +/* + * Set - block open + * Clear - block closed + */ +#define DECODER_STATE_PACKET ( 0x01 ) +#define DECODER_STATE_MESSAGE ( 0x02 ) +#define DECODER_STATE_TLV ( 0x04 ) + + +static rfc5444_decoder_message_fv_t message_parser_fv; + +/* + * We add one to the max to account for the 0 based array. The + * TLV code is the index straight-up. 0--invalid, 1-255 valid. + */ +static rfc5444_decoder_tlv_fv_t tlv_decoder_fv[RFC5444_MAX_TLV_CODE+1]; + + +/* + * The undefined TLV decoder! Steps over undefined TLVs. + */ +static rfc5444_rc_t +rfc5444_undefined_tlv_decoder ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint8_t tlv_flags; + uint8_t tlv8_length; + uint16_t tlv16_length; + + printf("\n Not supported TLV "); + if (p2decoder_state->tlv_block_length >= sizeof(uint8_t)) { + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_flags); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + } else { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + if (tlv_flags & + (THASTYPEEXT | THASSINGLEINDEX | THASMULTIINDEX | THASMULTIVALUE)) { + if (verbose) { + RFC5444_DEBUG("ERROR: %s-%u tlv code=%u flags=0x%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_flags); + } + return (RC_RFC5444_INVALID_TLV_FLAG); + } + + tlv16_length = 0; + if (tlv_flags & THASVALUE) { + if (tlv_flags & THASEXTLEN) { + if (p2decoder_state->tlv_block_length >= sizeof(uint16_t)) { + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, + tlv16_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->tlv_block_length -= sizeof(uint16_t); + } else { + if (verbose) { + RFC5444_DEBUG("ERROR: %s-%u tlv code=%u flags=0x%0x" + " tlv16_length=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_flags, + tlv16_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + } else { + if (p2decoder_state->tlv_block_length >= sizeof(uint8_t)) { + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, + tlv8_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + tlv16_length = tlv8_length; + } else { + if (verbose) { + RFC5444_DEBUG("ERROR: %s-%u tlv code=%u flags=0x%0x" + " tlv16_length=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_flags, + tlv16_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + } + + if (p2decoder_state->tlv_block_length >= tlv16_length) { + p2decoder_state->tlv_block_length -= tlv16_length; + } else { + tlv16_length = p2decoder_state->tlv_block_length; + p2decoder_state->tlv_block_length = 0; + if (verbose) { + RFC5444_DEBUG("ERROR: %s-%u tlv code=%u flags=0x%0x" + " tlv16_length=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_flags, + tlv16_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + RFC5444_DEBUG("%s-%u tlv block length %u bytes \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv16_length); + } + + p2decoder_state->parse_ptr += tlv16_length; + return (RC_RFC5444_OK); +} + + + +/* + * An internal function to manage TLV block decoding + */ +static rfc5444_rc_t +rfc5444_decoder_parse_tlv_block ( + uint8_t *base_ptr, + uint32_t block_len, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_code; + uint8_t tlv_len; + rfc5444_rc_t rc; + dlep_context_peer_t *p2peer; + + p2peer = context_ptr; + + /* + * The tlv_block_length does not include the + */ + rc = RC_RFC5444_OK; + while ((p2decoder_state->message_block_length) > 2){ + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_code); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= sizeof(uint16_t); + + if (dlep_client_fsm_get_state(p2peer)) { + if (!(p2peer->optional_data_item & (1 << (tlv_code - 1)))) { + printf("\n Optional data TLV %d ignore", tlv_code); + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_len); + p2decoder_state->message_block_length -= (tlv_len + 1); + p2decoder_state->parse_ptr += (tlv_len + 1); + continue; + } + } + + /* + * note that tlv_codes are the index into the vector + * table of decoders. 0--invalid, 254--max. + * now invoke the specific TLV parser + */ + rc = (*tlv_decoder_fv[tlv_code])(tlv_code, + p2decoder_state, + context_ptr, + verbose); + if (rc != RC_RFC5444_OK) { + break; + } + + } + + + return (rc); +} + + +/** + * NAME + * rfc5444_decoder_packet + * + * SYNOPSIS + * rfc5444_rc_t + * *rfc5444_decoder_packet(uint8_t *packet_ptr, + * uint32_t packet_len, + * void *context_ptr, + * boolean_t verbose) + * + * DESCRIPTION + * This function is used to allocate and initialize the + * decoder state variable and then decode the packet. + * + * INPUT PARAMETERS + * packet_ptr - a pointer to the packet to be parsed + * + * packet_len - the number of bytes in the packet + * + * context_ptr - a pointer passed through to the users + * parsing routine + * + * verbose - TRUE enables debug + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - packet successfully parsed + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_packet (uint8_t *packet_ptr, + uint32_t packet_len, + void *context_ptr, + boolean_t verbose) +{ + rfc5444_decoder_state_t *p2decoder_state; + rfc5444_rc_t rc; + dlep_context_peer_t *p2peer; + uint32_t dlep_signal_flag; + int signal = FALSE; + + p2peer = context_ptr; + + if (!packet_ptr) { + return (RC_RFC5444_NULL_POINTER); + } + // printf("Decoder packet reaching here\n"); + /* verify the packet length is in the ball park */ + if (packet_len < RFC5444_MIN_PACKET_LEN || + packet_len > RFC5444_MAX_PACKET_LEN) { + return (RC_RFC5444_INVALID_PACKET_LENGTH); + } + + p2decoder_state = malloc(sizeof(rfc5444_decoder_state_t)); + if (!p2decoder_state) { + return (RC_RFC5444_NO_RESOURCES); + } + + /* parse_ptr is the working buffer pointer */ + p2decoder_state->parse_ptr = packet_ptr; + + /*checking this is signal or message */ + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr,dlep_signal_flag); + if(dlep_signal_flag == 0x444C4550) { + signal = TRUE; + } + //printf("signal value is %d\n",signal); + + /* packet_length is the working length to parse */ + p2decoder_state->packet_length = packet_len; + + /* save the original packet pointer */ + p2decoder_state->packet_ptr = packet_ptr; + + // p2decoder_state->packet_flags = 0; + + p2decoder_state->message_block_length = 0; +// p2decoder_state->message_block_flags = 0; + +// p2decoder_state->tlv_block_length = 0; +// p2decoder_state->tlv_block_base = NULL; + + /* + * Notes on parsing - the parse_ptr is incremented to + * keep up with the next byte position to parse while + * the packet_len is decremented to track how many bytes + * to parse remain. + * If an error occurs, parsing stops and the remainder + * of the packet is discarded. It is too difficult to + * unwind and still maintain packet integrity to continue. + */ + + /* + * Loop through messages + */ + + if (p2decoder_state->packet_length < (2 * sizeof(uint8_t))) { + /** user must release the packet **/ + free(p2decoder_state); + return (RC_RFC5444_INVALID_PACKET_LENGTH); + } + + + if (signal) { + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->packet_length -= sizeof(uint32_t); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, + p2decoder_state->message_block_code); + + if(p2decoder_state->message_block_code > 20 ) { + if(verbose) { + RFC5444_DEBUG("%s-%u Error: message feature " + "not supported \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + /** user must release the packet **/ + free(p2decoder_state); + return (RC_RFC5444_INVALID_MESSAGE_LENGTH); + } + + /* if (dlep_client_fsm_get_state(p2peer)) { + if (!(p2peer->optional_signal & (1 << (p2decoder_state->message_block_code - 1)))) { + printf("\n Optional termination needed"); + } + } */ + + +/* NEED TO ADD MESSAGE VALIDATION */ + + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->packet_length -= sizeof(uint16_t); + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, + p2decoder_state->message_block_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->packet_length -= sizeof(uint16_t); + + + /* decode the TLV block if present */ + + if (p2decoder_state->message_block_length > 2) { + rc = rfc5444_decoder_parse_tlv_block( + p2decoder_state->tlv_block_base, + p2decoder_state->message_block_length, + p2decoder_state, + context_ptr, + verbose); + if (rc != RC_RFC5444_OK) { + if (verbose) { + RFC5444_DEBUG("%s-%u Error: tlv parser error %u-%s \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rc, + rfc5444_rc2string(rc)); + } + printf("\n lenth of message %d",p2decoder_state->message_block_length); + free(p2decoder_state); + return (rc); + } + } //END + /* + * now process the message + */ + (*message_parser_fv)(p2decoder_state->message_block_code, + p2decoder_state->seq_num, + context_ptr,signal); + + + /** user must release the buffer **/ + free(p2decoder_state); + + return (RC_RFC5444_OK); +} + + + +/** + * NAME + * rfc5444_decoder_free + * + * SYNOPSIS + * uint8_t + * *rfc5444_decoder_free( + * rfc5444_decoder_state_t *p2decoder_state) + * + * DESCRIPTION + * This function is used to release all resources associated with + * the decoding a packet. + * + * INPUT PARAMETERS + * rfc5444_decoder_state - This is a pointer to the decoder + * state variable to be freed. + * + * OUTPUT PARAMETERS + * rfc5444_decoder_state - contents and resources are freed + * + * RETURN VALUE + * none + * + */ +void +rfc5444_decoder_free (rfc5444_decoder_state_t *p2decoder_state) +{ + if (!p2decoder_state) { + return; + } + + if (p2decoder_state->packet_ptr) { + free(p2decoder_state->packet_ptr); + p2decoder_state->packet_ptr = NULL; + } + free(p2decoder_state); + return; +} + + +/** + * NAME + * rfc5444_decoder_tlv_register_cb + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_decoder_tlv_register_cb( + * uint8_t tlv_code, + * rfc5444_decoder_tlv_fv_t users_tlv_decoder) + * + * DESCRIPTION + * This function must be called to register a decoder for the + * specified RFC5444 TLV code. If there is a decoder already + * registered, the registration fails as the previous registration + * must be unregistered first. + * + * INPUT PARAMETERS + * tlv_code - The TLV code to be registered + * + * users_tlv_decoder - The user's TLV decoder function + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_tlv_register_cb ( + uint16_t tlv_code, + rfc5444_decoder_tlv_fv_t users_tlv_decoder) +{ + if (tlv_decoder_fv[tlv_code] != &rfc5444_undefined_tlv_decoder) { + /* someone is already registered */ + return (RC_RFC5444_STATE_ERROR); + } + + /* bind the new tlv decoder call-back */ + tlv_decoder_fv[tlv_code] = users_tlv_decoder; + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_decoder_tlv_unregister_cb + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_decoder_tlv_unregister_cb( + * uint8_t tlv_code) + * + * DESCRIPTION + * This function must be called to unregister a RFC5444 TLV decoder. + * The default decoder is installed for the TLV code. + * + * INPUT PARAMETERS + * tlv_code - The TLV code to be unregistered + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_tlv_unregister_cb (uint16_t tlv_code) +{ + tlv_decoder_fv[tlv_code] = &rfc5444_undefined_tlv_decoder; + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_decoder_init + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_decoder_init(void) + * + * DESCRIPTION + * This function must be called to initialize the decode prior to + * its use. Users may register specific TLV decoders after the + * initializatin. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_init (rfc5444_decoder_message_fv_t mp) +{ + uint32_t i; + + /*user call back to process a message */ + message_parser_fv = mp; + + for (i=0; i<(RFC5444_MAX_TLV_CODE+1); i++) { + tlv_decoder_fv[i] = &rfc5444_undefined_tlv_decoder; + } + + return (RC_RFC5444_OK); +} + diff --git a/dlep_radio_ipv4/rfc5444_decoder.h b/dlep_radio_ipv4/rfc5444_decoder.h new file mode 100644 index 0000000..d713e8d --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_decoder.h @@ -0,0 +1,130 @@ +/*------------------------------------------------------------------ + * rfc5444_decoder.h -- packet decoding routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + *------------------------------------------------------------------ + */ + +#ifndef ___RFC5444_DECODER__ +#define ___RFC5444_DECODER__ + +#include "safe_types.h" +#include "rfc5444_types.h" + +#include "rfc5444_scratch_pad.h" + +/* + * This is the structure type used to manage the decoding + * and parsing of the packet. + */ +/* D5 EDIT + * using packet_ptr, parse_ptr, packet_length and message block... + * remaining structure members need to remove + */ + +typedef struct { + uint8_t *packet_ptr; + + uint8_t *parse_ptr; + uint16_t packet_length; + + uint8_t packet_flags; + uint16_t seq_num; + + uint8_t message_block_code; + uint8_t message_block_flags; + uint16_t message_block_length; + + uint8_t *tlv_block_base; + uint8_t tlv_block_length; + +} rfc5444_decoder_state_t; + + +/* + * TLV decoder call-back type- must be provided by the user + * for each TLV processed by the protocol. + */ +typedef rfc5444_rc_t (*rfc5444_decoder_tlv_fv_t)( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *scratch_pad, + boolean_t verbose); + + +/* + * message decoder call-back type- must be provided + * by the user for his protocol. + */ +typedef void (*rfc5444_decoder_message_fv_t)( + uint16_t message_code, + uint16_t sequence_number, + void *context_ptr, int signal); + + +/* + * packet decoder call-back type- must be provided + * by the user for his protocol. + */ +typedef void (*rfc5444_decoder_packet_fv_t)( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *scratch_pad); + + + + +/* register a user tlv parser */ +extern rfc5444_rc_t +rfc5444_decoder_tlv_register_cb(uint16_t tlv_code, + rfc5444_decoder_tlv_fv_t users_tlv_decoder); + + +/* unregister a user's tlv parser, restoring the null parser */ +extern rfc5444_rc_t +rfc5444_decoder_tlv_unregister_cb(uint16_t tlv_code); + + +extern rfc5444_rc_t +rfc5444_decoder_packet(uint8_t *bufptr, + uint32_t buflen, + void *context_ptr, + boolean_t verbose); + + +/* release resources after decoding a packet */ +extern void +rfc5444_decoder_free(rfc5444_decoder_state_t *p2decoder_state); + + +/* required before use */ +extern rfc5444_rc_t +rfc5444_decoder_init(rfc5444_decoder_message_fv_t mp); + +#endif + diff --git a/dlep_radio_ipv4/rfc5444_decoder_tlv.c b/dlep_radio_ipv4/rfc5444_decoder_tlv.c new file mode 100644 index 0000000..fecc449 --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_decoder_tlv.c @@ -0,0 +1,1526 @@ +/*------------------------------------------------------------------ + * rfc5444_decoder_tlv.c -- decode DLEP RFC5444 TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "safe_types.h" +#include "network_order.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_decoder.h" + +#include "dlep_context_peer.h" + +#include "rfc5444_decoder_tlv.h" + +#define RFC5444_DEBUG printf +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ + +/* D5 EDIT */ + +/* + * Identification + */ +#if 0 +static rfc5444_rc_t +rfc5444_decoder_identification_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint32_t router_id; + uint32_t client_id; + uint8_t heartbeat_interval; + + dlep_context_peer_t *p2peer; + rfc5444_packet_scratch_pad_t *packet_scratch_pad; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + packet_scratch_pad = &p2peer->packet_scratch_pad; + message_scratch_pad = &p2peer->message_scratch_pad; + + // NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_flags); + // p2decoder_state->parse_ptr += sizeof(uint8_t); + // p2decoder_state->tlv_block_length -= sizeof(uint8_t); + + // if (tlv_flags != RFC5444_TLV_IDENTIFICATION_FLAGS) { + // return (RC_RFC5444_INVALID_TLV_FLAG); + // } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); +// p2decoder_state->tlv_block_length -= sizeof(uint8_t); +// p2decoder_state->message_block_length -= p2decoder_state->tlv_block_length ; + p2decoder_state->message_block_length -= tlv_length; + if (tlv_length != RFC5444_TLV_IDENTIFICATION_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, heartbeat_interval); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, router_id); + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->tlv_block_length -= sizeof(uint32_t); + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, client_id); + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->tlv_block_length -= sizeof(uint32_t); + + packet_scratch_pad->router_id = router_id; + packet_scratch_pad->router_id_present = TRUE; + + packet_scratch_pad->client_id = client_id; + packet_scratch_pad->client_id_present = TRUE; + + packet_scratch_pad->peer_heartbeat_interval = heartbeat_interval; + packet_scratch_pad->peer_heartbeat_interval_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s \n" + " router_id=%u client_id=%u " + "heartbeat_interval=%u seconds \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + router_id, + client_id, + heartbeat_interval); + } + return (RC_RFC5444_OK); +} + +#endif +/* + * Version + */ +static rfc5444_rc_t +rfc5444_decoder_version_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint16_t major_version; + uint16_t minor_version; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + if (tlv_length != RFC5444_TLV_VERSION_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, major_version); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, minor_version); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->major_version = major_version; + message_scratch_pad->major_version_present = TRUE; + + message_scratch_pad->minor_version = minor_version; + message_scratch_pad->minor_version_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s DLEP version=%u.%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + major_version, + minor_version); + } + return (RC_RFC5444_OK); +} + + +/* + * Peer Type + */ +static rfc5444_rc_t +rfc5444_decoder_peer_type_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + char *desc; + uint8_t *p2description; + uint32_t i; + uint8_t tlv_flags; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length > RFC5444_TLV_PEER_TYPE_MAX_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_flags); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + /* if (tlv_flags != RFC5444_TLV_PEER_TYPE_FLAGS) { + printf("suriya tlv flag of peer not matching\n"); + return (RC_RFC5444_INVALID_TLV_FLAG); + } */ + + + if (tlv_length) { + desc = message_scratch_pad->peer_type_description; + p2description = p2decoder_state->parse_ptr; + + for (i=0; iparse_ptr = p2description; + } + + if (verbose) { + RFC5444_DEBUG("%s-%u %s %s \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + p2peer->peer_type_description); + } + return (RC_RFC5444_OK); +} + + +/* + * MAC address + */ +static rfc5444_rc_t +rfc5444_decoder_mac_address_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint16_t mac_addr[MAC_ADDR_LEN_IN_BYTES]; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + if (tlv_length != RFC5444_TLV_MAC_ADDRESS_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + + p2decoder_state->parse_ptr = mac_get_address(mac_addr, + p2decoder_state->parse_ptr); + + mac_copy_address(message_scratch_pad->mac_address, mac_addr); + message_scratch_pad->mac_address_present = TRUE; + + return (RC_RFC5444_OK); +} + + +/* + * IPv4 address + */ +static rfc5444_rc_t +rfc5444_decoder_ipv4_address_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t operation; + ipv4_address_t ipv4_addr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != (RFC5444_TLV_IPV4_ADDRESS_LENGTH)) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + /** account for all parameters **/ + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, operation); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + p2decoder_state->parse_ptr = ipv4_get_address(&ipv4_addr, + p2decoder_state->parse_ptr); + + ipv4_copy_address(&message_scratch_pad->ipv4_address, &ipv4_addr); + + message_scratch_pad->ipv4_address_present = TRUE; + message_scratch_pad->ipv4_operation = operation; + + + if (verbose) { + ipv4_print_address("IPv4 Addr", &ipv4_addr); + RFC5444_DEBUG("%s-%u %s operation=%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + operation); + } + return (RC_RFC5444_OK); +} + +/* + * IPv4 attached subnet + */ +static rfc5444_rc_t +rfc5444_decoder_ipv4_attached_subnet_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t operation; + ipv4_address_t ipv4_addr; + uint8_t subnetmask; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + + } + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != (RFC5444_TLV_IPV4_ATTACHED_SUBNET_LENGTH)) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + /** account for all parameters **/ + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, operation); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + p2decoder_state->parse_ptr = ipv4_get_address(&ipv4_addr, + p2decoder_state->parse_ptr); + + ipv4_copy_address(&message_scratch_pad->ipv4_address, &ipv4_addr); + + message_scratch_pad->ipv4_address_present = TRUE; + message_scratch_pad->ipv4_operation = operation; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, subnetmask); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + + if (verbose) { + ipv4_print_address("IPv4 Addr", &ipv4_addr); + RFC5444_DEBUG("%s-%u %s operation=%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + operation); + } + return (RC_RFC5444_OK); +} + + +/* + * IPv6 address + */ +static rfc5444_rc_t +rfc5444_decoder_ipv6_address_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t operation; + ipv6_address_t ipv6_addr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != RFC5444_TLV_IPV6_ADDRESS_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + /** account for all parameters **/ + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, operation); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + p2decoder_state->parse_ptr = ipv6_get_address(&ipv6_addr, + p2decoder_state->parse_ptr); + + message_scratch_pad->ipv6_address_present = TRUE; + message_scratch_pad->ipv6_operation = operation; + + ipv6_copy_address(&message_scratch_pad->ipv6_address, &ipv6_addr); + + p2decoder_state->parse_ptr += sizeof(uint8_t); + if (verbose) { + ipv6_print_address("IPv6 Addr", &ipv6_addr); + RFC5444_DEBUG("%s-%u operation=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + operation); + } + return (RC_RFC5444_OK); +} + + +/* + * MDR TX Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_mdr_tx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint64_t mdr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_MDR_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, mdr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->mdr_tx = mdr; + message_scratch_pad->mdr_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s mdr tx=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + mdr); + } + return (RC_RFC5444_OK); +} + +/* + * MDR RX + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_mdr_rx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint64_t mdr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_MDR_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, mdr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->mdr_rx = mdr; + message_scratch_pad->mdr_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s mdr rx=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + mdr); + } + return (RC_RFC5444_OK); +} + + +/* + * CDR_TX Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_cdr_tx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint64_t cdr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_CDR_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, cdr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->cdr_tx = cdr; + message_scratch_pad->cdr_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s cdr tx =%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + cdr); + } + return (RC_RFC5444_OK); +} + +/* + * CDR_RX Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_cdr_rx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint64_t cdr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_CDR_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, cdr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->cdr_rx = cdr; + message_scratch_pad->cdr_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s cdr rx=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + cdr); + } + return (RC_RFC5444_OK); +} + + + + +/* + * Latency Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_latency_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint64_t latency; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, latency); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->latency = latency; + message_scratch_pad->latency_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s latency=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + latency); + } + return (RC_RFC5444_OK); +} + + +/* + * Resource Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_resources_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t resources; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, resources); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + message_scratch_pad->resources = resources; + message_scratch_pad->resources_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s resources=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + resources); + } + return (RC_RFC5444_OK); +} + + +/* + * Resources Link Metric TX + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_resources_tx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t resources; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, resources); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + message_scratch_pad->resources_tx = resources; + message_scratch_pad->resources_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s resources tx=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + resources); + } + return (RC_RFC5444_OK); +} + + +/* + * Resources Link Metric RX + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_resources_rx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t resources; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, resources); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= tlv_length; + message_scratch_pad->resources_rx = resources; + message_scratch_pad->resources_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s resources rx =%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + resources); + } + return (RC_RFC5444_OK); +} + + + +/* + * RLQ Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_rlq_tx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint16_t rlq; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RLQ_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, rlq); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->rlq_tx = rlq; + message_scratch_pad->rlq_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s rlq tx=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + rlq); + } + return (RC_RFC5444_OK); +} + +/* + * RLQ RX Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_rlq_rx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint16_t rlq; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RLQ_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, rlq); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->rlq_rx = rlq; + message_scratch_pad->rlq_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s rlq rx=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + rlq); + } + return (RC_RFC5444_OK); +} + +/* + * MTU Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_mtu_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint16_t mtu; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_MTU_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, mtu); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->mtu = mtu; + message_scratch_pad->mtu_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s rlq rx=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + mtu); + } + return (RC_RFC5444_OK); +} + + +/* + * Peer Status + */ +static rfc5444_rc_t +rfc5444_decoder_status_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t status_code; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, status_code); + p2decoder_state->parse_ptr += tlv_length; + + message_scratch_pad->status_code = status_code; + message_scratch_pad->status_code_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s status_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + status_code); + } + return (RC_RFC5444_OK); +} + +/*eft decoder */ +static rfc5444_rc_t +rfc5444_decoder_eft_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint32_t eft; + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_EFT_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, eft); + p2decoder_state->parse_ptr += sizeof(uint32_t); + + message_scratch_pad->eft = eft; + if (verbose) { + RFC5444_DEBUG("%s-%u %s eft=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + eft); + } + return (RC_RFC5444_OK); +} + +/* port TLV decoder */ +static rfc5444_rc_t +rfc5444_decoder_port_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint16_t port; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_PORT_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, port); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->port = port; + p2peer->peer_tcp_port = port; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s port=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + port); + } + return (RC_RFC5444_OK); +} + +/* credit_window_status_tlv */ + +static rfc5444_rc_t +rfc5444_decoder_credit_window_status_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint64_t mrw; + uint64_t rrw; + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_CREDIT_WINDOW_STATUS_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLLONG(p2decoder_state->parse_ptr, mrw); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + NETWORK_ORDER_GETLLONG(p2decoder_state->parse_ptr, rrw); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->mrw = mrw; + message_scratch_pad->rrw = rrw; + message_scratch_pad->cws_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s rrw=%llu mrw =%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + rrw, mrw); + } + return (RC_RFC5444_OK); +} + +/* credit grand */ + +static rfc5444_rc_t +rfc5444_decoder_credit_grand_request_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint64_t cgr; + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_CREDIT_GRANT_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLLONG(p2decoder_state->parse_ptr, cgr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->cgr = cgr; + if (verbose) { + RFC5444_DEBUG("%s-%u %s Credit grand req=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + cgr); + } + return (RC_RFC5444_OK); +} + +/*credit_request tlv */ +static rfc5444_rc_t +rfc5444_decoder_credit_request_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t cr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_CREDIT_REQUEST_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, cr); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + /* cr should be zero... add check later */ + + message_scratch_pad->credit_req_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s Credit req=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + cr); + } + return (RC_RFC5444_OK); +} + +static rfc5444_rc_t +rfc5444_decoder_heartbeat_interval_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint32_t hbt; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + if (tlv_length != 4) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, hbt); + p2decoder_state->parse_ptr += sizeof(uint32_t); + message_scratch_pad->hbt = hbt; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s Heart beat interval =%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + hbt); + } + + return (RC_RFC5444_OK); +} + +/* Below TLV functions are added for DLEPv7 */ +static rfc5444_rc_t +rfc5444_decoder_optinal_signal_supported_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t opt_signals; + uint8_t i; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint8_t); +#if 0 + if (tlv_length != RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } +#endif + for (i = 0; i < RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED_LENGTH ; i++) { + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, opt_signals); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + if(opt_signals) { + p2peer->optional_signal |= (1 << (opt_signals -1)); + } + + if (verbose) { + RFC5444_DEBUG("%s-%u %s dlepv7 optional_signal =%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + opt_signals); + } + } + + return (RC_RFC5444_OK); + +} + +static rfc5444_rc_t +rfc5444_decoder_optinal_data_item_supported_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint8_t opt_data_item; + uint8_t i; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint8_t); +#if 0 + if (tlv_length != RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } +#endif + for (i = 0; i < tlv_length ; i++) { + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, opt_data_item); + + p2decoder_state->parse_ptr += sizeof(uint8_t); + if (opt_data_item) { + p2peer->optional_data_item |= (1 << (opt_data_item -1)); + + } + + if (verbose) { + RFC5444_DEBUG("%s-%u %s dlepv7 opt_data_item =%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + opt_data_item); + } + } + return (RC_RFC5444_OK); +} + +/** + * NAME + * rfc5444_decoder_tlv_init + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_decoder_tlv_init(void) + * + * DESCRIPTION + * This function must be called to register the TLV decoders. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_tlv_init (void) +{ +#if 0 + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_IDENTIFICATION, + &rfc5444_decoder_identification_tlv); +#endif + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_VERSION, + &rfc5444_decoder_version_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_PEER_TYPE, + &rfc5444_decoder_peer_type_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_MAC_ADDRESS, + &rfc5444_decoder_mac_address_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_IPV4_ADDRESS, + &rfc5444_decoder_ipv4_address_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_IPV4_ATTACHED_SUBNET, + &rfc5444_decoder_ipv4_attached_subnet_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_IPV6_ADDRESS, + &rfc5444_decoder_ipv6_address_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_MDR_METRIC_TX, + &rfc5444_decoder_link_metric_mdr_tx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_MDR_METRIC_RX, + &rfc5444_decoder_link_metric_mdr_rx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_CDR_METRIC_TX, + &rfc5444_decoder_link_metric_cdr_tx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_CDR_METRIC_RX, + &rfc5444_decoder_link_metric_cdr_rx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_LATENCY_METRIC, + &rfc5444_decoder_link_metric_latency_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RESOURCES_METRIC_RX, + &rfc5444_decoder_link_metric_resources_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RESOURCES_METRIC_TX, + &rfc5444_decoder_link_metric_resources_tx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RESOURCES_METRIC_RX, + &rfc5444_decoder_link_metric_resources_rx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RLQ_METRIC_TX, + &rfc5444_decoder_link_metric_rlq_tx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RLQ_METRIC_RX, + &rfc5444_decoder_link_metric_rlq_rx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_MTU, + &rfc5444_decoder_link_metric_mtu_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_PORT, + &rfc5444_decoder_port_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_EFT_METRIC, + &rfc5444_decoder_eft_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_CREDIT_WINDOW_STATUS, + &rfc5444_decoder_credit_window_status_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_CREDIT_GRANT, + &rfc5444_decoder_credit_grand_request_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_CREDIT_REQUEST, + &rfc5444_decoder_credit_request_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_HEARTBEAT_INTERVAL, + &rfc5444_decoder_heartbeat_interval_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_STATUS, + &rfc5444_decoder_status_tlv); + +/* Below TLV functions are added for DLEPv7 */ + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED, + &rfc5444_decoder_optinal_signal_supported_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED, + &rfc5444_decoder_optinal_data_item_supported_tlv); + + return (RC_RFC5444_OK); +} diff --git a/dlep_radio_ipv4/rfc5444_decoder_tlv.h b/dlep_radio_ipv4/rfc5444_decoder_tlv.h new file mode 100644 index 0000000..bf96982 --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_decoder_tlv.h @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------ + * rfc5444_decoder_tlv.h -- + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + *------------------------------------------------------------------ + */ + +#ifndef __RFC5444_DECODER_TLV__ +#define __RFC5444_DECODER_TLV__ + +#include "safe_types.h" +#include "rfc5444_types.h" + + + +extern rfc5444_rc_t +rfc5444_decoder_tlv_init(void); + + +#endif + + diff --git a/dlep_radio_ipv4/rfc5444_encoder.c b/dlep_radio_ipv4/rfc5444_encoder.c new file mode 100644 index 0000000..6cacf9c --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_encoder.c @@ -0,0 +1,743 @@ +/*------------------------------------------------------------------ + * rfc5444_encoder.c -- RFC 5444 message encoding APIs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +/* + * Basic strucuture to format one or more messages in + * a RFC 5444 formatted packet. + * + * p2es = rfc5444_encoder_packet_start(); + * rfc5444_encoder_tlv_block_start(p2es, + * RFC5444_TLV_BLOCK_CONTEXT_PACKET); + * ... TLVs... + * rfc5444_encoder_tlv_block_end(p2es); + * + * rfc5444_encoder_message_block_start(p2es, + * RFC5444_MSG_NEIGHBOR_METRICS); + * + * p2neighbor->sequence = dlep_get_next_sequence_number( + * p2neighbor->sequence); + * + * rfc5444_encoder_message_block_add_sequence_number(p2es, + * p2neighbor->sequence); + * + * rfc5444_encoder_tlv_block_start(p2es, + * RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + * ... TLVs... + * rfc5444_encoder_tlv_block_end(p2es); + * rfc5444_encoder_message_block_end(p2es); + * + * rfc5444_encoder_message_block_start(p2es, + * RFC5444_MSG_NEIGHBOR_METRICS); + * + * p2neighbor->sequence = dlep_get_next_sequence_number( + * p2neighbor->sequence); + * + * rfc5444_encoder_message_block_add_sequence_number(p2es, + * p2neighbor->sequence); + * + * rfc5444_encoder_tlv_block_start(p2es, + * RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + * ... TLVs... + * rfc5444_encoder_tlv_block_end(p2es); + * rfc5444_encoder_message_block_end(p2es); + * + * rfc5444_encoder_packet_end(p2es); + */ + + +#include +#include +#include + +#include "safe_types.h" +#include "network_order.h" + +#include "rfc5444_types.h" +#include "rfc5444_packet_header.h" +#include "rfc5444_utils.h" + +#include "packet_dump.h" +#include "rfc5444_encoder.h" + + +#define RFC5444_DEBUG printf +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ + + + +/* + * Set - block open + * Clear - block closed + */ +#define ENCODER_STATE_PACKET ( 0x01 ) +#define ENCODER_STATE_MESSAGE ( 0x02 ) +#define ENCODER_STATE_TLV ( 0x04 ) + + +/** + * NAME + * rfc5444_encoder_packet_start + * + * SYNOPSIS + * rfc5444_encoder_state_t + * *rfc5444_encoder_packet_start(void) + * + * DESCRIPTION + * This function is used to allocate and initialize the + * encoder state variable. A packet buffer is also allocated + * and attached to the encoded state. As the packet is + * formatted, adding TLVs, the encoder variables are adjusted. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * Returns a pointer to the encoder state variable that + * must be passed to the encoding routines. + * + * NULL is returned if there was an error. + * + */ +rfc5444_encoder_state_t +*rfc5444_encoder_packet_start (void) +{ + uint8_t *ptr; + uint8_t *dest; + boolean_t verbose = FALSE; + + rfc5444_encoder_state_t *p2encoder_state; + + p2encoder_state = malloc(sizeof(rfc5444_encoder_state_t)); + if (!p2encoder_state) { + if (verbose) { + RFC5444_DEBUG("%s-%u Error: no encoder resources \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (NULL); + } + +/* port - may use a platform specific buffer allocation routine */ +#define MSG_BUFFER ( 1400 ) + ptr = malloc(MSG_BUFFER); + if (!ptr) { + if (verbose) { + RFC5444_DEBUG("%s-%u Error: no buffer resources \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + free(p2encoder_state); + return (NULL); + } + /* make space for packet header */ + dest = ptr; +#if 0 + NETWORK_ORDER_PUTBYTE(dest, 0); + dest += sizeof(uint8_t); +#endif + + /* save the working buffer pointer */ + p2encoder_state->buildit_ptr = dest; + + /* save the buffer pointer needed when complete */ + p2encoder_state->packet_ptr = ptr; + + /* update packet flags once the completed */ + p2encoder_state->p2packet_flags = ptr; + p2encoder_state->packet_flags = 0; + + /* completed packet length */ + p2encoder_state->packet_length = 0; + + p2encoder_state->p2message_block_length = NULL; + p2encoder_state->message_block_length = 0; + p2encoder_state->message_block_flags = 0; + + p2encoder_state->p2tlv_block_length = NULL; + p2encoder_state->tlv_block_length = 0; + + /* set packet open for business */ + p2encoder_state->state_flags = ENCODER_STATE_PACKET; + //printf("state=0x%0x \n", p2encoder_state->state_flags); + + return (p2encoder_state); +} + + +/** + * NAME + * rfc5444_encoder_packet_add_sequence_number + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_packet_add_sequence_number( + * rfc5444_encoder_state_t *p2encoder_state, + * uint16_t sequence_number) + * + * DESCRIPTION + * This function is used to insert the packet sequence number + * into the packet header when it is desired. The phasseqnum + * flag is set. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * sequence_number - The sequence number to be added to the + * packet. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_packet_add_sequence_number ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t sequence_number) +{ + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (p2encoder_state->state_flags != ENCODER_STATE_PACKET) { + /* packet must be open */ + return (RC_RFC5444_STATE_ERROR); + } + + if (verbose) { + RFC5444_DEBUG("%s-%u sequence number %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + sequence_number); + } + + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, + sequence_number); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + /* set the phasseqnum flag */ + p2encoder_state->packet_flags |= PHASSEQNUM; + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_packet_end + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_packet_end( + * rfc5444_encoder_state_t *p2encoder_state) + * + * DESCRIPTION + * This function is used after all messages and TLVs have been + * added to the packet to complete the packet formatting, + * making the packet ready for transmission. The final packet + * length is computed and all arears are set. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_packet_end ( + rfc5444_encoder_state_t *p2encoder_state) +{ + uint16_t length; + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + if (verbose) { + RFC5444_DEBUG("%s-%u Error: encoder null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (RC_RFC5444_NULL_POINTER); + } + + /* compute the final packet length */ + length = p2encoder_state->buildit_ptr - + p2encoder_state->packet_ptr; + p2encoder_state->packet_length = length; + if (verbose) { + RFC5444_DEBUG("%s-%u packet length=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + length); + } + + +// printf("\n Finding total length of packet::::%d ", +// p2encoder_state->packet_length); + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_free + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_free( + * rfc5444_encoder_state_t *p2encoder_state) + * + * DESCRIPTION + * This function is used to release all resources associated with + * the encoder state. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable to be freed. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents and resources are freed + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_free (rfc5444_encoder_state_t *p2encoder_state) +{ + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (p2encoder_state->packet_ptr) { + free(p2encoder_state->packet_ptr); + p2encoder_state->packet_ptr = NULL; + } + free(p2encoder_state); + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_signal_block_start + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_signal_block_start( + * rfc5444_encoder_state_t *p2encoder_state, + * uint16_t message_code) + * + * DESCRIPTION + * This function is used to append a new message + * to the packet being formatted. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * message_code - The code of the message to be appended. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_signal_block_start ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t message_code, uint32_t dlep_signal_flags) +{ + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + // p2encoder_state->message_block_base = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTLONG(p2encoder_state->buildit_ptr, dlep_signal_flags); + p2encoder_state->buildit_ptr += sizeof(uint32_t); + + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, message_code); +// printf(" Added message code =%d",message_code); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + p2encoder_state->p2message_block_length = p2encoder_state->buildit_ptr; + + p2encoder_state->message_block_length = 0; + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, 0); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_message_block_start + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_message_block_start( + * rfc5444_encoder_state_t *p2encoder_state, + * uint16_t message_code) + * + * DESCRIPTION + * This function is used to append a new message + * to the packet being formatted. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * message_code - The code of the message to be appended. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_message_block_start ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t message_code) +{ + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + // p2encoder_state->message_block_base = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, message_code); +// printf(" Added message code =%d",message_code); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + p2encoder_state->p2message_block_length = p2encoder_state->buildit_ptr; + + p2encoder_state->message_block_length = 0; + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, 0); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_message_block_add_sequence_number + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_message_block_add_sequence_number( + * rfc5444_encoder_state_t *p2encoder_state, + * uint16_t sequence_number) + * + * DESCRIPTION + * This function is used to insert the message sequence number + * into the message header when it is desired. The mhasseqnum + * flag is set. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * sequence_number - The sequence number to be inserted. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_message_block_add_sequence_number ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t sequence_number) +{ + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (!(p2encoder_state->state_flags & ENCODER_STATE_MESSAGE)) { + /* message block is not open */ + return (RC_RFC5444_STATE_ERROR); + } + + if (verbose) { + RFC5444_DEBUG("%s-%u sequence number %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + sequence_number); + } + + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, sequence_number); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + /* set the mhasseqnum flag */ + p2encoder_state->message_block_flags |= MHASSEQNUM; + + return(RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_message_block_end + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_message_block_end( + * rfc5444_encoder_state_t *p2encoder_state) + * + * DESCRIPTION + * This function is used after all parameters have been + * added to the message to complete the message formatting. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_message_block_end ( + rfc5444_encoder_state_t *p2encoder_state) +{ + uint16_t length; + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + length = p2encoder_state->buildit_ptr - + p2encoder_state->p2message_block_length - sizeof(uint16_t); +// printf(" \n Adding total TLV length %d",length); + + // need not keep + p2encoder_state->message_block_length = length; + + /* go back to update the message block length */ + NETWORK_ORDER_PUTSHORT(p2encoder_state->p2message_block_length, length); + + if (verbose) { + printf("%s-%u message block size=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + length); + } + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_tlv_block_start + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_tlv_block_start( + * rfc5444_encoder_state_t *p2encoder_state, + * uint32_t block_indicator) + * + * DESCRIPTION + * This function is used to open a new TLV block in the + * packet header or the message body. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * block_indicator - This enum indicates where the TLV + * block is being appended: + * RFC5444_TLV_BLOCK_CONTEXT_PACKET + * RFC5444_TLV_BLOCK_CONTEXT_MESSAGE + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_tlv_block_start ( + rfc5444_encoder_state_t *p2encoder_state, + uint32_t block_indicator) +{ + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (p2encoder_state->state_flags & ENCODER_STATE_TLV) { + /* TLV block already open */ + return (RC_RFC5444_STATE_ERROR); + } + + /* set the packet header TLV present bit */ + if (block_indicator == RFC5444_TLV_BLOCK_CONTEXT_PACKET) { + if (p2encoder_state->state_flags == ENCODER_STATE_PACKET) { + p2encoder_state->packet_flags |= PHASTLV; + } else { + return (RC_RFC5444_STATE_ERROR); + } + + } else if (block_indicator == RFC5444_TLV_BLOCK_CONTEXT_MESSAGE) { + if (p2encoder_state->state_flags & ENCODER_STATE_MESSAGE) { + /* do nothing */ + } else { + return (RC_RFC5444_STATE_ERROR); + } + } else { + return (RC_RFC5444_INVALID_BLOCK_INDICATOR); + } + + if (verbose) { + RFC5444_DEBUG("%s-%u adding %s TLV block \n", + DEBUG_FUNCTION, + DEBUG_LINE, + ((block_indicator == RFC5444_TLV_BLOCK_CONTEXT_PACKET) ? + "packet" : "message") ); + } + + /* save the ptr to update the TLV block length */ + p2encoder_state->p2tlv_block_length = p2encoder_state->buildit_ptr; + + p2encoder_state->tlv_block_length = 0; + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, 0); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + /* mark the TLV block open */ + p2encoder_state->state_flags |= ENCODER_STATE_TLV; + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_tlv_block_end + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_tlv_block_end( + * rfc5444_encoder_state_t *p2encoder_state) + * + * DESCRIPTION + * This function must be used to close a TLV block. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_tlv_block_end ( + rfc5444_encoder_state_t *p2encoder_state) +{ + uint16_t length; + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (!(p2encoder_state->state_flags & ENCODER_STATE_TLV)) { + /* tlv block not open */ + return (RC_RFC5444_STATE_ERROR); + } + + /* compute the final packet length, accounting for the length itself */ + length = p2encoder_state->buildit_ptr - + p2encoder_state->p2tlv_block_length - sizeof(uint16_t); + p2encoder_state->tlv_block_length = length; + + /* go back to update the TLV block length */ + NETWORK_ORDER_PUTSHORT(p2encoder_state->p2tlv_block_length, length); + + if (verbose) { + RFC5444_DEBUG("%s-%u tlv block size=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + length); + } + + p2encoder_state->state_flags &= ~ENCODER_STATE_TLV; + + return (RC_RFC5444_OK); +} + + diff --git a/dlep_radio_ipv4/rfc5444_encoder.h b/dlep_radio_ipv4/rfc5444_encoder.h new file mode 100644 index 0000000..0d6d6cc --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_encoder.h @@ -0,0 +1,129 @@ +/*------------------------------------------------------------------ + * rfc5444_encoder.h -- RFC5444 message encoding routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef ___RFC5444_ENCODER__ +#define ___RFC5444_ENCODER__ + +#include "safe_types.h" +#include "rfc5444_types.h" + + +#define RFC5444_TLV_BLOCK_CONTEXT_PACKET ( 3 ) +#define RFC5444_TLV_BLOCK_CONTEXT_MESSAGE ( 5 ) + + +/* + * This is the structure type used to manage the encoding of + * the packet-message and TLVs. + */ +typedef struct { + uint32_t *dlep_sig_flags; + + uint32_t state_flags; + + uint8_t *buildit_ptr; + + uint8_t *packet_ptr; + + uint8_t *p2packet_flags; + uint8_t packet_flags; + + uint16_t packet_length; + + uint8_t *message_block_base; + uint8_t *p2message_block_flags; + uint8_t message_block_flags; + + uint8_t *p2message_block_length; + uint16_t message_block_length; + + uint8_t *tlv_block_base; + uint8_t *p2tlv_block_length; + uint8_t tlv_block_length; + +} rfc5444_encoder_state_t; + + + + +extern rfc5444_encoder_state_t +*rfc5444_encoder_packet_start(void); + + +extern rfc5444_rc_t +rfc5444_encoder_packet_add_sequence_number( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t sequence_number); + + +extern rfc5444_rc_t +rfc5444_encoder_packet_end( + rfc5444_encoder_state_t *p2encoder_state); + + +extern rfc5444_rc_t +rfc5444_encoder_free(rfc5444_encoder_state_t *p2encoder_state); + + +extern rfc5444_rc_t +rfc5444_encoder_message_block_start( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t message_code); + +extern rfc5444_rc_t +rfc5444_encoder_signal_block_start ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t message_code, uint32_t dlep_signal_flags); + + +extern rfc5444_rc_t +rfc5444_encoder_message_block_add_sequence_number( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t sequence_number); + + +extern rfc5444_rc_t +rfc5444_encoder_message_block_end( + rfc5444_encoder_state_t *p2encoder_state); + + +extern rfc5444_rc_t +rfc5444_encoder_tlv_block_start( + rfc5444_encoder_state_t *p2encoder_state, + uint32_t block_indicator); + + +extern rfc5444_rc_t +rfc5444_encoder_tlv_block_end( + rfc5444_encoder_state_t *p2encoder_state); + + +#endif diff --git a/dlep_radio_ipv4/rfc5444_encoder_tlv.c b/dlep_radio_ipv4/rfc5444_encoder_tlv.c new file mode 100644 index 0000000..64d44de --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_encoder_tlv.c @@ -0,0 +1,1466 @@ +/*---------------------------------------------------------------------- + * rfc5444_encoder_tlv.c -- routines to encode TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "network_order.h" + +#include "rfc5444_types.h" +#include "rfc5444_encoder.h" +#include "rfc5444_encoder_tlv.h" + + +/** + * NAME + * rfc5444_identification_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_identification_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint32_t router_id, + * uint32_t client_id, + * uint8_t heartbeat_interval) + * + * DESCRIPTION + * Call this function to add the indentification TLV + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * router_id - indicates the router ID of the DLEP neighbor, set to + * '0' when unknown. + * + * client_id - indicates the client ID of the DLEP neighbor, set to + * '0' when unknown. + * + * heartbeat_interval - An 8-bit, unsigned value specifiying + * the peer-to-peer heartbeat interval. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | HB Intrvl | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Router ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | Client ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +#define RFC5444_TLV_IDENTIFICATION 255 + uint8_t +*rfc5444_identification_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t router_id, + uint32_t client_id, + uint8_t heartbeat_interval) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IDENTIFICATION); + dest += sizeof(uint8_t); + // if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IDENTIFICATION_FLAGS); + dest += sizeof(uint8_t); + // endif + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IDENTIFICATION_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, heartbeat_interval); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLONG(dest, router_id); + dest += sizeof(uint32_t); + + NETWORK_ORDER_PUTLONG(dest, client_id); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/** + * NAME + * rfc5444_version_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_version_tlv(rfc5444_encoder_state_t *p2encoder_state, + * uint16_t version_major, + * uint16_t version_minor) + * + * DESCRIPTION + * Call this function to insert the RFC5444 version TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * version_major - Major version of the client or router protocol. + * + * version_minor - Minor version of the client or router protocol. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Major Ver | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Major Ver | Minor Version | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + uint8_t +*rfc5444_version_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t version_major, + uint16_t version_minor) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VERSION); + dest += sizeof(uint8_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VERSION_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VERSION_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTSHORT(dest, version_major); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, version_minor); + dest += sizeof(uint16_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/* port TLV */ + + uint8_t +*rfc5444_port_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t port) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_PORT); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_PORT_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTSHORT(dest, port); + dest += sizeof(uint16_t); + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* CREDIT WINDOW STATUS TLV */ + uint8_t +*rfc5444_credit_window_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mrw, uint64_t rrw) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_WINDOW_STATUS); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_WINDOW_STATUS_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLLONG(dest, mrw); + dest += sizeof(uint64_t); + + NETWORK_ORDER_PUTLLONG(dest, rrw); + dest += sizeof(uint64_t); + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* CREDIT GRAND REQUEST */ + + uint8_t +*rfc5444_credit_grand_request_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cgr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest,RFC5444_TLV_CREDIT_GRANT ); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_GRANT_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLLONG(dest, cgr); + dest += sizeof(uint64_t); + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* CREDIT REQUEST */ + uint8_t +*rfc5444_credit_request_tlv(rfc5444_encoder_state_t *p2encoder_state) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest,RFC5444_TLV_CREDIT_REQUEST); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_REQUEST_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, 0); + dest += sizeof(uint8_t); + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* TLV_HEATBEAT_INTERVAL */ + + +uint8_t +*rfc5444_heartbeat_interval_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t hbt) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest,RFC5444_TLV_HEARTBEAT_INTERVAL); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_HEARTBEAT_INTERVAL_LENGTH); + dest += sizeof(uint16_t); + /* convert to milliseconds */ + hbt = hbt * 1000; + + NETWORK_ORDER_PUTLONG(dest, hbt); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + +/** + * NAME + * rfc5444_peer_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_peer_tlv(rfc5444_encoder_state_t *p2encoder_state, + * char *peer_type_string) + * + * DESCRIPTION + * Call this function to add the return code TLV + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * peer_type_string - non-NULL terminated string + * identifier. <= 80 characters. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Peer Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Peer Type String (non-NULL terminated) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-.... + * + */ + uint8_t +*rfc5444_peer_tlv(rfc5444_encoder_state_t *p2encoder_state, + char *peer_type_string) +{ + uint8_t *ptr; + uint8_t length; + uint8_t *dest; + uint32_t i; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_PEER_TYPE); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_PEER_TYPE_FLAGS); + dest += sizeof(uint8_t); +#endif + ptr = dest; + NETWORK_ORDER_PUTSHORT(dest, 1); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_PEER_TYPE_FLAGS); + dest += sizeof(uint8_t); + + length = 1; + for (i=0; (*peer_type_string) && ibuildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_mac_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_mac_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t mac_address[]) + * + * DESCRIPTION + * Call this function to insert the remote MAC address TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * mac_address - the remote router MAC address. The MAC + * is used to uniquely address all neighbor messages. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | MAC Addr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Remote Router MAC Continued (32-bit) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | MAC Addr | + * +-+-+-+-+-+-+-+-+ + * + */ + uint8_t +*rfc5444_mac_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t mac_address[]) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MAC_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_MAC_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MAC_ADDRESS_LENGTH); + dest += sizeof(uint16_t); + + dest = mac_put_address(dest, mac_address); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_ipv4_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_ipv4_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t operation, + * ipv4_address_t ipv4) + * + * DESCRIPTION + * Call this function to insert the IPv4 TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * operation - indicates the operation to be applied + * on the IPv4 address + * RFC5444_EXISTING_NEW_ADDRESS + * RFC5444_WITHDRAW_ADDRESS + * + * ipv4 - the address + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | operation | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | IPv4 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*rfc5444_ipv4_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv4_address_t *ipv4) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV4_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV4_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV4_ADDRESS_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv4_put_address(dest, ipv4); + + /* NETWORK_ORDER_PUTBYTE(dest, 24); + dest += sizeof(uint8_t); */ + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_ipv6_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_ipv6_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t operation, + * ipv6_address_t *ipv6_addr) + * + * DESCRIPTION + * Call this function to insert the IPv4 TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * operation - indicates the operation to be applied + * on the IPv4 address + * RFC5444_EXISTING_NEW_ADDRESS + * RFC5444_WITHDRAW_ADDRESS + * + * ipv6_addr - the address + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | operation | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | IPv6 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | IPv6 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 12 | IPv6 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 16 | IPv6 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + uint8_t +*rfc5444_ipv6_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv6_address_t *ipv6_addr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV6_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV6_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV6_ADDRESS_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv6_put_address(dest, ipv6_addr); + + /* NETWORK_ORDER_PUTBYTE(dest, 64); + dest += sizeof(uint8_t); */ + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_link_metric_mdr_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_mdr_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t mdr) + * + * DESCRIPTION + * Call this function to insert the maximum datarate TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * mdr - the maximum theoretical data rate, in bits per + * second (bps), achieved on the link. When + * metrics are reported, the maximum data rate + * MUST be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | MDR | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | MDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | MDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ + uint8_t +*rfc5444_link_metric_mdr_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_MDR_METRIC_TX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_MDR_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_MDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, mdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + uint8_t +*rfc5444_link_metric_mdr_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_MDR_METRIC_RX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_MDR_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_MDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, mdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + +/** + * NAME + * rfc5444_link_metric_cdr_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_cdr_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t cdr) + * + * DESCRIPTION + * Call this function to insert the current datarate TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * cdr - the current data rate, in bits per second + * (bps), achieved on the link. If there is no + * distinction between maximum and current + * data rate, current data rate SHOULD be set + * equal to the maximum data rate. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | CDR | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | CDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | CDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*rfc5444_link_metric_cdr_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_CDR_METRIC_TX); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_CDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, cdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*rfc5444_link_metric_latency_tlv1 (rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_LATENCY_METRIC); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, latency); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); + +} + +uint8_t +*rfc5444_link_metric_cdr_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_CDR_METRIC_RX); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_CDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, cdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/** + * NAME + * rfc5444_link_metric_latency_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_latency_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t latency) + * + * DESCRIPTION + * Call this function to insert the latency TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * latency - the transmission delay that a packet + * encounters as it is transmitted over the link. + * This is reported in absolute delay, in + * milliseconds. If latency cannot be calculated, + * a value of 0 should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Latency | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Latency | + * +-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*rfc5444_link_metric_latency_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_LATENCY_METRIC); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_LATENCY_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLONG(dest, latency); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_link_metric_resources_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t resources) + * + * DESCRIPTION + * Call this function to insert the resources TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * resources - a percentage, 0-100, representing the amount + * of remaining resources, such as battery power. + * If resources cannot be calculated, a value of + * 100 should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Resources | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*rfc5444_link_metric_resources_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RESOURCES_METRIC_TX); + dest += sizeof(uint8_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, resources); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +uint8_t +*rfc5444_link_metric_resources_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RESOURCES_METRIC_RX); + dest += sizeof(uint8_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, resources); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*rfc5444_link_metric_resources_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RESOURCES_METRIC); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, resources); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/** + * NAME + * rfc5444_link_metric_rlq_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_rq_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t rlq) + * + * DESCRIPTION + * Call this function to insert the RLQ TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * rlq - a non-dimensional number, 0-100, representing + * the relative link quality. A value of 100 + * represents a link of the highest quality. If + * the RLQ cannot be calculated, a value of 100 + * should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | RLQ | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*rfc5444_link_metric_rlq_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RLQ_METRIC_TX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RLQ_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, rlq); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*rfc5444_link_metric_rlq_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RLQ_METRIC_RX); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RLQ_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, rlq); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/* + * MTU + */ +uint8_t +*rfc5444_mtu_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint16_t mtu) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MTU); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MTU_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, mtu); + dest += sizeof(uint16_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* + * eft + */ +uint8_t +*rfc5444_link_metric_eft_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t eft) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_EFT_METRIC); + dest += sizeof(uint8_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_EFT_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLONG(dest, eft); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/** + * NAME + * rfc5444_status_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + * uint8_t status_code) + * + * DESCRIPTION + * Call this function to insert the peer status TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * status_code - protocol status code reflecting success + * of previous request + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Status Code | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*rfc5444_status_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t status_code) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_STATUS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_STATUS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_STATUS_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, status_code); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* Below TLV functions are added for DLEPv7 */ + +uint8_t +*rfc5444_ipv4_attached_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, uint8_t operation) + +{ + uint8_t *dest; + char subnet[16]; + char local_ipv4_dot[IPV4_ADDR_STRING_LEN] = "255.255.255.0"; + ipv4_address_t ipv4_subnet_addr; + + ipv4_dot_decimal2digits(&ipv4_subnet_addr, local_ipv4_dot); + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV4_ATTACHED_SUBNET); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV4_ATTACHED_SUBNET_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv4_put_address(dest, &ipv4_subnet_addr); + + NETWORK_ORDER_PUTBYTE(dest, 24); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + uint8_t +*rfc5444_ipv6_attached_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, + ipv6_address_t *ipv6_subnet_addr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV6_ADDRESS); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, (RFC5444_TLV_IPV6_ATTACHED_SUBNET_LENGTH)); + dest += sizeof(uint8_t); + + dest = ipv6_put_address(dest, ipv6_subnet_addr); + + NETWORK_ORDER_PUTBYTE(dest, 64); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* Suriya added for testing purpose */ + + uint8_t +*rfc5444_ipv6_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state,uint8_t operation, +uint8_t subnet,ipv6_address_t *ipv6_subnet_addr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV6_ATTACHED_SUBNET); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV6_ATTACHED_SUBNET_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv6_put_address(dest, ipv6_subnet_addr); + + NETWORK_ORDER_PUTBYTE(dest, subnet); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + uint8_t +*rfc5444_optinal_signal_supported_tlv (rfc5444_encoder_state_t *p2encoder_state) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED_LENGTH); + dest += sizeof(uint8_t); + + /* Reserved bit */ + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_MSG_PEER_UPDATE_RES); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest,RFC5444_MSG_PEER_UPDATE_REQ); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_MSG_LINK_CHAR_RES); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest,RFC5444_MSG_LINK_CHAR_REQ); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*rfc5444_optinal_data_item_supported_tlv (rfc5444_encoder_state_t *p2encoder_state) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED_LENGTH); + dest += sizeof(uint8_t); + + /* Reserved bit */ + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RESOURCES_METRIC_RX); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RESOURCES_METRIC_TX); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RLQ_METRIC_TX); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RLQ_METRIC_RX); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_WINDOW_STATUS); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_GRANT); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_REQUEST); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VENDOR_EXTENSION); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV4_ATTACHED_SUBNET); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV6_ATTACHED_SUBNET); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + uint8_t +*rfc5444_vendor_extension_tlv (rfc5444_encoder_state_t *p2encoder_state) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VENDOR_EXTENSION); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VENDOR_EXTENSION_LENGTH); + dest += sizeof(uint8_t); + + /* Reserved bit */ + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, VENDOR_OUI_LENGTH); + dest += sizeof(uint8_t); + +/* Vendor OUI */ + NETWORK_ORDER_PUTBYTE(dest, 0xAB); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, 0xBC); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, 0xCD); + dest += sizeof(uint8_t); + +/* Device type*/ + NETWORK_ORDER_PUTSHORT(dest, 0xBABE); + dest += sizeof(uint16_t); + +/*PAYLOAD in TLV format*/ + NETWORK_ORDER_PUTBYTE(dest, VENDOR_SPECIFIC_PAYLOAD_TYPE); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, VENDOR_SPECIFIC_PAYLOAD_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, 0xEF); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0xDC); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0xBA); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0xBD); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/* + * ipv4 connection point tlv + * + */ +uint8_t +*rfc5444_ipv4_connection_point_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint16_t port, + ipv4_address_t *ipv4) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV4_CONNECTION_POINT); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV4_CONNECTION_POINT_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV4_CONNECTION_POINT_FLAGS); + dest += sizeof(uint8_t); + + dest = ipv4_put_address(dest, ipv4); + + NETWORK_ORDER_PUTSHORT(dest, port); + dest += sizeof(uint16_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + diff --git a/dlep_radio_ipv4/rfc5444_encoder_tlv.h b/dlep_radio_ipv4/rfc5444_encoder_tlv.h new file mode 100644 index 0000000..c82c7b6 --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_encoder_tlv.h @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------- + * rfc5444_encoder_tlv.h -- routine prototypes to encode TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __RFC5444_ENCODER_TLV_H__ +#define __RFC5444_ENCODER_TLV_H__ + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_encoder.h" + + + +extern uint8_t +*rfc5444_identification_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t router_id, + uint32_t client_id, + uint8_t heartbeat_interval); + +extern uint8_t +*rfc5444_version_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t version_major, + uint16_t version_minor); + + +extern uint8_t +*rfc5444_peer_tlv(rfc5444_encoder_state_t *p2encoder_state, + char *peer_type_string); + + +extern uint8_t +*rfc5444_mac_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t mac_address[]); + + +extern uint8_t +*rfc5444_ipv4_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv4_address_t *ipv4); + +extern uint8_t +*rfc5444_ipv6_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv6_address_t *ipv6_dest_addr); + + +extern uint8_t +*rfc5444_link_metric_mdr_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr); + +extern uint8_t +*rfc5444_link_metric_mdr_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr); + +extern uint8_t +*rfc5444_link_metric_cdr_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr); +extern uint8_t +*rfc5444_link_metric_latency_tlv1(rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency); + +extern uint8_t +*rfc5444_link_metric_cdr_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr); + +extern uint8_t +*rfc5444_link_metric_latency_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency); + +extern uint8_t +*rfc5444_link_metric_resources_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources); + +extern uint8_t +*rfc5444_link_metric_resources_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources); + +extern uint8_t +*rfc5444_link_metric_rlq_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq); + +extern uint8_t +*rfc5444_link_metric_rlq_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq); + +extern uint8_t +*rfc5444_link_metric_eft_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t eft); + + +extern uint8_t +*rfc5444_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t termination_code); + + +extern uint8_t +*rfc5444_datarate_request_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t requested_cdr); + + +extern uint8_t +*rfc5444_datarate_request_ack_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t requested_cdr, + uint32_t granted_cdr); +extern uint8_t +*rfc5444_port_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t port); +extern uint8_t +*rfc5444_credit_window_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mrw, uint64_t rrw); +extern uint8_t +*rfc5444_credit_grand_request_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cgr); +extern uint8_t +*rfc5444_credit_request_tlv(rfc5444_encoder_state_t *p2encoder_state); + +extern uint8_t +*rfc5444_heartbeat_interval_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t hbt); + + +/* Below TLV functions are added for DLEPv7 */ + +extern uint8_t +*rfc5444_ipv4_attached_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation); + +extern uint8_t +*rfc5444_ipv6_attached_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, + ipv6_address_t *ipv6_subnet); + +extern uint8_t +*rfc5444_ipv6_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, uint8_t subnet, + ipv6_address_t *ipv6_subnet_addr); + +/* Below TLV functions are added for DLEPv27 */ +extern uint8_t +*rfc5444_link_metric_resources_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources); + +extern uint8_t +*rfc5444_mtu_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t mtu); + +extern uint8_t +*rfc5444_ipv4_connection_point_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint16_t port, + ipv4_address_t *ipv4); + +extern uint8_t +*rfc5444_optinal_signal_supported_tlv (rfc5444_encoder_state_t *p2encoder_state); + +extern uint8_t +*rfc5444_optinal_data_item_supported_tlv (rfc5444_encoder_state_t *p2encoder_state); + +extern uint8_t +*rfc5444_vendor_extension_tlv (rfc5444_encoder_state_t *p2encoder_state); + + +#endif + + diff --git a/dlep_radio_ipv4/rfc5444_experimental_tlv.c b/dlep_radio_ipv4/rfc5444_experimental_tlv.c new file mode 100644 index 0000000..6b25497 --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_experimental_tlv.c @@ -0,0 +1,261 @@ +/*------------------------------------------------------------------ + * rfc5444_experimental_tlv.c -- routines for standard TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "safe_types.h" +#include "network_order.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_decoder.h" + +#include "rfc5444_experimental_tlv.h" + + + +#define RFC5444_TLV_EXPER_8 ( 253 ) +#define RFC5444_TLV_EXPER_8_LENGTH ( 4 ) + +#define RFC5444_TLV_EXPER_16 ( 254 ) +#define RFC5444_TLV_EXPER_16_LENGTH ( 4 ) + + +#define RFC5444_DEBUG printf +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ + + + +/* + * RFC 5444 defines TLVs as + * + * := + * + * ? + * (?)? + * (?)? + * + * This is referred to as the T-F-L-V format. The + * field is used to describe the length field size, 8-bits + * or 16-bits as well as the presence of the value or not. + * + * The standard TLV encoding does not specify the + * field. The flag field is not needed as the tlv_code itself + * describes the value by definition of the code itself. + * http://en.wikipedia.org/wiki/Type-length-value + * + * This file experiments with the standard TLV format + * in RFC5444 formatting. It is also a good test for + * the decoder. + */ + +/* + * Experimental 8-bit length + */ +uint8_t +*rfc5444_exper_8_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t parameter) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_EXPER_8); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_EXPER_8_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLONG(dest, parameter); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/* + * Experimental 16-bit length + */ +uint8_t +*rfc5444_exper_16_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t parameter) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_EXPER_16); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_EXPER_16_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLONG(dest, parameter); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/* + * Experimental 8-bit length field decoder + */ +static rfc5444_rc_t +rfc5444_decoder_exper_8_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *scratch_pad, + boolean_t verbose) +{ + uint8_t tlv_length; + uint32_t parameter; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + + if (tlv_length != RFC5444_TLV_EXPER_8_LENGTH) { + if (verbose) { + RFC5444_DEBUG("%s-%u ERROR: invalid length tlv_code=%u " + "len=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, parameter); + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->tlv_block_length -= sizeof(uint32_t); + + if (verbose) { + RFC5444_DEBUG("%s-%u %s parameter=0x%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + parameter); + } + return (RC_RFC5444_OK); +} + + +/* + * Experimental 16-bit length field decoder + */ +static rfc5444_rc_t +rfc5444_decoder_exper_16_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *scratch_pad, + boolean_t verbose) +{ + uint16_t tlv_length; + uint32_t parameter; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->tlv_block_length -= sizeof(uint16_t); + + if (tlv_length != RFC5444_TLV_EXPER_16_LENGTH) { + if (verbose) { + RFC5444_DEBUG("%s-%u ERROR: invalid length tlv_code=%u " + "len=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, parameter); + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->tlv_block_length -= sizeof(uint32_t); + + if (verbose) { + RFC5444_DEBUG("%s-%u %s parameter=0x%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + parameter); + } + return (RC_RFC5444_OK); +} + + +/* + * + * NAME + * rfc5444_experimental_tlv_init + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_experimental_tlv_init(void) + * + * DESCRIPTION + * This function must be called to register the experimental + * TLV decoders. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + *- + */ +rfc5444_rc_t +rfc5444_experimental_tlv_init (void) +{ + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_EXPER_8, + &rfc5444_decoder_exper_8_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_EXPER_16, + &rfc5444_decoder_exper_16_tlv); + + return (RC_RFC5444_OK); +} + + diff --git a/dlep_radio_ipv4/rfc5444_experimental_tlv.h b/dlep_radio_ipv4/rfc5444_experimental_tlv.h new file mode 100644 index 0000000..65a4b32 --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_experimental_tlv.h @@ -0,0 +1,56 @@ +/*------------------------------------------------------------------ + * rfc5444_experimental_tlv.h -- prototypes for stndard TLV APIs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + *------------------------------------------------------------------ + */ + +#ifndef __RFC5444_EXPERIMENTAL_TLV__ +#define __RFC5444_EXPERIMENTAL_TLV__ + +#include "safe_types.h" +#include "rfc5444_types.h" +#include "rfc5444_encoder.h" + + +extern uint8_t +*rfc5444_exper_8_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t parameter); + + +extern uint8_t +*rfc5444_exper_16_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t parameter); + + +extern rfc5444_rc_t +rfc5444_experimental_tlv_init(void); + +#endif + + diff --git a/dlep_radio_ipv4/rfc5444_packet_header.c b/dlep_radio_ipv4/rfc5444_packet_header.c new file mode 100644 index 0000000..e7ce2cb --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_packet_header.c @@ -0,0 +1,177 @@ +/*------------------------------------------------------------------ + * rfc5444_packet_header.c -- + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include + +#include "safe_types.h" +#include "network_order.h" + +#include "rfc5444_packet_header.h" + + + +#define RFC5444_VERSION ( 0 ) + +/* + * This will change when authentication is supported. + */ +#define RFC5444_PACKET_FLAGS ( 2 ) + + +/* + * RFC5444 Control Header + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+ + * | | | + * | Vers | Flags | + * | | | + * +-+-+-+-+-+-+-+-+ + * + */ +#define RFC5444_PACKET_HDR_VERSION_MASK ( 0xF0 ) +#define RFC5444_PACKET_HDR_VERSION_SHIFT ( 4 ) + +#define RFC5444_PACKET_HDR_FLAGS_MASK ( 0x0F ) +#define RFC5444_PACKET_HDR_FLAGS_SHIFT ( 0 ) + + + +/** + * NAME + * rfc5444_add_packet_header + * + * SYNOPSIS + * uint8_t + * *rfc5444_add_packet_header(uint8_t *dest) + * + * DESCRIPTION + * Call this function to add the RFC5444 packet header + * when constructing a message. + * + * INPUT PARAMETERS + * dest - pointer to where the RFC5444 header is placed + * + * OUTPUT PARAMETERS + * dest - buffer is modified with the packet header + * + * RETURN VALUES + * Pointer to data area just beyond the newly added + * RFC5444 header. + * + * NOTES + * ASSUME all pointers are valid + */ +uint8_t +*rfc5444_add_packet_header (uint8_t *dest, uint8_t flags) +{ + uint8_t rfc5444_header; + + /* all fields are defaulted to zero */ + rfc5444_header = 0; + + rfc5444_header = (flags & RFC5444_PACKET_HDR_FLAGS_MASK); + + rfc5444_header |= ((RFC5444_VERSION << RFC5444_PACKET_HDR_VERSION_SHIFT) & + RFC5444_PACKET_HDR_VERSION_MASK); + + rfc5444_header |= rfc5444_header; + + NETWORK_ORDER_PUTBYTE(dest, rfc5444_header); + dest += sizeof(uint8_t); + return (dest); +} + + +/** + * NAME + * rfc5444_parse_packet_header + * + * SYNOPSIS + * uint8_t + * *rfc5444_parse_packet_header(uint8_t *msg, + * uint8_t *packet_flags, + * + * DESCRIPTION + * Call this function to extract the RFC5444 packet header + * fields when a message is received. + * + * INPUT PARAMETERS + * msg - pointer to the beginning of the RFC5444 message + * + * rsvrd - pointer to the reserved field + * + * rf0 - pointer to the rf0 flag + * + * OUTPUT PARAMETERS + * rsvrd - updated + * + * rf0 - updated + * + * RETURN VALUES: + * Pointer to data area just beyond the newly parsed + * RFC5444 header. + * NULL if the version is not supported. + * + * NOTES + * ASSUME all pointers are valid + * + */ +uint8_t +*rfc5444_parse_packet_header (uint8_t *msg, + uint8_t *packet_header_flags) +{ + uint8_t rfc5444_packet_header; + uint8_t rfc5444_version; + + *packet_header_flags = 0; + + NETWORK_ORDER_GETBYTE(msg, rfc5444_packet_header); + + rfc5444_version = ((rfc5444_packet_header & + RFC5444_PACKET_HDR_VERSION_MASK) >> + RFC5444_PACKET_HDR_VERSION_SHIFT); + + if (rfc5444_version == RFC5444_VERSION) { + *packet_header_flags = ((rfc5444_packet_header & + RFC5444_PACKET_HDR_FLAGS_MASK) >> + RFC5444_PACKET_HDR_FLAGS_SHIFT); + + msg += sizeof(uint8_t); + } else { + msg = NULL; + } + + return (msg); +} + + diff --git a/dlep_radio_ipv4/rfc5444_packet_header.h b/dlep_radio_ipv4/rfc5444_packet_header.h new file mode 100644 index 0000000..3b1f34a --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_packet_header.h @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------ + * rfc5444_packet_header.h -- + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __RFC5444_PACKET_HEADER_H__ +#define __RFC5444_PACKET_HEADER_H__ + +#include "safe_types.h" + + +extern uint8_t +*rfc5444_add_packet_header(uint8_t *dest, + uint8_t packet_header_flags); + + +extern uint8_t +*rfc5444_parse_packet_header(uint8_t *msg, + uint8_t *packet_header_flags); + + +#endif + diff --git a/dlep_radio_ipv4/rfc5444_scratch_pad.c b/dlep_radio_ipv4/rfc5444_scratch_pad.c new file mode 100644 index 0000000..46acada --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_scratch_pad.c @@ -0,0 +1,381 @@ +/*---------------------------------------------------------------------- + * rfc5444_scratch_pad.c -- Routines to manage parsed data + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_scratch_pad.h" + + +/** + * NAME + * rfc5444_show_packet_scratch_pad + * + * SYNOPSIS + * #include "rfc5444_scratch_pad.h" + * void + * rfc5444_show_packet_scratch_pad( + * rfc5444_packet_scratch_pad_t *scratch_pad) + * + * DESCRIPTION + * This function is used to display the packet scratch pad + * to facilitate debugging and integration. + * + * INPUT PARAMETERS + * pkt_scratch_pad - This is a pointer to the packet scratch + * pad area + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +rfc5444_show_packet_scratch_pad ( + rfc5444_packet_scratch_pad_t *pkt_scratch_pad) +{ + if (!pkt_scratch_pad) { + return; + } + + printf("\nPacket Scratch Pad \n"); + + if (pkt_scratch_pad->sequence_present) { + printf(" sequence number=%u \n", + pkt_scratch_pad->sequence); + } + + if (pkt_scratch_pad->router_id_present) { + printf(" router id=%u \n", + pkt_scratch_pad->router_id); + } + + if (pkt_scratch_pad->client_id_present) { + printf(" client id=%u \n", + pkt_scratch_pad->client_id); + } + + if (pkt_scratch_pad->peer_heartbeat_interval_present) { + printf(" peer heartbeat interval=%u seconds \n", + pkt_scratch_pad->peer_heartbeat_interval); + } + + return; +} + + +/** + * NAME + * rfc5444_show_message_scratch_pad + * + * SYNOPSIS + * #include "rfc5444_scratch_pad.h" + * void + * rfc5444_show_message_scratch_pad( + * rfc5444_message_scratch_pad_t *scratch_pad) + * + * DESCRIPTION + * This function is used to display the message scratch pad to + * facilitate debugging and ntegration. + * + * INPUT PARAMETERS + * msg_scratch_pad - This is a pointer to the message scratch + * pad area + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +rfc5444_show_message_scratch_pad ( + rfc5444_message_scratch_pad_t *msg_scratch_pad) +{ + if (!msg_scratch_pad) { + return; + } + + printf("Message Scratch Pad \n"); + + printf(" message code=%u %s \n", + msg_scratch_pad->message_code, + rfc5444_message_code2string(msg_scratch_pad->message_code)); + + /* if (msg_scratch_pad->sequence_present) { + printf(" sequence number=%u \n", + msg_scratch_pad->sequence); + } */ + + if (msg_scratch_pad->major_version_present || + msg_scratch_pad->minor_version_present) { + printf(" DLEP version=%u.%u \n", + msg_scratch_pad->major_version, + msg_scratch_pad->minor_version); + } + + if (msg_scratch_pad->status_code_present) { + printf(" status code=%u \n", + msg_scratch_pad->status_code); + } + + if (msg_scratch_pad->mac_address_present) { + mac_print_address(" MAC=", msg_scratch_pad->mac_address); + } + + if (msg_scratch_pad->ipv4_address_present) { + printf(" IPv4 operation=%u \n", + msg_scratch_pad->ipv4_operation); + ipv4_print_address(" IPv4", &msg_scratch_pad->ipv4_address); + } + + if (msg_scratch_pad->ipv6_address_present) { + printf(" IPv6 operation=%u \n", + msg_scratch_pad->ipv6_operation); + ipv6_print_address(" IPv6", &msg_scratch_pad->ipv6_address); + } + + if (msg_scratch_pad->rlq_present) { + printf(" rlq tx=%u percent \n", + msg_scratch_pad->rlq_tx); + + printf(" rlq rx=%u percent \n", + msg_scratch_pad->rlq_rx); + } + + if (msg_scratch_pad->resources_present) { + printf(" resources =%u percent\n", + msg_scratch_pad->resources); + + } + + if (msg_scratch_pad->latency_present) { + printf(" latency=%llu milliseconds \n", + msg_scratch_pad->latency); + } + + if (msg_scratch_pad->cdr_present) { + printf(" cdr tx=%llu bps \n", + msg_scratch_pad->cdr_tx); + + printf(" cdr rx=%llu bps \n", + msg_scratch_pad->cdr_rx); + } + + if (msg_scratch_pad->mdr_present) { + printf(" mdr tx=%llu bps\n", + msg_scratch_pad->mdr_tx); + + printf(" mdr rx=%llu bps\n", + msg_scratch_pad->mdr_rx); + } + + if (msg_scratch_pad->mtu_present) { + printf(" mtu=%u \n", + msg_scratch_pad->mtu); + } + + return; +} + + +/** + * NAME + * rfc5444_scrub_packet_scratch_pad + * + * SYNOPSIS + * #include "rfc5444_scratch_pad.h" + * void + * rfc5444_scrub_packet_scratch_pad( + * rfc5444_packet_scratch_pad_t *pkt_scratch_pad) + * + * DESCRIPTION + * This function is used to scrub the packet scratch pad + * prior to parsing a RFC5444 packet. + * + * INPUT PARAMETERS + * scratch_pad - This is a pointer to the scratch pad area + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +rfc5444_scrub_packet_scratch_pad ( + rfc5444_packet_scratch_pad_t *pkt_scratch_pad) +{ + if (!pkt_scratch_pad) { + return; + } + + pkt_scratch_pad->sequence = 0; + pkt_scratch_pad->sequence_present = FALSE; + + pkt_scratch_pad->router_id = 0; + pkt_scratch_pad->router_id_present = FALSE; + + pkt_scratch_pad->client_id = 0; + pkt_scratch_pad->client_id_present = FALSE; + + pkt_scratch_pad->peer_heartbeat_interval = 0; + pkt_scratch_pad->peer_heartbeat_interval_present = FALSE; + + return; +} + +#if 0 +/* Below two init functions are added for DLEPv7 */ +static uint32_t init_optional_signal(void) { + + uint32_t opt_signal = 0; + + opt_signal |= (~(~0 << (RFC5444_MAX_MESSAGE_CODE - 1))); + + opt_signal &= (~(1 << RFC5444_MSG_PEER_UPDATE_RES)); + opt_signal &= (~(1 << RFC5444_MSG_LINK_CHAR_RES)); + + return opt_signal; +} + +static uint32_t init_optional_data_item(void) { + + uint32_t opt_data = 0; + + opt_data |= (~(~0 << (RFC5444_MAX_DATA_ITEM - 1))); + + opt_data &= (~(1 << RFC5444_TLV_LINK_RESOURCES_METRIC_RX)); + opt_data &= (~(1 << RFC5444_TLV_LINK_RESOURCES_METRIC_TX)); + opt_data &= (~(1 << RFC5444_TLV_CREDIT_WINDOW_STATUS)); + opt_data &= (~(1 << RFC5444_TLV_CREDIT_GRANT)); + opt_data &= (~(1 << RFC5444_TLV_CREDIT_REQUEST)); + opt_data &= (~(1 << RFC5444_TLV_VENDOR_EXTENSION)); + opt_data &= (~(1 << RFC5444_TLV_IPV4_ATTACHED_SUBNET)); + opt_data &= (~(1 << RFC5444_TLV_IPV6_ATTACHED_SUBNET)); + + return opt_data; +} +#endif +/** + * NAME + * rfc5444_scrub_message_scratch_pad + * + * SYNOPSIS + * #include "rfc5444_scratch_pad.h" + * void + * rfc5444_scrub_message_scratch_pad( + * rfc5444_message_scratch_pad_t *msg_scratch_pad) + * + * DESCRIPTION + * This function is used to scrub the message scratch pad + * prior to parsing a RFC5444 message. + * + * INPUT PARAMETERS + * scratch_pad - This is a pointer to the scratch pad area + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +rfc5444_scrub_message_scratch_pad ( + rfc5444_message_scratch_pad_t *msg_scratch_pad) +{ + if (!msg_scratch_pad) { + return; + } + + msg_scratch_pad->message_code = 0; + + msg_scratch_pad->major_version = 0; + msg_scratch_pad->major_version_present = FALSE; + + msg_scratch_pad->minor_version = 0; + msg_scratch_pad->minor_version_present = FALSE; + + msg_scratch_pad->sequence = 0; + msg_scratch_pad->sequence_present = FALSE; + + msg_scratch_pad->status_code = 0; + msg_scratch_pad->status_code_present = 0; + + mac_zero_address(msg_scratch_pad->mac_address); + msg_scratch_pad->mac_address_present = FALSE; + + ipv4_zero_address(&msg_scratch_pad->ipv4_address); + msg_scratch_pad->ipv4_address_present = FALSE; + + ipv6_zero_address(&msg_scratch_pad->ipv6_address); + msg_scratch_pad->ipv6_address_present = FALSE; + + strcpy(msg_scratch_pad->peer_type_description, " "); + msg_scratch_pad->peer_type_description[ + RFC5444_TLV_PEER_TYPE_MAX_LENGTH]='\0'; + + msg_scratch_pad->rlq_tx = 0; + msg_scratch_pad->rlq_rx = 0; + msg_scratch_pad->rlq_present = FALSE; + + msg_scratch_pad->resources = 0; + msg_scratch_pad->resources_present = FALSE; + + msg_scratch_pad->latency = 0; + msg_scratch_pad->latency_present = FALSE; + + msg_scratch_pad->cdr_tx = 0; + msg_scratch_pad->cdr_rx = 0; + msg_scratch_pad->cdr_present = FALSE; + + msg_scratch_pad->mdr_tx = 0; + msg_scratch_pad->mdr_rx = 0; + msg_scratch_pad->mdr_present = FALSE; + + msg_scratch_pad->mtu = 0; + msg_scratch_pad->mtu_present = FALSE; + +#if 0 +/* Below code is added for DLEPv7 */ + msg_scratch_pad->dlepv7_optional_signal = init_optional_signal(); + msg_scratch_pad->dlepv7_optional_data_item = init_optional_data_item(); +#endif + return; +} diff --git a/dlep_radio_ipv4/rfc5444_scratch_pad.h b/dlep_radio_ipv4/rfc5444_scratch_pad.h new file mode 100644 index 0000000..19656ae --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_scratch_pad.h @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------- + * rfc5444_scratch_pad.h -- data to manage parsed data + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __RFC5444_SCRATCH_PAD_H__ +#define __RFC5444_SCRATCH_PAD_H__ + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" + + + +/* + * message scratch pad - when a message is parsed, its + * data is first saved here so the peer or neighbor can + * be looked up. The required and optional TLVs can + * also be managed. + */ +typedef struct { + uint16_t sequence; + boolean_t sequence_present; + + uint32_t router_id; + boolean_t router_id_present; + + uint32_t client_id; + boolean_t client_id_present; + + uint8_t peer_heartbeat_interval; + boolean_t peer_heartbeat_interval_present; + +} rfc5444_packet_scratch_pad_t; + + + +/* + * message scratch pad - when a message is parsed, its + * data is first saved here so the peer or neighbor can + * be looked up. The required and optional TLVs can + * also be managed. + */ +typedef struct { + uint16_t message_code; + + uint16_t sequence; + boolean_t sequence_present; + + uint8_t major_version; + boolean_t major_version_present; + + uint8_t minor_version; + boolean_t minor_version_present; + + uint16_t status_code; + boolean_t status_code_present; + + uint8_t mac_address[MAC_ADDR_LEN_IN_BYTES]; + boolean_t mac_address_present; + + ipv4_address_t ipv4_address; + ipv4_address_t ipv4_attached_subnet; + uint8_t ipv4_operation; + boolean_t ipv4_address_present; + + ipv6_address_t ipv6_address; + ipv6_address_t ipv6_attached_subnet; + uint8_t ipv6_operation; + boolean_t ipv6_address_present; + + char peer_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH+1]; + + /* metrics */ + boolean_t rlq_present; + uint8_t rlq_tx; + uint8_t rlq_rx; + + boolean_t resources_present; + uint8_t resources_tx; + uint8_t resources_rx; + uint8_t resources; /* addded for v27 */ + + boolean_t latency_present; + uint64_t latency; + + boolean_t cdr_present; + uint64_t cdr_tx; + uint64_t cdr_rx; + + boolean_t mdr_present; + uint64_t mdr_tx; + uint64_t mdr_rx; + + uint16_t port; + uint32_t eft; + + boolean_t cws_present; + uint64_t mrw; + uint64_t rrw; + uint64_t cgr; + + boolean_t credit_req_present; + + uint32_t hbt; + + boolean_t mtu_present; + uint16_t mtu; /* added for v27 */ + +#if 0 + uint32_t dlepv7_optional_signal; + uint32_t dlepv7_optional_data_item; +#endif + +} rfc5444_message_scratch_pad_t; + + +extern void +rfc5444_show_packet_scratch_pad( + rfc5444_packet_scratch_pad_t *pkt_scratch_pad); + +extern void +rfc5444_show_message_scratch_pad( + rfc5444_message_scratch_pad_t *msg_scratch_pad); + +extern void +rfc5444_scrub_packet_scratch_pad( + rfc5444_packet_scratch_pad_t *pkt_scratch_pad); + +extern void +rfc5444_scrub_message_scratch_pad( + rfc5444_message_scratch_pad_t *msg_scratch_pad); + +#endif + + diff --git a/dlep_radio_ipv4/rfc5444_types.h b/dlep_radio_ipv4/rfc5444_types.h new file mode 100644 index 0000000..f57b0b2 --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_types.h @@ -0,0 +1,292 @@ +/*------------------------------------------------------------------ + * rfc5444_types.h -- RFC5444 types + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef ___RFC5444_TYPES__ +#define ___RFC5444_TYPES__ + + +#include "rfc5444_api_rc.h" + + + +#define SECONDS_TO_MILLISECONDS ( 1000 ) + + + +/* reasonable bounds for good measure */ +#define RFC5444_MIN_PACKET_LEN ( 3 ) +#define RFC5444_MAX_PACKET_LEN ( 1400 ) + +#define RFC5444_MIN_MESSAGE_LEN ( 3 ) +#define RFC5444_MAX_MESSAGE_LEN ( 500 ) + + + +/* + * packet header flag definitions + */ +#define PHASSEQNUM ( 0x08 ) /* ignored */ +#define PHASTLV ( 0x04 ) + +/* + * message header flag definitions + */ +#define MHASHORIG ( 0x80 ) /* not supported */ +#define MHASHOPLIMIT ( 0x40 ) /* not supported */ +#define MHASHOPCOUNT ( 0x20 ) /* not supported */ +#define MHASSEQNUM ( 0x10 ) +#define MHASADDRLEN ( 0x03 ) /* not supported */ + +/* + * TLV flag definitions + */ +#define THASTYPEEXT ( 0x80 ) /* not supported */ +#define THASSINGLEINDEX ( 0x40 ) /* not supported */ +#define THASMULTIINDEX ( 0x20 ) /* not supported */ +#define THASVALUE ( 0x10 ) +#define THASEXTLEN ( 0x08 ) +#define THASMULTIVALUE ( 0x04 ) /* not supported */ + + +/* + * Signal header flags + */ +#define DLEP_SIGNAL_FLAGS (0x444C4550) + +/* + * Status codes used in the Status TLV. + */ +typedef enum { + RFC5444_SUCCESS = 0, + RFC5444_ERROR, + RFC5444_REQUEST_DENIED = 2, + RFC5444_MSG_UNKNOWN = 128, + RFC5444_MSG_UNEXPECTED = 129, + RFC5444_INVALID_DATA = 130, + RFC5444_INVALID_DESTINATION = 131, + RFC5444_MSG_TIMEOUT = 132, +} rfc5444_status_code_type_t; + + +/* + * The max value for RLQ and Resources + */ +#define RFC5444_100_PERCENT ( 100 ) + +/* DLEP version implemented and supported */ +#define RFC5444_DLEP_MAJOR_VERSION ( 1 ) +#define RFC5444_DLEP_MINOR_VERSION ( 7 ) + + +/* + * When the TLV vector table is allocated, we add one to + * the max to account for the 0 based array. The TLV + * code is the index straight-up. 0--invalid, 1-255 valid. + */ +#define RFC5444_MAX_TLV_CODE ( 255 ) + + +/* + * RFC5444 TLV Codes + ***FIX - TLV codes to be defined with IANA + */ +typedef enum { + RFC5444_TLV_RESERVED = 0, + RFC5444_TLV_STATUS = 1, + RFC5444_TLV_IPV4_CONNECTION_POINT = 2, + RFC5444_TLV_IPV6_CONNECTION_POINT = 3, + RFC5444_TLV_PEER_TYPE = 4, + RFC5444_TLV_HEARTBEAT_INTERVAL = 5, + RFC5444_TLV_EXTENSION_SUPPORTED = 6, + + RFC5444_TLV_MAC_ADDRESS = 7, + RFC5444_TLV_IPV4_ADDRESS = 8, + RFC5444_TLV_IPV6_ADDRESS = 9, + RFC5444_TLV_IPV4_ATTACHED_SUBNET = 10, + RFC5444_TLV_IPV6_ATTACHED_SUBNET = 11, + + RFC5444_TLV_LINK_MDR_METRIC_RX = 12, + RFC5444_TLV_LINK_MDR_METRIC_TX = 13, + RFC5444_TLV_LINK_CDR_METRIC_RX = 14, + RFC5444_TLV_LINK_CDR_METRIC_TX = 15, + RFC5444_TLV_LINK_LATENCY_METRIC = 16, + RFC5444_TLV_LINK_RESOURCES_METRIC = 17, + RFC5444_TLV_LINK_RLQ_METRIC_RX = 18, + RFC5444_TLV_LINK_RLQ_METRIC_TX = 19, + + RFC5444_TLV_MTU = 20, + + RFC5444_MAX_DATA_ITEM = 21, + /* added to avoid build error of 27 since existing v7 needs below */ + RFC5444_TLV_VERSION, + RFC5444_TLV_PORT, + RFC5444_TLV_LINK_RESOURCES_METRIC_RX , + RFC5444_TLV_LINK_RESOURCES_METRIC_TX , + RFC5444_TLV_LINK_EFT_METRIC , + RFC5444_TLV_CREDIT_WINDOW_STATUS , + RFC5444_TLV_CREDIT_GRANT , + RFC5444_TLV_CREDIT_REQUEST , + RFC5444_TLV_VENDOR_EXTENSION, + RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED , + RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED , +} rfc5444_tlv_t; + + +/* + * Flag values used to encode and decode TLVs + */ +#define RFC5444_TLV_IDENTIFICATION_FLAGS ( 0x10 ) +#define RFC5444_TLV_VERSION_FLAGS ( 0x10 ) +#define RFC5444_TLV_PEER_TYPE_FLAGS ( 0x00 ) + +#define RFC5444_TLV_MAC_ADDRESS_FLAGS ( 0x10 ) +#define RFC5444_TLV_IPV4_ADDRESS_FLAGS ( 0x10 ) +#define RFC5444_TLV_IPV6_ADDRESS_FLAGS ( 0x10 ) + +#define RFC5444_TLV_LINK_METRIC_MDR_FLAGS ( 0x10 ) +#define RFC5444_TLV_LINK_METRIC_CDR_FLAGS ( 0x10 ) +#define RFC5444_TLV_LINK_METRIC_LATENCY_FLAGS ( 0x10 ) +#define RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS ( 0x10 ) +#define RFC5444_TLV_LINK_METRIC_RLQ_FLAGS ( 0x10 ) + +#define RFC5444_TLV_STATUS_FLAGS ( 0x10 ) +#define RFC5444_TLV_IPV4_CONNECTION_POINT_FLAGS ( 0x00 ) + +/* + * Lengths (bytes) used to encode and decode TLVs + */ +#define RFC5444_TLV_IDENTIFICATION_LENGTH ( 9 ) +#define RFC5444_TLV_VERSION_LENGTH ( 4 ) + + /* string length <= 80 */ +#define RFC5444_TLV_PEER_TYPE_MAX_LENGTH ( 160 ) + +#define RFC5444_TLV_MAC_ADDRESS_LENGTH ( 6 ) +#define RFC5444_TLV_IPV4_ADDRESS_LENGTH ( 5 ) /* + operation */ +#define RFC5444_TLV_IPV6_ADDRESS_LENGTH ( 17 ) /* + operation */ + +#define RFC5444_TLV_LINK_METRIC_MDR_LENGTH ( 8 ) +#define RFC5444_TLV_LINK_METRIC_CDR_LENGTH ( 8 ) +#define RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH ( 8 ) +#define RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH ( 1 ) +#define RFC5444_TLV_LINK_METRIC_RLQ_LENGTH ( 1 ) +#define RFC5444_TLV_LINK_METRIC_EFT_LENGTH ( 4 ) +#define RFC5444_TLV_PORT_LENGTH ( 2 ) +#define RFC5444_TLV_CREDIT_WINDOW_STATUS_LENGTH ( 16 ) +#define RFC5444_TLV_STATUS_LENGTH ( 1 ) +#define RFC5444_TLV_CREDIT_GRANT_LENGTH ( 8 ) +#define RFC5444_TLV_CREDIT_REQUEST_LENGTH ( 1 ) +#define RFC5444_TLV_HEARTBEAT_INTERVAL_LENGTH ( 4 ) +#define RFC5444_TLV_MTU_LENGTH ( 2 ) +#define RFC5444_TLV_IPV4_CONNECTION_POINT_LENGTH ( 7 ) + +/* Below TLV's length are added for DLEPv7 */ +#define RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED_LENGTH ( 6 ) +#define RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED_LENGTH ( 12 ) +/* +Length (3) + OUI length(1) + VENDOR OUI (3 octets) ++ DEVICE TYPE (2) + PAYLOAD length (6 (T + L + V) = 15 +*/ +#define RFC5444_TLV_VENDOR_EXTENSION_LENGTH ( 15 ) +#define RFC5444_TLV_IPV4_ATTACHED_SUBNET_LENGTH ( 6 ) +#define RFC5444_TLV_IPV6_ATTACHED_SUBNET_LENGTH ( 18 ) + +/* For VENDOR EXTENSION TLV in DLEPv7 */ +#define VENDOR_OUI_LENGTH ( 3 ) +#define VENDOR_SPECIFIC_PAYLOAD_TYPE ( 30 ) +#define VENDOR_SPECIFIC_PAYLOAD_LENGTH 4 + +/* + * IPv4/6 addresses can be added or dropped by the + * RFC5444_MSG_NEIGHBOR_ADDRESS message. + */ +#define RFC5444_NO_ADDRESS ( 0x02 ) /* added to avoid error */ +#define RFC5444_EXISTING_ADD_ADDRESS ( 0x01 ) +#define RFC5444_DROP_ADDRESS ( 0x00 ) + + + + +/* + * RFC5444 Router-Radio Message codes + ***FIX - message codes to be defined with IANA + */ + +typedef enum { + RFC5444_SIG_RESERVED = 0, + + RFC5444_SIG_ATT_PEER_DISCOVERY, + + RFC5444_SIG_PEER_OFFER, + + RFC5444_MAX_SIGNAL_CODE +} rfc5444_sig_type_t; + +typedef enum { + RFC5444_MSG_RESERVED = 0, + + RFC5444_MSG_PEER_INIT_REQ, + RFC5444_MSG_PEER_INIT_RES, + + + RFC5444_MSG_PEER_UPDATE_REQ, + RFC5444_MSG_PEER_UPDATE_RES, + + RFC5444_MSG_PEER_TERM_REQ, + RFC5444_MSG_PEER_TERM_RES, + + RFC5444_MSG_NEIGHBOR_UP_REQ, + RFC5444_MSG_NEIGHBOR_UP_RES, + + RFC5444_MSG_NEIGHBOR_ANNOUNCE_REQ, + RFC5444_MSG_NEIGHBOR_ANNOUNCE_RES, + + RFC5444_MSG_NEIGHBOR_DOWN_REQ, + RFC5444_MSG_NEIGHBOR_DOWN_RES, + + RFC5444_MSG_NEIGHBOR_METRICS, + + RFC5444_MSG_LINK_CHAR_REQ, + RFC5444_MSG_LINK_CHAR_RES, + + RFC5444_MSG_PEER_HEARTBEAT, + + RFC5444_MAX_MESSAGE_CODE, + /* added to avoid build errors */ + RFC5444_MSG_DET_PEER_DISCOVERY, + RFC5444_MSG_NEIGHBOR_ADDRESS_REQ, + RFC5444_MSG_NEIGHBOR_ADDRESS_RES, + +} rfc5444_msg_type_t; + + +#endif + diff --git a/dlep_radio_ipv4/rfc5444_utils.c b/dlep_radio_ipv4/rfc5444_utils.c new file mode 100644 index 0000000..fd89af9 --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_utils.c @@ -0,0 +1,397 @@ +/*---------------------------------------------------------------------- + * rfc5444_utils.c -- RFC5444 utils + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "safe_types.h" +#include "rfc5444_types.h" + +#include "rfc5444_utils.h" + + +/** + * NAME + * r2rc2string + * + * SYNOPSIS + * #include "rfc5444_utils.h" + * char + * *rfc5444_rc2string(uint32_t rc) + * + * DESCRIPTION + * This function converts a RFC5444 return code to a string + * for display. + * + * INPUT PARAMETERS + * rc - The return code to be converted to a string + * + * OUTPUT PARAMETERS + * None + * + * RETURN VALUE + * A pointer to a string description of the return code + * + */ +char +*rfc5444_rc2string (uint32_t rc) +{ + char *p2text; + + switch (rc) { + + case RC_RFC5444_OK: + p2text = "RC_RFC5444_OK"; + break; + + case RC_RFC5444_NULL_POINTER: + p2text = "RC_RFC5444_NULL_POINTER"; + break; + + case RC_RFC5444_NO_RESOURCES: + p2text = "RC_RFC5444_NO_RESOURCES"; + break; + + case RC_RFC5444_STATE_ERROR: + p2text = "RC_RFC5444_STATE_ERROR"; + break; + + case RC_RFC5444_VERSION_ERROR: + p2text = "RC_RFC5444_VERSION_ERROR"; + break; + + case RC_RFC5444_INVALID_PACKET_HEADER: + p2text = "RC_RFC5444_INVALID_PACKET_HEADER"; + break; + + case RC_RFC5444_INVALID_PACKET_LENGTH: + p2text = "RC_RFC5444_INVALID_PACKET_LENGTH"; + break; + + case RC_RFC5444_INVALID_BLOCK_INDICATOR: + p2text = "RC_RFC5444_INVALID_BLOCK_INDICATOR"; + break; + + case RC_RFC5444_INVALID_MESSAGE_FLAG: + p2text = "RC_RFC5444_INVALID_MESSAGE_FLAG"; + break; + + case RC_RFC5444_INVALID_MESSAGE_MAL: + p2text = "RC_RFC5444_INVALID_MESSAGE_MAL"; + break; + + case RC_RFC5444_INVALID_MESSAGE_LENGTH: + p2text = "RC_RFC5444_INVALID_MESSAGE_LENGTH"; + break; + + case RC_RFC5444_INVALID_MESSAGE_SEQUENCE: + p2text = "RC_RFC5444_INVALID_MESSAGE_SEQUENCE"; + break; + + case RC_RFC5444_INVALID_MESSAGE_CODE: + p2text = "RC_RFC5444_INVALID_MESSAGE_CODE"; + break; + + case RC_RFC5444_INVALID_TLV_BLOCK_LENGTH: + p2text = "RC_RFC5444_INVALID_TLV_BLOCK_LENGTH"; + break; + + case RC_RFC5444_UNKNOWN_TLV_CODE: + p2text = "RC_RFC5444_UNKNOWN_TLV_CODE"; + break; + + case RC_RFC5444_INVALID_TLV_FLAG: + p2text = "RC_RFC5444_INVALID_TLV_FLAG"; + break; + + case RC_RFC5444_INVALID_TLV_LENGTH: + p2text = "RC_RFC5444_INVALID_TLV_LENGTH"; + break; + + default: + p2text = "RFC5444_UNKNOWN_RETURN_CODE"; + break; + } + return (p2text); +} + + +/** + * NAME + * rfc5444_tlv_code2string + * + * SYNOPSIS + * #include "rfc5444_utils.h" + * char + * *rfc5444_tlv_code2string(uint8_t tlv_code) + * + * DESCRIPTION + * This function converts a RFC5444 TLV code to a string + * for display. + * + * INPUT PARAMETERS + * tlv_code - The code to be converted to a string + * + * OUTPUT PARAMETERS + * None + * + * RETURN VALUE + * A pointer to a string description of the TLV code + * + */ +char +*rfc5444_tlv_code2string (uint16_t tlv_code) +{ + char *p2text; + + switch (tlv_code) { +#if 0 + case RFC5444_TLV_IDENTIFICATION: + p2text = "RFC5444_TLV_IDENTIFICATION"; + break; +#endif + case RFC5444_TLV_VERSION: + p2text = "RFC5444_TLV_VERSION"; + break; + + case RFC5444_TLV_PORT: + p2text = "RFC5444_TLV_PORT"; + break; + + case RFC5444_TLV_PEER_TYPE: + p2text = "RFC5444_TLV_PEER_TYPE"; + break; + + case RFC5444_TLV_MAC_ADDRESS: + p2text = "RFC5444_TLV_MAC_ADDRESS"; + break; + + case RFC5444_TLV_IPV4_ADDRESS: + p2text = "RFC5444_TLV_IPV4_ADDRESS"; + break; + + case RFC5444_TLV_IPV6_ADDRESS: + p2text = "RFC5444_TLV_IPV6_ADDRESS"; + break; + + case RFC5444_TLV_LINK_MDR_METRIC_TX: + p2text = "RFC5444_TLV_LINK_MDR_TX_METRIC"; + break; + + case RFC5444_TLV_LINK_MDR_METRIC_RX: + p2text = "RFC5444_TLV_LINK_MDR_RX_METRIC"; + break; + + case RFC5444_TLV_LINK_CDR_METRIC_TX: + p2text = "RFC5444_TLV_LINK_CDR_TX_METRIC"; + break; + + case RFC5444_TLV_LINK_CDR_METRIC_RX: + p2text = "RFC5444_TLV_LINK_CDR_RX_METRIC"; + break; + + case RFC5444_TLV_LINK_LATENCY_METRIC: + p2text = "RFC5444_TLV_LINK_LATENCY_METRIC"; + break; + + case RFC5444_TLV_LINK_RESOURCES_METRIC_TX: + p2text = "RFC5444_TLV_LINK_RESOURCES_TX_METRIC"; + break; + + case RFC5444_TLV_LINK_RESOURCES_METRIC_RX: + p2text = "RFC5444_TLV_LINK_RESOURCES_RX_METRIC"; + break; + + case RFC5444_TLV_LINK_RLQ_METRIC_TX: + p2text = "RFC5444_TLV_LINK_RLQ_METRIC"; + break; + + case RFC5444_TLV_LINK_RLQ_METRIC_RX: + p2text = "RFC5444_TLV_LINK_RLQ_RX_METRIC"; + break; + + case RFC5444_TLV_HEARTBEAT_INTERVAL: + p2text = "RFC5444_TLV_HEARTBEAT_INTERVAL"; + break; + + case RFC5444_TLV_STATUS: + p2text = "RFC5444_TLV_STATUS"; + break; + + case RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED: + p2text = "RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED"; + break; + + case RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED: + p2text = "RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED"; + break; + + case RFC5444_TLV_VENDOR_EXTENSION: + p2text = "RFC5444_TLV_VENDOR_EXTENSION"; + break; + + case RFC5444_TLV_IPV4_ATTACHED_SUBNET: + p2text = "RFC5444_TLV_IPV4_ATTACHED_SUBNET"; + break; + + case RFC5444_TLV_IPV6_ATTACHED_SUBNET: + p2text = "RFC5444_TLV_IPV6_ATTACHED_SUBNET"; + break; + + /* added for dlepv 27 */ + + case RFC5444_TLV_LINK_RESOURCES_METRIC: + p2text = "RFC5444_TLV_LINK_RESOURCES_METRIC"; + break; + + case RFC5444_TLV_MTU: + p2text = "RFC5444_TLV_MTU"; + break; + + default: + p2text = "RFC5444_UNKNOWN_TLV_CODE"; + break; + } + return (p2text); +} + + +/** + * NAME + * rfc5444_message_code2string + * + * SYNOPSIS + * #include "rfc5444_utils.h" + * char + * *rfc5444_message_code2string(uint8_t message_code) + * + * DESCRIPTION + * This function converts a RFC5444 message code to a string + * for display. + * + * INPUT PARAMETERS + * message_code - The message code to be converted to a string + * + * OUTPUT PARAMETERS + * None + * + * RETURN VALUE + * A pointer to a string description of the message code + * + */ +char +*rfc5444_message_code2string (uint16_t message_code) +{ + char *p2text; + + switch (message_code) { + /* case RFC5444_SIG_ATT_PEER_DISCOVERY: + p2text = "RFC5444_SIG_ATT_PEER_DISCOVERY"; + break; */ + + case RFC5444_MSG_DET_PEER_DISCOVERY: + p2text = "RFC5444_MSG_DET_PEER_DISCOVERY"; + break; + + /* case RFC5444_SIG_PEER_OFFER: + p2text = "RFC5444_SIG_PEER_OFFER"; + break; */ + + case RFC5444_MSG_PEER_INIT_REQ: + p2text = "RFC5444_MSG_PEER_INIT_REQ"; + break; + + case RFC5444_MSG_PEER_INIT_RES: + p2text = "RFC5444_MSG_PEER_INIT_RES"; + break; + + case RFC5444_MSG_PEER_HEARTBEAT: + p2text = "RFC5444_MSG_PEER_HEARTBEAT"; + break; + + case RFC5444_MSG_PEER_UPDATE_REQ: + p2text = "RFC5444_MSG_PEER_UPDATE_REQ"; + break; + + case RFC5444_MSG_PEER_UPDATE_RES: + p2text = "RFC5444_MSG_PEER_UPDATE_RES"; + break; + + case RFC5444_MSG_PEER_TERM_REQ: + p2text = "RFC5444_MSG_PEER_TERM_REQ"; + break; + + case RFC5444_MSG_PEER_TERM_RES: + p2text = "RFC5444_MSG_PEER_TERM_RES"; + break; + + case RFC5444_MSG_NEIGHBOR_UP_REQ: + p2text = "RFC5444_MSG_NEIGHBOR_UP_REQ"; + break; + + case RFC5444_MSG_NEIGHBOR_UP_RES: + p2text = "RFC5444_MSG_NEIGHBOR_UP_RES"; + break; + + case RFC5444_MSG_NEIGHBOR_DOWN_REQ: + p2text = "RFC5444_MSG_NEIGHBOR_DOWN_REQ"; + break; + + case RFC5444_MSG_NEIGHBOR_DOWN_RES: + p2text = "RFC5444_MSG_NEIGHBOR_DOWN_RES"; + break; + + case RFC5444_MSG_NEIGHBOR_METRICS: + p2text = "RFC5444_MSG_NEIGHBOR_METRICS"; + break; + + case RFC5444_MSG_NEIGHBOR_ADDRESS_REQ: + p2text = "RFC5444_MSG_NEIGHBOR_ADDRESS_REQ"; + break; + + case RFC5444_MSG_NEIGHBOR_ADDRESS_RES: + p2text = "RFC5444_MSG_NEIGHBOR_ADDRESS_RES"; + break; + + case RFC5444_MSG_LINK_CHAR_REQ: + p2text = "RFC5444_MSG_LINK_CHAR_REQ"; + break; + + case RFC5444_MSG_LINK_CHAR_RES: + p2text = "RFC5444_MSG_LINK_CHAR_RES"; + break; + + default: + p2text = "RFC5444_UNKNOWN_MESSAGE_CODE"; + break; + } + return (p2text); +} + diff --git a/dlep_radio_ipv4/rfc5444_utils.h b/dlep_radio_ipv4/rfc5444_utils.h new file mode 100644 index 0000000..bce8a1e --- /dev/null +++ b/dlep_radio_ipv4/rfc5444_utils.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------- + * rfc5444_utils.h -- utility prototypes + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __RFC5444_UTILS_H__ +#define __RFC5444_UTILS_H__ + +#include "safe_types.h" + + +extern char *rfc5444_rc2string(uint32_t rc); + +extern char *rfc5444_tlv_code2string(uint16_t tlv_code); + +extern char *rfc5444_message_code2string(uint16_t message_code); + +#endif + diff --git a/dlep_radio_ipv4/runtime_environment.h b/dlep_radio_ipv4/runtime_environment.h new file mode 100644 index 0000000..5971b60 --- /dev/null +++ b/dlep_radio_ipv4/runtime_environment.h @@ -0,0 +1,41 @@ +/*------------------------------------------------------------------ + * runtime_environment.h -- Abstractions + * + * Februrary 2002, Bo Berry + * + * Copyright (c) 2002-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __RUNTIME_ENVIRONMENT_H__ +#define __RUNTIME_ENVIRONMENT_H__ + + +#define LOCK_INTERRUPTS() +#define UNLOCK_INTERRUPTS() + + +#endif + diff --git a/dlep_radio_ipv4/safe_limits.h b/dlep_radio_ipv4/safe_limits.h new file mode 100644 index 0000000..b028026 --- /dev/null +++ b/dlep_radio_ipv4/safe_limits.h @@ -0,0 +1,195 @@ +/*------------------------------------------------------------------ + * safe_limits.h + * + * February 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __SAFE_LIMITS__ +#define __SAFE_LIMITS__ + +/* + * Abstract header file for portability. + */ + + +/* + * ANSI C - number of bits by type + */ +#ifndef CHAR_BIT +#define CHAR_BIT ( 8 ) +#endif + +#ifndef BYTE_BIT +#define BYTE_BIT ( 8 ) +#endif + +#ifndef SHORT_BIT +#define SHORT_BIT ( 16 ) +#endif + +#ifndef INT_BIT +#define INT_BIT ( 32 ) +#endif + +#ifndef LONG_BIT +// #define LONG_BIT ( 32 ) +#define LONG_BIT ( 64 ) +#endif + +#ifndef LONG_LONG_BIT +#define LONG_LONG_BIT ( 64 ) +#endif + +#ifndef POINTER_BIT +#define POINTER_BIT ( 64 ) +#endif + + + +#ifndef BYTE_MAX +#define BYTE_MAX ( 255 ) +#endif + +#ifndef SCHAR_MAX +#define SCHAR_MAX ( 127 ) +#define SCHAR_MIN ( -SCHAR_MAX - 1 ) +#endif + +#ifndef CHAR_MAX +#define CHAR_MAX ( 127 ) +#define CHAR_MIN ( -CHAR_MAX - 1 ) +#endif + +#ifndef UCHAR_MAX +#define UCHAR_MAX ( 0xff ) +#endif + +#ifndef SHRT_MAX +#define SHRT_MAX ( 32767 ) +#define SHRT_MIN ( -SHRT_MAX - 1 ) +#endif + +#ifndef USHRT_MAX +#define USHRT_MAX ( 0xffff ) +#endif + +#ifndef INT_MAX +#define INT_MAX ( 2147483647 ) +#define INT_MIN ( -INT_MAX - 1 ) +#endif + +#ifndef UINT_MAX +#define UINT_MAX ( 0xffffffff ) +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX ( 9223372036854775807 ) +#define LLONG_MIN ( -LLONG_MAX - 1 ) +#endif + +#ifndef ULLONG_MAX +#define ULLONG_MAX ( 0xffffffffffffffff ) +#endif + + +#if LONG_BIT == INT_BIT + +#ifndef LONG_MAX +#define LONG_MAX ( INT_MAX) +#define LONG_MIN ( -LONG_MAX - 1 ) +#endif + +#ifndef ULONG_MAX +#define ULONG_MAX ( UINT_MAX ) +#endif + +#else + +#ifndef LONG_MAX +#define LONG_MAX ( LLONG_MAX) +#define LONG_MIN ( -LONG_MAX - 1 ) +#endif + +#ifndef ULONG_MAX +#define ULONG_MAX ( ULLONG_MAX ) +#endif + +#endif + + +#ifndef INT8_MIN +#define INT8_MIN ( SCHAR_MIN ) +#endif + +#ifndef INT8_MAX +#define INT8_MAX ( SCHAR_MAX ) +#endif + +#ifndef UINT8_MAX +#define UINT8_MAX ( UCHAR_MAX ) +#endif + +#ifndef INT16_MIN +#define INT16_MIN ( SHRT_MIN ) +#endif + +#ifndef INT16_MAX +#define INT16_MAX ( SHRT_MAX ) +#endif + +#ifndef UINT16_MAX +#define UINT16_MAX ( USHRT_MAX ) +#endif + +#ifndef INT32_MIN +#define INT32_MIN ( INT_MIN ) +#endif + +#ifndef INT32_MAX +#define INT32_MAX ( INT_MAX ) +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX ( UINT_MAX ) +#endif + +#ifndef INT64_MIN +#define INT64_MIN ( LLONG_MIN ) +#endif + +#ifndef INT64_MAX +#define INT64_MAX ( LLONG_MAX ) +#endif + +#ifndef UINT64_MAX +#define UINT64_MAX ( ULLONG_MAX ) +#endif + + +#endif /* __SAFE_LIMITS__ */ + diff --git a/dlep_radio_ipv4/safe_types.h b/dlep_radio_ipv4/safe_types.h new file mode 100644 index 0000000..eafaa0a --- /dev/null +++ b/dlep_radio_ipv4/safe_types.h @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------ + * safe_types.h + * + * March 2007, Bo Berry + * + * Copyright (c) 2007-2011 by Cisco Systems, Inc + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __SAFE_TYPES__ +#define __SAFE_TYPES__ + +#include + +#include "safe_limits.h" + + +/* + * Abstract header file for portability. + */ + +#ifndef TRUE +#define TRUE ( 1 ) +#endif + +#ifndef FALSE +#define FALSE ( 0 ) +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#ifndef boolean_t +typedef unsigned char boolean_t; +#endif + + + +#ifndef int8_t +typedef signed char int8_t; +#endif + +#ifndef int16_t +typedef short int16_t; +#endif + +#ifndef int32_t +typedef int int32_t; +#endif + +#ifndef uchar_t +typedef unsigned char uchar_t; +#endif + +#ifndef uint8_t +typedef unsigned char uint8_t; +#endif + +#ifndef uint16_t +typedef unsigned short uint16_t; +#endif + +#ifndef uint32_t +typedef unsigned int uint32_t; +#endif + +#ifndef uint64_t +//typedef unsigned long long uint64_t; +#endif + +#if 0 +#if POINTER_BIT == 64 +#ifndef intptr_t; +typedef long long intptr_t; +#endif + +#ifndef uintptr_t; +typedef unsigned long long uintptr_t; +#endif + +#else + +#ifndef intptr_t; +typedef signed int intptr_t; +#endif +#ifndef uintptr_t; +typedef unsigned int uintptr_t; +#endif + +#endif +#endif + + +#ifndef ushort +typedef unsigned short ushort; +#endif + +#ifndef int_t +typedef int int_t; +#endif + +#ifndef uint_t +typedef unsigned int uint_t; +#endif + +#ifndef ulong +typedef unsigned long ulong; +#endif + +#ifndef ulonglong +typedef unsigned long long ullong; +#endif + + +#endif /* __SAFE_TYPES__ */ + diff --git a/dlep_radio_ipv4/sim_dlep_radio.c b/dlep_radio_ipv4/sim_dlep_radio.c new file mode 100644 index 0000000..b6ddbb3 --- /dev/null +++ b/dlep_radio_ipv4/sim_dlep_radio.c @@ -0,0 +1,466 @@ +/*---------------------------------------------------------------------- + * sim_dlep_radio.c -- Radio simulator + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +static char FileID[] = "@(#)dlep_radio "__DATE__" "__TIME__" "; + +#include +#include +#include +//#include +#include +#include + +#include "safe_types.h" +#include "cli.h" +#include "time_units.h" +#include "stw_system_timer.h" +#include "packet_dump.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_encoder_tlv.h" +#include "rfc5444_encoder.h" +#include "rfc5444_decoder.h" +#include "rfc5444_decoder_tlv.h" +#include "rfc5444_experimental_tlv.h" + + +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" +#include "dlep_client_timer.h" +#include "dlep_client_peer_fsm.h" +#include "sim_dlep_radio_cli.h" + +#include "dlep_porter.h" + +#include "dlep_client_message_parser.h" + + +#define MAXMESG ( 1500 ) + + +static char *instructions[] = { + " dlep_radio ", + " options: ", + " -d Debug peer flags, hex ", + " -f Configuration filename ", + " -h This help file ", + " -v Display version ", + " ", + }; + + +int TCP_READY = 0; +int TCP_CLIENT_READY = 0; + +/** + * NAME + * show_instructions + * + * DESCRIPTION + * Displays the help info to stdout. + * + * INPUT PARAMETERS + * None. + * + * RETURN VALUE + * None. + * + */ +static void +show_instructions( ) +{ + int i; + + for (i=0; ifilename, args); + printf(" Config file = %s \n", p2config->filename); + break; + + case 'h': + show_instructions(); + exit (EXIT_SUCCESS); + break; + + case 'v': + printf("\n%s \n\n", &FileID[4]); + exit (EXIT_SUCCESS); + break; + + default: + fprintf(stderr, "\nUnknown option: %s\n", args); + exit (EXIT_SUCCESS); + break; + } + + } else { + return (i); + } + } + + return (argc); +} + + +/* + * This function is envoked as result of the interval timer expiration + */ +static void timer_handler (int signum) +{ + stw_system_timer_tick(); +} + + +int main (int argc, char **argv) +{ + dlep_config_t *p2config; + rfc5444_rc_t rc; + + uint8_t *tmp; + uint8_t udp_msg[2000]; + int32_t udp_msg_len; + uint8_t tcp_msg[2000]; + int32_t tcp_msg_len; + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + +#define SCENARIO_INDICATOR ( 0xFFFF ) + uint16_t scenario_key; + + /* + * interval timer variables + */ + struct sigaction sa; + struct itimerval timer; + uint32_t microseconds; + //uint32_t milliseconds; + dlep_context_peer_t *p2peer; + + struct sockaddr_in rcvd_msg_addr; + socklen_t rcvd_msg_socket_length; + + int highsock=0; + fd_set readfds={0}; + boolean_t verbose; + rfc5444_decoder_init(&dlep_client_message_parser); + rfc5444_decoder_tlv_init(); + rfc5444_experimental_tlv_init(); + + dlep_cli_init(); + dlep_debug_init(&dlep_debug_flags, 0); + + dlep_default_config(); + p2config = dlep_get_config_ptr(); + + dlep_parse_user_options(p2config, argc, argv); + + dlep_read_config_file(p2config); + dlep_display_config(p2config); + + dlep_porter_init(p2config); + dlep_porter_open(p2config); + dlep_tcp_porter_open(p2config); + + /* + * create and configure the timer + */ +#define DLEP_STW_NUMBER_BUCKETS ( 512 ) +#define DLEP_STW_RESOLUTION ( 100 ) + + stw_system_timer_create(DLEP_STW_NUMBER_BUCKETS, + DLEP_STW_RESOLUTION, + "DLEP Timer"); + + /* + * Install the interval timer_handler as the signal handler + * for SIGALRM. + */ + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = &timer_handler; + sigaction (SIGALRM, &sa, NULL); + + /* + * Configure the initial and post delay + */ + microseconds = milli_to_microseconds(DLEP_STW_RESOLUTION); + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = microseconds; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = microseconds; + + /* + * Now start the interval timer. + */ + setitimer (ITIMER_REAL, &timer, NULL); + + + /* + * allocate and instantiate a peer for simulation + */ + p2peer = dlep_peer_allocate(&p2config->local_ipv4, + p2config->local_udp_port, + p2config->local_tcp_port); + + if (!p2peer) { + printf("%s-%u ERROR: did not allocate peer block \n", + DEBUG_FUNCTION, + DEBUG_LINE); + exit (0); + } + dlep_peer_init(p2config, p2peer); + + /* set the peer udp/tcp port to router udp/tcp port and + * peer address to the router address */ + + p2peer->peer_udp_port = p2config->router_udp_port; + p2peer->peer_tcp_port = p2config->router_tcp_port; + p2peer->peer_ipv4.v4_addr.v4_addr32 = + p2config->router_ipv4.v4_addr.v4_addr32; + +//for verification only +// ipv4_print_address("router IPv4", &p2peer->peer_ipv4); + + /* position the DLEP IDs */ + p2peer->client_id = p2config->local_id; + p2peer->router_id = 0; + + p2config->client_lenght = sizeof(p2config->client); + printf("start on launch\n"); +#if 0 + if (p2config->start_on_launch) { + ** start the state machine ** + if (p2config->start_on_discovery) { + dlep_client_fsm_engine(start_init_e, p2peer, NULL); + } else { + dlep_client_fsm_engine(peer_init_request_e, p2peer, NULL); + } + } +#endif + + cli_set_prompt(p2config->sim_name); + highsock = p2config->dlep_tcp_sockfd +1 ; + +#if 0 + FD_ZERO(&readfds); + FD_SET(0, &readfds); + FD_SET(p2config->dlep_udp_sockfd, &readfds); + FD_SET(p2config->dlep_tcp_sockfd, &readfds); +#endif + while (1) { + + /* zero out the control header and initial payload data */ + memset(udp_msg, 0, 20); + + FD_ZERO(&readfds); + FD_SET(0, &readfds); + FD_SET(p2config->dlep_udp_sockfd, &readfds); + FD_SET(p2config->dlep_tcp_sockfd, &readfds); + + if (TCP_CLIENT_READY == 1) { + FD_SET(p2config->dlep_tcp_client_sockfd, &readfds); + } + + /* Since tcp socket is created after udp socket, it will have + * the highest-numbered file descriptor. + */ + if (select(highsock, &readfds, NULL, NULL, NULL) < 0 ) { + continue; + } + /* check is udp socket ready for read operation */ + if (FD_ISSET(p2config->dlep_udp_sockfd, &readfds)) { + printf("ready udp\n"); + /* blocking call */ + udp_msg_len = dlep_udp_receive(p2config, + &rcvd_msg_addr, + &rcvd_msg_socket_length, + udp_msg, + 1400); + if (udp_msg_len < 1 ) { + continue; + } + + tmp = udp_msg; + NETWORK_ORDER_GETSHORT(udp_msg, scenario_key); + tmp += sizeof(uint16_t); + if (scenario_key == SCENARIO_INDICATOR) { + printf(" %s \n", tmp); + dlep_cli_engine((char *)tmp); + } else { + + rfc5444_scrub_packet_scratch_pad( + &p2peer->packet_scratch_pad); + rfc5444_scrub_message_scratch_pad( + &p2peer->message_scratch_pad); + + if (dlep_debug_flags & DLEP_INCOMING_TRACE_FLAG) { + packet_dump("INCOMING-", udp_msg, udp_msg_len); + } + + verbose = + ((dlep_debug_flags & DLEP_DECODER_TRACE_FLAG) ? TRUE : FALSE); + //printf("reaching decoder packet\n"); + rc = rfc5444_decoder_packet(udp_msg, + udp_msg_len, + p2peer, + verbose); + if (verbose) { + DLEP_DEBUG("%s-%u Packet decode rc=%u %s \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rc, + rfc5444_rc2string(rc) ); + } + } + } + + /* check is tcp socket ready for read operation */ + if (FD_ISSET(p2config->dlep_tcp_sockfd, &readfds)) { + p2config->dlep_tcp_client_sockfd = accept(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2config->client, &p2config->client_lenght); + + if (p2config->dlep_tcp_client_sockfd < 0) { + perror("ERROR on accept"); + } + + FD_SET(p2config->dlep_tcp_client_sockfd, &readfds); + highsock = (p2config->dlep_tcp_client_sockfd + 1); + TCP_CLIENT_READY = 1; + } + + if (FD_ISSET(p2config->dlep_tcp_client_sockfd, &readfds) && TCP_CLIENT_READY) { + /* blocking call */ + tcp_msg_len = dlep_tcp_receive(p2config, + &rcvd_msg_addr, + &rcvd_msg_socket_length, + tcp_msg, + 1400); + if (tcp_msg_len < 1 ) { + if (TCP_CLIENT_READY == 0) { + printf("\n TCP Connection closed"); + close(p2config->dlep_tcp_client_sockfd); + } + continue; + } + + tmp = tcp_msg; + NETWORK_ORDER_GETSHORT(tcp_msg, scenario_key); + tmp += sizeof(uint16_t); + if (scenario_key == SCENARIO_INDICATOR) { + printf(" %s \n", tmp); + dlep_cli_engine((char *)tmp); + } else { + + rfc5444_scrub_packet_scratch_pad( + &p2peer->packet_scratch_pad); + rfc5444_scrub_message_scratch_pad( + &p2peer->message_scratch_pad); + + if (dlep_debug_flags & DLEP_INCOMING_TRACE_FLAG) { + packet_dump("INCOMING-", tcp_msg, tcp_msg_len); + } + + verbose = + ((dlep_debug_flags & DLEP_DECODER_TRACE_FLAG) ? TRUE : FALSE); + rc = rfc5444_decoder_packet(tcp_msg, + tcp_msg_len, + p2peer, + verbose); + if (verbose) { + DLEP_DEBUG("%s-%u Packet decode rc=%u %s \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rc, + rfc5444_rc2string(rc) ); + } + } + } + + + /* console */ + if (FD_ISSET(0, &readfds)) { + fgets((char *)udp_msg, MAXMESG, stdin); + dlep_cli_engine((char *)udp_msg); + } + + } + + exit (0); +} + + diff --git a/dlep_radio_ipv4/sim_dlep_radio_cli.c b/dlep_radio_ipv4/sim_dlep_radio_cli.c new file mode 100644 index 0000000..2ade6bf --- /dev/null +++ b/dlep_radio_ipv4/sim_dlep_radio_cli.c @@ -0,0 +1,2053 @@ +/*------------------------------------------------------------------ + * sim_dlep_radio_cli.c -- Radio simulator CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reerved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#include "safe_types.h" +#include "cli.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_debug_cli.h" +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" +#include "dlep_message_builder.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" +#include "dlep_client_timer.h" + +#include "dlep_source_cli.h" +#include "fuzz_dlep_cli.h" + +#include "sim_dlep_radio_cli.h" +#include "dlep_porter.h" + +static boolean_t started = FALSE; +//static boolean_t CREDIT_NOT_SUPPORTED = FALSE; +//static boolean_t CREDIT_ENABLED = FALSE; + + +/* + * directory record + */ +static cli_record_t show_system_dir; +static cli_record_t show_peer_dir; +static cli_record_t show_neighbor_dir; + +//static cli_record_t clear_peer_dir; +//static cli_record_t clear_neighbor_dir; + +static cli_record_t test_peer_dir; +static cli_record_t test_neighbor_dir; + + +/* + * allocate command records + */ +static cli_record_t system_start_cmd; +static cli_record_t system_stop_cmd; + +static cli_record_t show_timer_stats_cmd; + +static cli_record_t show_peer_all_cmd; +static cli_record_t show_peer_fsm_history_cmd; +static cli_record_t show_peer_fsm_table_cmd; + +//static cli_record_t show_neighbor_id_cmd; +static cli_record_t show_neighbor_mac_cmd; +static cli_record_t show_neighbors_on_peer_cmd; +static cli_record_t show_neighbor_fsm_history_cmd; +static cli_record_t show_neighbor_fsm_table_cmd; + + +/* + * test command records + */ +static cli_record_t test_session_init_cmd; +static cli_record_t test_peer_term_cmd; +static cli_record_t test_peer_update_cmd; +static cli_record_t test_peer_offer_cmd; +static cli_record_t test_peer_update_res_cmd; +static cli_record_t test_peer_term_res_cmd; +static cli_record_t test_peer_init_ack_cmd; +static cli_record_t test_peer_heartbeat_cmd; +static cli_record_t test_neighbor_up_cmd; +static cli_record_t test_neighbor_update_cmd; +//static cli_record_t test_neighbor_l3_up_cmd; +static cli_record_t test_neighbor_credit_up_cmd; +static cli_record_t test_neighbor_metric_up_cmd; + +static cli_record_t test_neighbor_ipv4_req_cmd; +static cli_record_t test_neighbor_ipv6_req_cmd; + +static cli_record_t test_neighbor_down_cmd; + +static cli_record_t test_neighbor_metrics_cmd; +static cli_record_t test_neighbor_rlq_cmd; +static cli_record_t test_neighbor_resources_cmd; +static cli_record_t test_neighbor_latency_cmd; +static cli_record_t test_neighbor_cdr_cmd; +static cli_record_t test_neighbor_mdr_cmd; +static cli_record_t test_neighbor_mtu_cmd; +int init = 0; + + + +static void +system_start (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + dlep_config_t *p2config; + + if (argv[1] && *argv[1] == '?') { + printf("start - starts the discovery process when MANUAL " + "is defined in the config file. \n"); + return; + } + + if (started) { + printf("\n"); + printf("Hey, the radio sim is already running!! \n"); + printf("\n"); + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + p2config = dlep_get_config_ptr(); + if (p2peer) { + /*** start the state machine ***/ +/* if (p2config->start_on_discovery) { + dlep_client_fsm_engine(start_init_e, p2peer, NULL); + } else { + dlep_client_fsm_engine(peer_init_request_e, p2peer, NULL); + } + started = TRUE; +*/ + + } else { + printf("ERROR: hum, could not find peer to start \n"); + } + return; +} + + +static void +system_stop (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("stop - immediately exits the simulation \n"); + return; + } + + exit (0); + return; +} + + + +/** + ** show system commands + **/ +static void +system_show_timer (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("system_show_timer - lists timer stats \n"); + return; + } + + stw_system_timer_stats(); + return; +} + + +/** + ** show peer commands + **/ +static void +peer_show_peer_all (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("peer_show_all - lists all peers \n"); + printf("\n"); + return; + } + + dlep_peer_list_all(); + return; +} + + +static void +peer_show_fsm_history (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_show_fsm_history - display peer state history \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + dlep_client_fsm_show_history(p2peer); + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + + +static void +peer_show_fsm_table (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_show_fsm_table - displays peer state machine \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + dlep_client_fsm_show_state_table(p2peer); + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + + +static void +neighbor_show_neighbor_mac (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + uint16_t nid; + + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_show_mac - " + "display neighbor info for MAC address \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + p2config = dlep_get_config_ptr(); + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (!p2peer) { + printf("Input error: local peer id %u not known \n", nid); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac address missing \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (p2neighbor) { + dlep_neighbor_display(p2neighbor); + } else { + printf("Input error: mac address %s not known \n", argv[1]); + } + return; +} + + +static void +neighbor_show_all_neighbors (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("neighbor_show_all - lists all client neighbors \n"); + printf("\n"); + return; + } + + dlep_peer_neighbor_list_all(); + return; +} + + +static void +neighbor_show_fsm_history (uint32_t argc, char *argv[]) +{ + uint32_t nid; + uint8_t mac_address[8]; + dlep_context_neighbor_t *p2neighbor; + dlep_context_peer_t *p2peer; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_show_fsm_history - displays " + "neighbor state history\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (!p2peer) { + printf("Input error: local peer id %u not known \n", nid); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac address missing \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (p2neighbor) { + dlep_client_neighbor_fsm_show_history(p2neighbor); + } else { + printf("Input error: mac address %s not known \n", argv[1]); + } + return; +} + + +static void +neighbor_show_fsm_table (uint32_t argc, char *argv[]) +{ + uint32_t nid; + uint8_t mac_address[8]; + dlep_context_neighbor_t *p2neighbor; + dlep_context_peer_t *p2peer; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_show_fsm_table - displays neighbor " + "state machine\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (!p2peer) { + printf("Input error: local peer id %u not known \n", nid); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac address missing \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (p2neighbor) { + dlep_client_neighbor_fsm_show_state_table(p2neighbor); + } else { + printf("Input error: mac address %s not known \n", argv[1]); + } + return; +} + + +/** + ** test peer commands + **/ +static void +peer_test_peer_term (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_test_terminate - sends a peer terminate \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + p2peer->status_code = RFC5444_MSG_TIMEOUT; /* suriya just added for now */ + dlep_client_fsm_engine(user_peer_term_request_e, p2peer, NULL); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; + +} + +static void +peer_test_peer_update (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + uint8_t rlq_tx,rlq_rx; + uint8_t resources; + uint64_t latency; + uint64_t cdr_tx,cdr_rx; + uint64_t mdr_tx,mdr_rx; + uint16_t mtu; + uint64_t temp; + uint32_t ttl; + + + if (argv[1] && *argv[1] == '?') { + printf("peer_test_update - sends a peer update \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + if (argv[1]) { + temp = strtoul(argv[1], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_tx = RFC5444_100_PERCENT; + } else { + rlq_tx = temp; + } + } else { + printf("Input error: rlq tx missing \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_rx = RFC5444_100_PERCENT; + } else { + rlq_rx = temp; + } + } else { + printf("Input error: rlq rx missing \n"); + return; + } + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + resources = RFC5444_100_PERCENT; + } else { + resources = temp; + } + } else { + printf("Input error: resources missing \n"); + return; + } + + latency=0; + + if (argv[4]) { + latency = strtoull(argv[4], NULL, 10); + } else { + printf("Input error: latency missing \n"); + return; + } + cdr_tx = 0; + if (argv[5]) { + cdr_tx = strtoull(argv[5], NULL, 10); + } else { + printf("Input error: cdr tx missing \n"); + return; + } + + cdr_rx = 0; + if (argv[6]) { + cdr_rx = strtoull(argv[6], NULL, 10); + } else { + printf("Input error: cdr rx missing \n"); + return; + } + + + mdr_tx = 0; + if (argv[7]) { + mdr_tx = strtoull(argv[7], NULL, 10); + } else { + printf("Input error: mdr tx missing \n"); + return; + } + + mdr_rx = 0; + if (argv[8]) { + mdr_rx = strtoull(argv[8], NULL, 10); + } else { + printf("Input error: mdr rx missing \n"); + return; + } + + mtu = 0; + if (argv[9]) { + mtu = strtoull(argv[9], NULL, 10); + } else { + printf("Input error: mtu missing \n"); + return; + } + + ttl = 0; + if (argv[10]) { + ttl = strtoull(argv[10], NULL, 10); + } + +#if 0 + if (argv[11]) { + printf(" Input error: extra argument is passed \n"); + return; + } +#endif + + /* set the neighbor data to be picked up at the next interval */ + p2peer->rlq_tx = rlq_tx; + p2peer->rlq_rx = rlq_rx; + p2peer->resources = resources; + p2peer->latency = latency; + p2peer->cdr_tx = cdr_tx; + p2peer->cdr_rx = cdr_rx; + p2peer->mdr_tx = mdr_tx; + p2peer->mdr_rx = mdr_rx; + p2peer->mtu = mtu; + p2peer->ttl = ttl; + + send_dlep_peer_update_request(p2peer); + + printf(" metrics updated: RLQ TX=%u RLQ RX=%u \n" + + "Resources =%u \n" + "Latency=%llu \n" + "CDR TX=%llu CDR RX=%llu \n" + "MDR TX=%llu MDR RX=%llu \n" + "MTU =%u", + rlq_tx, + rlq_rx, + resources, + latency, + cdr_tx, + cdr_rx, + mdr_tx, + mdr_rx, + mtu); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + + +/** + ** test neighbor commands + **/ +static void +cli_test_neighbor_update_msg (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_update_msg - generate a neighbor up \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + /* don't send the layer 3 addresses, force router to ARP/ND */ + ipv4_zero_address(&p2neighbor->ipv4_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + + /* set the neighbor metrics */ + p2neighbor->rlq_rx = 100; + p2neighbor->rlq_tx = 100; + p2neighbor->resources = 100; + p2neighbor->latency = 250; + p2neighbor->cdr_rx = 100000000; + p2neighbor->cdr_tx = 100000000; + p2neighbor->mdr_rx = 100000000; + p2neighbor->mdr_tx = 100000000; + p2neighbor->mtu = 1500; + send_dlep_neighbor_address_request(p2peer, p2neighbor); + /* + * start the ack timer + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_init_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_init_ack_tmr, + (void *)p2neighbor); + + return; +} + + + +static void +cli_test_neighbor_up (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + ipv4_address_t ipv4_address; + + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_up - generate " + " a neighbor up with Layer 3 addresse\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 210.123.234.102 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + + if (argv[2]) { + ipv4_dot_decimal2digits(&ipv4_address, argv[2]); + ipv4_print_address(NULL, &ipv4_address); + } else { + printf("Input error: IPv4 is missing \n"); + return; + } + + /* if (argv[3]) { + ipv6_ascii2digits(&ipv6_address, argv[3]); + ipv6_print_address(NULL, &ipv6_address); + } else { + printf("Input error: IPv6 is missing \n"); + return; + } */ + + if (argv[3]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + ipv4_copy_address(&p2neighbor->ipv4_address, &ipv4_address); + //ipv6_copy_address(&p2neighbor->ipv6_address, &ipv6_address); + + /* set the neighbor metrics */ + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources = 100; + p2neighbor->latency = 250; + p2neighbor->cdr_tx = 100000000; + p2neighbor->cdr_rx = 100000000; + p2neighbor->mdr_tx = 100000000; + p2neighbor->mdr_rx = 100000000; + p2neighbor->mtu = 1500; + + send_dlep_neighbor_up(p2peer, p2neighbor); + + /* + * start the ack timer + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_init_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_init_ack_tmr, + (void *)p2neighbor); + + return; +} + + +static void +cli_test_neighbor_credit_up (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_up - generate a neighbor up \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + /* don't send the layer 3 addresses, force router to ARP/ND */ + ipv4_zero_address(&p2neighbor->ipv4_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + + /* set the neighbor metrics */ + p2neighbor->rlq_rx = 100; + p2neighbor->rlq_tx = 100; + p2neighbor->resources = 100; + p2neighbor->latency = 250; + p2neighbor->cdr_rx = 100000000; + p2neighbor->cdr_tx = 100000000; + p2neighbor->mdr_rx = 100000000; + p2neighbor->mdr_tx = 100000000; + p2neighbor->mtu = 1500; + + if (p2neighbor->CREDIT_NOT_SUPPORTED) { + p2neighbor->mrw = 0; + } else { + p2neighbor->mrw = 65534; + } + p2neighbor->rrw = 0; + + + send_dlep_neighbor_up(p2peer, p2neighbor); + + /* + * start the ack timer + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_init_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_init_ack_tmr, + (void *)p2neighbor); + + return; +} + + +static void +cli_test_neighbor_metric_up (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + ipv4_address_t ipv4_address; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + uint8_t rlq_tx; + uint8_t rlq_rx; + uint8_t resources; + uint64_t latency; + uint64_t cdr_tx; + uint64_t cdr_rx; + uint64_t mdr_tx; + uint64_t mdr_rx; + uint16_t mtu; + uint32_t temp; + + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_metric_up " + " - generate a " + "neighbor up w/ metrics \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" ipv4 addrss \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf(" - 64-bit millisecond value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 16-bit \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + if (argv[2]) { + ipv4_dot_decimal2digits(&ipv4_address, argv[2]); + ipv4_print_address(NULL, &ipv4_address); + } else { + printf("Input error: IPv4 is missing \n"); + return; + } + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + ipv4_copy_address(&p2neighbor->ipv4_address, &ipv4_address); + + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_tx = RFC5444_100_PERCENT; + rlq_rx = RFC5444_100_PERCENT; + } else { + rlq_tx = temp; + rlq_rx = temp; + } + } else { + printf("Input error: rlq missing \n"); + return; + } + + if (argv[4]) { + temp = strtoul(argv[4], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + resources = RFC5444_100_PERCENT; + } else { + resources = temp; + } + } else { + printf("Input error: resources tx missing \n"); + return; + } + + latency =0; + if (argv[5]) { + latency = strtoull(argv[5], NULL, 10); + } else { + printf("Input error: latency missing \n"); + return; + } + + cdr_tx = 0; + cdr_rx = 0; + if (argv[6]) { + cdr_tx = strtoull(argv[6], NULL, 10); + cdr_rx = strtoull(argv[6], NULL, 10); + } else { + printf("Input error: cdr missing \n"); + return; + } + + + mdr_tx = 0; + mdr_rx = 0; + if (argv[7]) { + mdr_tx = strtoull(argv[7], NULL, 10); + mdr_rx = strtoull(argv[7], NULL, 10); + } else { + printf("Input error: mdr_tx missing \n"); + return; + } + + + mtu = 0; + if (argv[8]) { + mtu = strtoul(argv[8], NULL, 10); + } else { + printf("Input error: mtu missing \n"); + return; + } + + if (argv[9]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor metrics for the neighbor up */ + p2neighbor->rlq_tx = rlq_tx; + p2neighbor->rlq_rx = rlq_rx; + p2neighbor->resources = resources; + p2neighbor->latency = latency; + p2neighbor->cdr_tx = cdr_tx; + p2neighbor->cdr_rx = cdr_rx; + p2neighbor->mdr_tx = mdr_tx; + p2neighbor->mdr_rx = mdr_rx; + p2neighbor->mtu = mtu; + + printf(" sending reaching here\n"); + send_dlep_neighbor_up(p2peer, p2neighbor); + return; +} + + +static void +cli_test_neighbor_ipv4_req (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + ipv4_address_t ipv4_address; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_ipv4 " + " - generate " + " a neighbor address IPv4 update \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - add | drop \n"); + printf(" - 210.123.234.102 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + if (argv[3]) { + ipv4_dot_decimal2digits(&ipv4_address, argv[3]); + printf("\n Going to print entered ip add"); + ipv4_print_address(NULL, &ipv4_address); + } else { + printf("Input error: IPv4 is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Input error: local peer not present \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Input error: neighbor mac not known \n"); + return; + } + + if (strcmp("add", argv[2]) == 0) { + p2neighbor->update_ipv4_operation = RFC5444_EXISTING_ADD_ADDRESS; + ipv4_copy_address(&p2neighbor->update_ipv4_address, &ipv4_address); +// send_dlep_neighbor_address_request(p2peer, p2neighbor); + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + } else if (strcmp("drop", argv[2]) == 0) { + p2neighbor->update_ipv4_operation = RFC5444_DROP_ADDRESS; + ipv4_copy_address(&p2neighbor->update_ipv4_address, &ipv4_address); + // send_dlep_neighbor_address_request(p2peer, p2neighbor); + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + } else { + printf("Input error: invalid add-drop operation \n"); + return; + } + return; +} + + +static void +cli_test_neighbor_ipv6_req (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8] , subnet; + ipv6_address_t ipv6_address; + ipv6_address_t ipv6_subnet_address; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_ipv6 " + " - generate " + " a neighbor address IPv6 update \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - add | drop \n"); + printf(" - 11223344:22334455:33445566:44556677 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + if (argv[3]) { + ipv6_ascii2digits(&ipv6_address, argv[3]); + ipv6_print_address(NULL, &ipv6_address); + } else { + printf("Input error: IPv6 is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Input error: local peer not present \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Input error: neighbor mac not known \n"); + return; + } + + if (argv[4]) { + ipv6_ascii2digits(&ipv6_subnet_address, argv[4]); + ipv6_print_address(NULL, &ipv6_subnet_address); + } else { + printf("Input error: IPv6 subnet is missing \n"); + return; + } + + + if(argv[5]) { + subnet = strtoul(argv[5], NULL, 10); + } else { + printf("Input error: subnet prefix is missing \n"); + return; + } + + if (strcmp("add", argv[2]) == 0) { + p2neighbor->update_ipv6_operation = RFC5444_EXISTING_ADD_ADDRESS; + ipv6_copy_address(&p2neighbor->update_ipv6_address, &ipv6_address); + ipv6_copy_address(&p2neighbor->update_ipv6_subnet_address, &ipv6_subnet_address); + p2neighbor->ipv6_subnet_prefix = subnet; + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + } else if (strcmp("drop", argv[2]) == 0) { + p2neighbor->update_ipv6_operation = RFC5444_DROP_ADDRESS; + ipv6_copy_address(&p2neighbor->update_ipv6_address, &ipv6_address); + ipv6_copy_address(&p2neighbor->update_ipv6_subnet_address, &ipv6_subnet_address); + p2neighbor->ipv6_subnet_prefix = subnet; + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + } else { + printf("Input error: invalid add-drop operation \n"); + return; + } + return; +} + + +static void +cli_test_neighbor_metrics (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + uint8_t rlq_tx,rlq_rx; + uint8_t resources_tx,resources_rx,resources; + uint64_t latency; + uint64_t cdr_tx,cdr_rx; + uint64_t mdr_tx,mdr_rx; + uint16_t mtu; + uint32_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_metrics " + " " + " - " + "generate a neighbor metrics update \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf(" - 16-bit millisecond value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 16-bit \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_tx = RFC5444_100_PERCENT; + } else { + rlq_tx = temp; + } + } else { + printf("Input error: rlq tx missing \n"); + return; + } + + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_rx = RFC5444_100_PERCENT; + } else { + rlq_rx = temp; + } + } else { + printf("Input error: rlq rx missing \n"); + return; + } + + if (argv[4]) { + temp = strtoul(argv[4], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + resources = RFC5444_100_PERCENT; + } else { + resources = temp; + } + } else { + printf("Input error: resources tx missing \n"); + return; + } + + latency = 0; + + if (argv[5]) { + latency = strtoull(argv[5], NULL, 10); + } else { + printf("Input error: latency missing \n"); + return; + } + + cdr_tx = 0; + if (argv[6]) { + cdr_tx = strtoull(argv[6], NULL, 10); + } else { + printf("Input error: cdr tx missing \n"); + return; + } + + cdr_rx = 0; + if (argv[7]) { + cdr_rx = strtoull(argv[7], NULL, 10); + } else { + printf("Input error: cdr rx missing \n"); + return; + } + + + mdr_tx = 0; + if (argv[8]) { + mdr_tx = strtoull(argv[8], NULL, 10); + } else { + printf("Input error: mdr tx missing \n"); + return; + } + + mdr_rx = 0; + if (argv[9]) { + mdr_rx = strtoull(argv[9], NULL, 10); + } else { + printf("Input error: mdr rx missing \n"); + return; + } + + mtu = 0; + if (argv[10]) { + mtu = strtoull(argv[10], NULL, 10); + } else { + printf("Input error: mtu missing \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->rlq_tx = rlq_tx; + p2neighbor->rlq_rx = rlq_rx; + p2neighbor->resources = resources; + p2neighbor->latency = latency; + p2neighbor->cdr_tx = cdr_tx; + p2neighbor->cdr_rx = cdr_rx; + p2neighbor->mdr_tx = mdr_tx; + p2neighbor->mdr_rx = mdr_rx; + p2neighbor->mtu = mtu; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: RLQ TX=%u RLQ RX=%u \n" + "Resources =%u \n" + "Latency=%llu \n" + "CDR TX=%llu CDR RX=%llu \n" + "MDR TX=%llu MDR RX=%llu \n" + "MTU =%u", + rlq_tx, + rlq_rx, + resources, + latency, + cdr_tx, + cdr_rx, + mdr_tx, + mdr_rx, + mtu); + return; +} + + +static void +cli_test_neighbor_rlq (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint8_t rlq_tx, rlq_rx; + uint32_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_rlq - " + "generate a neighbor metrics update with a new RLQ \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > 100) { + rlq_tx =100; + } else { + rlq_tx = temp; + } + } else { + printf("Input error: rlq tx missing \n"); + return; + } + + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > 100) { + rlq_rx =100; + } else { + rlq_rx = temp; + } + } else { + printf("Input error: rlq rx missing \n"); + return; + } + + if (argv[4]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->rlq_tx = rlq_tx; + p2neighbor->rlq_rx = rlq_rx; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: RLQ TX=%u \n", + rlq_tx); + printf(" metrics updated: RLQ RX=%u \n", + rlq_rx); + return; +} + + +static void +cli_test_neighbor_resources (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint8_t resources; + uint8_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_resources - " + "" + "generate a neighbor metrics update with a new resource \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > 100) { + resources = 100; + } else { + resources = temp; + } + } else { + printf("Input error: resources missing \n"); + return; + } + + if (argv[3]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->resources = resources; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: Resources=%u \n", + resources); + return; +} + + +static void +cli_test_neighbor_latency (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint64_t latency; + uint64_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_latency -" + "generate a neighbor metrics update with a new latency \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" 64-bit millisecond value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + latency = 0 ; + if (argv[2]) { + latency = strtoull(argv[2], NULL, 10); + } else { + printf("Input error: latency missing \n"); + return; + } + + if (argv[3]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->latency = latency; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: Latency=%u \n", + latency); + return; +} + + +static void +cli_test_neighbor_cdr (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint64_t cdr_tx, cdr_rx; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_cdr - " + "generate a neighbor metrics update with a new CDR\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" 64-bit bps value \n"); + printf(" 64-bit bps value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + cdr_tx = 0; + if (argv[2]) { + cdr_tx = strtoull(argv[2], NULL, 10); + } else { + printf("Input error: cdr_tx missing \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->cdr_tx = cdr_tx; + + cdr_rx = 0; + if (argv[3]) { + cdr_rx = strtoull(argv[3], NULL, 10); + } else { + printf("Input error: cdr_rx missing \n"); + return; + } + + if (argv[4]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->cdr_rx = cdr_rx; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: CDR TX=%llu \n", + cdr_tx); + printf(" metrics updated: CDR RX=%llu \n", + cdr_rx); + return; +} + + +static void +cli_test_neighbor_mdr (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint64_t mdr_tx, mdr_rx; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_mdr - " + "generate a neighbor metrics update with a new MDR\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" 64-bit bps value \n"); + printf(" 64-bit bps value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + mdr_tx = 0; + if (argv[2]) { + mdr_tx = strtoull(argv[2], NULL, 10); + } else { + printf("Input error: mdr_tx missing \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->mdr_tx = mdr_tx; + + mdr_rx = 0; + if (argv[3]) { + mdr_rx = strtoull(argv[3], NULL, 10); + } else { + printf("Input error: mdr_rx missing \n"); + return; + } + + if (argv[4]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->mdr_rx = mdr_rx; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: MDR TX=%llu \n", + mdr_tx); + printf(" metrics updated: MDR RX=%llu \n", + mdr_rx); + return; +} + +static void +cli_test_neighbor_mtu (uint16_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint16_t mtu; + uint16_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_mdr - " + "generate a neighbor metrics update with a new MDR\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" 64-bit bps value \n"); + printf(" 64-bit bps value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoull(argv[2], NULL, 10); + if ((temp >= 64) && (temp <= 1500)) { + mtu = temp; + } else { + mtu = 1500; + } + } else { + printf("Input error: mtu missing \n"); + return; + } + + if (argv[3]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->mtu = mtu; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: MTU=%u \n", + mtu); + return; +} + + +static void +cli_test_neighbor_down (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_down - generate a " + "neighbor down \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + if (argv[2]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + //return; + } + + dlep_client_neighbor_fsm_engine(neighbor_term_user_req_e, + p2peer, p2neighbor); + return; +} + +static void +peer_test_peer_offer (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + dlep_client_fsm_engine(peer_offer_e, p2peer, NULL); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} +static void +peer_test_init_ack (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + printf("reaching here\n"); + send_dlep_peer_init_ack(p2peer); + return; +} +static void +peer_test_update_res (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + send_dlep_peer_update_response(p2peer); + return; +} +static void +peer_test_term_res (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + + send_dlep_peer_termination_ack(p2peer); + return; +} +static void +peer_test_heartbeat (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + + send_dlep_peer_heartbeat(p2peer); + return; +} +static void +test_session_init (uint32_t argc, char *argv[]) +{ + int temp; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("session init enter 0 or 1 \n"); + printf("\n"); + return; + } + + temp = strtoul(argv[1], NULL, 10); + if(temp ==0 || temp ==1) { + init = strtoul(argv[1], NULL, 10); + } + else { + printf("Input error : Invalid option should be 0 or 1 \n"); + } + + return; +} + +/** + * NAME + * dlep_cli_engine + * + * SYNOPSIS + * void + * dlep_cli_engine() + * + * DESCRIPTION + * Drives the Radio Test Tool CLI. + * + * INPUT PARAMETERS + * input_string This is a string containing user input. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_cli_engine (char *input_string) +{ + cli_engine(input_string); + return; +} + + +/** + * NAME + * dlep_cli_init + * + * SYNOPSIS + * void + * dlep_cli_init() + * + * DESCRIPTION + * Registers the dlep test tool commands with the cli + * facility. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_cli_init (void) +{ + cli_init_data_t init_data; + RC_CLI_t rc; + + strcpy(init_data.prefix, "Radio Test Tool"); + cli_init(&init_data); + + dlep_debug_cli_init(); + //dlep_source_cli_init(); + fuzz_dlep_cli_init(); + + + /* + * Create directory and commands + */ + + rc = cli_mkdir("system", &cli_show_dir, &show_system_dir); + rc = cli_mkdir("peer", &cli_show_dir, &show_peer_dir); + rc = cli_mkdir("neighbor", &cli_show_dir, &show_neighbor_dir); + +// rc = cli_mkdir("peer", &cli_clear_dir, &clear_peer_dir); +// rc = cli_mkdir("neighbor", &cli_clear_dir, &clear_neighbor_dir); + + rc = cli_mkdir("peer", &cli_test_dir, &test_peer_dir); + rc = cli_mkdir("neighbor", &cli_test_dir, &test_neighbor_dir); + + + /* + * root commands + */ + rc = cli_mkcmd("start", system_start, + NULL, &system_start_cmd); + rc = cli_mkcmd("stop", system_stop, + NULL, &system_stop_cmd); + + /* + * show system + */ + rc = cli_mkcmd("system_show_timer", system_show_timer, + &show_system_dir, &show_timer_stats_cmd); + + /* + * show peer + */ + rc = cli_mkcmd("peer_show_all", peer_show_peer_all, + &show_peer_dir, &show_peer_all_cmd); + rc = cli_mkcmd("peer_show_fsm_history", peer_show_fsm_history, + &show_peer_dir, &show_peer_fsm_history_cmd); + rc = cli_mkcmd("peer_show_fsm_table", peer_show_fsm_table, + &show_peer_dir, &show_peer_fsm_table_cmd); + + /* + * show neighbor + */ + rc = cli_mkcmd("neighbor_show_mac", neighbor_show_neighbor_mac, + &show_neighbor_dir, &show_neighbor_mac_cmd); + rc = cli_mkcmd("neighbor_show_all", neighbor_show_all_neighbors, + &show_neighbor_dir, &show_neighbors_on_peer_cmd); + rc = cli_mkcmd("neighbor_show_fsm_history", neighbor_show_fsm_history, + &show_neighbor_dir, &show_neighbor_fsm_history_cmd); + rc = cli_mkcmd("neighbor_show_fsm_table", neighbor_show_fsm_table, + &show_neighbor_dir, &show_neighbor_fsm_table_cmd); + + /* + * test peer + */ + + rc = cli_mkcmd("test_session_init", test_session_init, + &test_peer_dir, &test_session_init_cmd); + + rc = cli_mkcmd("peer_test_terminate", peer_test_peer_term, + &test_peer_dir, &test_peer_term_cmd); + + rc = cli_mkcmd("peer_test_update", peer_test_peer_update, + &test_peer_dir, &test_peer_update_cmd); + + /* added for testing purpose */ + rc= cli_mkcmd("peer_test_offer", peer_test_peer_offer, + &test_peer_dir, &test_peer_offer_cmd); + + rc=cli_mkcmd("peer_test_init_ack", peer_test_init_ack, + &test_peer_dir, &test_peer_init_ack_cmd); + rc=cli_mkcmd("peer_test_update_res", peer_test_update_res, + &test_peer_dir, &test_peer_update_res_cmd); + rc=cli_mkcmd("peer_test_term_res", peer_test_term_res, + &test_peer_dir, &test_peer_term_res_cmd); + rc=cli_mkcmd("peer_test_heartbeat", peer_test_heartbeat, + &test_peer_dir, &test_peer_heartbeat_cmd); + + /* + * test neighbor + */ + rc = cli_mkcmd("neighbor_test_up", cli_test_neighbor_up, + &test_neighbor_dir, &test_neighbor_up_cmd); + /* rc = cli_mkcmd("neighbor_test_l3_up", cli_test_neighbor_l3_up, + &test_neighbor_dir, &test_neighbor_l3_up_cmd); */ + rc = cli_mkcmd("neighbor_test_credit_up", cli_test_neighbor_credit_up, + &test_neighbor_dir, &test_neighbor_credit_up_cmd); + rc = cli_mkcmd("neighbor_test_metric_up", cli_test_neighbor_metric_up, + &test_neighbor_dir, &test_neighbor_metric_up_cmd); + + rc = cli_mkcmd("neighbor_test_ipv4", cli_test_neighbor_ipv4_req, + &test_neighbor_dir, &test_neighbor_ipv4_req_cmd); + rc = cli_mkcmd("neighbor_test_ipv6", cli_test_neighbor_ipv6_req, + &test_neighbor_dir, &test_neighbor_ipv6_req_cmd); + + rc = cli_mkcmd("neighbor_test_down", cli_test_neighbor_down, + &test_neighbor_dir, &test_neighbor_down_cmd); + rc = cli_mkcmd("neighbor_test_metrics", cli_test_neighbor_metrics, + &test_neighbor_dir, &test_neighbor_metrics_cmd); + + rc = cli_mkcmd("neighbor_test_rlq", cli_test_neighbor_rlq, + &test_neighbor_dir, &test_neighbor_rlq_cmd); + rc = cli_mkcmd("neighbor_test_resources", cli_test_neighbor_resources, + &test_neighbor_dir, &test_neighbor_resources_cmd); + rc = cli_mkcmd("neighbor_test_latency", cli_test_neighbor_latency, + &test_neighbor_dir, &test_neighbor_latency_cmd); + rc = cli_mkcmd("neighbor_test_cdr", cli_test_neighbor_cdr, + &test_neighbor_dir, &test_neighbor_cdr_cmd); + rc = cli_mkcmd("neighbor_test_mdr", cli_test_neighbor_mdr, + &test_neighbor_dir, &test_neighbor_mdr_cmd); + rc = cli_mkcmd("neighbor_test_mtu", cli_test_neighbor_mtu, + &test_neighbor_dir, &test_neighbor_mtu_cmd); + rc = cli_mkcmd("neighbor_test_update_msg", cli_test_neighbor_update_msg, + &test_neighbor_dir, &test_neighbor_update_cmd); + + return; +} + diff --git a/dlep_radio_ipv4/sim_dlep_radio_cli.h b/dlep_radio_ipv4/sim_dlep_radio_cli.h new file mode 100644 index 0000000..c8f08b4 --- /dev/null +++ b/dlep_radio_ipv4/sim_dlep_radio_cli.h @@ -0,0 +1,43 @@ +/*------------------------------------------------------------------ + * sim_radio_cli.h -- Radio simulator CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __SIM_RADIO_CLI_H__ +#define __SIM_RADIO_CLI_H__ + + +extern +void dlep_cli_engine(char *input_string); + +extern +void dlep_cli_init(void); + +#endif + diff --git a/dlep_radio_ipv4/stw_system_timer.c b/dlep_radio_ipv4/stw_system_timer.c new file mode 100644 index 0000000..56f74e6 --- /dev/null +++ b/dlep_radio_ipv4/stw_system_timer.c @@ -0,0 +1,339 @@ +/*----------------------------------------------------------------- + * stw_system_timer.c -- System Timer Wheel APIs + * + * February 2005, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include "stw_system_timer.h" + + +static stw_t *stw_system_handle = 0; + + +/** + * NAME + * stw_system_timer_prepare + * + * SYNOPSIS + * #include "stw_system_timer.h" + * void + * stw_system_timer_prepare(stw_tmr_t *tmr) + * + * DESCRIPTION + * Utility routine to initialize the links of timer elements. + * + * INPUT PARAMETERS + * tmr - pointer to the timer + * + * OUTPUT PARAMETERS + * tmr - updated + * + * RETURN VALUE + * none + * + */ +void +stw_system_timer_prepare (stw_tmr_t *tmr) +{ + stw_timer_prepare(tmr); + return; +} + + +/** + * NAME + * stw_system_timer_stats + * + * SYNOPSIS + * #include "stw_system_timer.h" + * void + * stw_system_timer_stats(void) + * + * DESCRIPTION + * Displays the stats for the system timer wheel. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +stw_system_timer_stats (void) +{ + stw_timer_stats(stw_system_handle); + return; +} + + +/** + * NAME + * stw_system_timer_running + * + * SYNOPSIS + * #include "stw_system_timer.h" + * boolean_t + * stw_system_timer_running(stw_tmr_t *tmr) + * + * DESCRIPTION + * Returns TRUE if the timer is active + * + * INPUT PARAMETERS + * tmr - pointer to the timer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE==tmer is active + * False==timer is not active + * + */ +boolean_t +stw_system_timer_running (stw_tmr_t *tmr) +{ + return (stw_timer_running(tmr)); +} + + +/** + * NAME + * stw_system_timer_start + * + * SYNOPSIS + * #include "stw_system_timer.h" + * RC_STW_t + * stw_system_timer_start(stw_tmr_t *tmr, + * uint32_t delay, + * uint32_t periodic_delay, + * stw_call_back user_cb, + * void *parm) + * + * DESCRIPTION + * Start (or restart) a system timer to expire + * in the future. If the timer is currently active, + * it will be stopped first then restarted with + * time delay requested. + * + * INPUT PARAMETERS + * tmr - pointer to the timer element + * + * delay - specified delay in milliseconds + * + * periodic_delay - periodic delay in milliseconds + * + * user_cb - application function call-back to be + * invoked when the timer expires. This + * call-back must not block. + * + * parm - persistent parameter passed to the application + * call-back upon expiration + * + * OUTPUT PARAMETERS + * tmr - updated with the user_cb and the parm, and + * put on the tiemr wheel of fortune. + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_system_timer_start (stw_tmr_t *tmr, + uint32_t delay, + uint32_t periodic_delay, + stw_call_back user_cb, + void *parm) +{ + return (stw_timer_start(stw_system_handle, + tmr, + delay, + periodic_delay, + user_cb, + parm)); +} + + +/** + * NAME + * stw_system_timer_stop + * + * SYNOPSIS + * #include "stw_system_timer.h" + * RC_STW_t + * stw_system_timer_stop(stw_tmr_t *tmr) + * + * DESCRIPTION + * Stop the timer by removing it from the timer wheel. + * Note that it is safe to call this function with a + * timer that has already been stopped in order to + * avoid making all callers check for an active timer + * first. + * + * INPUT PARAMETERS + * tmr - pointer to the timer element + * + * OUTPUT PARAMETERS + * tmr - updated, taken off the wheel + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_system_timer_stop (stw_tmr_t *tmr) +{ + return (stw_timer_stop(stw_system_handle, tmr)); +} + + +/** + * NAME + * stw_system_timer_tick + * + * SYNOPSIS + * #include "stw_system_timer.h" + * void + * stw_system_timer_tick(void) + * + * DESCRIPTION + * Expire timers on the current spoke and move + * the wheel cursor forward to the next spoke. + * + * Application call-backs must be non-blocking + * + * INPUT PARAMETERS + * stw - pointer to the timer wheel + * + * OUTPUT PARAMETERS + * stw is updated, timers at the current tick are + * expired. + * + * RETURN VALUE + * none + * + */ +void +stw_system_timer_tick (void) +{ + /* + * protect from the possibility of not having initialized the stw yet + */ + if (stw_system_handle) { + stw_timer_tick(stw_system_handle); + } + return; +} + + +/** + * NAME + * stw_system_timer_destroy + * + * SYNOPSIS + * #include "stw_system_timer.h" + * RC_STW_t + * stw_system_timer_destroy(void) + * + * DESCRIPTION + * Destroys the timer wheel. All timers are stopped + * and resources released. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_system_timer_destroy (void) +{ + return (stw_timer_destroy(stw_system_handle)); +} + + +/** + * NAME + * stw_system_timer_create + * + * SYNOPSIS + * #include "stw_system_timer.h" + * RC_STW_t + * stw_system_timer_create(uint32_t wheel_size, + * uint32_t granularity, + * const char *p2name ) + * + * DESCRIPTION + * This function is used to create and initialize the system timer + * wheel. Timers must not be started before this routine is called. + * + * INPUT PARAMETERS + * wheel_size - number of spokes in the wheel. The number + * of spoks should be engineered such that + * wheel_size >= (longest duration / granularity ) + * Depending upon the number of concurrent timers, the + * distribution of those timers, it may be beneficial to + * further increase the wheel size. Objective is to + * minimize frequency of 'long' timers requiring wheel + * revolutions. + * + * granularity - milliseconds between ticks + * + * *p2name - pointer to the name of identify wheel. + * Limited to STW_NAME_LENGTH + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_system_timer_create (uint32_t wheel_size, + uint32_t granularity, + const char *p2name) +{ + return (stw_timer_create(wheel_size, + granularity, + p2name, + &stw_system_handle)); +} + + diff --git a/dlep_radio_ipv4/stw_system_timer.h b/dlep_radio_ipv4/stw_system_timer.h new file mode 100644 index 0000000..ed6019e --- /dev/null +++ b/dlep_radio_ipv4/stw_system_timer.h @@ -0,0 +1,102 @@ +/*------------------------------------------------------------------ + * stw_system_timer.h -- System Timer Wheel Definitions + * + * July 2009 - Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __STW_SYSTEM_TIMER_H__ +#define __STW_SYSTEM_TIMER_H__ + +#include "safe_types.h" +#include "stw_timer.h" + + +/* + * Utility routine to initialize the links of timer elements. + */ +extern void +stw_system_timer_prepare(stw_tmr_t *tmr); + + +/* + * Displays timer wheel stats and counters to stdout. + */ +extern void +stw_system_timer_stats(void); + + +/* + * Returns the active status of a timer. + */ +extern boolean_t +stw_system_timer_running(stw_tmr_t *tmr); + + +/* + * Starts a new timer. If the timer is currently + * running, it is stopped and restarted anew. + */ +extern RC_STW_t +stw_system_timer_start(stw_tmr_t *tmr, + uint32_t delay, + uint32_t periodic_delay, + stw_call_back user_cb, + void *parm); + +/* + * Stops a currently running timer + */ +extern RC_STW_t +stw_system_timer_stop(stw_tmr_t *); + + +/* + * System Timer Wheel tick handler + */ +extern void +stw_system_timer_tick(void); + + +/* + * destroy the R2CP timer wheel + */ +extern RC_STW_t +stw_system_timer_destroy(void); + + +/* + * Creates and initializes the R2CP timer wheel + */ +extern RC_STW_t +stw_system_timer_create(uint32_t wheel_size, + uint32_t granularity, + const char *name); + + +#endif /* __STW_SYSTEM_TIMER_H__ */ + diff --git a/dlep_radio_ipv4/stw_timer.c b/dlep_radio_ipv4/stw_timer.c new file mode 100644 index 0000000..db77dd0 --- /dev/null +++ b/dlep_radio_ipv4/stw_timer.c @@ -0,0 +1,761 @@ +/*------------------------------------------------------------------ + * stw_timer.c -- Single Timer Wheel Timer + * + * February 2005, Bo Berry + * + * Copyright (c) 2002-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "runtime_environment.h" +#include "safe_types.h" + +#include "stw_timer.h" + + +/* + * used to verify wheel pointers. Nothing special about + * the value, other than to help identify a valid stw pointer + */ +#define MAGIC_TAG ( 0x0FEDCA3BA ) + + +/* + * NAME + * tmr_enqueue + * + * SYNOPSIS + * #include "stw_timer.h" + * static void + * tmr_enqueue(stw_t *stw, stw_tmr_t *tmr, uint32_t delay) + * + * DESCRIPTION + * Enqueues the timer to the proper spoke per delay. + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel that the timer + * will run on + * + * *tmr - pointer to the timer element + * + * delay - delay in milliseconds + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + */ +static void +tmr_enqueue (stw_t *stw, stw_tmr_t *tmr, uint32_t delay) +{ + stw_links_t *prev, *spoke; + + uint32_t cursor; + uint32_t ticks; + uint32_t td; + + /* + * BEGIN CRITICAL REGION + */ + LOCK_INTERRUPTS(); + + if (delay < stw->granularity) { + /* + * must delay at least one tick, can not delay in past... + */ + ticks = 1; + + } else { + /* + * compute number ticks reqquired to expire the duration + */ + ticks = (delay / stw->granularity); + } + + /* + * tick displacement from current cursor + */ + td = (ticks % stw->wheel_size); + + /* + * times around the wheel required to expire duration + */ + tmr->rotation_count = (ticks / stw->wheel_size); + + /* + * calculate cursor to place the timer + */ + cursor = ((stw->spoke_index + td) % stw->wheel_size); + + spoke = &stw->spokes[cursor]; + /* + * We have a timer and now we have a spoke. All that is left is to + * link the timer to the spoke's list of timers. With a doubly linked + * list, there is no need to check for an empty list. We simply link + * it to the end of the list. This is the same price as putting it + * on the front of the list but feels more 'right'. + */ + prev = spoke->stw_prev; + tmr->links.stw_next = spoke; /* append to end of spoke */ + tmr->links.stw_prev = prev; + + prev->stw_next = (stw_links_t *)tmr; + spoke->stw_prev = (stw_links_t *)tmr; + + UNLOCK_INTERRUPTS(); + /* + * END CRITICAL REGION + */ + + return; +} + + + +/** + * NAME + * stw_timer_stats + * + * SYNOPSIS + * #include "stw_timer.h" + * void + * stw_timer_stats(const stw_t *stw) + * + * DESCRIPTION + * Displays the stats for the specified timer wheel. + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +stw_timer_stats (const stw_t *stw) +{ + /* + * protect against a bad wheel + */ + if ((stw == NULL) || (stw->magic_tag != MAGIC_TAG)) { + return; + } + + printf("\n%s \n", stw->wheel_name ); + printf(" Granularity=%u\n", stw->granularity); + printf(" Wheel Size=%u\n", stw->wheel_size); + printf(" Tick Count=%u\n", stw->ticks); + printf(" Spoke Index=%u\n", stw->spoke_index); + + printf(" Active timers=%u\n", stw->timer_active); + printf(" Expired timers=%u\n", stw->timer_expired); + printf(" Hiwater mark=%u\n", stw->timer_hiwater_mark); + printf(" Started timers=%u\n", stw->timer_starts); + printf(" Cancelled timers=%u\n", stw->timer_cancelled); + return; +} + + +/** + * NAME + * stw_timer_running + * + * SYNOPSIS + * #include "stw_timer.h" + * boolean_t + * stw_timer_running(stw_tmr_t *tmr) + * + * DESCRIPTION + * RETURN VALUE TRUE if the timer structure is active + * + * INPUT PARAMETERS + * *tmr - pointer to the timer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE==timer is active + * FALSE==timer is not active + * + */ +boolean_t +stw_timer_running (stw_tmr_t *tmr) +{ + if (tmr == NULL) { + return (FALSE); + } + + /* + * if the timer is linked, its active + */ + if (tmr->links.stw_next != NULL) { + return (TRUE); + } + + return (FALSE); +} + + +/** + * NAME + * stw_timer_prepare + * + * SYNOPSIS + * #include "stw_timer.h" + * void + * stw_timer_prepare(stw_tmr_t *tmr) + * + * Descriiption + * Utility routine to initialize the links of timer elements. + * + * INPUT PARAMETERS + * *tmr - pointer to the timer + * + * OUTPUT PARAMETERS + * *tmr - The timer links are initialized. + * + * RETURN VALUE + * none + * + */ +void +stw_timer_prepare (stw_tmr_t *tmr) +{ + if (tmr) { + tmr->links.stw_next = NULL; + tmr->links.stw_prev = NULL; + } +} + + +/** + * NAME + * stw_timer_start + * + * SYNOPSIS + * #include "stw_timer.h" + * RC_STW_t + * stw_timer_start(stw_t *stw, + * stw_tmr_t *tmr, + * uint32_t delay, + * uint32_t periodic_delay, + * stw_call_back user_cb, + * void *parm) + * + * DESCRIPTION + * Start (or restart) a timer to expire in the future. If the timer is + * currently linked to a timer wheel spoke, it will be removed + * first. A new timer spoke will be determined based on the millisecond + * time delay requested and linked into the appropriate + * timer wheel spoke. + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel + * + * *tmr - pointer to the timer element + * + * delay - initial delay in milliseconds + * + * periodic_delay - periodic delay in milliseconds + * + * user_cb - application function call-back to be + * invoked when the timer expires. This call-back + * must run-to-completion and not block. + * + * parm - persistent parameter passed to the application + * call-back upon expiration + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_timer_start (stw_t *stw, + stw_tmr_t *tmr, + uint32_t delay, + uint32_t periodic_delay, + stw_call_back user_cb, + void *parm) +{ + stw_links_t *next, *prev; + + + if (stw == NULL) { + return (RC_STW_NULL_WHEEL); + } + + if (tmr == NULL) { + return (RC_STW_NULL_TMR); + } + + if (stw->magic_tag != MAGIC_TAG) { + return (RC_STW_INVALID_WHEEL); + } + + + /* + * BEGIN CRITICAL REGION + */ + LOCK_INTERRUPTS(); + + /* + * First check to see if it is already running. If so, remove + * it from the wheel. We don't bother cleaning up the fields + * because we will be setting them below. + */ + next = tmr->links.stw_next; + if (next) { + prev = tmr->links.stw_prev; + next->stw_prev = prev; + prev->stw_next = next; + + /* + * stats book keeping + */ + stw->timer_active--; + } + + UNLOCK_INTERRUPTS(); + /* + * END CRITICAL REGION + */ + + + /* + * set user call_back and parameter + */ + tmr->func_ptr = user_cb; + tmr->parm = parm; + tmr->delay = delay; + tmr->periodic_delay = periodic_delay; + + tmr_enqueue(stw, tmr, delay); + + + stw->timer_starts++; + stw->timer_active++; + if (stw->timer_active > stw->timer_hiwater_mark) { + stw->timer_hiwater_mark = stw->timer_active; + } + + return (RC_STW_OK); +} + + +/** + * NAME + * stw_timer_stop + * + * SYNOPSIS + * #include "stw_timer.h" + * RC_STW_t + * stw_timer_stop(stw_t *stw, stw_tmr_t *tmr) + * + * DESCRIPTION + * Stop the timer by removing it from whatever timer wheel spoke list + * it is currently attached to (if any). Note that it is safe to call + * this function with a timer that has already been stopped in order to + * avoid making all callers check for a running timer first. + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel + * + * *tmr - pointer to the timer element + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_timer_stop (stw_t *stw, stw_tmr_t *tmr) +{ + stw_links_t *next, *prev; + + if (stw == NULL) { + return (RC_STW_NULL_WHEEL); + } + + if (tmr == NULL) { + return (RC_STW_NULL_TMR); + } + + if (stw->magic_tag != MAGIC_TAG ) { + return (RC_STW_INVALID_WHEEL); + } + + /* + * BEGIN CRITICAL REGION + */ + LOCK_INTERRUPTS(); + + next = tmr->links.stw_next; + if (next) { + prev = tmr->links.stw_prev; + next->stw_prev = prev; + prev->stw_next = next; + tmr->links.stw_next = NULL; /* NULL == tmr is free */ + tmr->links.stw_prev = NULL; + + /* + * stats bookkeeping + */ + stw->timer_active--; + stw->timer_cancelled++; + } + + UNLOCK_INTERRUPTS(); + /* + * END CRITICAL REGION + */ + + return (RC_STW_OK); +} + + +/** + * NAME + * stw_timer_tick + * + * SYNOPSIS + * #include "stw_timer.h" + * void + * stw_timer_tick(stw_t *stw) + * + * DESCRIPTION + * This function moves the wheel cursor forward to the + * next spoke and expire the timers. + * + * Application call-backs must be non-blocking + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +stw_timer_tick (stw_t *stw) +{ + stw_links_t *spoke, *next, *prev; + stw_tmr_t *tmr; + + stw_call_back user_call_back; + + if ((stw == NULL) || (stw->magic_tag != MAGIC_TAG)) { + return; + } + + /* + * keep track of rolling the wheel + */ + stw->ticks++; + + /* + * advance the index to the next spoke + */ + stw->spoke_index = ( stw->spoke_index + 1 ) % + stw->wheel_size; + + /* + * Process the spoke, removing timers that have expired. + * If the timer rotation count is positive + * decrement and catch the timer on the next wheel revolution. + */ + spoke = &stw->spokes[stw->spoke_index]; + tmr = (stw_tmr_t *)spoke->stw_next; + + while( (stw_links_t *)tmr != spoke) { + + next = (stw_links_t *)tmr->links.stw_next; + prev = (stw_links_t *)tmr->links.stw_prev; + + /* + * if the timer is a long one and requires one or more rotations + * decrement rotation count and leave for next turn. + */ + if (tmr->rotation_count != 0) { + tmr->rotation_count--; + } else { + + /* + ** BEGIN CRITICAL REGION + */ + LOCK_INTERRUPTS(); + + prev->stw_next = next; + next->stw_prev = prev; + + tmr->links.stw_next = NULL; + tmr->links.stw_prev = NULL; + + /* book keeping */ + stw->timer_active--; + stw->timer_expired++; + + UNLOCK_INTERRUPTS(); + /* + ** END CRITICAL REGION + */ + + /* + * automatically restart the timer if periodic_delay > 0 + */ + if (tmr->periodic_delay > 0) { + tmr_enqueue(stw, tmr, tmr->periodic_delay); + stw->timer_active++; + } + + /* + * Invoke the user expiration handler to do the actual work. + */ + user_call_back = tmr->func_ptr; + (*user_call_back)(tmr, tmr->parm); + + } + + tmr = (stw_tmr_t *)next; + } + return; +} + + +/** + * NAME + * stw_timer_destroy + * + * SYNOPSIS + * #include "stw_timer.h" + * + * DESCRIPTION + * Destroys the specified timer wheel. All + * timers are stopped and resources released. + * + * INPUT PARAMETERS + * stw - pointer to the timer wheel + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_timer_destroy (stw_t *stw) +{ + uint32_t j; + stw_links_t *spoke; + + stw_tmr_t *tmr; + + + if (stw == NULL) { + return (RC_STW_NULL_WHEEL); + } + + if (stw->magic_tag != MAGIC_TAG ) { + return (RC_STW_INVALID_WHEEL); + } + + + /* + * Drive around the wheel and stop all timers + */ + + for (j = 0; j < stw->wheel_size; j++) { + spoke = &stw->spokes[j]; + + tmr = (stw_tmr_t *)spoke->stw_next; + + while ( (stw_links_t *)tmr != spoke) { + stw_timer_stop(stw, tmr); + + tmr = (stw_tmr_t *)spoke->stw_next; + } /* end while */ + + } /* end for */ + + /* + * clear the magic so we do not mistakenly access this wheel + */ + stw->magic_tag = 0; + + /* + * now free the wheel structures + */ + free(stw->spokes); + free(stw); + + return (RC_STW_OK); +} + + +/** + * NAME + * stw_timer_create + * + * SYNOPSIS + * #include "stw_timer.h" + * RC_STW_t + * stw_timer_create(uint32_t wheel_size, + * uint32_t granularity, + * const char *p2name, + * stw_t **stw) + * + * DESCRIPTION + * This function creates and initializes the timer wheel. Timers + * must not be started before this routine is called. + * + * Parmeters + * wheel_size - number of spokes in the wheel. The number + * of spokes should be engineered such that + * wheel_size >= (longest duration / granularity) + * Depending upon the number of concurrent timers, the + * distribution of those timers, it may be beneficial to + * further increase the wheel size. Objective is to + * minimize frequency of 'long' timers requiring wheel + * revolutions. + * + * granularity - milliseconds between ticks + * + * *p2name - pointer to the name of identify wheel. Limited + * to STW_NAME_LENGTH + * + * **stw - returned pointer to the created timer wheel + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_timer_create (uint32_t wheel_size, + uint32_t granularity, + const char *p2name, + stw_t **stw) +{ + uint32_t j; + stw_links_t *spoke; + + stw_t *p2stw; + + + if (stw == NULL) { + return (RC_STW_NULL_WHEEL); + } + *stw = NULL; + + /* + * we need to put some bounds to protect against extremely + * large numbers + */ + if (wheel_size < STW_MIN_WHEEL_SIZE || wheel_size > STW_MAX_WHEEL_SIZE) { + return (RC_STW_INVALID_WHEEL_SIZE); + } + + if (granularity < STW_MIN_GRANULARITY || + granularity > STW_MAX_GRANULARITY) { + return (RC_STW_INVALID_GRANULARITY); + } + + /* + * allocate memory for wheel control structure + */ + p2stw = (stw_t *)malloc( sizeof(stw_t)); + if (p2stw == NULL) { + return (RC_STW_NO_RESOURCES); + } + + /* + * allocate memory for wheel spokes + */ + p2stw->spokes = (stw_links_t *)malloc(wheel_size * sizeof(stw_links_t)); + if (p2stw->spokes == NULL) { + free(p2stw); + return (RC_STW_NO_RESOURCES); + } + + + /* + * Initialize the internal tick count at zero, should use + * safe string lib! + */ + strncpy(p2stw->wheel_name, p2name, STW_NAME_LENGTH-1); + p2stw->wheel_name[STW_NAME_LENGTH-1] = '\0'; + + p2stw->magic_tag = MAGIC_TAG; + + p2stw->ticks = 0; + + p2stw->spoke_index = 0; + p2stw->granularity = granularity; + p2stw->wheel_size = wheel_size; + + /* + * timer stats to tune wheel + */ + p2stw->timer_hiwater_mark = 0; + p2stw->timer_active = 0; + p2stw->timer_cancelled=0; + p2stw->timer_expired=0; + p2stw->timer_starts=0; + + /* + * Set all spokes to empty + */ + spoke = &p2stw->spokes[0]; + for (j = 0; j < wheel_size; j++) { + spoke->stw_next = spoke; /* empty spoke points to itself */ + spoke->stw_prev = spoke; + spoke++; + } + + *stw = p2stw; + return (RC_STW_OK); +} + + diff --git a/dlep_radio_ipv4/stw_timer.h b/dlep_radio_ipv4/stw_timer.h new file mode 100644 index 0000000..60219c6 --- /dev/null +++ b/dlep_radio_ipv4/stw_timer.h @@ -0,0 +1,234 @@ +/*------------------------------------------------------------------ + * stw_timer.h -- Definitions for Single Timer Wheel + * + * Februrary 2002, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __STW_TIMER_H__ +#define __STW_TIMER_H__ + +#include "safe_types.h" + + +/* + * This file provides the public definitions for external users of the + * Timer Wheel Timer facility. + * + * The Single Timer Wheel Timer facility is optimized to support embedded + * timer structures, ie where the timer structure is integrated into the + * structure it is associated with. + * + * Definitions + * + * Spoke - A queue of timers set to expire. A timer wheel consists of + * multiple spokes. + * + * Granularity - The amount of time between the processing of each + * spoke. Granularity is measured in time units between ticks. + * + * Rotation - one complete turn around the wheel + * + * Timer Duration given 32 bits + * Time per Tick Duration + * ------------------------------------ + * 10ms 497.1 days + * 20ms 994.2 + * 50ms 2485.5 + * + * milliseconds per day [1000 * 60 * 60 * 24] + * + */ + + +typedef enum { + RC_STW_OK = 0, + RC_STW_NULL_NAME, + RC_STW_NULL_FV, + RC_STW_NULL_WHEEL, + RC_STW_NULL_TMR, + RC_STW_INVALID_WHEEL, + RC_STW_INVALID_WHEEL_SIZE, + RC_STW_INVALID_GRANULARITY, + RC_STW_NO_RESOURCES, +} RC_STW_t; + + + +/* + * we need to put some bounds to protect against extremely + * large numbers. Ranges selected from pratical experience. + */ + +/* + * range of valid wheel sizes + */ +#define STW_MIN_WHEEL_SIZE ( 32 ) +#define STW_MAX_WHEEL_SIZE ( 4096 ) + +/* + * Granularity of a timer tick in milliseconds + */ +#define STW_MIN_GRANULARITY ( 1 ) +#define STW_MAX_GRANULARITY ( 100 ) + + +/* + * stw_links + * Definition of the pointers used to link a timer into + * a spoke. Double-linked list for efficiency. + */ +typedef struct stw_links_t_ { + struct stw_links_t_ *stw_next; + struct stw_links_t_ *stw_prev; +} stw_links_t; + + + +/* + * Timer Wheel Structure used to manage the timer wheel + * and keep stats to help understand performance + */ +#define STW_NAME_LENGTH ( 32 ) + +typedef struct { + char wheel_name[ STW_NAME_LENGTH ]; + uint32_t magic_tag; /* for sanity check */ + uint32_t wheel_size; + uint32_t spoke_index; /* mod index around wheel */ + uint32_t ticks; /* absolute ticks */ + uint32_t granularity; /* millisecond per tick */ + + /* + * few book keeping parameters to help engineer the wheel + */ + uint32_t timer_hiwater_mark; + uint32_t timer_active; + uint32_t timer_cancelled; + uint32_t timer_expired; + uint32_t timer_starts; + + stw_links_t *spokes; +} stw_t; + + +/* + * stw_tmr_t + * Definition of a timer element. + * This can be malloc'ed or embedded into an existing + * application structure. + */ +typedef struct { + stw_links_t links; + uint32_t rotation_count; + uint32_t delay; /* initial delay */ + uint32_t periodic_delay; /* auto-restart if > 0 */ + void *func_ptr; + void *parm; +} stw_tmr_t; + + +/* + * Application call-back type to be invoked at timer + * expiration. The call-back must be short-n-sweet, + * non-blocking. + */ +typedef void (*stw_call_back)(stw_tmr_t *tmr, void *parm); + + + +/* + * stw_timer_running + * RETURN VALUEs TRUE if the timer is active + */ +extern boolean_t +stw_timer_running(stw_tmr_t *tmr); + + +/* + * stw_timer_prepare + * Utility routine to initialize the links of timer elements. + */ +extern void +stw_timer_prepare(stw_tmr_t *tmr); + + +/* + * Displays timer wheel stats and counters to stdout. + */ +extern void +stw_timer_stats(const stw_t *stw); + + +/* + * Starts a new timer. If the timer is currently running, + * it is stopped and restarted anew + */ +extern RC_STW_t +stw_timer_start(stw_t *stw, + stw_tmr_t *tmr, + uint32_t delay, + uint32_t periodic_delay, + stw_call_back user_cb, + void *parm); + + +/* + * stops a currently running timer + */ +extern RC_STW_t +stw_timer_stop(stw_t *stw, stw_tmr_t *tmr); + + +/* + * Timer Wheel tick handler which drives time for the + * specified wheel + */ +extern void +stw_timer_tick(stw_t *stw); + + +/* + * Destroys a timer wheel + */ +extern RC_STW_t +stw_timer_destroy(stw_t *stw); + + +/* + * creates and initializes a single timer wheel + */ +extern RC_STW_t +stw_timer_create(uint32_t wheel_size, + uint32_t granularity, + const char *name, + stw_t **stw); + + +#endif /* __STW_TIMER_H__ */ + + diff --git a/dlep_radio_ipv4/tags.lst b/dlep_radio_ipv4/tags.lst new file mode 100644 index 0000000..552eaed --- /dev/null +++ b/dlep_radio_ipv4/tags.lst @@ -0,0 +1,88 @@ +./rfc5444_decoder.c +./fsm.c +./dlep_client_metrics.c +./rfc5444_scratch_pad.c +./sim_dlep_radio.c +./ipv4_address.c +./dlep_porter.c +./fuzz_dlep_cli.c +./dlep_debug.c +./dlep_config.c +./sim_dlep_radio_cli.c +./rfc5444_packet_header.c +./fuzz_packet.c +./dlep_client_peer_event_handlers.c +./stw_system_timer.c +./fuzz_encoder_tlv.c +./mac_address.c +./dlep_client_peer_fsm.c +./dlep_message_builder.c +./rfc5444_decoder_tlv.c +./stw_timer.c +./dlep_source_cli.c +./rfc5444_encoder_tlv.c +./rfc5444_utils.c +./dlep_context_peer.c +./dlep_context_peer_management.c +./dlep_debug_cli.c +./fuzz_message_builder.c +./packet_dump.c +./dlep_client_neighbor_event_handlers.c +./rfc5444_encoder.c +./dlep_buffers.c +./dlep_client_message_parser.c +./dlep_client_neighbor_fsm.c +./dlep_context_neighbor.c +./dlep_client_timer.c +./rfc5444_experimental_tlv.c +./cli.c +./ipv6_address.c +./dlep_context_neighbor_management.c +./fuzz_message_builder.h +./rfc5444_experimental_tlv.h +./time_units.h +./dlep_context_peer_management.h +./dlep_client_peer_fsm.h +./dlep_source_cli.h +./stw_timer.h +./rfc5444_utils.h +./dlep_context_neighbor.h +./mac_address.h +./fsm.h +./rfc5444_decoder_tlv.h +./dlep_client_neighbor_event_handlers.h +./packet_dump.h +./runtime_environment.h +./dlep_buffers.h +./rfc5444_decoder.h +./dlep_client_message_parser.h +./dlep_sim_options.h +./dlep_client_metrics.h +./ipv4_address.h +./stw_system_timer.h +./dlep_message_builder.h +./sim_dlep_radio_cli.h +./fuzz_encoder_tlv.h +./network_order.h +./safe_limits.h +./dlep_debug_cli.h +./rfc5444_encoder.h +./dlep_debug.h +./dlep_server_neighbor_fsm.h +./rfc5444_types.h +./rfc5444_encoder_tlv.h +./safe_types.h +./fuzz_packet.h +./dlep_context_peer.h +./dlep_porter.h +./dlep_client_neighbor_fsm.h +./rfc5444_api_rc.h +./rfc5444_packet_header.h +./dlep_context_neighbor_management.h +./dlep_client_timer.h +./fuzz_dlep_cli.h +./dlep_client_peer_event_handlers.h +./rfc5444_scratch_pad.h +./dlep_config.h +./cli.h +./ipv6_address.h diff --git a/dlep_radio_ipv4/time_units.h b/dlep_radio_ipv4/time_units.h new file mode 100644 index 0000000..e835e0d --- /dev/null +++ b/dlep_radio_ipv4/time_units.h @@ -0,0 +1,173 @@ +/*---------------------------------------------------------------------- + * time_units.h + * + * January 2009, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __TIME_UNITS_H__ +#define __TIME_UNITS_H__ + +#include "safe_limits.h" +#include "safe_types.h" + + +#define NANOSECONDS_PER_SECONDS ( 1000 * 1000 * 1000 ) +#define MICROSECONDS_PER_SECONDS ( 1000 * 1000 ) +#define MILLISECONDS_PER_SECONDS ( 1000 ) +#define DECISECONDS_PER_SECONDS ( 10 ) + + +/* + * Converts nanoseconds to microseconds. + * Can return 0. + */ +static inline uint32_t nano_to_microseconds (uint32_t nanoseconds) +{ + return (nanoseconds / 1000); +} + + +/* + * Converts nanoseconds to milliseconds. + * Can return 0. + */ +static inline uint32_t nano_to_milliseconds (uint32_t nanoseconds) +{ + return (nanoseconds / 1000 / 1000); +} + + +/* + * Converts nanoseconds to seconds. + * Can return 0. + */ +static inline uint32_t nano_to_seconds (uint32_t nanoseconds) +{ + return (nanoseconds / 1000 / 1000 / 1000); +} + + + +/* + * Converts milliseconds to nanoseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t milli_to_nanoseconds (uint32_t milliseconds) +{ + uint32_t nanoseconds; + + if (milliseconds > (UINT32_MAX / 1000 / 1000)) { + nanoseconds = 0; + } else { + nanoseconds = (milliseconds * 1000 * 1000); + } + + return (nanoseconds); +} + + +/* + * Converts milliseconds to microseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t milli_to_microseconds (uint32_t milliseconds) +{ + uint32_t microseconds; + + if (milliseconds > (UINT32_MAX / 1000)) { + microseconds = 0; + } else { + microseconds = (milliseconds * 1000); + } + return (microseconds); +} + + +/* + * Converts milliseconds to seconds. + * Can return 0. + */ +static inline uint32_t milli_to_seconds (uint32_t milliseconds) +{ + return (milliseconds / 1000); +} + + +/* + * Converts seconds to nanoseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t secs_to_nanoseconds (uint32_t seconds) +{ + uint32_t nanoseconds; + + if (seconds > (UINT32_MAX / 1000 / 1000 / 1000)) { + nanoseconds = 0; + } else { + nanoseconds = (seconds * 1000 * 1000 * 1000); + } + return (nanoseconds); +} + + +/* + * Converts seconds to microseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t secs_to_microseconds (uint32_t seconds) +{ + uint32_t microseconds; + + if (seconds > (UINT32_MAX / 1000 / 1000)) { + microseconds = 0; + } else { + microseconds = (seconds * 1000 * 1000); + } + return (microseconds); +} + + +/* + * Converts seconds to milliseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t secs_to_milliseconds (uint32_t seconds) +{ + uint32_t milliseconds; + + if (seconds > (UINT32_MAX / 1000)) { + milliseconds = 0; + } else { + milliseconds = (seconds * 1000); + } + return (milliseconds); +} + + +#endif + diff --git a/dlep_radio_ipv6/1fuzz_dlep_cli.c b/dlep_radio_ipv6/1fuzz_dlep_cli.c new file mode 100644 index 0000000..efeebcc --- /dev/null +++ b/dlep_radio_ipv6/1fuzz_dlep_cli.c @@ -0,0 +1,406 @@ +/*------------------------------------------------------------------ + * fuzz_dlep_cli.c -- fuzz CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reerved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#include "safe_types.h" +#include "cli.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" +#include "packet_dump.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_debug_cli.h" +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" +#include "dlep_porter.h" + +#include "fuzz_message_builder.h" +#include "fuzz_packet.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "fuzz_dlep_cli.h" + + + + +/* + * directory record + */ +static cli_record_t cli_fuzz_dir; +static cli_record_t fuzz_peer_dir; +static cli_record_t fuzz_neighbor_dir; + + +/* + * test command records + */ +static cli_record_t test_peer_hbt_cmd; +static cli_record_t test_peer_term_cmd; +static cli_record_t fuzz_neighbor_up_cmd; + +static cli_record_t fuzz_neighbor_term_cmd; +static cli_record_t fuzz_neighbor_metrics_cmd; + + +/** + ** test peer commands + **/ +static void +peer_fuzz_peer_term (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_fuzz_terminate - sends a peer terminate \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + send_fuzz_peer_terminate(p2peer); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + +static void +peer_fuzz_heartbeat (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_fuzz_heartbeat - sends a peer heartbeat \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + send_fuzz_peer_heartbeat(p2peer); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + + + + +/** + ** test neighbor commands + **/ +static void +cli_fuzz_neighbor_up (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_fuzz_up - generate a neighbor up \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + /* don't send the layer 3 addresses, force router to ARP/ND */ + ipv4_zero_address(&p2neighbor->ipv4_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + + /* set the neighbor metrics */ + p2neighbor->rlq_tx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->latency = 250; + p2neighbor->cdr_tx = 100000000; + p2neighbor->mdr_tx = 100000000; + + send_fuzz_neighbor_up(p2peer, p2neighbor); + return; +} + + +static void +cli_fuzz_neighbor_metrics (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + uint8_t rlq; + uint8_t resources; + uint16_t latency; + uint64_t cdr; + uint64_t mdr; + uint32_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_fuzz_metrics " + " \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf(" - 16-bit millisecond value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq = RFC5444_100_PERCENT; + } else { + rlq = temp; + } + } else { + printf("Input error: rlq missing \n"); + return; + } + + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + resources = RFC5444_100_PERCENT; + } else { + resources = temp; + } + } else { + printf("Input error: resources missing \n"); + return; + } + + if (argv[4]) { + temp = strtoul(argv[4], NULL, 10); + if (temp > 16535) { + latency = 16535; /* 16-bit max */ + } else { + latency = temp; + } + } else { + printf("Input error: latency missing \n"); + return; + } + + cdr = 0; + if (argv[5]) { + cdr = strtoul(argv[5], NULL, 10); + } else { + printf("Input error: cdr missing \n"); + return; + } + + mdr = 0; + if (argv[6]) { + mdr = strtoul(argv[6], NULL, 10); + } else { + printf("Input error: mdr missing \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->rlq_tx = rlq; + p2neighbor->resources_tx = resources; + p2neighbor->latency = latency; + p2neighbor->cdr_tx = cdr; + p2neighbor->mdr_tx = mdr; + + send_fuzz_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: RLQ=%u Resources=%u Latency=%u \n" + " CDR=%llu MDR=%llu \n", + rlq, + resources, + latency, + cdr, + mdr); + return; +} + + +static void +cli_fuzz_neighbor_term (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_fuzz_term - generate a " + "neighbor terminate \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + send_fuzz_neighbor_down(p2peer, p2neighbor); + + //dlep_client_neighbor_fsm_engine(neighbor_term_user_req_e, + // p2peer, p2neighbor); + return; +} + + +/** + * NAME + * fuzz_dlep_cli_init + * + * SYNOPSIS + * void + * fuzz_dlep_cli_init() + * + * DESCRIPTION + * Registers the dlep fuzzing commands with the cli + * facility. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +fuzz_dlep_cli_init (void) +{ + RC_CLI_t rc; + + /* + * Create directory and commands + */ + rc = cli_mkdir("fuzz", NULL, &cli_fuzz_dir); + + rc = cli_mkdir("peer", &cli_fuzz_dir, &fuzz_peer_dir); + rc = cli_mkdir("neighbor", &cli_fuzz_dir, &fuzz_neighbor_dir); + + + /* + * test peer + */ + rc = cli_mkcmd("peer_fuzz_terminate", peer_fuzz_peer_term, + &fuzz_peer_dir, &test_peer_term_cmd); + + rc = cli_mkcmd("peer_fuzz_heartbeat", peer_fuzz_heartbeat, + &fuzz_peer_dir, &test_peer_hbt_cmd); + + /* + * test neighbor + */ + rc = cli_mkcmd("neighbor_fuzz_up", cli_fuzz_neighbor_up, + &fuzz_neighbor_dir, &fuzz_neighbor_up_cmd); + + rc = cli_mkcmd("neighbor_fuzz_term", cli_fuzz_neighbor_term, + &fuzz_neighbor_dir, &fuzz_neighbor_term_cmd); + rc = cli_mkcmd("neighbor_fuzz_metrics", cli_fuzz_neighbor_metrics, + &fuzz_neighbor_dir, &fuzz_neighbor_metrics_cmd); + + return; +} + diff --git a/dlep_radio_ipv6/1fuzz_encoder_tlv.c b/dlep_radio_ipv6/1fuzz_encoder_tlv.c new file mode 100644 index 0000000..a253ef3 --- /dev/null +++ b/dlep_radio_ipv6/1fuzz_encoder_tlv.c @@ -0,0 +1,693 @@ +/*---------------------------------------------------------------------- + * fuzz_encoder_tlv.c -- routines to encode TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "network_order.h" + +#include "rfc5444_types.h" +#include "rfc5444_encoder.h" +#include "rfc5444_encoder_tlv.h" + + + +/** + * NAME + * rfc5444_mac_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_mac_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t mac_address[]) + * + * DESCRIPTION + * Call this function to insert the remote MAC address TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * mac_address - the remote router MAC address. The MAC + * is used to uniquely address all neighbor messages. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | MAC Addr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Remote Router MAC Continued (32-bit) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | MAC Addr | + * +-+-+-+-+-+-+-+-+ + * + */ + uint8_t +*fuzz_mac_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t mac_address[]) +{ +printf("fuzz_mac_address_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MAC_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_MAC_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MAC_ADDRESS_LENGTH); + dest += sizeof(uint16_t); + + dest = mac_put_address(dest, mac_address); + + /*** FUZZ the pointer ***/ + p2encoder_state->buildit_ptr = dest + 1; + return (dest); +} + + +/** + * NAME + * rfc5444_ipv4_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_ipv4_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t operation, + * ipv4_address_t ipv4) + * + * DESCRIPTION + * Call this function to insert the IPv4 TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * operation - indicates the operation to be applied + * on the IPv4 address + * RFC5444_EXISTING_NEW_ADDRESS + * RFC5444_WITHDRAW_ADDRESS + * + * ipv4 - the address + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | operation | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | IPv4 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*fuzz_ipv4_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv4_address_t *ipv4) +{ +printf("fuzz_ipv4_address_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV4_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV4_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV4_ADDRESS_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv4_put_address(dest, ipv4); + + /* NETWORK_ORDER_PUTBYTE(dest, 24); + dest += sizeof(uint8_t); */ + + /*** FUZZ the pointer to short***/ + p2encoder_state->buildit_ptr = dest - 2; + return (dest); +} + + +//ipv6_address_tlv + +uint8_t +*fuzz_ipv6_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv6_address_t *ipv6) +{ +printf("fuzz_ipv6_address_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV6_ADDRESS); + dest += sizeof(uint8_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV6_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTLONG(dest, (RFC5444_TLV_IPV6_ADDRESS_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv6_put_address(dest, ipv6); + + /* NETWORK_ORDER_PUTBYTE(dest, 24); + dest += sizeof(uint8_t); */ + + /*** FUZZ the pointer to short***/ + p2encoder_state->buildit_ptr = dest - 2; + return (dest); +} + + +/** + * NAME + * rfc5444_link_metric_mdr_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_mdr_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t mdr) + * + * DESCRIPTION + * Call this function to insert the maximum datarate TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * mdr - the maximum theoretical data rate, in bits per + * second (bps), achieved on the link. When + * metrics are reported, the maximum data rate + * MUST be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | MDR | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | MDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | MDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ + uint8_t +*fuzz_link_metric_mdr_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr) +{ +printf("fuzz_link_metric_mdr_tx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_MDR_METRIC_TX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_MDR_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_MDR_LENGTH); + /*** FUZZ over write length ***/ + //dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, mdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + uint8_t +*fuzz_link_metric_mdr_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr) +{ +printf("fuzz_link_metric_mdr_rx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_MDR_METRIC_RX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_MDR_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_MDR_LENGTH); + /*** FUZZ over write length ***/ + //dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, mdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + +/** + * NAME + * rfc5444_link_metric_cdr_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_cdr_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t cdr) + * + * DESCRIPTION + * Call this function to insert the current datarate TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * cdr - the current data rate, in bits per second + * (bps), achieved on the link. If there is no + * distinction between maximum and current + * data rate, current data rate SHOULD be set + * equal to the maximum data rate. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | CDR | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | CDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | CDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*fuzz_link_metric_cdr_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr) +{ +printf("fuzz_link_metric_cdr_tx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + /*** FUZZ the tlv type ***/ + //NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_CDR_METRIC_TX); + //dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_CDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, cdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*fuzz_link_metric_cdr_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr) +{ +printf("fuzz_link_metric_cdr_rx_tlv"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + /*** FUZZ the tlv type ***/ + //NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_CDR_METRIC_RX); + //dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_CDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, cdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/** + * NAME + * rfc5444_link_metric_latency_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_latency_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t latency) + * + * DESCRIPTION + * Call this function to insert the latency TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * latency - the transmission delay that a packet + * encounters as it is transmitted over the link. + * This is reported in absolute delay, in + * milliseconds. If latency cannot be calculated, + * a value of 0 should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Latency | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Latency | + * +-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*fuzz_link_metric_latency_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency) +{ +printf("fuzz_link_metric_latency_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_LATENCY_METRIC); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_LATENCY_FLAGS); + dest += sizeof(uint8_t); +#endif + /*** FUZZ the length***/ + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH + 2); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLONG(dest, latency); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*fuzz_link_metric_resources_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources) +{ +printf("fuzz_link_metric_resources_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RESOURCES_METRIC); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, resources); + dest += sizeof(uint8_t); + + /*** FUZZ the pointer ***/ + p2encoder_state->buildit_ptr = dest + 1; + return (dest); +} +/** + * NAME + * rfc5444_link_metric_rlq_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_rq_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t rlq) + * + * DESCRIPTION + * Call this function to insert the RLQ TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * rlq - a non-dimensional number, 0-100, representing + * the relative link quality. A value of 100 + * represents a link of the highest quality. If + * the RLQ cannot be calculated, a value of 100 + * should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | RLQ | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*fuzz_link_metric_rlq_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq) +{ +printf("fuzz_link_metric_rlq_tx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RLQ_METRIC_TX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RLQ_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, rlq); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*fuzz_link_metric_rlq_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq) +{ +printf("fuzz_link_metric_rlq_rx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RLQ_METRIC_RX); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RLQ_LENGTH); + dest += sizeof(uint16_t); + + /*** FUZZ the rlq value ***/ + //NETWORK_ORDER_PUTBYTE(dest, rlq); + //dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/* + * MTU + */ +uint8_t +*fuzz_mtu_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint16_t mtu) +{ +printf("fuzz_mtu_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MTU); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MTU_LENGTH); + dest += sizeof(uint16_t); + + /*** FUZZ the mtu value ***/ + + //NETWORK_ORDER_PUTBYTE(dest, mtu); + //dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_status_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + * uint8_t status_code) + * + * DESCRIPTION + * Call this function to insert the peer status TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * status_code - protocol status code reflecting success + * of previous request + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Status Code | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*fuzz_status_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t status_code) +{ +printf("fuzz_status_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_STATUS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_STATUS_FLAGS); + dest += sizeof(uint8_t); +#endif + + /*** FUZZ the length ***/ + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_STATUS_LENGTH+2); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, status_code); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + diff --git a/dlep_radio_ipv6/1fuzz_message_builder.c b/dlep_radio_ipv6/1fuzz_message_builder.c new file mode 100644 index 0000000..528b377 --- /dev/null +++ b/dlep_radio_ipv6/1fuzz_message_builder.c @@ -0,0 +1,2411 @@ +/*---------------------------------------------------------------------- + * dlep_message_builder.c -- Routines to build the DLEP messages + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "packet_dump.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_encoder_tlv.h" +#include "rfc5444_encoder.h" + +#include "dlep_sim_options.h" +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" +#include "rfc5444_experimental_tlv.h" + +#include "dlep_message_builder.h" +#include "dlep_client_timer.h" +#include "fuzz_encoder_tlv.h" + +#include "fuzz_message_builder.h" + +extern int TCP_READY; + + +/* + * Local API to increment a sequence number. Sequence numbers + * are simply request-response correlators. They are not + * checked for 'sequencing' or lost messages. The originator + * determines the sequence number so it can correlate the + * response. + */ +static uint16_t +dlep_get_next_sequence_number (uint16_t sequence_number) +{ + sequence_number++; + if (!sequence_number) { + sequence_number++; + } + return (sequence_number); +} + + +/** + * NAME + * send_fuzz_attached_peer_discovery + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_attached_peer_discovery( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a attached peer discovery message + * from the radio to the router to initiate the discovery process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_attached_peer_discovery (dlep_context_peer_t *p2peer) +{ +printf("send_fuzz_attached_peer_discovery\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + TCP_READY = 0; +// printf("\n INSIDE send_fuzz_attached_peer_discovery "); + p2es = rfc5444_encoder_packet_start(); + + /* Adding message header */ + rfc5444_encoder_message_block_start(p2es, + RFC5444_SIG_ATT_PEER_DISCOVERY); + + packet_dump("OUTGOING-", + p2es->packet_ptr, + 1); + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_detached_peer_discovery + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_detached_peer_discovery( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a detached peer discovery message + * from the radio to the router to initiate the discovery process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_detached_peer_discovery (dlep_context_peer_t *p2peer) +{ +printf("send_fuzz_detached_peer_discovery\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + /* + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); +*/ + +// added for D5 + +rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_DET_PEER_DISCOVERY); + +/* This function call to add message lenth */ + +#if 0 +rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); +#endif +#if 0 + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +/* + // added for testing, will remove it +// rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_DET_PEER_DISCOVERY); + */ + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + p2peer->expected_peer_offer_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + +#endif + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + /* optional */ + rfc5444_peer_tlv(p2es, p2config->local_type_description); +#if 0 + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); +#if 0 + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#endif + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_peer_offer + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_offer(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer offer message + * from the router to the radio in response to the + * peer attached/detached discovery message. This + * confirms discovery. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_offer (dlep_context_peer_t *p2peer) +{ +printf("send_fuzz_peer_offer\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + p2es = rfc5444_encoder_packet_start(); + + /* Adding Message header */ + + rfc5444_encoder_signal_block_start(p2es, + RFC5444_SIG_PEER_OFFER, + DLEP_SIGNAL_FLAGS); + + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_ipv4_connection_point_tlv(p2es, p2config->local_tcp_port, + &p2config->local_ipv4); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending peer offer : \n"); + printf(" signal code=%u RFC5444_SIG_PEER_OFFER \n", + RFC5444_SIG_PEER_OFFER); + } + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + + /* Oppening TCP socket */ +// dlep_tcp_porter_open(p2config); + + rfc5444_encoder_free(p2es); + + return; +} + + + /** + * NAME + * send_fuzz_peer_init + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_init( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer init message + * from the radio to the router to initiate the TCP synchronization process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ + void + send_fuzz_peer_init (dlep_context_peer_t *p2peer) + { +printf("send_fuzz_peer_init\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_INIT_REQ); + + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); + + rfc5444_link_metric_mdr_rx_tlv(p2es, 100000000); + p2peer->mdr_rx=100000000; + + rfc5444_link_metric_mdr_tx_tlv(p2es, 100000000); + p2peer->mdr_tx=100000000; + + rfc5444_link_metric_cdr_rx_tlv(p2es, 100000000); + p2peer->cdr_rx=100000000; + rfc5444_link_metric_cdr_tx_tlv(p2es, 250); + p2peer->cdr_tx =250; + + rfc5444_link_metric_latency_tlv(p2es, 250); + p2peer->latency = 250; + + rfc5444_link_metric_resources_tx_tlv(p2es, 100); + p2peer->resources_tx = 100; + rfc5444_link_metric_resources_rx_tlv(p2es, 100); + p2peer->resources_rx = 100; + + rfc5444_link_metric_rlq_rx_tlv(p2es, 100); + p2peer->rlq_rx = 100; + rfc5444_link_metric_rlq_tx_tlv(p2es, 100); + p2peer->rlq_tx = 100; + + + + /* optional */ + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#if 0 + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + + + printf("\n CALLING dlep_tcp_connect"); +#endif + +#if 0 + dlep_tcp_connect(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); +#endif + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + /* Setting this flag inorder for dlep_tcp_receive to get called after tcp connect + * and first dlep_tcp_send is called inorder to avoid infinite call in loop. + */ + TCP_READY = 1; + + rfc5444_encoder_free(p2es); +// printf("\n PEER INIT REQUEST Sent"); + + return; +} + + /** + * NAME + * send_fuzz_peer_init_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_init( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer init message response + * from the radio to the router. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ + void + send_fuzz_peer_init_ack (dlep_context_peer_t *p2peer) + { +printf("send_fuzz_peer_init_ack\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_INIT_RES); + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); + + rfc5444_link_metric_mdr_rx_tlv(p2es, 100000000); + p2peer->mdr_rx=100000000; + + rfc5444_link_metric_mdr_tx_tlv(p2es, 100000000); + p2peer->mdr_tx=100000000; + + rfc5444_link_metric_cdr_rx_tlv(p2es, 100000000); + p2peer->cdr_rx=100000000; + + rfc5444_link_metric_cdr_tx_tlv(p2es, 250); + p2peer->cdr_tx = 100000000; + + rfc5444_link_metric_latency_tlv(p2es, 250); + p2peer->latency = 250; + + rfc5444_link_metric_rlq_rx_tlv(p2es, 100); + p2peer->rlq_rx = 100; + + rfc5444_link_metric_rlq_tx_tlv(p2es, 100); + p2peer->rlq_tx = 100; + + rfc5444_link_metric_resources_tlv(p2es, 100); + p2peer->resources = 100; + + rfc5444_mtu_tlv(p2es, 100); + p2peer->mtu = 100; +/* + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2config->local_ipv4); + ipv4_zero_address(&p2peer->ipv4_address); +*/ + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2config->local_ipv6); + ipv6_zero_address(&p2peer->ipv6_address); + + /* rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + rfc5444_encoder_message_block_end(p2es); +*/ + // rfc5444_ipv6_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + rfc5444_encoder_message_block_end(p2es); + + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#if 0 + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + + + printf("\n CALLING dlep_tcp_connect"); +#endif + +#if 0 + dlep_tcp_connect(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); +#endif + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Session initialization response : \n"); + printf(" Message code=%u RFC5444_MSG_PEER_INIT_RES\n",RFC5444_MSG_PEER_INIT_RES); + + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + /* Setting this flag inorder for dlep_tcp_receive to get called after tcp connect + * and first dlep_tcp_send is called inorder to avoid infinite call in loop. + */ + TCP_READY = 1; + + rfc5444_encoder_free(p2es); + + return; +} + + +/** + * NAME + * send_fuzz_peer_heartbeat + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_heartbeat( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer heartbeat to + * maintain a persistent presence with the peer. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_heartbeat (dlep_context_peer_t *p2peer) +{ +printf("send_fuzz_peer_heartbeat\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + +// printf("\n INSIDE send_fuzz_peer_heartbeat"); + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + 18); + +#if 0 + /* + * Get a unique sequence number + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + /* rfc5444_heartbeat_interval_tlv(p2es, + p2config->peer_heartbeat_interval); */ + rfc5444_encoder_message_block_end(p2es); +#if 0 +#ifdef MULTIPLE_PEER_MESSAGES_PACKED + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_HEARTBEAT); + + /* + * Get a unique sequence number + * HB does not have an ACK, so the sequence number is not important. + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); +#endif +#endif + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + /* if (TCP_READY ) { + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + } else { // Else send with UDP socket if heartbeat sent before TCP connection. + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + } */ + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending heartbeat message : \n"); + printf(" Message code=18 RFC5444_MSG_PEER_HEARTBEAT\n"); + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_peer_update_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_update_request( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer update message + * from the router to the radio. It is used to indicate + * a new layer 3 address or the removal of a layer 3 + * address. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_update_request (dlep_context_peer_t *p2peer) +{ +printf("send_fuzz_peer_update_request\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_UPDATE_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = dlep_get_next_sequence_number(p2peer->sequence); + p2peer->expected_peer_update_response_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + if (p2peer->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2peer->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2peer->update_ipv4_operation, + &p2peer->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2peer->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2peer->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2peer->update_ipv6_operation, + &p2peer->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } +#if 0 + rfc5444_encoder_tlv_block_end(p2es); +#endif + printf("Sending mdr ,cdr, latency as fuzz\n"); + fuzz_link_metric_mdr_rx_tlv(p2es, p2peer->mdr_rx); + fuzz_link_metric_mdr_tx_tlv(p2es, p2peer->mdr_tx); + fuzz_link_metric_cdr_rx_tlv(p2es, p2peer->cdr_rx); + fuzz_link_metric_cdr_tx_tlv(p2es, p2peer->cdr_tx); + fuzz_link_metric_latency_tlv(p2es, p2peer->latency); + rfc5444_link_metric_resources_tlv(p2es, p2peer->resources); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2peer->rlq_tx); + rfc5444_link_metric_rlq_rx_tlv(p2es, p2peer->rlq_rx); + rfc5444_mtu_tlv(p2es, p2peer->mtu); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session update request :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_UPDATE_REQ\n", + RFC5444_MSG_PEER_UPDATE_REQ); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + + return; +} + + +/** + * NAME + * send_fuzz_peer_update_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_update_response( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer update response message + * from the radio to the router. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_update_response (dlep_context_peer_t *p2peer) +{ +printf("send_fuzz_peer_update_response\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_UPDATE_RES); +#if 0 + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session update response :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_UPDATE_RES\n", + RFC5444_MSG_PEER_UPDATE_RES); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_peer_termination + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_termination(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer termination message + * from the router to the radio or from the radio to the + * router to termiante the association. As result all + * neighbor neighbors are also terminated. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_terminate (dlep_context_peer_t *p2peer) +{ +printf("send_fuzz_peer_terminate\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + printf("\n send_fuzz_peer_termination in builder.c "); + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = dlep_get_next_sequence_number( + p2peer->sequence); + p2peer->expected_peer_offer_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +// printf("\n Adding Status TLV"); + rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + rfc5444_encoder_message_block_end(p2es); +#endif +#ifdef MULTIPLE_PEER_MESSAGES_PACKED + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); + + /* + * acks will not align with incremented sequence + * + * p2peer->sequence = dlep_get_next_sequence_number( + * p2peer->sequence); + * p2peer->expected_peer_offer_sequence = p2peer->sequence; + */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + + printf("Sending fuzz status tlv\n"); + fuzz_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session termination :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_TERM_REQ\n", + RFC5444_MSG_PEER_TERM_REQ); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_peer_termination_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_peer_termination_ack(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer termination ACK + * message from the router to the radio or from the radio + * to the router in response to the peer terminate request. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_peer_termination_ack (dlep_context_peer_t *p2peer) +{ +printf("send_fuzz_peer_termination_ack\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_RES); +#if 0 + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + +// rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session terrmination message :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_TERM_REQ\n", + RFC5444_MSG_PEER_TERM_REQ); + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_up + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_up(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor up message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_up (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_up\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_REQ); + printf("Sending ip address as fuzz\n"); + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* add the IPv4 address if there is one to add */ + if (p2neighbor->ipv4_address.v4_addr.v4_addr32) { + fuzz_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv4_address); + ipv4_zero_address(&p2neighbor->ipv4_address); + } + + /* add the IPv6 address if there is one to add */ + else if (p2neighbor->ipv6_address.v6_addr.v6_addr32[0] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[1] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[2] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[3]) { + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv6_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + + + if (!p2neighbor->CREDIT_NOT_SUPPORTED) { + rfc5444_credit_window_status_tlv(p2es, p2neighbor->mrw, p2neighbor->rrw); + } + + rfc5444_encoder_message_block_end(p2es); +#if 0 +//ifdef MULTIPLE_NEIGHBOR_MESSAGES_PACKED + /**** neighbor down ****/ + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_term_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + /**** neighbor up ****/ + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_init_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* add the IPv4 address if there is one to add */ + if (p2neighbor->ipv4_address.v4_addr.v4_addr32) { + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv4_address); + ipv4_zero_address(&p2neighbor->ipv4_address); + } + + /* add the IPv6 address if there is one to add */ + if (p2neighbor->ipv6_address.v6_addr.v6_addr32[0] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[1] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[2] || + p2neighbor->ipv6_address.v6_addr.v6_addr32[3]) { + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv6_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + } + + rfc5444_link_metric_mdr_tlv(p2es, p2neighbor->mdr); + + rfc5444_link_metric_cdr_tlv(p2es, p2neighbor->cdr); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); +#endif + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination up:\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_UP_REQ\n", + RFC5444_MSG_NEIGHBOR_UP_REQ); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_up_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_up_ack(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor up ack message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_up_ack (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_up_ack\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); +#if 0 + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_metrics + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_metrics(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor metrics message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context with the + * metrics data set + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_metrics (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_metrics\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + else if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + printf("Sending relative link quality , resources, mtu as fuzz\n"); + + fuzz_link_metric_resources_tlv(p2es, p2neighbor->resources); + + fuzz_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + fuzz_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + + fuzz_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination update to metrics:\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_METRICS\n", + RFC5444_MSG_NEIGHBOR_METRICS); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + +void +send_fuzz_neighbor_credit_grant_req (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_credit_grant_req\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); + +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + +#if 0 + /* + * Get a unique sequence number */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_credit_grand_request_tlv(p2es, p2neighbor->cgr); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + + /* + * start the ack timer. Using same neighbor_up_ack_tmo Neighbor Up Time. + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_update_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_update_ack_tmr, + (void *)p2neighbor); + + return; +} + + +void +send_fuzz_neighbor_credit_reject (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_credit_reject\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); + + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_rx_tlv(p2es, p2neighbor->resources_tx); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_address_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_address_request(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a peer heartbeat. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_address_request (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_address_request\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_ADDRESS_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = + dlep_get_next_sequence_number(p2neighbor->sequence); + p2neighbor->expected_neighbor_address_response_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_address_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_address_response(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor address response. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_address_response (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_address_response\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_ADDRESS_RES); + + /* + * echo the neighbor sequence number + */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_down + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_down(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor down message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_down (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_down\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_REQ); +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_term_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + + printf("Sending mac address as fuzz\n"); + fuzz_mac_address_tlv(p2es, p2neighbor->mac_address); + +// rfc5444_status_tlv(p2es, p2neighbor->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination down :\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_DOWN_REQ\n", + RFC5444_MSG_NEIGHBOR_DOWN_REQ); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_down_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_down_ack(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor down ack message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_down_ack (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_down_ack\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination down response :\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_DOWN_RES\n", + RFC5444_MSG_NEIGHBOR_DOWN_RES); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_link_char_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_link_char_request(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor, + * uint64_t cdr, + * uint16_t latency) + * + * DESCRIPTION + * This function is used to send a link characteristic message from + * the server to the client. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * cdr - requested data rate + * + * latency - maximum latency requested + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_link_char_request (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor, + uint64_t cdr, + uint64_t latency) +{ +printf("send_fuzz_neighbor_link_char_request\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_LINK_CHAR_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = + dlep_get_next_sequence_number(p2neighbor->sequence); + p2neighbor->expected_neighbor_link_char_response_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (cdr) { + rfc5444_link_metric_cdr_tx_tlv(p2es, cdr); + rfc5444_link_metric_cdr_rx_tlv(p2es, cdr); + } + + + if (latency) { + rfc5444_link_metric_latency_tlv(p2es, latency); + } + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_fuzz_neighbor_link_char_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_fuzz_neighbor_link_char_response(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a link characteristic response from + * the client to the server. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_fuzz_neighbor_link_char_response (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_fuzz_neighbor_link_char_response\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_LINK_CHAR_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + +#if 0 + rfc5444_link_metric_resources_rx_tlv(p2es, p2neighbor->resources_tx); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination link char response :\n"); + printf(" Message code=%u FC5444_MSG_LINK_CHAR_RES\n", + RFC5444_MSG_LINK_CHAR_RES); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + diff --git a/dlep_radio_ipv6/CMakeLists.txt b/dlep_radio_ipv6/CMakeLists.txt new file mode 100644 index 0000000..e1bad66 --- /dev/null +++ b/dlep_radio_ipv6/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0.0) +project (dlep_radio_ipv6) +file(GLOB SOURCES "*.c") +add_executable(dlep_radio_ipv6 ${SOURCES}) +install( + TARGETS dlep_radio_ipv6 + RUNTIME DESTINATION bin) + diff --git a/dlep_radio_ipv6/cli.c b/dlep_radio_ipv6/cli.c new file mode 100644 index 0000000..4db9b26 --- /dev/null +++ b/dlep_radio_ipv6/cli.c @@ -0,0 +1,936 @@ +/*------------------------------------------------------------------ + * cli.c -- command line interpreter + * + * Copyright (c) 2009 by B. Berry + * All rights resevered. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include "safe_types.h" + +#include "cli.h" + + +/** + * cli -- command line interpreter + * + * DESCRIPTION + * command line interpreter (cli) provides a directory + * hierarchy of commands similar in concept to the linux + * directory structure. There exists the concept of a root + * directory and subdirectory. Subdirectories can be created + * under root or under other subdirectories. Commands can + * be created under root or any subdirectory. + * + * When the user enters a command, the matching command + * structure is located from the registered commands + * and the associated call-back function is invoked to + * execute the command. + * + * When the user enters a directory name to change directories, + * the cli will change to that directory and display the + * contents. This new directory becomes the present + * working directory (pwd). + * + * User call backs are invoked with the (argc, *argv[]) parameters. + * argv[0] is the command string while argv[1,2,...,ARGC_MAX] are + * command specific parameters. + * + * There are several built-in commands for directory navigation: + * h help + * ~ moves to the top directory, root + * .. moves the directory up one level + * ld lists both commands and directories + * ! (bang) global command execution + * ls global list of commands + * + * Optional built in directories + * cli_config_dir - Commands to manage configuration. + * cli_show_dir - Commands to show internals: configuration, data, etc. + * cli_clear_dir - Commands to clear counters, runtime data, etc. + * cli_opertion_dir - Commands to manage the runtime operation. + * cli_debug_dir - Commands to facilitate debugging. + * + * PUBLIC FUNCTIONS + * cli_mkcmd - add a command to a directory + * cli_mkdir - add a subdirectory to directory + * cli_engine - command processing engine + * cli_init - initialization + * + * + */ + +/* + * #define CLI_DEBUG ( 1 ) + */ +//#define CLI_DEBUG ( 1 ) + +#ifdef CLI_DEBUG +#define DEBUG_PRINTF(myargs...) printf(myargs) +#else +#define DEBUG_PRINTF(myargs...) ((void)0) +#endif + + + +/* + * The maximum number of entries displayed on a single line + * is ENTRIES_PER_LINE. If there are more than ENTRIES_PER_LINE, + * a newline is injected to avoid line wrap. Useful for small + * screens. + */ +#define ENTRIES_PER_LINE ( 3 ) + + + + +/* + * navigation commands + */ +#define CLI_H "h" /* h => help */ +#define CLI_HELP "help" /* help */ +#define CLI_QUESTION "?" /* help */ +#define CLI_UP_ONE ".." /* move up one directory level */ +#define CLI_ROOT_DIR "~" /* move to root directory */ +#define CLI_LIST_DIR "ld" /* list the current directory */ +#define CLI_GLOBAL_BANG "!" /* global execution */ +#define CLI_GLOBAL_LIST "ls" /* global command list */ + + + +/* + * root directory structure + */ +static cli_record_t cli_root_element; + +/* + * pointer to present working directory (pwd) + */ +static cli_record_t *current_directory; + + +static struct t_nodal_record *list; + + +/* + * Public directories that applications can register with. + * Enable define for these root directories. Once defined, + * apps can register in this directory structure. If not, + * applications register to the root directory. + */ +#ifdef CLI_ROOT_DIRS +//cli_record_t cli_config_dir; +cli_record_t cli_show_dir; +//cli_record_t cli_clear_dir; +//cli_record_t cli_operation_dir; +cli_record_t cli_debug_dir; +cli_record_t cli_test_dir; +#endif + + +#define CLI_PROMPT_LEN ( 32 ) +static char cli_prompt[CLI_PROMPT_LEN]; + + + + +static void +cli_help (void) +{ + printf("\n"); + printf(" Built-in commands \n"); + printf(" h help \n"); + printf(" ~ Returns to the top or root command directory \n"); + printf(" .. Moves the from the current directory up one directory \n"); + printf(" ld current directory listing \n"); + printf(" ! (bang) global command seek and execute \n"); + printf(" ls Global list of commands \n"); + printf(" All commands followed by \n"); + + printf("\n"); + return; +} + + + +static boolean_t +str_exact (char *p1, char *p2, size_t n) +{ + while (*p1) { + if (*p1 == *p2) { + p1++; + p2++; + } else { + return (FALSE); + } + } + + if (*p1 == *p2) { + return (TRUE); + } else { + return (FALSE); + } +} + + + + +/* + * NAME + * cli_bind_entry + * + * SYNOPSIS + * #include "cli.h" + * static RC_CLI_t + * cli_bind_entry(char *name, + * cli_funcvar_t fv, + * cli_record_t *dir_rec, + * cli_record_t *cmd_rec) + * + * DESCRIPTION + * This is an internal function to add a command/directory + * into the specified chain. To add an entry into the + * root directory, specify NULL for the directory pointer. + * + * INPUT PARAMETERS + * name the name of the user command. + * + * fv a pointer to the target function to be invoked + * when the command is entered. If NULL then + * the name is considered to be a directory. + * + * dir_rec a pointer to the directory record + * + * cmd_rec a pointer to the command record to be added + * + * RETURN VALUE + * RC_CLI_OK + * error otherwise + * + */ +static RC_CLI_t +cli_bind_entry (char *name, + cli_funcvar_t fv, + cli_record_t *dir_rec, + cli_record_t *cmd_rec) +{ + cli_record_t *p2list; + cli_record_t *p2parent_directory; + + if (name == NULL) { + return (RC_CLI_NULL_NAME); + } + + if (cmd_rec == NULL) { + return (RC_CLI_NULL_CMD); + } + + if (dir_rec == NULL) { + p2list = &cli_root_element; + } else { + p2list = dir_rec; + } + + p2parent_directory = p2list; + + + /* + * can not re-use a record + */ + if (cmd_rec == p2list) { + return (RC_CLI_RECORD_CORRUPT); + } + + /* + * check if the directory is empty to add the + * first entry + */ + if (p2list->link2subdir == NULL) { + p2list->link2subdir = cmd_rec; + + DEBUG_PRINTF("\"%s\" is the First entry in directory [%s]\n", + name, p2list->name ); + + } else { + /* + * Directory is not empty, so walk the list to + * check for duplicates and append the entry. + */ + + p2list = p2list->link2subdir; + + while (p2list->next_entry != NULL) { + /* + * can not re-use a record + */ + if (cmd_rec == p2list) { + return (RC_CLI_RECORD_CORRUPT); + } + + /* + * do not allow duplicate names within the same subdirectory + */ + if (str_exact(p2list->name, name, CLI_ENTRY_LEN)) { + return (RC_CLI_DUPLICATE); + } + + p2list = p2list->next_entry; + } + + /* + * Now we can append the new entry. + */ + p2list->next_entry = cmd_rec; + + DEBUG_PRINTF("Appended \"%s\" in directory [%s]\n", + name, dir_rec->name); + } + + /* + * setup the new entry record + */ + strncpy(cmd_rec->name, name, CLI_ENTRY_LEN-1); + cmd_rec->name[CLI_ENTRY_LEN-1] = '\0'; + cmd_rec->parent_dir = p2parent_directory; + cmd_rec->next_entry = NULL; + cmd_rec->link2subdir = NULL; + cmd_rec->fv = fv; + + if (cmd_rec->fv) { + cmd_rec->cmd_list = list; + list = cmd_rec; + } + + return (RC_CLI_OK); +} + + +/** + * NAME + * cli_mkcmd + * + * SYNOPSIS + * #include "cli.h" + * RC_CLI_t + * cli_mkcmd(char *name, + * cli_funcvar_t fv, + * cli_record_t *dir_rec, + * cli_record_t *cmd_rec) + * + * DESCRIPTION + * Add the new command into the specified directory. + * To add a command into the root directory, + * specify NULL for the directory pointer. + * + * INPUT PARAMETERS + * name pointer to the command name. + * + * fv pointer to the target function to be invoked + * when the command is entered. + * + * dir_rec pointer to the directory record where the + * new command is to be added. Use NULL for root. + * + * cmd_rec pointer to the new command record. + * + * RETURN VALUE + * RC_CLI_OK + * error otherwise + * + * EXAMPLES + * The examples below add three commands to my_directory. + * + * rcode = cli_mkcmd ( "command_one", funct_one, + * &my_directory_record, &cmd_one_record ); + * rcode = cli_mkcmd ( "command_two", funct_two, + * &my_directory_record, &cmd_two_record ); + * rcode = cli_mkcmd ( "command_three", funct_three, + * &my_directory_record, &cmd_three_record ); + * + */ +RC_CLI_t +cli_mkcmd (char *name, + cli_funcvar_t fv, + cli_record_t *dir_rec, + cli_record_t *cmd_rec) +{ + RC_CLI_t rc; + + if (fv == NULL) { + return (RC_CLI_NULL_FV); + } + + /* + * bind into ROOT if directory not specified + */ + if (dir_rec == NULL) { + dir_rec = &cli_root_element; + } + + /* + * you must bind only to a directory + */ + if (dir_rec->fv != NULL) { + return (RC_CLI_DIR_INVALID); + } + + rc = cli_bind_entry(name, fv, dir_rec, cmd_rec); + return (rc); +} + + +/** + * NAME + * cli_mkdir + * + * SYNOPSIS + * #include "cli.h" + * RC_CLI_t + * cli_mkdir(char *name, cli_record_t *dir_rec, + * cli_record_t *sub_dir) + * + * DESCRIPTION + * Add a new directory into the specified directory. + * To add a new directory into the ROOT directory, + * specify NULL for the directory pointer. + * + * INPUT PARAMETERS + * name pointer to the direcory name. + * + * dir_rec pointer to the directory record where the + * new subdir is to be added. Use NULL for root. + * + * cmd_rec pointer to the new directory record. + * + * RETURN VALUE + * RC_CLI_OK + * error otherwise + * + * EXAMPLES + * The example below adds a_directory (subdirectory) to the + * root directory. This is a visible entry. + * + * rc = cli_mkdir( "a_directory", NULL, + * &a_directory_record); + * + * + * The example below adds a_sub_directory (subdirectory) to the + * previously created directory 'a_directory_record'. + * + * rc = cli_mkdir( "a_sub_directory", &a_directory_record, + * &a_subdir_record); + * + */ +RC_CLI_t +cli_mkdir (char *name, cli_record_t *dir_rec, + cli_record_t *sub_dir) +{ + RC_CLI_t rc; + + /* + * bind into ROOT if the directory is not specified + */ + if (dir_rec == NULL) { + dir_rec = &cli_root_element; + } + + /* + * must bind only to an existing directory + */ + if (dir_rec->fv != NULL) { + return (RC_CLI_DIR_INVALID); + } + + rc = cli_bind_entry(name, NULL, dir_rec, sub_dir); + return (rc); +} + + +/* + * NAME + * global_command_list + * + * SYNOPSIS + * #include "cli.h" + * static void + * global_command_list(void) + * + * DESCRIPTION + * Displays the global list of commands. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * void + * + */ +static void +global_command_list (void) +{ + uint16_t count; + cli_record_t *cmd_rec; + + count = 0; + + /* + * global list of command + */ + printf("\n"); + cmd_rec = list; + while (cmd_rec != NULL) { + if (count){ printf(", "); } + + printf("%s", cmd_rec->name); + count++; + + /* + * prevent line wrap + */ + if (count >= ENTRIES_PER_LINE) { + printf("\n"); + count = 0; + } + cmd_rec = cmd_rec->cmd_list; + } + + return; +} + + +/* + * NAME + * list_directory + * + * SYNOPSIS + * #include "cli.h" + * static void + * list_directory(void) + * + * DESCRIPTION + * Display the contents of the directory, both commands and + * subdirectories. Directories are enclosed in brackets, [..]. + * + * INPUT PARAMETERS + * none + * + * RETURN VALUE + * void + * + */ +static void +list_directory (void) +{ + uint16_t count; + cli_record_t *cmd_tmp; + + count = 0; + + /* + * first list all directoies + * list directory with brackets: [ directory ] + */ + printf("\n"); + cmd_tmp = current_directory->link2subdir; + while (cmd_tmp != NULL) { + + /* fv == NULL means it is a directory */ + if (cmd_tmp->fv == NULL) { + if (count){ printf(", "); } + + printf("[%s]", cmd_tmp->name); + count++; + + /* + * prevent line wrap + */ + if (count >= ENTRIES_PER_LINE) { + printf("\n"); + count = 0; + } + } + cmd_tmp = cmd_tmp->next_entry; + } + + /* + * list commands + */ + cmd_tmp = current_directory->link2subdir; + while (cmd_tmp != NULL) { + + if (cmd_tmp->fv != NULL) { + if (count){ printf(", "); } + + printf("%s", cmd_tmp->name); + count++; + + /* + * prevent line wrap + */ + if (count >= ENTRIES_PER_LINE) { + printf("\n"); + count = 0; + } + } + cmd_tmp = cmd_tmp->next_entry; + } + + return; +} + + +/* + * NAME + * cli_find_cmd + * + * SYNOPSIS + * #include "cli.h" + * static cli_record_t + * *cli_find_cmd(char *name) + * + * DESCRIPTION + * An internal function to scan the current directory for the + * specified entry. + * + * INPUT PARAMETERS + * name pointer to the string to look for (null terminated). + * + * RETURN VALUE + * NULL string NOT found + * ptr Pointer to entry record if a match was found + * + */ +static cli_record_t +*cli_find_cmd (char *name) +{ + cli_record_t *cmd_rec; + + DEBUG_PRINTF("\nAttempting to Find \"%s\" in directory [%s]\n", + name, current_directory->name ); + + /* + * check for global command search + */ + if (*name == '!') { + DEBUG_PRINTF("\nGlobal command search! \n"); + + name++; + cmd_rec = list; + while (cmd_rec != NULL) { + DEBUG_PRINTF("\nglobal comparing \"%s\" with entry \"%s\"\n", + name, cmd_rec->name); + + if (str_exact(cmd_rec->name, name, CLI_ENTRY_LEN)) { + DEBUG_PRINTF("\nGlobal match found for -%s- \n", name); + return (cmd_rec); + } + cmd_rec = cmd_rec->cmd_list; + } + + printf("\n*Unknown entry \"%s\"\n", name); + return (NULL); + } + + /* + * now compare to existing command and directory entries + */ + cmd_rec = current_directory->link2subdir; + while (cmd_rec != NULL) { + DEBUG_PRINTF("\ncomparing \"%s\" with entry \"%s\"\n", + name, cmd_rec->name); + + if (str_exact(cmd_rec->name, name, CLI_ENTRY_LEN)) { + DEBUG_PRINTF("\nMatch found for -%s- \n", name); + return (cmd_rec); + } + cmd_rec = cmd_rec->next_entry; + } + + /* + * check to see if the user wants to go back one directory + */ + if (str_exact(name, CLI_UP_ONE, 2)) { + DEBUG_PRINTF("\nGo up one dir level \n"); + current_directory = current_directory->parent_dir; + return (NULL); + } + + /* + * check to see if user wants to go to the root directory + */ + if (str_exact(name, CLI_ROOT_DIR, 1)) { + DEBUG_PRINTF("\nGo to root \n"); + current_directory = &cli_root_element; + return (NULL); + } + + /* + * check to see if user wants to list entries + */ + if (str_exact(name, CLI_LIST_DIR, 2)) { + DEBUG_PRINTF("\nList directory \n"); + list_directory(); + return (NULL); + } + + if (str_exact(name, CLI_GLOBAL_LIST, 2)) { + DEBUG_PRINTF("\nGlobal List \n"); + global_command_list(); + return (NULL); + } + + if (str_exact(name, CLI_H, 1) || + str_exact(name, CLI_HELP, 4) || + str_exact(name, CLI_QUESTION, 1)) { + cli_help(); + return (NULL); + } + + /* did not find a match */ + printf("\n*Unknown entry \"%s\"\n", name); + return (NULL); +} + + +/** + * NAME + * cli_engine + * + * SYNOPSIS + * #include "cli.h" + * void + * cli_engine(char *input_string) + * + * DESCRIPTION + * The CLI engine. + * + * INPUT PARAMETERS + * input_string - The string as entered by the user. The cli + * processor will use the first token to match a + * valid directory or command entry. If the + * entry matches with a directory, the current + * directory is changed to that directory. + * + * If the entry is a command, the remainder of the + * string is passed to the user function. The user + * function can then continue parsing token. + * + * RETURN VALUE + * None + * + * : + * For example, a simple CLI process. + * for(;;) { + * gets(input_string); + * cli_engine(input_string); + * } + * + */ +void +cli_engine (char *input_string) +{ + cli_record_t *next_level; + uint32_t i; + char *p2str; + + uint32_t argc; + char *argv[ARGC_MAX]; + + if ((input_string == NULL) || (*input_string == '\0')) { + DEBUG_PRINTF("\nEmpty string entered\n"); + + printf("\n%s >", cli_prompt); + fflush(stdout); + return; + } + + for (i=0; i", cli_prompt); + fflush(stdout); + return; + } + + DEBUG_PRINTF("\n0 input token \"%s\"\n", argv[0]); + + /* + * now pick off parameters. + */ + argc = 1; + for (i=1; ifv != NULL) { + /* + * call users registered function + */ + (next_level->fv)(argc, &argv[0]); + + } else { + /* + * change to the subdirectory + */ + current_directory = next_level; + } + } else { + /* Did not find a match */ + } + + printf("\n%s >", cli_prompt); + fflush(stdout); + return; +} + + + +/** + * NAME + * cli_set_prompt + * + * SYNOPSIS + * #include "cli.h" + * void + * cli_set_prompt(char *prompt) + * + * DESCRIPTION + * This function is used to set a prompt string. + * + * INPUT PARAMETERS + * prompt - pointer to the string prompt + * + * RETURN VALUE + * none + * + */ +void +cli_set_prompt (char *prompt) +{ + if (prompt) { + strncpy(cli_prompt, prompt, CLI_PROMPT_LEN); + cli_prompt[CLI_PROMPT_LEN-1] = '\0'; + } + + return; +} + + + +/** + * NAME + * cli_init + * + * SYNOPSIS + * #include "cli.h" + * RC_CLI_t + * cli_init (cli_init_data_t *init_data) + * + * DESCRIPTION + * This function initializes the CLI facility. All the + * parameters listed in init_data must be provided. + * + * INPUT PARAMETERS + * init_data pointer to initialization information + * prefix - string to be displayed at the + * root directory + * + * RETURN VALUE + * RC_CLI_OK + * error otherwise + * + */ +RC_CLI_t +cli_init (cli_init_data_t *init_data) +{ + RC_CLI_t rc; + + strncpy(cli_prompt, "prompt", CLI_PROMPT_LEN); + cli_prompt[CLI_PROMPT_LEN-1] = '\0'; + + /* + * initialize the ROOT directory + */ + strncpy(cli_root_element.name, init_data->prefix, CLI_ENTRY_LEN); + + cli_root_element.name[CLI_ENTRY_LEN-1] = '\0'; + cli_root_element.fv = NULL; + cli_root_element.parent_dir = &cli_root_element; + cli_root_element.next_entry = NULL; + cli_root_element.link2subdir = NULL; + + /* mark end of hte command list */ + list = NULL; + + +#ifdef CLI_ROOT_DIRS +// rc = cli_mkdir("config", NULL, &cli_config_dir); + rc = cli_mkdir("show", NULL, &cli_show_dir); +// rc = cli_mkdir("clear", NULL, &cli_clear_dir); +// rc = cli_mkdir("operation", NULL, &cli_operation_dir); + rc = cli_mkdir("debug", NULL, &cli_debug_dir); + rc = cli_mkdir("test", NULL, &cli_test_dir); +#endif + + current_directory = &cli_root_element; + return (RC_CLI_OK); +} + diff --git a/dlep_radio_ipv6/cli.h b/dlep_radio_ipv6/cli.h new file mode 100644 index 0000000..62ffb92 --- /dev/null +++ b/dlep_radio_ipv6/cli.h @@ -0,0 +1,148 @@ +/*------------------------------------------------------------------ + * cli.h -- embedded command line interpreter + * + * Copyright (C) 2009 by B. Berry + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __CLI_H__ +#define __CLI_H__ + +#include + +/* + * Public directories that applications can register with. + * Enable define for these root directories. Once defined, + * apps can register in this directory structure. If not, + * applications register to the root directory. + */ +#define CLI_ROOT_DIRS ( 1 ) + + +/* + * This is the maximum number of parameters that can be passed + * to the application function. The parameters are passed to + * the application in the argument count and argument value + * format. + */ +#define ARGC_MAX ( 11 ) + + +/* + * Number of characters in an entry's name, for directories + * and commands + */ +#define CLI_ENTRY_LEN ( 34 ) + + +/* + * return codes + */ +typedef enum { + RC_CLI_OK = 0, + RC_CLI_NULL_NAME, + RC_CLI_NULL_FV, + RC_CLI_DUPLICATE, + RC_CLI_RECORD_CORRUPT, + RC_CLI_NULL_CMD, + RC_CLI_DIR_INVALID, +} RC_CLI_t; + + + +/* + * type def for call back function to process user command parsers + */ +typedef void (*cli_funcvar_t)(uint32_t argc, char *argv[]); + + +/* + * The structure for a directory or command entry. + */ +typedef struct t_nodal_record { + struct t_nodal_record *cmd_list; + char name[CLI_ENTRY_LEN+1]; + cli_funcvar_t fv; + struct t_nodal_record *parent_dir; + struct t_nodal_record *next_entry; + struct t_nodal_record *link2subdir; +} cli_record_t; + + + +/* + * A few common root command directories + * if enabled. + */ +#ifdef CLI_ROOT_DIRS +extern cli_record_t cli_config_dir; +extern cli_record_t cli_show_dir; +extern cli_record_t cli_clear_dir; +//extern cli_record_t cli_operation_dir; +extern cli_record_t cli_debug_dir; +extern cli_record_t cli_test_dir; +#endif + + +/* + * The structure required to initialize the CLI facility. + * It must be initialized before use. + */ +typedef struct { + char prefix[CLI_ENTRY_LEN]; +} cli_init_data_t; + + + +/* + * prototypes + */ + +/* add a command */ +extern RC_CLI_t cli_mkcmd(char *name, + cli_funcvar_t fv, + cli_record_t *dir_rec, + cli_record_t *cmd_rec); + + +/* make a directory */ +extern RC_CLI_t cli_mkdir(char *name, + cli_record_t *dir_rec, + cli_record_t *sub_dir); + + +/* drive the cli */ +extern void cli_engine(char *input_string); + + +/* set the prompt string */ +void cli_set_prompt(char *prompt); + + +/* init function */ +extern RC_CLI_t cli_init(cli_init_data_t *init_data); + +#endif /* __CLI_H__ */ + diff --git a/dlep_radio_ipv6/config_examples/ipv6_radio1.cfg b/dlep_radio_ipv6/config_examples/ipv6_radio1.cfg new file mode 100644 index 0000000..dad4baf --- /dev/null +++ b/dlep_radio_ipv6/config_examples/ipv6_radio1.cfg @@ -0,0 +1,60 @@ +# +# DLEP Sim Radio Config File +# +SIM_NAME ipv6_radio1 + +DEBUG_FLAGS 0xFF +#DEBUG_FLAGS 0x00 + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +MANUAL_START +#DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_Sim_1 + +LOCAL_UDP_PORT 854 +LOCAL_TCP_PORT 11115 +LOCAL_IPV6 3000:1:1:1:1:1:1:1111 + +#Server pot values +ROUTER_UDP_PORT 11116 +ROUTER_TCP_PORT 11117 +ROUTER_IPV6 3000:1:1:1:1:1:1:1112 + +LOCAL_ID 1111 + + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 1000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 1000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# diff --git a/dlep_radio_ipv6/config_examples/ipv6_radio2.cfg b/dlep_radio_ipv6/config_examples/ipv6_radio2.cfg new file mode 100644 index 0000000..93fb51d --- /dev/null +++ b/dlep_radio_ipv6/config_examples/ipv6_radio2.cfg @@ -0,0 +1,60 @@ +# +# DLEP Sim Radio Config File +# +SIM_NAME ipv6_radio1 + +DEBUG_FLAGS 0xFF +#DEBUG_FLAGS 0x00 + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +MANUAL_START +#DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_Sim_1 + +LOCAL_UDP_PORT 854 +LOCAL_TCP_PORT 11125 +LOCAL_IPV6 3000:1:1:1:1:1:1:1111 + +#Server pot values +ROUTER_UDP_PORT 11126 +ROUTER_TCP_PORT 11127 +ROUTER_IPV6 3000:1:1:1:1:1:1:1113 + +LOCAL_ID 1111 + + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 1000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 1000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# diff --git a/dlep_radio_ipv6/config_examples/my_radio_discovery.cfg b/dlep_radio_ipv6/config_examples/my_radio_discovery.cfg new file mode 100644 index 0000000..8aaaa0a --- /dev/null +++ b/dlep_radio_ipv6/config_examples/my_radio_discovery.cfg @@ -0,0 +1,60 @@ +# +# DLEP Sim Radio Config File +# +SIM_NAME radio_2 + +#DEBUG_FLAGS 0xFF + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +#MANUAL_START +DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_Sim_2 + +LOCAL_UDP_PORT 38681 +LOCAL_TCP_PORT 38682 +LOCAL_IPV4 9.0.0.179 + +ROUTER_UDP_PORT 38677 + +ROUTER_TCP_PORT 38675 +ROUTER_IPV4 9.1.1.201 + +LOCAL_ID 2222 + + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 1000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 1000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# + diff --git a/dlep_radio_ipv6/config_examples/my_radio_discovery_2.cfg b/dlep_radio_ipv6/config_examples/my_radio_discovery_2.cfg new file mode 100644 index 0000000..f70d272 --- /dev/null +++ b/dlep_radio_ipv6/config_examples/my_radio_discovery_2.cfg @@ -0,0 +1,60 @@ +# +# DLEP Sim Radio Config File +# +SIM_NAME radio_2 + +DEBUG_FLAGS 0xFF + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +#MANUAL_START +DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_Sim_2 + +LOCAL_UDP_PORT 38700 +LOCAL_TCP_PORT 38710 +LOCAL_IPV4 20.1.1.4 + +ROUTER_UDP_PORT 38777 + +ROUTER_TCP_PORT 38775 +ROUTER_IPV4 9.1.1.202 + +LOCAL_ID 2222 + + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 1000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 1000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# + diff --git a/dlep_radio_ipv6/config_examples/uut.cfg b/dlep_radio_ipv6/config_examples/uut.cfg new file mode 100644 index 0000000..a6eb58e --- /dev/null +++ b/dlep_radio_ipv6/config_examples/uut.cfg @@ -0,0 +1,60 @@ +# +# DLEP Sim Radio Config File +# +SIM_NAME ipv6_radio1 + +DEBUG_FLAGS 0xFF +#DEBUG_FLAGS 0x00 + +# When the MANUAL_START is enabled, the user +# will need to enter "start" on the simulator +# cli to start the simulator. +MANUAL_START +#DISCOVERY_START + +# string for the peer type TLV +TYPE_DESCRIPTION DLEP_Radio_Sim_1 + +LOCAL_UDP_PORT 854 +LOCAL_TCP_PORT 11115 +LOCAL_IPV6 3000:1:1:1:1:1:1:1111 + +#Server pot values +ROUTER_UDP_PORT 11116 +ROUTER_TCP_PORT 11117 +ROUTER_IPV6 3000:1:1:1:1:1:1:1112 + +LOCAL_ID 1111 + + +### +### Add counters and timers and thresholds +### + +# The node heartbeat interval is only used by the client. The +# server takes the clients value. Time units are seconds. +DLEP_PEER_HEARTBEAT_INTERVAL 5 +DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD 2 + + +# The heuristics to retry a lost session init ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_UP_ACK_TMO 1000 +DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD 4 + + +# The interval to send metrics. +# Time units are in milliseconds. +#DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 2000 +DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO 0 + + +# The heuristics to retry a lost session term ack. +# Time units are in milliseconds. +DLEP_NEIGHBOR_DOWN_ACK_TMO 1000 +DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD 4 + +# +# end config +# + diff --git a/dlep_radio_ipv6/dlep_buffers.c b/dlep_radio_ipv6/dlep_buffers.c new file mode 100644 index 0000000..620e263 --- /dev/null +++ b/dlep_radio_ipv6/dlep_buffers.c @@ -0,0 +1,144 @@ +/*---------------------------------------------------------------------- + * dlep_buffers.c -- abstracted buffer routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include + +#include "safe_types.h" +#include "dlep_debug.h" + +#include "dlep_buffers.h" + +/* + * Porting: The implementation of the functions in this file can be + * changed to platform specific buffer management APIs. + */ + + +#define MAX_BUFFER_SIZE ( 1400 ) + + +/** + * NAME + * dlep_allocate_transmit_buffer + * + * SYNOPSIS + * uint8_t + * *dlep_allocate_transmit_buffer(void) + * + * DESCRIPTION + * This function is used to allocate a buffer for transmit + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * Pointer to a buffer or NULL if no buffer is available. + * + */ +uint8_t +*dlep_allocate_transmit_buffer (void) +{ +printf("dlep_allocate_transmit_buffer\n"); + void *ptr; + + ptr = malloc(MAX_BUFFER_SIZE); + return (ptr); +} + + +/** + * NAME + * dlep_allocate_receive_buffer + * + * SYNOPSIS + * uint8_t + * *dlep_allocate_receive_buffer(void) + * + * DESCRIPTION + * This function is used to allocate a receive buffer + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * Pointer to a buffer or NULL if no buffer is available. + * + */ +uint8_t +*dlep_allocate_receive_buffer (void) +{ +printf("dlep_allocate_receive_buffer\n"); + void *ptr; + + ptr = malloc(MAX_BUFFER_SIZE); + return (ptr); +} + + +/** + * NAME + * dlep_free_buffer + * + * SYNOPSIS + * void + * *dlep_free_buffer(void) + * + * DESCRIPTION + * This routine frees a previously allocated (transmit and + * receive) buffer. + * + * INPUT PARAMETERS + * ptr - This is a pointer to the buffer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_free_buffer (void *ptr) +{ +printf("dlep_free_buffer\n"); + if (ptr) { + free(ptr); + } + return; +} + diff --git a/dlep_radio_ipv6/dlep_buffers.h b/dlep_radio_ipv6/dlep_buffers.h new file mode 100644 index 0000000..f868081 --- /dev/null +++ b/dlep_radio_ipv6/dlep_buffers.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------- + * dlep_buffers.h -- abstracted buffer routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_BUFFERS_H__ +#define __DLEP_BUFFERS_H__ + +#include "safe_types.h" + + +extern uint8_t +*dlep_allocate_transmit_buffer(void); + +extern uint8_t +*dlep_allocate_receive_buffer(void); + +extern void +dlep_free_buffer(void *ptr); + +#endif + diff --git a/dlep_radio_ipv6/dlep_client_message_parser.c b/dlep_radio_ipv6/dlep_client_message_parser.c new file mode 100644 index 0000000..3392051 --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_message_parser.c @@ -0,0 +1,379 @@ +/*---------------------------------------------------------------------- + * dlep_client_message_parser.c -- client message parsing routine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" + +#include "dlep_client_message_parser.h" + +void +rfc5444_show_signal_scratch_pad ( + rfc5444_message_scratch_pad_t *msg_scratch_pad) +{ +printf("rfc5444_show_signal_scratch_pad\n"); + char *p2text; + + if (!msg_scratch_pad) { + return; + } + + switch (msg_scratch_pad->message_code) { + case RFC5444_SIG_ATT_PEER_DISCOVERY: + p2text = "RFC5444_SIG_ATT_PEER_DISCOVERY"; + break; + + case RFC5444_SIG_PEER_OFFER: + p2text = "RFC5444_SIG_PEER_OFFER"; + break; + } + + + printf("Signal Scratch Pad \n"); + + printf(" signal code=%u %s \n", + msg_scratch_pad->message_code, + p2text); +} + +/** + * NAME + * dlep_client_message_parser + * + * SYNOPSIS + * void + * dlep_client_message_parser(uint16_t message_code, + * uint16_t sequence_number, + * void *context_ptr) + * + * DESCRIPTION + * This function is used by the client application to handle the + * initial parse of a DLEP message. Only the valid set of DLEP + * messages expected by the client are processed. + * + * INPUT PARAMETERS + * message_code - This is the message code representing the + * message to be parsed. + * + * sequence_number - The sequence number of the message + * + * context_ptr - The pointer to the message scratch pad + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_client_message_parser (uint16_t message_code, + uint16_t sequence_number, + void *context_ptr, int signal) +{ +printf("dlep_client_message_parser\n"); + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *scratch_pad; + dlep_context_neighbor_t *p2neighbor; + + p2peer = context_ptr; + if (!p2peer) { + return; + } + + p2peer->status_code = RFC5444_SUCCESS; + + scratch_pad = &p2peer->message_scratch_pad; + + scratch_pad->message_code = message_code; + + scratch_pad->sequence = sequence_number; + scratch_pad->sequence_present = TRUE; + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + if (signal) { + rfc5444_show_signal_scratch_pad(scratch_pad); + } else { + rfc5444_show_message_scratch_pad(scratch_pad); + } + } + + /* + * now drive the state machine by the message type + */ + + if (signal) { + switch (message_code) { + + case RFC5444_SIG_ATT_PEER_DISCOVERY: + dlep_client_fsm_engine(peer_att_discovery_e, p2peer, NULL); + break; + /* this signal client does not receive */ + case RFC5444_SIG_PEER_OFFER: + dlep_client_fsm_engine(peer_offer_e, p2peer, NULL); + DLEP_DEBUG("%s-%u DLEP unexpected signal, signal_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + break; + default: + DLEP_DEBUG("%s-%u DLEP unknown signal, signal_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + break; + } + } + else { + switch (message_code) { + + case RFC5444_MSG_PEER_INIT_REQ: + dlep_client_fsm_engine(peer_init_request_e, p2peer, NULL); + break; + + case RFC5444_MSG_PEER_HEARTBEAT: + dlep_client_fsm_engine(peer_heartbeat_e, p2peer, NULL); + break; + + case RFC5444_MSG_PEER_UPDATE_REQ: + dlep_client_fsm_engine(peer_update_request_e, p2peer, NULL); + break; + + case RFC5444_MSG_PEER_UPDATE_RES: + dlep_client_fsm_engine(peer_update_response_e,p2peer, NULL); + break; + + case RFC5444_MSG_PEER_TERM_REQ: + dlep_client_fsm_engine(peer_term_request_e, p2peer, NULL); + break; + + case RFC5444_MSG_PEER_TERM_RES: + dlep_client_fsm_engine(peer_term_response_e, p2peer, NULL); + break; + + case RFC5444_MSG_NEIGHBOR_UP_RES: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_init_ack_e, + p2peer, p2neighbor); + } + break; + + case RFC5444_MSG_NEIGHBOR_METRICS: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + printf("\nRFC5444_MSG_NEIGHBOR_METRICS: Received with ERROR"); + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + printf("\nRFC5444_MSG_NEIGHBOR_METRICS: Received "); + dlep_client_neighbor_fsm_engine(neighbor_update_ack_e, + p2peer, p2neighbor); + } + break; + + case RFC5444_MSG_NEIGHBOR_ADDRESS_RES: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_update_addr_res_e, + p2peer, p2neighbor); + } + break; + + case RFC5444_MSG_NEIGHBOR_DOWN_REQ: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_term_e, + p2peer, p2neighbor); + } + break; + + case RFC5444_MSG_NEIGHBOR_DOWN_RES: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_term_ack_e, + p2peer, p2neighbor); + } + break; + + + case RFC5444_MSG_LINK_CHAR_REQ: + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, + scratch_pad->mac_address); + if (!p2neighbor) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + scratch_pad->mac_address[0], + scratch_pad->mac_address[1], + scratch_pad->mac_address[2], + scratch_pad->mac_address[3], + scratch_pad->mac_address[4], + scratch_pad->mac_address[5]); + } else { + dlep_client_neighbor_fsm_engine(neighbor_link_char_req_e, + p2peer, p2neighbor); + } + break; + + + /* messages that the client peer can not receive */ + case RFC5444_MSG_PEER_INIT_RES: + DLEP_DEBUG("%s-%u DLEP unexpected message, msg_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + printf("\nUnexpected message sending termination message\n"); + p2peer->status_code = RFC5444_MSG_UNEXPECTED; + send_dlep_peer_termination(p2peer); + break; + case RFC5444_MSG_NEIGHBOR_UP_REQ: + DLEP_DEBUG("%s-%u DLEP unexpected message, msg_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + printf("\nUnexpected message sending termination message\n"); + p2peer->status_code = RFC5444_MSG_UNEXPECTED; + send_dlep_peer_termination(p2peer); + break; + case RFC5444_MSG_LINK_CHAR_RES: + DLEP_DEBUG("%s-%u DLEP unexpected message, msg_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + printf("\nUnexpected message sending termination message\n"); + p2peer->status_code = RFC5444_MSG_UNEXPECTED; + send_dlep_peer_termination(p2peer); + break; + + default: + DLEP_DEBUG("%s-%u DLEP unknown message, msg_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + message_code); + printf("\nUnknown message sending termination message\n"); + p2peer->status_code = RFC5444_MSG_UNKNOWN; + send_dlep_peer_termination(p2peer); + break; + } + + } + rfc5444_scrub_message_scratch_pad(scratch_pad); + + return; +} + diff --git a/dlep_radio_ipv6/dlep_client_message_parser.h b/dlep_radio_ipv6/dlep_client_message_parser.h new file mode 100644 index 0000000..e3580f8 --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_message_parser.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------- + * dlep_client_message_parser.h -- Message parsing routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_MESSAGE_PARSER_H__ +#define __DLEP_CLIENT_MESSAGE_PARSER_H__ + +#include "safe_types.h" +#include "dlep_context_peer.h" + + +extern void +dlep_client_message_parser(uint16_t message_code, + uint16_t sequence_number, + void *context_ptr,int signal); + +#endif + diff --git a/dlep_radio_ipv6/dlep_client_metrics.c b/dlep_radio_ipv6/dlep_client_metrics.c new file mode 100644 index 0000000..12a1f1c --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_metrics.c @@ -0,0 +1,207 @@ +/*---------------------------------------------------------------------- + * dlep_client_metrics.c -- dynamic client metrics + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "safe_types.h" +#include "dlep_context_neighbor.h" + + +static int32_t metric_index = 0; +static int32_t metric_direction = 1; + + +/** + * NAME + * dlep_client_metrics + * + * SYNOPSIS + * void + * dlep_client_metrics(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to insert a dynamic nature to the + * metrics for test. + * + * INPUT PARAMETERS + * p2neighbor - pointer to the neighbor + * + * OUTPUT PARAMETERS + * p2neighbor - neighbor metrics updated + * + * RETURN VALUE + * none + * + */ +void +dlep_client_metrics (dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_client_metrics\n"); + if (!p2neighbor) { + return; + } + + /* + * could be more creative with file inputs + * or radio models. + */ + switch (metric_index) { + case 0: + p2neighbor->rlq_rx = 100; + p2neighbor->rlq_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_rx = 0; + p2neighbor->cdr_tx = 0; + p2neighbor->mdr_rx = 110000000; + p2neighbor->mdr_tx = 110000000; + break; + + case 1: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 11000000; + p2neighbor->cdr_rx = 11000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 2: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 22000000; + p2neighbor->cdr_rx = 22000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 3: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 33000000; + p2neighbor->cdr_rx = 33000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 4: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 44000000; + p2neighbor->cdr_rx = 44000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_tx = 110000000; + break; + + case 5: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 55000000; + p2neighbor->cdr_rx = 55000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 6: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 66000000; + p2neighbor->cdr_rx = 66000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 7: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 77000000; + p2neighbor->cdr_rx = 77000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 8: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 88000000; + p2neighbor->cdr_rx = 88000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + + case 9: + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources_tx = 100; + p2neighbor->resources_rx = 100; + p2neighbor->latency = 0; + p2neighbor->cdr_tx = 99000000; + p2neighbor->cdr_rx = 99000000; + p2neighbor->mdr_tx = 110000000; + p2neighbor->mdr_rx = 110000000; + break; + } + + if (metric_index >= 9) { + metric_direction = -1; + } else if (metric_index == 0) { + metric_direction = 1; + } + + metric_index += metric_direction; + return; +} + diff --git a/dlep_radio_ipv6/dlep_client_metrics.h b/dlep_radio_ipv6/dlep_client_metrics.h new file mode 100644 index 0000000..7efc8da --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_metrics.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------- + * dlep_client_metrics.h -- dynamic client metrics + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_METRICS_H__ +#define __DLEP_CLIENT_METRICS_H__ + +#include "safe_types.h" + + +extern void +dlep_client_metrics(dlep_context_neighbor_t *p2neighbor); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_client_neighbor_event_handlers.c b/dlep_radio_ipv6/dlep_client_neighbor_event_handlers.c new file mode 100644 index 0000000..08fcd4e --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_neighbor_event_handlers.c @@ -0,0 +1,1125 @@ +/*---------------------------------------------------------------------- + * dlep_client_neighbor_event_handlers.c -- client neighbor event handlers + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "safe_types.h" +#include "time_units.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_sim_options.h" +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_config.h" +#include "dlep_message_builder.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_timer.h" +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" + +#include "dlep_client_metrics.h" + +#include "dlep_client_neighbor_event_handlers.h" + + + +/** + * NAME + * initializing_neighbor_up_ack + * + * SYNOPSIS + * RC_FSM_t + * initializing_neighbor_up_ack(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor up ack message + * is received during the initializing state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +initializing_neighbor_up_ack (void *p2event, void *p2parm) +{ +printf("initializing_neighbor_up_ack\n"); + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (msg_scratch_pad->status_code_present) { + if (msg_scratch_pad->status_code == 0) { + //send_dlep_neighbor_up_ack(p2peer,p2neighbor); + //printf("\n SENT DLEP NEIGHBOR ACK \n"); + printf("success dest ack received\n"); + /* 0 is a success code */ + } else { + printf("Status code is not success\n"); + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u return code %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + msg_scratch_pad->status_code); + } + } + } + else { + printf("status tlv is mandatory , is not present \n"); + } + + +#if 0 + if (p2neighbor->expected_neighbor_init_ack_sequence != + msg_scratch_pad->sequence) { + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + "unexpected neighbor up ack \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor up ack rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + stw_system_timer_stop(&p2neighbor->neighbor_init_ack_tmr); + + /* + * conditionally start the periodic timer to generate metrics + */ + /* if (p2peer->neighbor_update_interval_tmo) { + (void)stw_system_timer_start(&p2neighbor->neighbor_update_interval_tmr, + p2peer->neighbor_update_interval_tmo, + p2peer->neighbor_update_interval_tmo, + &dlep_neighbor_metrics_interval_tmr, + (void *)p2neighbor); + } */ + + return (RC_FSM_OK); +} + + +/** + * NAME + * initializing_neighbor_up_ack_tmo + * + * SYNOPSIS + * RC_FSM_t + * initializing_neighbor_up_ack_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor up ack + * message was not received within the guard timer during + * the initializing state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESING + * + */ +RC_FSM_t +initializing_neighbor_up_ack_tmo (void *p2event, void *p2parm) +{ +printf("initializing_neighbor_up_ack_tmo\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } +// printf("\n INSIDE START initializing_neighbor_up_ack_tmo"); + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor->neighbor_up_ack_tmo_count++; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor up ack missed, count=%u threshold=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5], + p2neighbor->neighbor_up_ack_tmo_count, + p2peer->neighbor_up_missed_ack_threshold); + } + + if (p2neighbor->neighbor_up_ack_tmo_count >= + p2peer->neighbor_up_missed_ack_threshold) { +// printf("\n INSIDE neighbor_up_missed_ack_threshold "); + /* stop timers and clear context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + return (RC_FSM_STOP_PROCESSING); + } +// printf("\n EXIT initializing_neighbor_up_ack_tmo "); + //send_dlep_neighbor_up(p2peer, p2neighbor); + return (RC_FSM_OK); +} + + + +RC_FSM_t +initializing_neighbor_update_ack (void *p2event, void *p2parm) +{ +printf("initializing_neighbor_update_ack\n"); + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (msg_scratch_pad->cws_present) { + msg_scratch_pad->cws_present = FALSE; + p2neighbor->mrw = msg_scratch_pad->mrw; + printf("\n DLEP NEIGHBOR ACK : Credit Accepted " + "Client MRW %llu , Router MRW %llu \n", + p2neighbor->mrw, msg_scratch_pad->mrw); + // printf("\n DLEP NEIGHBOR ACK : Credit Not Matches : " + // "Client MRW %llu , Router MRW %llu \n", + // p2neighbor->mrw, msg_scratch_pad->mrw); + stw_system_timer_stop(&p2neighbor->neighbor_update_ack_tmr); + } else if (msg_scratch_pad->credit_req_present) { + msg_scratch_pad->credit_req_present = FALSE; + if (p2neighbor->CREDIT_NOT_SUPPORTED) { + send_dlep_neighbor_credit_reject(p2peer, p2neighbor); + } else { + p2neighbor->cgr = 65534; + send_dlep_neighbor_credit_grant_req(p2peer, p2neighbor); + } + } else if (msg_scratch_pad->status_code_present) { + msg_scratch_pad->status_code_present = FALSE; + if (msg_scratch_pad->status_code == 0) { + printf("\n DLEP NEIGHBOR ACK : Credit Not Supported \n"); + /* 0 is a success code */ + } else { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u return code %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + msg_scratch_pad->status_code); + } + } + stw_system_timer_stop(&p2neighbor->neighbor_update_ack_tmr); + } else { + printf("\n DLEP NEIGHBOR ACK : Unknown TLV received \n"); + } + + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor up ack rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + +// stw_system_timer_stop(&p2neighbor->neighbor_update_ack_tmr); + + + return (RC_FSM_OK); +} + + +/** + * NAME + * initializing_neighbor_update_ack_tmo + * + * SYNOPSIS + * RC_FSM_t + * initializing_neighbor_update_ack_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor update ack + * message was not received within the guard timer during + * the update state. This is currently used only for Credit Grant + * Request. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESING + * + */ +RC_FSM_t +initializing_neighbor_update_ack_tmo (void *p2event, void *p2parm) +{ +printf("initializing_neighbor_update_ack_tmo\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } +// printf("\n INSIDE START initializing_neighbor_up_ack_tmo"); + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor->neighbor_update_ack_tmo_count++; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor up ack missed, count=%u threshold=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5], + p2neighbor->neighbor_update_ack_tmo_count, + p2peer->neighbor_up_missed_ack_threshold); + } + + /* Leveraging the same threshold of Neighbor up */ + if (p2neighbor->neighbor_update_ack_tmo_count >= + p2peer->neighbor_up_missed_ack_threshold) { +// printf("\n INSIDE neighbor_up_missed_ack_threshold "); + /* stop timers and clear context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + return (RC_FSM_STOP_PROCESSING); + } +// printf("\n EXIT initializing_neighbor_up_ack_tmo "); + send_dlep_neighbor_credit_grant_req(p2peer, p2neighbor); + return (RC_FSM_OK); +} + + +/** + * NAME + * update_neighbor_update_interval + * + * SYNOPSIS + * RC_FSM_t + * update_neighbor_update_interval(void *p2event, void *p2parm) + * + * DESCRIPTION + * The event handler is invoked when the neighbor update interval + * timer has expired indicating that it is time to send + * neighbor metrics. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + */ +RC_FSM_t +update_neighbor_update_interval (void *p2event, void *p2parm) +{ +printf("update_neighbor_update_interval\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + /* dynamically tweak metrics for testing */ +#ifdef DYNAMIC_METRICS_ENABLED + dlep_client_metrics(p2neighbor); +#endif + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + return (RC_FSM_OK); +} + + +/** + * NAME + * update_neighbor_update_address_response + * + * SYNOPSIS + * RC_FSM_t + * update_neighbor_update_address_response(void *p2event, void *p2parm) + * + * DESCRIPTION + * The event handler is invoked when the neighbor update address + * response was received. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + */ +RC_FSM_t +update_neighbor_update_address_response (void *p2event, void *p2parm) +{ +printf("update_neighbor_update_address_response\n"); + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor address response rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + return (RC_FSM_OK); +} + + +/** + * NAME + * update_neighbor_down_request + * + * SYNOPSIS + * RC_FSM_t + * update_neighbor_down_request(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked upon user or system request to + * terminate the neighbor. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +update_neighbor_down_request (void *p2event, void *p2parm) +{ +printf("update_neighbor_down_request\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " user-system neighbor down request \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + stw_system_timer_stop(&p2neighbor->neighbor_update_interval_tmr); + + send_dlep_neighbor_down(p2peer, p2neighbor); + + /* + * conditionally start the periodic timer to guard against + * lost term acks + */ + if (p2peer->neighbor_down_ack_tmo) { + (void)stw_system_timer_start(&p2neighbor->neighbor_term_ack_tmr, + p2peer->neighbor_down_ack_tmo, + p2peer->neighbor_down_ack_tmo, + &dlep_neighbor_term_ack_tmr, + (void *)p2neighbor); + } + + return (RC_FSM_OK); +} + + +/** + * NAME + * update_neighbor_down + * + * SYNOPSIS + * RC_FSM_t + * update_neighbor_down(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor down + * message is received during the synchronized state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_STOP_PROCESING + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +update_neighbor_down (void *p2event, void *p2parm) +{ +printf("update_neighbor_down\n"); + RC_FSM_t rc_fsm; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor down rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + send_dlep_neighbor_down_ack(p2peer, p2neighbor); + + /* stop timers and clear context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + rc_fsm = RC_FSM_STOP_PROCESSING; + return (rc_fsm); +} + + +/** + * NAME + * update_link_char_request + * + * SYNOPSIS + * RC_FSM_t + * update_link_char_request(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the link characteristic + * request is received during the synchronized state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * p2neighbor->cdr = msg_scratch_pad->cdr; + * p2neighbor->latency = msg_scratch_pad->latency; + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_STOP_PROCESING + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +update_link_char_request (void *p2event, void *p2parm) +{ +printf("update_link_char_request\n"); + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " link char request \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + p2neighbor->cdr_tx = msg_scratch_pad->cdr_tx; + + p2neighbor->latency = msg_scratch_pad->latency; + + send_dlep_neighbor_link_char_response(p2peer, p2neighbor); + + return (RC_FSM_OK); +} + + + +/** + * NAME + * terminating_neighbor_down_ack + * + * SYNOPSIS + * RC_FSM_t + * terminating_neighbor_down_ack(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor down + * ack is received during the terminating state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_STOP_PROCESSING + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +terminating_neighbor_down_ack (void *p2event, void *p2parm) +{ +printf("terminating_neighbor_down_ack\n"); + RC_FSM_t rc_fsm; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + if (p2neighbor->expected_neighbor_link_char_response_sequence != + msg_scratch_pad->sequence) { + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " unexpected neighbor down ack \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u " + "mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor down ack \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5]); + } + + /* stop timers and clear context */ + stw_system_timer_stop(&p2neighbor->neighbor_term_ack_tmr); + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + rc_fsm = RC_FSM_STOP_PROCESSING; + return (rc_fsm); +} + + +/** + * NAME + * terminating_neighbor_down_ack_tmo + * + * SYNOPSIS + * RC_FSM_t + * terminating_neighbor_down_ack_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the neighbor down + * ack was not received within the guard timer during the + * terminating state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - This is a pointer to the neighbor context which is set prior + * to invoking the state machine. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESSING + * + */ +RC_FSM_t +terminating_neighbor_down_ack_tmo (void *p2event, void *p2parm) +{ +printf("terminating_neighbor_down_ack_tmo\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor = p2parm; + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u neighbor " + "does not exist \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + p2neighbor->neighbor_down_ack_tmo_count++; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u mac=%02x:%02x:%02x:%02x:%02x:%02x \n" + " neighbor down ack missed, count=%u threshold=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2neighbor->mac_address[0], p2neighbor->mac_address[1], + p2neighbor->mac_address[2], p2neighbor->mac_address[3], + p2neighbor->mac_address[4], p2neighbor->mac_address[5], + p2neighbor->neighbor_down_ack_tmo_count, + p2peer->neighbor_down_missed_ack_threshold); + } + + if (p2neighbor->neighbor_down_ack_tmo_count >= + p2peer->neighbor_down_missed_ack_threshold) { + /* stop timers and clear context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + return (RC_FSM_STOP_PROCESSING); + } + + //send_dlep_neighbor_down(p2peer, p2neighbor); + return (RC_FSM_OK); +} + + diff --git a/dlep_radio_ipv6/dlep_client_neighbor_event_handlers.h b/dlep_radio_ipv6/dlep_client_neighbor_event_handlers.h new file mode 100644 index 0000000..678509b --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_neighbor_event_handlers.h @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------- + * dlep_client_neighbor_event_handlers.h -- client neighbor state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reseved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_SESSION_EVENT_HANDLERS_H__ +#define __DLEP_CLIENT_SESSION_EVENT_HANDLERS_H__ + +#include "safe_types.h" +#include "fsm.h" + + + +extern RC_FSM_t +initializing_neighbor_up_ack(void *p2event, void *p2parm); + +extern RC_FSM_t +initializing_neighbor_up_ack_tmo(void *p2event, void *p2parm); + +extern RC_FSM_t +initializing_neighbor_update_ack(void *p2event, void *p2parm); + +extern RC_FSM_t +initializing_neighbor_update_ack_tmo(void *p2event, void *p2parm); + +extern RC_FSM_t +update_neighbor_update_interval(void *p2event, void *p2parm); + +extern RC_FSM_t +update_neighbor_update_address_response(void *p2event, void *p2parm); + +extern RC_FSM_t +update_neighbor_down_request(void *p2event, void *p2parm); + +extern RC_FSM_t +update_neighbor_down(void *p2event, void *p2parm); + +extern RC_FSM_t +update_link_char_request(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_neighbor_down_ack(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_neighbor_down_ack_tmo(void *p2event, void *p2parm); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_client_neighbor_fsm.c b/dlep_radio_ipv6/dlep_client_neighbor_fsm.c new file mode 100644 index 0000000..35fa8fb --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_neighbor_fsm.c @@ -0,0 +1,498 @@ +/*---------------------------------------------------------------------- + * dlep_client_neighbor_fsm.c -- client neighbor state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "fsm.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_neighbor_event_handlers.h" +#include "dlep_client_timer.h" + +#include "dlep_client_neighbor_fsm.h" + + + +/* + * normalized client neighbor event description + */ +static event_description_t normalized_event_table[] = + {{neighbor_init_ack_e, "Neighbor Up ACK Event"}, + {neighbor_up_ack_tmo_e, "Neighbor Up ACK TMO Event"}, + {neighbor_update_metrics_interval_e, "Internal Metrics Event"}, + {neighbor_update_ack_e, "Neighbor Update ACK Event"}, + {neighbor_update_ack_tmo_e, "Neighbor Update ACK TMO Event"}, + {neighbor_update_addr_res_e, "Neighbor Update Address Response Event"}, + {neighbor_term_user_req_e, "Neighbor Down User Request Event"}, + {neighbor_term_e, "Neighbor Down Recieved Event"}, + {neighbor_term_ack_e, "Neighbor Down ACK Event"}, + {neighbor_down_ack_tmo_e, "Neighbor Down ACK TMO Event"}, + {neighbor_link_char_req_e, "Neighbor Link Char Request Event"}, + {FSM_NULL_EVENT_ID, NULL} }; + + +/* + * normalized neighbor state description + */ +static state_description_t normalized_state_table[] = + {{neighbor_initializing_s, "Initializing` State"}, + {neighbor_update_s, "Update State"}, + {neighbor_terminating_s, "Terminating State"}, + {FSM_NULL_STATE_ID, NULL} }; + + +/* + * catch-all to ignore events + */ +static RC_FSM_t event_ignore (void *p2event, void *p2parm) +{ +printf("RC_FSM_t event_ignore\n"); + dlep_context_peer_t *p2peer; + p2peer = p2event; + + if (p2peer) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u event ignored \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + } else { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u event ignored! \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + } + return (RC_FSM_IGNORE_EVENT); +} + + +/* + * State event tables + */ +static event_tuple_t state_initializing_events[] = + {{neighbor_init_ack_e, + initializing_neighbor_up_ack, neighbor_update_s}, + {neighbor_up_ack_tmo_e, + initializing_neighbor_up_ack_tmo, neighbor_initializing_s}, + {neighbor_update_metrics_interval_e, + event_ignore, neighbor_initializing_s}, + {neighbor_update_ack_e, + event_ignore, neighbor_initializing_s}, + {neighbor_update_ack_tmo_e, + event_ignore, neighbor_initializing_s}, + {neighbor_update_addr_res_e, + event_ignore, neighbor_initializing_s}, + {neighbor_term_user_req_e, + event_ignore, neighbor_initializing_s}, + {neighbor_term_e, + event_ignore, neighbor_initializing_s}, + {neighbor_term_ack_e, + event_ignore, neighbor_initializing_s}, + {neighbor_down_ack_tmo_e, + event_ignore, neighbor_initializing_s}, + {neighbor_link_char_req_e, + event_ignore, neighbor_initializing_s}}; + + +static event_tuple_t state_update_events[] = + {{neighbor_init_ack_e, + event_ignore, neighbor_update_s}, + {neighbor_up_ack_tmo_e, + event_ignore, neighbor_update_s}, + {neighbor_update_metrics_interval_e, + update_neighbor_update_interval, neighbor_update_s}, + {neighbor_update_ack_e, + initializing_neighbor_update_ack, neighbor_update_s}, + {neighbor_update_ack_tmo_e, + initializing_neighbor_update_ack_tmo, neighbor_update_s}, + {neighbor_update_addr_res_e, + update_neighbor_update_address_response, neighbor_update_s}, + {neighbor_term_user_req_e, + update_neighbor_down_request, neighbor_terminating_s}, + {neighbor_term_e, + update_neighbor_down, neighbor_terminating_s}, + {neighbor_term_ack_e, + event_ignore, neighbor_update_s}, + {neighbor_down_ack_tmo_e, + event_ignore, neighbor_update_s}, + {neighbor_link_char_req_e, + update_link_char_request, neighbor_update_s}}; + + +static event_tuple_t state_terminating_events[] = + {{neighbor_init_ack_e, + event_ignore, neighbor_terminating_s}, + {neighbor_up_ack_tmo_e, + event_ignore, neighbor_terminating_s}, + {neighbor_update_metrics_interval_e, + event_ignore, neighbor_terminating_s}, + {neighbor_update_ack_e, + event_ignore, neighbor_terminating_s}, + {neighbor_update_ack_tmo_e, + event_ignore, neighbor_terminating_s}, + {neighbor_update_addr_res_e, + event_ignore, neighbor_terminating_s}, + {neighbor_term_user_req_e, + event_ignore, neighbor_terminating_s}, + {neighbor_term_e, + event_ignore, neighbor_terminating_s}, + {neighbor_term_ack_e, + terminating_neighbor_down_ack, neighbor_terminating_s}, + {neighbor_down_ack_tmo_e, + terminating_neighbor_down_ack_tmo, neighbor_terminating_s}, + {neighbor_link_char_req_e, + event_ignore, neighbor_terminating_s}}; + + + +/* + * neighbor state table + */ +static state_tuple_t dlep_neighbor_state_table[] = + {{neighbor_initializing_s, state_initializing_events}, + {neighbor_update_s, state_update_events}, + {neighbor_terminating_s, state_terminating_events}, + {FSM_NULL_STATE_ID, NULL} }; + + +/** + * NAME + * dlep_client_neighbor_fsm_get_state + * + * SYNOPSIS + * uint32_t + * dlep_client_neighbor_fsm_get_state( + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to return the current state + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * current state + * FSM_NULL_STATE_ID if there is an error. + * + */ +uint32_t +dlep_client_neighbor_fsm_get_state (dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_client_neighbor_fsm_get_state\n"); + uint32_t state; + + state = FSM_NULL_STATE_ID; + + if (p2neighbor) { + fsm_get_state(p2neighbor->neighbor_fsm_handle, &state); + } else { + /* ignore */ + } + return (state); +} + + +/** + * NAME + * dlep_client_neighbor_fsm_show_state_table + * + * SYNOPSIS + * void + * dlep_client_neighbor_fsm_show_state_table( + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to display the state machine table + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_client_neighbor_fsm_show_state_table ( + dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_client_neighbor_fsm_show_state_table\n"); + if (p2neighbor) { + fsm_display_table(p2neighbor->neighbor_fsm_handle); + } else { + /* ignore */ + } + return; +} + + +/** + * NAME + * dlep_client_neighbor_fsm_show_history + * + * SYNOPSIS + * void + * dlep_client_neighbor_fsm_show_history( + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to display the state machine history + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_client_neighbor_fsm_show_history (dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_client_neighbor_fsm_show_history\n"); + if (p2neighbor) { + fsm_show_history(p2neighbor->neighbor_fsm_handle); + } else { + /* ignore */ + } + return; +} + + +/** + * NAME + * dlep_client_neighbor_fsm_engine + * + * SYNOPSIS + * void + * dlep_client_neighbor_fsm_engine(uint32_t normalized_event, + * dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to process the state machine normalized + * events. + * + * INPUT PARAMETERS + * normalized_event - This is the state machine event to process. + * + * p2peer - This is a pointer to the peer context. + * + * p2neighbor - This is a pointer to the neighbor context. This is + * NULL for peer specific events. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESSING This indicates that the state machine + * is to be terminated and resources released. + * error otherwise + * + */ +void +dlep_client_neighbor_fsm_engine (uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_client_neighbor_fsm_engine\n"); + RC_FSM_t rc; + +// printf("\n INSIDE dlep_client_neighbor_fsm_engine "); + if (!p2peer) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer context is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return; + } + + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: neighbor context is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return; + } + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u normalized_event=%u peer_id=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + normalized_event, + p2peer->peer_id); + } + + rc = fsm_engine(p2neighbor->neighbor_fsm_handle, + normalized_event, + p2peer, + p2neighbor); + + if (rc == RC_FSM_STOP_PROCESSING) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u stopped \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + /* cancel all neighbor timers and context */ + dlep_neighbor_clear(p2neighbor); + dlep_neighbor_remove(p2peer, &p2neighbor); + + } else if (rc == RC_FSM_IGNORE_EVENT) { + /* do nothing */ + } else if (rc != RC_FSM_OK) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u state machine rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + return; +} + + +/** + * NAME + * dlep_neighbor_fsm_destroy + * + * SYNOPSIS + * void + * dlep_neighbor_fsm_destroy(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to destroy the neighbor state machine. + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * p2neighbor - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_fsm_destroy (dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_neighbor_fsm_destroy\n"); + if (!p2neighbor) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: neighbor context is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + } else { + /* fsm_handle is nulled */ + fsm_destroy((fsm_t **)&p2neighbor->neighbor_fsm_handle); + } + return; +} + + +/** + * NAME + * dlep_neighbor_fsm_create + * + * SYNOPSIS + * void + * dlep_neighbor_fsm_create(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to create the neighbor state machine. + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context. + * + * OUTPUT PARAMETERS + * p2neighbor - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_fsm_create (dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_neighbor_fsm_create\n"); + RC_FSM_t rc; + + if (!p2neighbor) { + return; + } + + p2neighbor->neighbor_fsm_handle = NULL; + rc = fsm_create((fsm_t **)&p2neighbor->neighbor_fsm_handle, + "Session State Machine", + neighbor_initializing_s, + normalized_state_table, + normalized_event_table, + dlep_neighbor_state_table); + if (rc != RC_FSM_OK) { + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: neighbor local_id=%u state " + "machine rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2neighbor->local_id, + rc); + } + } + + return; +} + + diff --git a/dlep_radio_ipv6/dlep_client_neighbor_fsm.h b/dlep_radio_ipv6/dlep_client_neighbor_fsm.h new file mode 100644 index 0000000..e075c7a --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_neighbor_fsm.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------- + * dlep_client_neighbor_fsm.h -- client neighbor state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_SESSION_FSM_H__ +#define __DLEP_CLIENT_SESSION_FSM_H__ + +#include "safe_types.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_peer.h" + +/* + * normalized client events + */ +typedef enum { + neighbor_init_ack_e = 0, + neighbor_up_ack_tmo_e, + neighbor_update_metrics_interval_e, + neighbor_update_ack_e, + neighbor_update_ack_tmo_e, + neighbor_update_addr_res_e, + neighbor_term_user_req_e, + neighbor_term_e, + neighbor_term_ack_e, + neighbor_down_ack_tmo_e, + neighbor_link_char_req_e, +} dlep_client_neighbor_events_e; + + +/* + * normalized client states + */ +typedef enum { + neighbor_initializing_s = 0, + neighbor_update_s, + neighbor_terminating_s, +} dlep_client_neighbor_states_e; + + + + +extern uint32_t +dlep_client_neighbor_fsm_get_state( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_client_neighbor_fsm_show_counter( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_client_neighbor_fsm_show_state_table( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_client_neighbor_fsm_show_history( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_client_neighbor_fsm_engine(uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +dlep_neighbor_fsm_destroy(dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_neighbor_fsm_create(dlep_context_neighbor_t *p2neighbor); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_client_peer_event_handlers.c b/dlep_radio_ipv6/dlep_client_peer_event_handlers.c new file mode 100644 index 0000000..0a0013a --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_peer_event_handlers.c @@ -0,0 +1,1634 @@ +/*---------------------------------------------------------------------- + * dlep_client_peer_event_handlers.c -- client peer state event handlers + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include + +#include "safe_types.h" +#include "time_units.h" + +#include "rfc5444_utils.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_config.h" +#include "dlep_message_builder.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_timer.h" +#include "dlep_client_peer_fsm.h" + +#include "dlep_client_peer_event_handlers.h" + +extern int TCP_READY; +extern int init; +/** + * NAME + * discovery_start_init + * + * SYNOPSIS + * RC_FSM_t + * discovery_start_init(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the start event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTNPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +discovery_start_init (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; +#if 0 + send_dlep_attached_peer_discovery(p2peer); + + /*** start the peer offer guard timer ***/ + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); +#endif + return (RC_FSM_OK); +} + +/** + * NAME + * discovery_peer_attached_rcvd + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_attached_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer discovery event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +discovery_peer_attached_rcvd (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + p2peer = p2event; + dlep_config_t *p2config; + + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + msg_scratch_pad = &p2peer->message_scratch_pad; + + p2config = p2peer->p2config; + + /* To avoid discovery message from unconfigured router */ + if (p2config->router_udp_port != htons(p2config->client_udp.sin_port)) { + return (RC_FSM_IGNORE_EVENT); + } + + + /* + * optional: peer type string was null terminated in scratch + */ + strcpy(p2peer->peer_type_description, + msg_scratch_pad->peer_type_description); + + dlep_client_fsm_engine(peer_offer_e, p2peer, NULL); + return (RC_FSM_OK); +} + +#if 0 +/** + * NAME + * discovery_peer_offer_rcvd + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_offer_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer offer event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +discovery_peer_offer_rcvd (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } +// printf("\n PEER OFFER RECEIVED"); + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; +#if 0 + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + /* + * verify that this is the expected response + */ + if (msg_scratch_pad->sequence != + p2peer->expected_peer_offer_sequence) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sequence number miss-match, " + "expected %u-%u rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->expected_peer_offer_sequence, + msg_scratch_pad->sequence); + } + return (RC_FSM_IGNORE_EVENT); + } + + + /* optional */ + if (msg_scratch_pad->status_code_present) { + if (msg_scratch_pad->status_code == 0) { + /* 0 is a success code */ + } else { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u return code %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + msg_scratch_pad->status_code); + } + return (RC_FSM_IGNORE_EVENT); + } + } + + stw_system_timer_stop(&p2peer->peer_offer_tmr); + + /* save the router ID */ + p2peer->router_id = pkt_scratch_pad->router_id; + + + /* + * optional: peer type string was null terminated in scratch + */ + strcpy(p2peer->peer_type_description, + msg_scratch_pad->peer_type_description); + + /* start the peer hb timer if non-zero */ + if (p2peer->peer_heartbeat_interval) { + + printf("\n start peer_heartbeat timer"); + stw_system_timer_start(&p2peer->peer_heartbeat_tmr, + (p2peer->peer_heartbeat_interval), + (p2peer->peer_heartbeat_interval), + &dlep_peer_heartbeat_tmr, + (void *)p2peer->peer_id); + } + printf("\n calling peer_init"); + dlep_client_fsm_engine(peer_init_request_e, p2peer, NULL); + + return (RC_FSM_OK); +} + +#endif + +/** + * NAME + * discovery_peer_offer_tmo + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_offer_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer offer message + * was not received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +discovery_peer_offer_tmo (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2peer->peer_offer_timeout_count++; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u peer offer timer expiration " + "count %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->peer_offer_timeout_count); + } +// send_dlep_attached_peer_discovery(p2peer); + + /* reset the state */ + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + return (RC_FSM_OK); +} + + + +/** + * NAME + * discovery_peer_offer_start + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_init_start(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the start event is + * received during the discovery state. + * + * INPUT PARAMETERS + * NAME + * discovery_peer_offer_start + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_init_start(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the start event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTNPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +discovery_peer_offer_start (void *p2event, void *p2parm) +{ +// dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + +// p2config = p2peer->p2config; + +// send_dlep_peer_init(p2peer); + + send_dlep_peer_offer(p2peer); + return (RC_FSM_OK); +} + + +#if 0 +/** + * NAME + * discovery_peer_init_start + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_init_start(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the start event is + * received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTNPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +discovery_peer_init_start (void *p2event, void *p2parm) +{ +// dlep_config_t *p2config; + dlep_context_peer_t *p2peer; +// printf("\n SENDING send_dlep_peer_init "); + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + +// p2config = p2peer->p2config; + + send_dlep_peer_init(p2peer); + + + return (RC_FSM_OK); +} + +#endif + + + + + +/** + * NAME + * discovery_peer_init_ack_rcvd + * + * SYNOPSIS + * RC_FSM_t + * discovery_peer_init_ack_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer initialization + * response event is received during the discovery state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +discovery_peer_init_ack_rcvd (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +// printf("\n INSIDE discovery_peer_init_ack_rcvd"); +#if 0 + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + /* + * verify that this is the expected response + */ +#if 0 + if (msg_scratch_pad->sequence != + p2peer->expected_peer_offer_sequence) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sequence number miss-match, " + "expected %u-%u rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->expected_peer_offer_sequence, + msg_scratch_pad->sequence); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + /* mandatory */ + if (msg_scratch_pad->status_code_present) { + if (msg_scratch_pad->status_code == 0) { + /* 0 is a success code */ +// printf("\n PEER INIT ACK Received SUCCESS"); + } else { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u return code %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + msg_scratch_pad->status_code); + } + return (RC_FSM_IGNORE_EVENT); + } + } + + /* save the router ID */ + p2peer->router_id = pkt_scratch_pad->router_id; + + + /* + * optional: peer type string was null terminated in scratch + */ + strcpy(p2peer->peer_type_description, + msg_scratch_pad->peer_type_description); + + /* start the peer hb timer if non-zero */ + + if (p2peer->peer_heartbeat_interval) { + stw_system_timer_start(&p2peer->peer_heartbeat_tmr, + (p2peer->peer_heartbeat_interval), + (p2peer->peer_heartbeat_interval), + &dlep_peer_heartbeat_tmr, + (uint32_t *)p2peer->peer_id); + } + + return (RC_FSM_OK); +} + + + + + + +/* + * peer_init_rcvd + * + * SYNOPSIS + * RC_FSM_t + * initialization_peer_init_ack_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer initialization + * request event is received during the initialization state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +initialization_peer_init_rcvd (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + /* + * verify that this is the expected response + */ +#if 0 + if (msg_scratch_pad->sequence != + p2peer->expected_peer_offer_sequence) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sequence number miss-match, " + "expected %u-%u rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->expected_peer_offer_sequence, + msg_scratch_pad->sequence); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + p2peer->peer_heartbeat_interval = msg_scratch_pad->hbt; // ASL__ change + + strcpy(p2peer->peer_type_description, + msg_scratch_pad->peer_type_description); + + if (msg_scratch_pad->ipv4_address_present) { + p2peer->update_ipv4_operation = msg_scratch_pad->ipv4_operation; + p2peer->ipv4_address = msg_scratch_pad->ipv4_address; + p2peer->ipv4_attached_subnet = msg_scratch_pad->ipv4_attached_subnet; + } + + /* start the peer hb timer if non-zero */ + + if (p2peer->peer_heartbeat_interval) { + p2peer->peer_heartbeat_timeout_count = 0; + stw_system_timer_start(&p2peer->peer_heartbeat_tmr, + (p2peer->peer_heartbeat_interval), + (p2peer->peer_heartbeat_interval), + &dlep_peer_heartbeat_tmr, + (void *)p2peer->peer_id); + } + + if(init == 1) { + stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + + dlep_neighbor_deallocate_all(p2peer); + TCP_READY = 0; + + p2peer->peer_heartbeat_timeout_count = 0; + + send_dlep_peer_init_ack(p2peer); + + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + return (RC_FSM_OK); + } + + dlep_client_fsm_engine(peer_init_response_e, p2peer, NULL); + return (RC_FSM_OK); +} + + + /* NAME + * initialization_peer_init_ack_start + * + * SYNOPSIS + * RC_FSM_t + * initialization_peer_init_ack_start (void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked as response to the peer initialization + * request received in initialization state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +initialization_peer_init_ack_start (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + /* clear count */ + +// printf(" resting time out count"); + // p2peer->peer_heartbeat_timeout_count = 0; + + p2peer->status_code = RFC5444_SUCCESS; + send_dlep_peer_init_ack(p2peer); + rc = RC_FSM_OK; + +// send_peer_init_ack(p2peer); + return (rc); +} + + + + /* NAME + * in_session_peer_heartbeat_rcvd + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_heartbeat_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer heartbeat message + * is received during the in_session state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +in_session_peer_heartbeat_rcvd (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + printf("\n EXIT BEFOR clear counter in_session_peer_heartbeat_rcvd"); + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + /* clear count */ + +// printf(" resting time out count"); + p2peer->peer_heartbeat_timeout_count = 0; + return (RC_FSM_OK); +} + + +/** + * NAME + * in_session_peer_heartbeat_tmo + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_heartbeat_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer heartbeat message + * was not received within the guard timer during the in_session + * state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESSING + * + */ +RC_FSM_t +in_session_peer_heartbeat_tmo (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } + +#endif + p2peer->peer_heartbeat_timeout_count++; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u missed heartbeats %u " + "threshold=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->peer_heartbeat_timeout_count, + p2peer->peer_heartbeat_missed_threshold); + } + + if (p2peer->peer_heartbeat_timeout_count > + p2peer->peer_heartbeat_missed_threshold) { + stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + + dlep_neighbor_deallocate_all(p2peer); + TCP_READY = 0; + + p2peer->peer_heartbeat_timeout_count = 0; + send_dlep_peer_termination(p2peer); + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + rc = RC_FSM_OK; + + /* p2peer->status_code = RFC5444_MSG_TIMEOUT; + dlep_client_fsm_engine(user_peer_term_request_e, p2peer, NULL); + rc = RC_FSM_OK; */ + + } else { + send_dlep_peer_heartbeat(p2peer); + rc = RC_FSM_OK; + } + return (rc); +} + +/** + * NAME + * in_session_peer_update_request_rcvd + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_update_request_rcvd(void *p2event, + * void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer update request + * message is received during the in_session state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +in_session_peer_update_request_rcvd (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + + if (msg_scratch_pad->ipv4_address_present) { + p2peer->update_ipv4_operation = msg_scratch_pad->ipv4_operation; + p2peer->ipv4_address = msg_scratch_pad->ipv4_address; + p2peer->ipv4_attached_subnet = msg_scratch_pad->ipv4_attached_subnet; + } + + /* Reseting time out count */ + p2peer->peer_heartbeat_timeout_count = 0; + + send_dlep_peer_update_response(p2peer); + return (RC_FSM_OK); +} + + +/** + * NAME + * synchronized_peer_update_response_rcvd + * + * SYNOPSIS + * RC_FSM_t + * synchronized_peer_update_response_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * The event handler is invoked when the peer update response + * message has been received during the synchronized state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_IGNORE_EVENT + * + */ +RC_FSM_t +in_session_peer_update_response_rcvd (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u peer update rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + p2peer->status_code = msg_scratch_pad->status_code; + return (RC_FSM_OK); +} + + +/** + * NAME + * in_session_peer_term_request + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_term_request(void *p2event, void *p2parm) + * + * DESCRIPTION + * The event handler is invoked when the user or system issues + * a request to terminate the peer and all neighbors associated + * with the peer. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is + * set prior to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_OK + * + */ +RC_FSM_t +in_session_peer_term_request (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + //printf("\n in_session_peer_term_request calling send_peer_ter "); + dlep_neighbor_deallocate_all(p2peer); + + //p2peer->status_code = RFC5444_SUCCESS; + send_dlep_peer_termination(p2peer); + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + + /* start the peer term timer */ + stw_system_timer_start(&p2peer->peer_term_ack_tmr, + (4*p2peer->peer_heartbeat_interval), + (4*p2peer->peer_heartbeat_interval), + &dlep_peer_term_ack_tmr, + (void *)p2peer->peer_id); + + return (RC_FSM_OK); +} + +/** + * NAME + * in_session_peer_term_rcvd + * + * SYNOPSIS + * RC_FSM_t + * in_session_peer_term_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer terminate message + * is received during the in_session state. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_STOP_PROCESSING + * + */ +RC_FSM_t +in_session_peer_term_rcvd (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + p2peer->status_code = msg_scratch_pad->status_code; + + send_dlep_peer_termination_ack(p2peer); + + /* Reset the state *\ + fsm_set_exception_state(p2peer->fsm_handle, reset_s); + + /* cancel all timers and clear context */ + dlep_neighbor_deallocate_all(p2peer); + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + rc = stw_system_timer_stop(&p2peer->peer_term_ack_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + +#if 0 + /*** start the router offer guard timer ***/ + + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); +#endif + /* reset the state */ + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + + return (RC_FSM_OK); +} + + +/** + * NAME + * terminating_peer_term_ack_rcvd + * + * SYNOPSIS + * RC_FSM_t + * terminating_peer_term_ack_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer terminate + * ack is received during the terminating state. The neighbor + * are all terminated and cleaned and the peer state machine + * is stopped and removed. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_IGNORE_EVENT + * RC_FSM_STOP_PROCESSING which removes the state machine + * + */ +RC_FSM_t +terminating_peer_term_ack_rcvd (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + printf("\n peer_term ack rcvd \n"); + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->expected_peer_term_ack_sequence != + msg_scratch_pad->sequence) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u unexpected term ack \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + return (RC_FSM_IGNORE_EVENT); + } + } +#endif + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term ack rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + /* cancel all timers and clear context */ + dlep_neighbor_deallocate_all(p2peer); +// close(p2config->dlep_udp_sockfd); +// close(p2config->dlep_tcp_sockfd); + TCP_READY = 0; + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + rc = stw_system_timer_stop(&p2peer->peer_term_ack_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } +#if 0 + /*** start the router offer guard timer ***/ + + if (p2config->start_on_discovery) { + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); + } +// dlep_porter_open(p2config); +#endif + /* reset the state */ + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + + return (RC_FSM_OK); +} + + +/** + * NAME + * terminating_peer_term_ack_tmo + * + * SYNOPSIS + * RC_FSM_t + * terminating_peer_term_ack_tmo(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer terminate + * ack is not received dnd the guard timer expires. The neighbor + * are all terminated and cleaned and the peer state machine + * is stopped and removed. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_STOP_PROCESSING which removes the state machine + * + */ +RC_FSM_t +terminating_peer_term_ack_tmo (void *p2event, void *p2parm) +{ + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + + printf("\n terminating_peer_term_ack_tmo "); + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term ack timeout \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + + /* ignoring retry timers, just restart discovery */ + + /* cancel all timers and clear context */ + dlep_neighbor_deallocate_all(p2peer); +// close(p2config->dlep_udp_sockfd); +// close(p2config->dlep_tcp_sockfd); + TCP_READY = 0; +#if 0 + /*** start the router offer guard timer ***/ + if (p2config->start_on_discovery) { + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); + } +#endif + /* reset the state */ +// dlep_porter_open(p2config); + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + + return (RC_FSM_OK); +} + + +/** + * NAME + * terminating_peer_term_rcvd + * + * SYNOPSIS + * RC_FSM_t + * terminating_peer_term_rcvd(void *p2event, void *p2parm) + * + * DESCRIPTION + * This event handler is invoked when the peer terminate + * message is received during the terminating state. The neighbors + * are all terminated and the peer state machine + * is stopped and removed. + * + * INPUT PARAMETERS + * p2event - This is a pointer to the peer context which is set prior + * to invoking the state machine. + * + * p2parm - NULL on entry + * + * OUTPUT PARAMETERS + * p2event - peer state and context updated + * + * RETURN VALUE + * RC_FSM_STOP_PROCESSING which removes the state machine + * + */ +RC_FSM_t +terminating_peer_term_rcvd (void *p2event, void *p2parm) +{ + RC_FSM_t rc; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + + rfc5444_packet_scratch_pad_t *pkt_scratch_pad; + rfc5444_message_scratch_pad_t *msg_scratch_pad; + + p2peer = p2event; + if (!p2peer) { + return (RC_FSM_IGNORE_EVENT); + } + + p2config = p2peer->p2config; + pkt_scratch_pad = &p2peer->packet_scratch_pad; + msg_scratch_pad = &p2peer->message_scratch_pad; + + printf("\n terminating_peer_term_rcvd "); + +#if 0 + if (p2peer->router_id != pkt_scratch_pad->router_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u router_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->router_id, + pkt_scratch_pad->router_id); + } + return (RC_FSM_IGNORE_EVENT); + } + + if (p2peer->client_id != pkt_scratch_pad->client_id) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u client_id %u-%u invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->client_id, + pkt_scratch_pad->client_id); + } + return (RC_FSM_IGNORE_EVENT); + } +#endif + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u term rcvd \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id); + } + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + + send_dlep_peer_termination_ack(p2peer); + + /* Reset the state */ + fsm_set_exception_state(p2peer->fsm_handle, reset_s); + + +// close(p2config->dlep_udp_sockfd); +// close(p2config->dlep_tcp_sockfd); + TCP_READY = 0; + +#if 0 + /*** start the router offer guard timer ***/ + if (p2config->start_on_discovery) { + stw_system_timer_start(&p2peer->peer_offer_tmr, + secs_to_milliseconds(p2config->peer_offer_interval), + secs_to_milliseconds(p2config->peer_offer_interval), + &dlep_peer_offer_tmr, + (void *)p2peer->peer_id); + + } +#endif + /* reset the state */ +// dlep_porter_open(p2config); + fsm_set_exception_state(p2peer->fsm_handle, discovery_s); + + return (RC_FSM_OK); +} + + diff --git a/dlep_radio_ipv6/dlep_client_peer_event_handlers.h b/dlep_radio_ipv6/dlep_client_peer_event_handlers.h new file mode 100644 index 0000000..023b33f --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_peer_event_handlers.h @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------- + * dlep_client_peer_event_handlers.h -- client peer state event handlers + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_PEER_EVENT_HANDLERS_H__ +#define __DLEP_CLIENT_PEER_EVENT_HANDLERS_H__ + +#include "fsm.h" + + +extern RC_FSM_t +discovery_start_init(void *p2event, void *p2parm); + +extern RC_FSM_t +discovery_peer_attached_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +discovery_peer_offer_start(void *p2event, void *p2parm); + +/* extern RC_FSM_t +discovery_peer_offer_rcvd(void *p2event, void *p2parm); */ + +extern RC_FSM_t +initialization_peer_init_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +initialization_peer_init_ack_start(void *p2event, void *p2parm); +/* extern RC_FSM_t +discovery_peer_offer_tmo(void *p2event, void *p2parm); */ + +/* extern RC_FSM_t +discovery_peer_init_start(void *p2event, void *p2parm); */ + +/* extern RC_FSM_t +discovery_peer_init_ack_rcvd(void *p2event, void *p2parm); */ + +extern RC_FSM_t +in_session_peer_heartbeat_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +in_session_peer_heartbeat_tmo(void *p2event, void *p2parm); + +/* extern RC_FSM_t +in_session_peer_update_rcvd(void *p2event, void *p2parm); */ + + +extern RC_FSM_t +in_session_peer_update_request_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +in_session_peer_update_response_rcvd(void *p2event, void *p2parm); + + +extern RC_FSM_t +in_session_peer_term_request(void *p2event, void *p2parm); + +extern RC_FSM_t +in_session_peer_term_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_peer_term_ack_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_peer_term_ack_tmo(void *p2event, void *p2parm); + +extern RC_FSM_t +terminating_peer_term_rcvd(void *p2event, void *p2parm); + +extern RC_FSM_t +out_of_state_rom_rcvd(void *p2event, void *p2parm); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_client_peer_fsm.c b/dlep_radio_ipv6/dlep_client_peer_fsm.c new file mode 100644 index 0000000..f732212 --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_peer_fsm.c @@ -0,0 +1,568 @@ +/*---------------------------------------------------------------------- + * dlep_client_fsm.c -- DLEP Client state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "fsm.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + +#include "dlep_client_neighbor_event_handlers.h" +#include "dlep_client_peer_event_handlers.h" +#include "dlep_client_timer.h" +#include "dlep_client_peer_fsm.h" + +/* + * normalized client peer event description + */ +static event_description_t normalized_event_table[] = + {{start_init_e, "Start Event"}, + {peer_att_discovery_e, "Attached Discovery Event"}, + {peer_offer_e, "Peer Offer Event"}, + {peer_offer_tmo_e, "Peer Offer TMO Event"}, + {peer_init_request_e, "Peer Initialization Request Event"}, + {peer_init_response_e, "Peer Initialization Response Event"}, + {peer_heartbeat_e, "Peer Heartbeat Event"}, + {peer_heartbeat_tmo_e, "Peer Heartbeat TMO Event"}, + {peer_update_request_e, "Peer Update Request Event"}, + {peer_update_response_e, "Peer Update Response Event"}, + {user_peer_term_request_e, "User Node Term Request Event"}, + {peer_term_request_e, "Peer Term Event"}, + {peer_term_response_e, "Peer Term Response Event"}, + {peer_term_response_tmo_e, "Peer Term Response TMO Event"}, + {FSM_NULL_EVENT_ID, NULL} }; + + +/* + * normalized peer state description + */ +static state_description_t normalized_state_table[] = + {{discovery_s, "Idle State"}, + {initialization_s, "Initialized State"}, + {in_session_s, "Established State"}, + {terminating_s, "Terminating State"}, + {reset_s, "Resetting state"}, + {FSM_NULL_STATE_ID, NULL} }; + + +/* + * catch-all to ignore events + */ +static RC_FSM_t event_ignore (void *p2event, void *p2parm) +{ + dlep_context_peer_t *p2peer; + + p2peer = p2event; + + if (p2peer) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u event ignored: p2peer=%p peer_id=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer, + p2peer->peer_id); + } + } else { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u event ignored! \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + } + return (RC_FSM_OK); // IGNORE_EVENT); +} + + +/* + _ State event tables + */ +static event_tuple_t state_discovery_events[] = + {{start_init_e, + discovery_start_init, discovery_s}, + {peer_att_discovery_e, + discovery_peer_attached_rcvd, initialization_s}, + {peer_offer_e, + discovery_peer_offer_start, initialization_s}, + {peer_offer_tmo_e, + event_ignore, discovery_s}, + {peer_init_request_e, + initialization_peer_init_rcvd, in_session_s}, + {peer_init_response_e, + initialization_peer_init_ack_start, in_session_s}, + {peer_heartbeat_e, + event_ignore, discovery_s}, + {peer_heartbeat_tmo_e, + event_ignore, discovery_s}, + {peer_update_request_e, + event_ignore, discovery_s}, + {peer_update_response_e, + event_ignore, discovery_s}, + {user_peer_term_request_e, + event_ignore, discovery_s}, + {peer_term_request_e, + event_ignore, discovery_s}, + {peer_term_response_e, + event_ignore, discovery_s}, + {peer_term_response_tmo_e, + event_ignore, discovery_s}}; + +static event_tuple_t state_initialization_events[] = + {{start_init_e, + event_ignore, initialization_s}, + {peer_att_discovery_e, + event_ignore, initialization_s}, + {peer_offer_e, + event_ignore, initialization_s}, + {peer_offer_tmo_e, + event_ignore, initialization_s}, + {peer_init_request_e, + initialization_peer_init_rcvd, in_session_s}, + {peer_init_response_e, + initialization_peer_init_ack_start, in_session_s}, + {peer_heartbeat_e, + event_ignore, initialization_s}, + {peer_heartbeat_tmo_e, + event_ignore, initialization_s}, + {peer_update_request_e, + event_ignore, initialization_s}, + {peer_update_response_e, + event_ignore, initialization_s}, + {user_peer_term_request_e, + event_ignore, initialization_s}, + {peer_term_request_e, + event_ignore, initialization_s}, + {peer_term_response_e, + event_ignore, initialization_s}, + {peer_term_response_tmo_e, + event_ignore, initialization_s}}; + + + +static event_tuple_t state_in_session_events[] = + { {start_init_e, + event_ignore, in_session_s}, + {peer_att_discovery_e, + event_ignore, in_session_s}, + {peer_offer_e, + event_ignore, in_session_s}, + {peer_offer_tmo_e, + event_ignore, in_session_s}, + {peer_init_request_e, + event_ignore, in_session_s}, + {peer_init_response_e, + event_ignore, in_session_s}, + {peer_heartbeat_e, + in_session_peer_heartbeat_rcvd, in_session_s}, + {peer_heartbeat_tmo_e, + in_session_peer_heartbeat_tmo, in_session_s}, + {peer_update_request_e, + in_session_peer_update_request_rcvd, in_session_s}, + {peer_update_response_e, + in_session_peer_update_response_rcvd, in_session_s}, + {user_peer_term_request_e, + in_session_peer_term_request, terminating_s}, + {peer_term_request_e, + in_session_peer_term_rcvd, terminating_s}, + {peer_term_response_e, + event_ignore, in_session_s}, + {peer_term_response_tmo_e, + event_ignore, in_session_s}}; + + +static event_tuple_t state_terminating_events[] = + { {start_init_e, + event_ignore, terminating_s}, + {peer_att_discovery_e, + event_ignore, terminating_s}, + {peer_offer_e, + event_ignore, terminating_s}, + {peer_offer_tmo_e, + event_ignore, terminating_s}, + {peer_init_request_e, + event_ignore, terminating_s}, + {peer_init_response_e, + event_ignore, terminating_s}, + {peer_heartbeat_e, + event_ignore, terminating_s}, + {peer_heartbeat_tmo_e, + event_ignore, terminating_s}, + {peer_update_request_e, + event_ignore, terminating_s}, + {peer_update_response_e, + event_ignore, terminating_s}, + {user_peer_term_request_e, + event_ignore, terminating_s}, + {peer_term_request_e, + terminating_peer_term_rcvd, terminating_s}, + {peer_term_response_e, + terminating_peer_term_ack_rcvd, reset_s}, + {peer_term_response_tmo_e, + terminating_peer_term_ack_tmo, reset_s}}; + +static event_tuple_t state_reset_events[] = + {{start_init_e, + event_ignore, reset_s}, + {peer_att_discovery_e, + event_ignore, reset_s}, + {peer_offer_e, + event_ignore, reset_s}, + {peer_offer_tmo_e, + event_ignore, reset_s}, + {peer_init_request_e, + event_ignore, reset_s}, + {peer_init_response_e, + event_ignore, reset_s}, + {peer_heartbeat_e, + event_ignore, reset_s}, + {peer_heartbeat_tmo_e, + event_ignore, reset_s}, + {peer_update_request_e, + event_ignore, reset_s}, + {peer_update_response_e, + event_ignore, reset_s}, + {user_peer_term_request_e, + event_ignore, reset_s}, + {peer_term_request_e, + event_ignore, reset_s}, + {peer_term_response_e, + event_ignore, reset_s}, + {peer_term_response_tmo_e, + event_ignore, reset_s}}; + + +/* + * State table + */ +static state_tuple_t dlep_client_state_table[] = + + { {discovery_s, state_discovery_events}, + {initialization_s, state_initialization_events}, + {in_session_s, state_in_session_events}, + {terminating_s, state_terminating_events}, + {reset_s,state_reset_events}, + {FSM_NULL_STATE_ID, NULL} }; + + +/** + * NAME + * dlep_client_fsm_get_state + * + * SYNOPSIS + * uint32_t + * dlep_client_fsm_get_state(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to return the current state + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * current state + * FSM_NULL_STATE_ID if there is an error. + * + */ +uint32_t +dlep_client_fsm_get_state (dlep_context_peer_t *p2peer) +{ + uint32_t state; + + state = FSM_NULL_STATE_ID; + + if (p2peer) { + fsm_get_state(p2peer->fsm_handle, &state); + } else { + /* ignore */ + } + return (state); +} + + +/** + * NAME + * dlep_client_fsm_show_state_table + * + * SYNOPSIS + * void + * dlep_client_fsm_show_state_table(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to display the state machine counters + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_client_fsm_show_state_table (dlep_context_peer_t *p2peer) +{ + if (p2peer) { + fsm_display_table(p2peer->fsm_handle); + } else { + /* ignore */ + } + return; +} + + +/** + * NAME + * dlep_client_fsm_show_history + * + * SYNOPSIS + * void + * dlep_client_fsm_show_history(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to display the state machine history + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_client_fsm_show_history (dlep_context_peer_t *p2peer) +{ + if (p2peer) { + fsm_show_history(p2peer->fsm_handle); + } else { + /* ignore */ + } + return; +} + + +/** + * NAME + * dlep_client_fsm_engine + * + * SYNOPSIS + * void + * dlep_client_fsm_engine(uint32_t normalized_event, + * dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to process the state machine normalized + * events. + * + * INPUT PARAMETERS + * normalized_event - This is the state machine event to process. + * + * p2peer - This is a pointer to the peer context. + * + * p2neighbor - This is a pointer to the neighbor context. This is + * NULL for peer specific events. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * RC_FSM_STOP_PROCESSING This indicates that the state machine + * is to be terminated and resources released. + * error otherwise + * + */ +void +dlep_client_fsm_engine (uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ + RC_FSM_t rc; + + if (!p2peer) { + DLEP_DEBUG("%s-%u Error: peer is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return; + } + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u normalized_event=%u p2peer=%p " + "peer_id=%u p2neighbor=%p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + normalized_event, + p2peer, + p2peer->peer_id, + p2neighbor); + } + + rc = fsm_engine(p2peer->fsm_handle, + normalized_event, + p2peer, + p2neighbor); + + if (rc == RC_FSM_STOP_PROCESSING) { + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u p2peer=%p peer_id=%u stopped \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer, + p2peer->peer_id); + } + + /* cancel all timers and clear context */ + dlep_neighbor_deallocate_all(p2peer); + + /* stop peer timers */ + dlep_peer_clear(p2peer); + dlep_peer_remove(&p2peer); + + } else if (rc != RC_FSM_OK) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u radio state " + "machine rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + return; +} + + +/** + * NAME + * dlep_fsm_destroy + * + * SYNOPSIS + * void + * dlep_fsm_destroy(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to destroy the client state machine. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * p2peer - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_fsm_destroy (dlep_context_peer_t *p2peer) +{ + if (!p2peer) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer is null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + } else { + /* fsm_handle is nulled */ + fsm_destroy((fsm_t **)&p2peer->fsm_handle); + } + return; +} + + +/** + * NAME + * dlep_fsm_create + * + * SYNOPSIS + * void + * dlep_fsm_create(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to create the client state machine. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * OUTPUT PARAMETERS + * p2peer - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_fsm_create (dlep_context_peer_t *p2peer) +{ + RC_FSM_t rc; + + if (!p2peer) { + return; + } + + p2peer->fsm_handle = NULL; + rc = fsm_create((fsm_t **)&p2peer->fsm_handle, + "DLEP State Machine", + discovery_s, + normalized_state_table, + normalized_event_table, + dlep_client_state_table); + if (rc != RC_FSM_OK) { + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u radio state " + "machine rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + } + + return; +} + + diff --git a/dlep_radio_ipv6/dlep_client_peer_fsm.h b/dlep_radio_ipv6/dlep_client_peer_fsm.h new file mode 100644 index 0000000..8334007 --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_peer_fsm.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------- + * dlep_client_fsm.h -- DLEP Client state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reseved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_FSM_H__ +#define __DLEP_CLIENT_FSM_H__ + +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" + +/* + * normalized client events + */ +typedef enum { + start_init_e = 0, + peer_att_discovery_e, + peer_offer_e, + peer_offer_tmo_e, + peer_init_request_e, + peer_init_response_e, + peer_heartbeat_e, + peer_heartbeat_tmo_e, + peer_update_request_e, + peer_update_response_e, + user_peer_term_request_e, + peer_term_request_e, + peer_term_response_e, + peer_term_response_tmo_e, +} dlep_client_events_e; + + +/* + * normalized client states + */ +typedef enum { + discovery_s = 0, + initialization_s, + in_session_s, + terminating_s, + reset_s, +} dlep_client_states_e; + + + + +extern uint32_t +dlep_client_fsm_get_state(dlep_context_peer_t *p2peer); + + +extern void +dlep_client_fsm_show_counter(dlep_context_peer_t *p2peer); + + +extern void +dlep_client_fsm_show_state_table(dlep_context_peer_t *p2peer); + + +extern void +dlep_client_fsm_show_history(dlep_context_peer_t *p2peer); + + +extern void +dlep_client_fsm_engine(uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +dlep_fsm_destroy(dlep_context_peer_t *p2peer); + + +extern void +dlep_fsm_create(dlep_context_peer_t *p2peer); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_client_timer.c b/dlep_radio_ipv6/dlep_client_timer.c new file mode 100644 index 0000000..c63b988 --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_timer.c @@ -0,0 +1,301 @@ +/*---------------------------------------------------------------------- + * dlep_client_timer.c -- Client state machine guard timers + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "dlep_context_peer_management.h" +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" +#include "dlep_client_timer.h" + + + +/** + * NAME + * dlep_peer_offer_tmr + * + * SYNOPSIS + * void + * dlep_peer_offer_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that the peer offer + * response expected by the peer has not been received. + * + * INPUT PARAMETERS + * tmr - This is the timer handle + * + * p2arm - This is the local peer id that was set when the timer + * was started. + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_offer_tmr (stw_tmr_t *tmr, void *parm) +{ +printf("dlep_peer_offer_tmr \n"); + uint32_t peer_id; + dlep_context_peer_t *p2peer; + + peer_id = (uint32_t)parm; + p2peer = dlep_get_peer_by_peer_id(peer_id); + + printf("\n peer offer time out"); + dlep_client_fsm_engine(peer_offer_tmo_e, p2peer, NULL); + return; +} + + +/** + * NAME + * dlep_peer_heartbeat_tmr + * + * SYNOPSIS + * void + * dlep_peer_heartbeat_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that it is time to + * for the peer send another peer heartbeat. + * + * INPUT PARAMETERS + * tmr - This is the timer handle + * + * p2arm - This is the local peer id that was set when + * the timer was started. + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_heartbeat_tmr (stw_tmr_t *tmr, void *parm) +{ +printf("dlep_peer_heartbeat_tmr"); + uint32_t peer_id; + dlep_context_peer_t *p2peer; + + peer_id = (uint32_t)parm; + p2peer = dlep_get_peer_by_peer_id(peer_id); + + dlep_client_fsm_engine(peer_heartbeat_tmo_e, p2peer, NULL); + return; +} + + +/** + * NAME + * dlep_peer_term_ack_tmr + * + * SYNOPSIS + * void + * dlep_peer_term_ack_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that the term ACK + * expected by the peer was not received. + * + * INPUT PARAMETERS + * tmr - This is the timer handle + * + * p2arm - This is the local peer id that was set when + * the timer was started. + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_term_ack_tmr (stw_tmr_t *tmr, void *parm) +{ +printf("dlep_peer_term_ack_tmr\n"); + uint32_t peer_id; + dlep_context_peer_t *p2peer; + + peer_id = (uint32_t)parm; + p2peer = dlep_get_peer_by_peer_id(peer_id); + + printf("\n Peer term ack tmr out "); + dlep_client_fsm_engine(peer_term_response_tmo_e, p2peer, NULL); + return; +} + + +/** + * NAME + * dlep_neighbor_init_ack_tmr + * + * SYNOPSIS + * void + * dlep_neighbor_init_ack_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that the neighbor + * neighbor up ack was not received. The neighbor up may the + * be retransmitted. + * + * INPUT PARAMETERS + * p2arm + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_init_ack_tmr (stw_tmr_t *tmr, void *parm) +{ +printf("dlep_neighbor_init_ack_tmr\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2neighbor = parm; + p2peer = p2neighbor->p2peer; + + dlep_client_neighbor_fsm_engine(neighbor_up_ack_tmo_e, + p2peer, p2neighbor); + return; +} + + +/** + * NAME + * dlep_neighbor_update_ack_tmr + * + * SYNOPSIS + * void + * dlep_neighbor_update_ack_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that the neighbor + * update ack was not received. The neighbor update may the + * be retransmitted. + * + * INPUT PARAMETERS + * p2arm + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_update_ack_tmr (stw_tmr_t *tmr, void *parm) +{ +printf("dlep_neighbor_update_ack_tmr\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2neighbor = parm; + p2peer = p2neighbor->p2peer; + + dlep_client_neighbor_fsm_engine(neighbor_update_ack_tmo_e, + p2peer, p2neighbor); + return; +} + + + +/** + * NAME + * dlep_neighbor_metrics_interval_tmr + * + * SYNOPSIS + * void + * dlep_neighbor_metrics_interval_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer is used to periodically + * generate the periodic neighbor metrics message. + * + * INPUT PARAMETERS + * tmr - This is a handle to the timer + * + * p2arm - This is a pointer to the neighbor context that + * was set when the timer was started. + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_metrics_interval_tmr (stw_tmr_t *tmr, void *parm) +{ +printf("dlep_neighbor_metrics_interval_tmr\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2neighbor = parm; + p2peer = p2neighbor->p2peer; + + dlep_client_neighbor_fsm_engine(neighbor_update_metrics_interval_e, + p2peer, p2neighbor); + return; +} + + +/** + * NAME + * dlep_neighbor_term_ack_tmr + * + * SYNOPSIS + * void + * dlep_neighbor_term_ack_tmr(stw_tmr_t *tmr, void *parm) + * + * DESCRIPTION + * The expiration of this timer indicates that theneighbor + * neighbor down was not received. The neighbor down may the + * be retransmitted. + * + * INPUT PARAMETERS + * p2arm + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_term_ack_tmr (stw_tmr_t *tmr, void *parm) +{ +printf("dlep_neighbor_term_ack_tmr\n"); + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + p2neighbor = parm; + p2peer = p2neighbor->p2peer; + + dlep_client_neighbor_fsm_engine(neighbor_down_ack_tmo_e, + p2peer, p2neighbor); + return; +} + diff --git a/dlep_radio_ipv6/dlep_client_timer.h b/dlep_radio_ipv6/dlep_client_timer.h new file mode 100644 index 0000000..c133dc6 --- /dev/null +++ b/dlep_radio_ipv6/dlep_client_timer.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------- + * dlep_client_timer.h + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CLIENT_TIMER_H__ +#define __DLEP_CLIENT_TIMER_H__ + +#include "stw_system_timer.h" + + +extern void +dlep_peer_offer_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_peer_heartbeat_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_peer_term_ack_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_neighbor_init_ack_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_neighbor_update_ack_tmr(stw_tmr_t *tmr, void *parm); + +//exter n void +//d lep_n ei ghbor_met rics_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_neighbor_metrics_interval_tmr(stw_tmr_t *tmr, void *parm); + +extern void +dlep_neighbor_term_ack_tmr(stw_tmr_t *tmr, void *parm); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_config.c b/dlep_radio_ipv6/dlep_config.c new file mode 100644 index 0000000..fa74704 --- /dev/null +++ b/dlep_radio_ipv6/dlep_config.c @@ -0,0 +1,670 @@ +/*---------------------------------------------------------------------- + * dlep_config.c -- Routine to parse the configuration file + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" + + +static dlep_config_t dlep_config; + + +/** + * NAME + * dlep_get_config_ptr + * + * SYNOPSIS + * dlep_config_t *dlep_get_config_ptr(void) + * + * DESCRIPTION + * This function can be used to get the pointer to the + * configuration structure. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * The configuration structure pointer. + * + */ +dlep_config_t *dlep_get_config_ptr (void) +{ + return (&dlep_config); +} + + +/** + * NAME + * dlep_default_config + * + * SYNOPSIS + * void + * dlep_default_config(void) + * + * DESCRIPTION + * This function sets the configuration data to default values, where + * default values apply. + * + * INPUT PARAMETERS + * p2config Pointer to the config structure + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * None + * + */ +void +dlep_default_config (void) +{ + dlep_config_t *p2config; + + p2config = &dlep_config; + + strcpy(p2config->filename, "dlep_sim.cfg"); + + strcpy(p2config->sim_name, "dlep"); + + p2config->local_udp_port = 0; + p2config->local_tcp_port = 0; + + p2config->local_ipv4_dot[0] = '\0'; + ipv4_zero_address(&p2config->local_ipv4); + + p2config->local_ipv6_dot[0] = '\0'; + ipv6_zero_address(&p2config->local_ipv6); + + p2config->router_udp_port = 0; + p2config->router_tcp_port = 0; + + p2config->router_ipv4_dot[0] = '\0'; + ipv4_zero_address(&p2config->router_ipv4); + + p2config->router_ipv6_dot[0] = '\0'; + ipv6_zero_address(&p2config->router_ipv6); + + p2config->start_on_launch = TRUE; + + strcpy(p2config->local_type_description, "no type description"); + + + p2config->local_id = 0; + + p2config->peer_offer_interval = + DLEP_PEER_OFFER_INTERVAL_DEFAULT; + + p2config->peer_heartbeat_interval = + DLEP_PEER_HEARTBEAT_INTERVAL_DEFAULT; + p2config->peer_heartbeat_missed_threshold = + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_DEFAULT; + + p2config->peer_term_ack_tmo = + DLEP_PEER_TERM_ACK_TMO_DEFAULT; + p2config->peer_term_missed_ack_threshold = + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_DEFAULT; + + p2config->neighbor_up_ack_tmo = + DLEP_NEIGHBOR_UP_ACK_TMO_DEFAULT; + p2config->neighbor_up_missed_ack_threshold = + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_DEFAULT; + + p2config->neighbor_update_interval_tmo = + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_DEFAULT; + + p2config->neighbor_activity_timer = + DLEP_NEIGHBOR_ACTIVITY_TIMER_DEFAULT; + + p2config->neighbor_down_ack_tmo = + DLEP_NEIGHBOR_DOWN_ACK_TMO_DEFAULT; + p2config->neighbor_down_missed_ack_threshold = + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_DEFAULT; + + return; +} + + +/** + * NAME + * dlep_display_config + * + * SYNOPSIS + * void + * dlep_display_config(dlep_config_t *p2config) + * + * DESCRIPTION + * This function displays the configuration data to the console. + * + * INPUT PARAMETERS + * p2config Pointer to the config structure + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_display_config (dlep_config_t *p2config) +{ + if (!p2config) { + return; + } + + printf("\n%s DLEP Configuration from %s \n", + p2config->sim_name, + p2config->filename); + + printf(" local udp port=%u \n", + p2config->local_udp_port); + printf(" local tcp port=%u \n", + p2config->local_tcp_port); + printf(" local ipv6=%s \n", + p2config->local_ipv6_dot); + + if (p2config->router_udp_port) { + printf(" router udp port=%u \n", + p2config->router_udp_port); + } + + if (p2config->router_tcp_port) { + printf(" router tcp port=%u \n", + p2config->router_tcp_port); + } + + if (p2config->router_udp_port && p2config->router_tcp_port) { + printf(" router ipv6=%s \n", + p2config->router_ipv6_dot); + } + + + printf("\n"); + + printf(" Type Description: %s \n", + p2config->local_type_description); + + printf(" local ID=%u \n", + p2config->local_id); + + printf(" peer_offer_tmo=%u seconds \n", + p2config->peer_offer_interval); + + printf(" peer_heartbeat_interval=%u seconds \n", + p2config->peer_heartbeat_interval); + + printf(" peer_heartbeat_missed_threshold=%u \n", + p2config->peer_heartbeat_missed_threshold); + + printf(" peer_term_ack_tmo=%u milliseconds \n", + p2config->peer_term_ack_tmo); + + printf(" peer_term_missed_ack_threshold=%u \n", + p2config->peer_term_missed_ack_threshold); + + printf("\n"); + + printf(" neighbor_up_ack_tmo=%u milliseconds \n", + p2config->neighbor_up_ack_tmo); + + printf(" neighbor_up_missed_ack_threshold=%u \n", + p2config->neighbor_up_missed_ack_threshold); + + printf(" neighbor_update_interval_tmo=%u milliseconds \n", + p2config->neighbor_update_interval_tmo); + + printf(" neighbor_activity_timer=%u seconds \n", + p2config->neighbor_activity_timer); + + printf(" neighbor_down_ack_tmo=%u milliseconds \n", + p2config->neighbor_down_ack_tmo); + + printf(" neighbor_down_missed_ack_threshold=%u \n", + p2config->neighbor_down_missed_ack_threshold); + + printf("\n"); + return; +} + + +/** + * NAME + * dlep_read_config_file + * + * SYNOPSIS + * void + * dlep_read_config_file(dlep_config_t *p2config) + * + * DESCRIPTION + * This function parses the configuration file and assigns + * the appropriate parameters in the config struct. + * + * INPUT PARAMETERS + * p2config - This is a pointer to the DLEP configuration data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_read_config_file (dlep_config_t *p2config) +{ + int i, line_count; + uint32_t temp; + + FILE *fp; + +#define MAX_INPUT_LENGTH ( 512 ) + char input_string[MAX_INPUT_LENGTH]; + +#define ARGC_MAX ( 5 ) + uint32_t argc; + char *argv[ARGC_MAX]; + + fp = fopen(p2config->filename, "r"); + if (!fp) { + printf("Error: problem opening config file: %s\n", + p2config->filename); + return; + } + + line_count = 0; + while (fgets(input_string, MAX_INPUT_LENGTH, fp)) { + + if (input_string[0] == '\0') { + continue; + } else if (input_string[0] == '#') { + continue; + } + + argv[0] = strtok(input_string, " \t\n"); + argc = 1; + + for (i=1; isim_name, argv[1], DLEP_SIM_NAME_LEN); + } + + /* peer debug flags */ + else if (strncmp(argv[0], "DEBUG_FLAGS", + strlen("DEBUG_FLAGS")) == 0) { + if (dlep_debug_flags) { + /* cli debug flag sticks */ + } else { + dlep_debug_flags = strtoul(argv[1], NULL, 16); + } + } + + else if (strncmp(argv[0], "MANUAL_START", + strlen("MANUAL_START")) == 0) { + p2config->start_on_launch = FALSE; + } + + else if (strncmp(argv[0], "DISCOVERY_START", + strlen("DISCOVERY_START")) == 0) { + p2config->start_on_discovery = TRUE; + } + + else if (strncmp(argv[0], "LOCAL_UDP_PORT", + strlen("LOCAL_UDP_PORT")) == 0) { + p2config->local_udp_port = strtoul(argv[1], NULL, 10); + } + + else if (strncmp(argv[0], "LOCAL_TCP_PORT", + strlen("LOCAL_TCP_PORT")) == 0) { + p2config->local_tcp_port = strtoul(argv[1], NULL, 10); + } + + else if (strncmp(argv[0], "LOCAL_IPV4", + strlen("LOCAL_IPV4")) == 0) { + strcpy(p2config->local_ipv4_dot, argv[1]); + + ipv4_dot_decimal2digits(&p2config->local_ipv4, argv[1]); + } + + else if (strncmp(argv[0], "LOCAL_IPV6", //added for local + strlen("LOCAL_IPV6")) == 0) { + strcpy(p2config->local_ipv6_dot, argv[1]); + ipv6_ascii2digits(&p2config->local_ipv6, argv[1]); + int j; +#if 0 + for(j=0;j<4;j++) + printf("local ipv6 ascii values %lu\n",p2config->local_ipv6.v6_addr.v6_addr32[i]); +#endif + } + + + else if (strncmp(argv[0], "ROUTER_UDP_PORT", + strlen("ROUTER_UDP_PORT")) == 0) { + p2config->router_udp_port = strtoul(argv[1], NULL, 10); + } + + else if (strncmp(argv[0], "ROUTER_TCP_PORT", + strlen("ROUTER_TCP_PORT")) == 0) { + p2config->router_tcp_port = strtoul(argv[1], NULL, 10); + } + + else if (strncmp(argv[0], "ROUTER_IPV4", + strlen("ROUTER_IPV4")) == 0) { + strcpy(p2config->router_ipv4_dot, argv[1]); + + ipv4_dot_decimal2digits(&p2config->router_ipv4, argv[1]); + p2config->router_ipv4.v4_addr.v4_addr32 = + htonl(p2config->router_ipv4.v4_addr.v4_addr32); + } + + else if (strncmp(argv[0], "ROUTER_IPV6", //added for router + strlen("ROUTER_IPV6")) == 0) { + strcpy(p2config->router_ipv6_dot, argv[1]); + + ipv6_ascii2digits(&p2config->router_ipv6, argv[1]); +#if 0 + memcpy(p2config->router_ipv6.v6_addr.v6_addr32,p2config->router_ipv6.v6_addr.v6_addr32,sizeof(ipv6_address_t)); + char ipAddress[16]; + inet_ntop(AF_INET6, &(p2config->router_ipv6.v6_addr), ipAddress,16); + printf("The IPV6 address is: %s\n", ipAddress); +#endif + // int i; + // for(i=0;i<4;i++) +#if 0 + printf("ipv6 ascii values %02x:02x:%02x:%02x:%02x:%02x:%02x:%02x\n",(int)p2config->router_ipv6.v6_addr.v6_addr16[0], + (int)p2config->router_ipv6.v6_addr.v6_addr16[1], + (int)p2config->router_ipv6.v6_addr.v6_addr16[2], + (int)p2config->router_ipv6.v6_addr.v6_addr16[3], + (int)p2config->router_ipv6.v6_addr.v6_addr16[4], + (int)p2config->router_ipv6.v6_addr.v6_addr16[5], + (int)p2config->router_ipv6.v6_addr.v6_addr16[6], + (int)p2config->router_ipv6.v6_addr.v6_addr16[7]); +#endif +#if 0 //vinod + p2config->router_ipv6.v6_addr.v6_addr32[0] = + htonl(p2config->router_ipv6.v6_addr.v6_addr32[0]); + p2config->router_ipv6.v6_addr.v6_addr32[1] = + htonl(p2config->router_ipv6.v6_addr.v6_addr32[1]); + p2config->router_ipv6.v6_addr.v6_addr32[2] = + htonl(p2config->router_ipv6.v6_addr.v6_addr32[2]); + p2config->router_ipv6.v6_addr.v6_addr32[3] = + htonl(p2config->router_ipv6.v6_addr.v6_addr32[3]); +#endif + + p2config->router_ipv6.v6_addr.v6_addr16[0] = + htonl(p2config->router_ipv6.v6_addr.v6_addr16[0]); + p2config->router_ipv6.v6_addr.v6_addr16[1] = + htonl(p2config->router_ipv6.v6_addr.v6_addr16[1]); + p2config->router_ipv6.v6_addr.v6_addr16[2] = + htonl(p2config->router_ipv6.v6_addr.v6_addr16[2]); + p2config->router_ipv6.v6_addr.v6_addr16[3] = + htonl(p2config->router_ipv6.v6_addr.v6_addr16[3]); + p2config->router_ipv6.v6_addr.v6_addr16[4] = + htonl(p2config->router_ipv6.v6_addr.v6_addr16[4]); + p2config->router_ipv6.v6_addr.v6_addr16[5] = + htonl(p2config->router_ipv6.v6_addr.v6_addr16[5]); + p2config->router_ipv6.v6_addr.v6_addr16[6] = + htonl(p2config->router_ipv6.v6_addr.v6_addr16[6]); + p2config->router_ipv6.v6_addr.v6_addr16[7] = + htonl(p2config->router_ipv6.v6_addr.v6_addr16[7]); + + + } + + + else if (strncmp(argv[0], "TYPE_DESCRIPTION", + strlen("TYPE_DESCRIPTION")) == 0) { + strncpy(p2config->local_type_description, + argv[1], RFC5444_TLV_PEER_TYPE_MAX_LENGTH); + + p2config->local_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH] = '\0'; + } + + else if (strncmp(argv[0], "LOCAL_ID", + strlen("LOCAL_ID")) == 0) { + temp = strtoul(argv[1], NULL, 10); + p2config->local_id = temp; + } + + else if (strncmp(argv[0], "DLEP_PEER_HEARTBEAT_INTERVAL", + strlen("DLEP_PEER_HEARTBEAT_INTERVAL")) == 0) { + p2config->peer_heartbeat_interval = strtoul(argv[1], NULL, 10); + + if (p2config->peer_heartbeat_interval < + DLEP_PEER_HEARTBEAT_INTERVAL_MIN) { + p2config->peer_heartbeat_interval = + DLEP_PEER_HEARTBEAT_INTERVAL_MIN; + } + + if (p2config->peer_heartbeat_interval > + DLEP_PEER_HEARTBEAT_INTERVAL_MAX) { + p2config->peer_heartbeat_interval = + DLEP_PEER_HEARTBEAT_INTERVAL_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD", + strlen("DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD")) == 0) { + p2config->peer_heartbeat_missed_threshold = + strtoul(argv[1], NULL, 10); + + if (p2config->peer_heartbeat_missed_threshold < + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MIN) { + p2config->peer_heartbeat_missed_threshold = + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MIN; + } + + if (p2config->peer_heartbeat_missed_threshold > + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MAX) { + p2config->peer_heartbeat_missed_threshold = + DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_PEER_TERM_ACK_TMO", + strlen("DLEP_PEER_TERM_ACK_TMO")) == 0) { + p2config->peer_term_ack_tmo = strtoul(argv[1], NULL, 10); + + if (p2config->peer_term_ack_tmo < + DLEP_PEER_TERM_ACK_TMO_MIN) { + p2config->peer_term_ack_tmo = + DLEP_PEER_TERM_ACK_TMO_MIN; + } + + if (p2config->peer_term_ack_tmo > + DLEP_PEER_TERM_ACK_TMO_MAX) { + p2config->peer_term_ack_tmo = + DLEP_PEER_TERM_ACK_TMO_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_PEER_TERM_MISSED_ACK_THRESHOLD", + strlen("DLEP_PEER_TERM_MISSED_ACK_THRESHOLD")) == 0) { + p2config->peer_term_missed_ack_threshold = + strtoul(argv[1], NULL, 10); + + if (p2config->peer_term_missed_ack_threshold < + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MIN) { + p2config->peer_term_missed_ack_threshold = + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MIN; + } + + if (p2config->peer_term_missed_ack_threshold > + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MAX) { + p2config->peer_term_missed_ack_threshold = + DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_UP_ACK_TMO", + strlen("DLEP_NEIGHBOR_UP_ACK_TMO")) == 0) { + p2config->neighbor_up_ack_tmo = strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_up_ack_tmo < + DLEP_NEIGHBOR_UP_ACK_TMO_MIN) { + p2config->neighbor_up_ack_tmo = + DLEP_NEIGHBOR_UP_ACK_TMO_MIN; + } + + if (p2config->neighbor_up_ack_tmo > + DLEP_NEIGHBOR_UP_ACK_TMO_MAX) { + p2config->neighbor_up_ack_tmo = + DLEP_NEIGHBOR_UP_ACK_TMO_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD", + strlen("DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD")) == 0) { + p2config->neighbor_up_missed_ack_threshold = + strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_up_missed_ack_threshold < + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MIN) { + p2config->neighbor_up_missed_ack_threshold = + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MIN; + } + + if (p2config->neighbor_up_missed_ack_threshold > + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MAX) { + p2config->neighbor_up_missed_ack_threshold = + DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO", + strlen("DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO")) == 0) { + p2config->neighbor_update_interval_tmo = + strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_update_interval_tmo > 0) { + if (p2config->neighbor_update_interval_tmo < + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MIN) { + p2config->neighbor_update_interval_tmo = + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MIN; + } + + if (p2config->neighbor_update_interval_tmo > + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MAX) { + p2config->neighbor_update_interval_tmo = + DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MAX; + } + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_ACTIVITY_TIMER", + strlen("DLEP_NEIGHBOR_ACTIVITY_TIMER")) == 0) { + p2config->neighbor_activity_timer = strtoul(argv[1], NULL, 10); + + if (!p2config->neighbor_activity_timer) { + if (p2config->neighbor_activity_timer < + DLEP_NEIGHBOR_ACTIVITY_TIMER_MIN) { + p2config->neighbor_activity_timer = + DLEP_NEIGHBOR_ACTIVITY_TIMER_MIN; + } + + if (p2config->neighbor_activity_timer > + DLEP_NEIGHBOR_ACTIVITY_TIMER_MAX) { + p2config->neighbor_activity_timer = + DLEP_NEIGHBOR_ACTIVITY_TIMER_MAX; + } + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_DOWN_ACK_TMO", + strlen("DLEP_NEIGHBOR_DOWN_ACK_TMO")) == 0) { + p2config->neighbor_down_ack_tmo = strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_down_ack_tmo < + DLEP_NEIGHBOR_DOWN_ACK_TMO_MIN) { + p2config->neighbor_down_ack_tmo = + DLEP_NEIGHBOR_DOWN_ACK_TMO_MIN; + } + + if (p2config->neighbor_down_ack_tmo > + DLEP_NEIGHBOR_DOWN_ACK_TMO_MAX) { + p2config->neighbor_down_ack_tmo = + DLEP_NEIGHBOR_DOWN_ACK_TMO_MAX; + } + } + + else if (strncmp(argv[0], "DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD", + strlen("DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD")) == 0) { + p2config->neighbor_down_missed_ack_threshold = + strtoul(argv[1], NULL, 10); + + if (p2config->neighbor_down_missed_ack_threshold < + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MIN) { + p2config->neighbor_down_missed_ack_threshold = + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MIN; + } + + if (p2config->neighbor_down_missed_ack_threshold > + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MAX) { + p2config->neighbor_down_missed_ack_threshold = + DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MAX; + } + } + + else { + printf("%s-%u Unknown config file option -%s-\n", + __FUNCTION__, + __LINE__, + argv[0]); + } + } + + fclose(fp); + return; +} + diff --git a/dlep_radio_ipv6/dlep_config.h b/dlep_radio_ipv6/dlep_config.h new file mode 100644 index 0000000..6004ad6 --- /dev/null +++ b/dlep_radio_ipv6/dlep_config.h @@ -0,0 +1,285 @@ +/*---------------------------------------------------------------------- + * dlep_config.h - routines to parse the config file + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONFIG_H__ +#define __DLEP_CONFIG_H__ + +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" + +#include "rfc5444_types.h" + + + + +#define ROUTER_DEFAULT_PORT ( 5000 ) +#define RADIO_DEFAULT_PORT ( 5001 ) + + +/* + * The configuration range for the router offer timeout + * in seconds. The MIM is retransmitted if the ROM is + * not received. + */ +#define DLEP_PEER_OFFER_INTERVAL_MIN ( 1 ) +#define DLEP_PEER_OFFER_INTERVAL_MAX ( 60 ) +#define DLEP_PEER_OFFER_INTERVAL_DEFAULT ( 5 ) + +/* + * The configuration range for the peer heartbeat timeout. + * This is the time that each node, server and client, + * expects to receive the peer heartbeat. 0 disables. + * Time units are in seconds. + */ +#define DLEP_PEER_HEARTBEAT_INTERVAL_MIN ( 1 ) +#define DLEP_PEER_HEARTBEAT_INTERVAL_MAX ( 60 ) +#define DLEP_PEER_HEARTBEAT_INTERVAL_DEFAULT ( 5 ) + +/* + * The number of consecutive missed HBs that result in + * a failure. + */ +#define DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MIN ( 2 ) +#define DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_MAX ( 8 ) +#define DLEP_PEER_HEARTBEAT_MISSED_THRESHOLD_DEFAULT ( 3 ) + + +/* + * The configuration range for the peer terminate ack timeout. + * This is the time the client waits for the peer term ack. + * Time units are milliseconds. + */ +#define DLEP_PEER_TERM_ACK_TMO_MIN ( 100 ) +#define DLEP_PEER_TERM_ACK_TMO_MAX ( 5000 ) +#define DLEP_PEER_TERM_ACK_TMO_DEFAULT ( 1000 ) + +/* + * The max number of peer term ack timeouts that are tolerated. + */ +#define DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MIN ( 1 ) +#define DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_MAX ( 5 ) +#define DLEP_PEER_TERM_MISSED_ACK_THRESHOLD_DEFAULT ( 3 ) + + +/* + * The configuration range for the neighbor up ack timeout. + * This is the time the client waits for the neighbor up ack. + * Time units are milliseconds. + */ +#define DLEP_NEIGHBOR_UP_ACK_TMO_MIN ( 100 ) +#define DLEP_NEIGHBOR_UP_ACK_TMO_MAX ( 40000 ) +#define DLEP_NEIGHBOR_UP_ACK_TMO_DEFAULT ( 1000 ) + +/* + * The configuration range for the retransmission threshold for + * the neighbor up. + */ +#define DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MIN ( 1 ) +#define DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_MAX ( 5 ) +#define DLEP_NEIGHBOR_UP_MISSED_ACK_THRESHOLD_DEFAULT ( 3 ) + + +/* + * The configuration range the for the periodic neighbor update + * timer. The client sends neighbor updates at this interval. + * Time units are milliseconds. + */ +#define DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MIN ( 100 ) +#define DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_MAX ( 5000 ) +#define DLEP_NEIGHBOR_UPDATE_INTERVAL_TMO_DEFAULT ( 400 ) + +/* + * The configuration range the for the neighbor activity + * timer. The server expects to see traffic on a neighbor + * session during this interval. Time units are seconds. + * 0 disables. + */ +#define DLEP_NEIGHBOR_ACTIVITY_TIMER_MIN ( 0 ) +#define DLEP_NEIGHBOR_ACTIVITY_TIMER_MAX ( 5 ) +#define DLEP_NEIGHBOR_ACTIVITY_TIMER_DEFAULT ( 10 ) + + +/* + * The configuration range the neighbor down ack timeout. + * This is the time the client waits for the neighbor down ack. + * Time units are milliseconds. + */ +#define DLEP_NEIGHBOR_DOWN_ACK_TMO_MIN ( 100 ) +#define DLEP_NEIGHBOR_DOWN_ACK_TMO_MAX ( 5000 ) +#define DLEP_NEIGHBOR_DOWN_ACK_TMO_DEFAULT ( 1000 ) + +/* + * The max number of neighbor down ack timeouts that are tolerated. + * Once the threshold is reached, neighbor downs are stopped + * and the neighbor cleaned up. + */ +#define DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MIN ( 1 ) +#define DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_MAX ( 5 ) +#define DLEP_NEIGHBOR_DOWN_MISSED_ACK_THRESHOLD_DEFAULT ( 3 ) + + +#define DLEP_FILENAME_LEN ( 128 ) +#define ROOT_PATH_LEN ( 512 ) +#define DLEP_SIM_NAME_LEN ( 32 ) + + +/* + * Defines the data used to manage config data + * and stateless data + */ +typedef struct { + char filename[DLEP_FILENAME_LEN]; + + char sim_name[DLEP_SIM_NAME_LEN]; + + /* port for the local udp and tcp */ + uint16_t local_udp_port; + uint16_t local_tcp_port; + + /* ipv4 for the local */ + char local_ipv4_dot[IPV4_ADDR_STRING_LEN]; + ipv4_address_t local_ipv4; + + /* ipv6 for the local */ // added for local + char local_ipv6_dot[IPV6_ADDR_STRING_LEN]; + ipv6_address_t local_ipv6; + + /* port for the client */ + uint16_t router_udp_port; + uint16_t router_tcp_port; + boolean_t router_port_present; + + /* The router IPv4 address info */ + char router_ipv4_dot[IPV4_ADDR_STRING_LEN]; + ipv4_address_t router_ipv4; + boolean_t router_ipv4_present; + + /* The router IPv6 address info */ //added for router + char router_ipv6_dot[IPV6_ADDR_STRING_LEN]; + ipv6_address_t router_ipv6; + boolean_t router_ipv6_present; + + /* Used by radio discovery */ + char dlep_multicast_ipv4_dot[IPV4_ADDR_STRING_LEN]; + ipv4_address_t dlep_multicast_ipv4; + + char dlep_multicast_ipv6_dot[IPV6_ADDR_STRING_LEN]; + ipv6_address_t dlep_multicast_ipv6; + + /* + * Configuration data + */ + char local_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH+1]; + + + uint16_t flow_control; + uint16_t auth_type; + + boolean_t start_on_launch; + boolean_t start_on_discovery; + + uint32_t local_id; + + //FIX -- uint8_t heartbeat_interval; + + uint32_t peer_offer_interval; + + /* 0-60 seconds. 0-disables. Must match the peer's interval */ + uint32_t peer_heartbeat_interval; + + /* missed HBs that indicate failure */ + uint32_t peer_heartbeat_missed_threshold; + + uint32_t peer_term_ack_tmo; + uint32_t peer_term_missed_ack_threshold; + + uint32_t neighbor_up_ack_tmo; + uint32_t neighbor_up_missed_ack_threshold; + + /* to drive periodic updates in milliseconds, 400 default */ + uint32_t neighbor_update_interval_tmo; + + uint32_t neighbor_activity_timer; + + uint32_t neighbor_down_ack_tmo; + uint32_t neighbor_down_missed_ack_threshold; + + int dlep_udp_sockfd; + int dlep_tcp_sockfd; + int dlep_tcp_client_sockfd; + + struct sockaddr_in dlep_addr; + struct sockaddr_in client; + struct sockaddr_in client_udp; + + struct sockaddr_in6 client_udp_6; + struct sockaddr_in6 dlep_addr6; + struct sockaddr_in6 client_6; + + struct ipv6_mreq group6; + struct ip_mreq group; + int reuse; + + int client_lenght; + socklen_t dlep_sock_len; + + struct sockaddr_in msg_addr; + struct sockaddr_in6 msg6_addr; + socklen_t msg_sock_len; + +} dlep_config_t; + + + + +extern +dlep_config_t *dlep_get_config_ptr(void); + +extern void +dlep_default_config(void); + +extern void +dlep_display_config(dlep_config_t *p2config); + +extern void +dlep_read_config_file(dlep_config_t *p2config); + + +#endif + + diff --git a/dlep_radio_ipv6/dlep_context_neighbor.c b/dlep_radio_ipv6/dlep_context_neighbor.c new file mode 100644 index 0000000..2c58ad6 --- /dev/null +++ b/dlep_radio_ipv6/dlep_context_neighbor.c @@ -0,0 +1,316 @@ +/*---------------------------------------------------------------------- + * dlep_context_neighbor.c -- neighbor context management routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include + +#include "stw_system_timer.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_server_neighbor_fsm.h" +#include "dlep_context_neighbor.h" + + +static uint16_t sid = 0; + + +static uint16_t sid_alloc (void) +{ + sid++; + return (sid); +} + + +/** + * NAME + * dlep_get_next_neighbor_id + * + * SYNOPSIS + * #include "dlep_context_neighbor.h" + * uint16_t + * dlep_get_next_neighbor_id(void) + * + * DESCRIPTION + * This function returns the next neighbor ID. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * Next neighbor ID + * + */ +uint16_t +dlep_get_next_neighbor_id (void) +{ + return (sid_alloc()); +} + + +/** + * NAME + * dlep_neighbor_init + * + * SYNOPSIS + * #include "dlep_context_neighbor.h" + * void + * dlep_neighbor_init(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function initializes the neighbor context data after the + * neighbor has been allocated. + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context + * + * OUTPUT PARAMETERS + * p2neighbor - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_init (dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_neighbor_init\n"); + if (!p2neighbor) { + return; + } + + p2neighbor->p2next_neighbor = NULL; + + p2neighbor->local_id = 0; + + /* The global neighbor id to be assigned by the server */ + p2neighbor->sequence = 0; + + p2neighbor->status_code = RFC5444_SUCCESS; + + /* + * Saved sequence number to match the neighbor init + * ACK from the router. + */ + p2neighbor->expected_neighbor_init_ack_sequence = 0; + p2neighbor->expected_neighbor_term_ack_sequence = 0; + p2neighbor->expected_neighbor_address_response_sequence = 0; + p2neighbor->expected_neighbor_link_char_response_sequence = 0; + + /* + * RF metrics + */ + p2neighbor->rlq_tx = 100; + p2neighbor->resources = 100; + p2neighbor->latency = 10; + p2neighbor->cdr_tx = 1000000000; + p2neighbor->mdr_tx = 1000000000; + p2neighbor->mtu = 1500; + + /* + * This is the number of times the init ACK timer has + * expired waiting on the init ACK. + */ + p2neighbor->neighbor_up_ack_tmo_count = 0; + + /* + * This is the number of times the update ACK timer has + * expired waiting on the update ACK. + */ + p2neighbor->neighbor_update_ack_tmo_count = 0; + + /* + * used by the activity tmr to track messages on the neighbor neighbor + * TRUE == active + */ + p2neighbor->neighbor_activity_flag = 0; + + /* + * default activity timer duration, seconds + */ + p2neighbor->neighbor_activity_duration = 5; + + /* Initialize IPv4/IPv6 addresses */ + ipv4_zero_address(&p2neighbor->ipv4_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + + p2neighbor->ipv6_subnet_prefix = 0; + p2neighbor->update_ipv6_operation = RFC5444_NO_ADDRESS; + + /* + * This is the number of times the terminate ACK timer has + * expired waiting on the terminate ACK. + */ + p2neighbor->neighbor_down_ack_tmo_count = 0; + + p2neighbor->neighbor_fsm_handle = NULL; + dlep_neighbor_fsm_create(p2neighbor); + + stw_system_timer_prepare(&p2neighbor->neighbor_init_ack_tmr); + stw_system_timer_prepare(&p2neighbor->neighbor_update_ack_tmr); + stw_system_timer_prepare(&p2neighbor->neighbor_activity_tmr); + stw_system_timer_prepare(&p2neighbor->neighbor_update_interval_tmr); + stw_system_timer_prepare(&p2neighbor->neighbor_term_ack_tmr); + + return; +} + + +/** + * NAME + * dlep_neighbor_clear + * + * SYNOPSIS + * #include "dlep_context_neighbor.h" + * void + * dlep_neighbor_clear(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function should be called as part of the work needed to + * tear down a neighbor. All activity is stopped and neighbor + * internal resources are released. + * + * The context block itself is not released. + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context + * + * OUTPUT PARAMETERS + * p2neighbor - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_neighbor_clear (dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_neighbor_clear\n"); + if (!p2neighbor) { + return; + } + + p2neighbor->local_id = 0; + + mac_zero_address(p2neighbor->mac_address); + + stw_system_timer_stop(&p2neighbor->neighbor_init_ack_tmr); + stw_system_timer_stop(&p2neighbor->neighbor_update_ack_tmr); + stw_system_timer_stop(&p2neighbor->neighbor_activity_tmr); + stw_system_timer_stop(&p2neighbor->neighbor_update_interval_tmr); + stw_system_timer_stop(&p2neighbor->neighbor_term_ack_tmr); + return; +} + + +/** + * NAME + * dlep_neighbor_display + * + * SYNOPSIS + * #include "dlep_context_neighbor.h" + * void + * dlep_neighbor_display(dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function displays the neighbor context data + * + * INPUT PARAMETERS + * p2neighbor - This is a pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_neighbor_display (dlep_context_neighbor_t *p2neighbor) +{ +printf("dlep_neighbor_display\n"); + ipv4_address_t addr_ipv4; + ipv6_address_t addr_ipv6; + if (!p2neighbor) { + return; + } + + mac_print_address (" Neighbor MAC=", p2neighbor->mac_address); +#if 0 + addr_ipv6.v6_addr.v6_addr32[0] = p2neighbor->ipv6_address.v6_addr.v6_addr32[0]; //added + addr_ipv6.v6_addr.v6_addr32[1] = p2neighbor->ipv6_address.v6_addr.v6_addr32[1]; + addr_ipv6.v6_addr.v6_addr32[2] = p2neighbor->ipv6_address.v6_addr.v6_addr32[2]; + addr_ipv6.v6_addr.v6_addr32[3] = p2neighbor->ipv6_address.v6_addr.v6_addr32[3]; +#endif +//vinod + + addr_ipv6.v6_addr.v6_addr16[0] = p2neighbor->ipv6_address.v6_addr.v6_addr16[0]; + addr_ipv6.v6_addr.v6_addr16[1] = p2neighbor->ipv6_address.v6_addr.v6_addr16[1]; + addr_ipv6.v6_addr.v6_addr16[2] = p2neighbor->ipv6_address.v6_addr.v6_addr16[2]; + addr_ipv6.v6_addr.v6_addr16[3] = p2neighbor->ipv6_address.v6_addr.v6_addr16[3]; + addr_ipv6.v6_addr.v6_addr16[4] = p2neighbor->ipv6_address.v6_addr.v6_addr16[4]; + addr_ipv6.v6_addr.v6_addr16[5] = p2neighbor->ipv6_address.v6_addr.v6_addr16[5]; + addr_ipv6.v6_addr.v6_addr16[6] = p2neighbor->ipv6_address.v6_addr.v6_addr16[6]; + addr_ipv6.v6_addr.v6_addr16[7] = p2neighbor->ipv6_address.v6_addr.v6_addr16[7]; + + + ipv6_print_address(" Neighbor IPv6=", &addr_ipv6); + + addr_ipv4.v4_addr.v4_addr32 = p2neighbor->ipv4_address.v4_addr.v4_addr32; + ipv4_print_address(" Neighbor IPv4=", &addr_ipv4); + + /* ipv4_print_address(" Neighbor IPv4=",&p2neighbor->ipv4_address); + ipv4_print_address(NULL,&p2neighbor->ipv4_address); */ + + printf(" activity timer=%u milliseconds \n", + p2neighbor->neighbor_activity_duration); + + printf(" Metrics:\n"); + printf(" RLQ TX=%u <0-100>", p2neighbor->rlq_tx); + printf(" RLQ RX=%u <0-100> \n", p2neighbor->rlq_rx); + printf(" Resources =%u <0-100> \n", p2neighbor->resources); + printf(" Latency=%llu milliseconds \n", p2neighbor->latency); + printf(" CDR TX=%llu bps ", p2neighbor->cdr_tx); + printf(" CDR RX=%llu bps \n", p2neighbor->cdr_rx); + printf(" MDR TX=%llu bps ", p2neighbor->mdr_tx); + printf(" MDR RX=%llu bps \n", p2neighbor->mdr_rx); + printf(" MTU=%u \n",p2neighbor->mtu); + + return; +} + + diff --git a/dlep_radio_ipv6/dlep_context_neighbor.h b/dlep_radio_ipv6/dlep_context_neighbor.h new file mode 100644 index 0000000..993a501 --- /dev/null +++ b/dlep_radio_ipv6/dlep_context_neighbor.h @@ -0,0 +1,151 @@ +/*---------------------------------------------------------------------- + * dlep_context_neighbor.h -- Session context definitions + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONTEXT_NEIGHBOR_H__ +#define __DLEP_CONTEXT_NEIGHBOR_H__ + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" + +#include "rfc5444_types.h" + + + +/* + * Defines the data used to manage a neighbor + * and its stateful data + */ +typedef struct context_neighbor_t_ { + struct context_neighbor_t_ *p2next_neighbor; + + /* pointer back to the peer context */ + void *p2peer; + + /* used to track responses */ + uint16_t sequence; + + /* a locally metered neighbor ID for user I/F */ + uint32_t local_id; + + /* Set the status code from the last neighbor operation + * or as required to sending a neighbor message. + */ + uint16_t status_code; + + /* squirrel away the sequence number to track responses */ + uint16_t expected_neighbor_init_ack_sequence; + uint16_t expected_neighbor_term_ack_sequence; + uint16_t expected_neighbor_address_response_sequence; + uint16_t expected_neighbor_link_char_response_sequence; + + uint8_t mac_address[MAC_ADDR_LEN_IN_BYTES]; + ipv4_address_t ipv4_address; + ipv6_address_t ipv6_address; + + /* + * neighbor_update_address layer 3 addresses + * update layer 3 addresses for the sim + */ + uint8_t update_ipv4_operation; + ipv4_address_t update_ipv4_address; + + uint8_t update_ipv6_operation; + uint8_t ipv6_subnet_prefix; + ipv6_address_t update_ipv6_address; + ipv6_address_t update_ipv6_subnet_address; + + /* + * RF metrics + */ +#if 0 + uint8_t rlq; /* 0-poor, 100-good */ + uint8_t resources; /* 0-100% */ + uint16_t latency; /* millisec */ + uint64_t cdr; /* kbps */ + uint64_t mdr; /* kbps */ +#endif + uint8_t rlq_rx; /* 0-poor, 100-good */ + uint8_t rlq_tx; /* 0-poor, 100-good */ + uint8_t resources_rx; /* 0 -100% */ + uint8_t resources_tx; /* 0 -100% */ + uint64_t latency; /* millisec */ + uint8_t resources; /* 0 -100% */ + uint16_t mtu; + uint64_t cdr_rx; /* bps */ + uint64_t cdr_tx; /* bps */ + uint64_t mdr_tx; /* bps */ + uint64_t mdr_rx; /* bps */ + uint64_t mrw; /* credits */ + uint64_t rrw; /* credits */ + uint64_t cgr; /* credits */ + uint32_t eft; /* millisec */ + + boolean_t CREDIT_NOT_SUPPORTED; /* credits */ + /* neighbor state machine handle */ + void *neighbor_fsm_handle; + + /* state machine working variables */ + uint32_t neighbor_up_ack_tmo_count; + uint32_t neighbor_update_ack_tmo_count; + uint32_t neighbor_down_ack_tmo_count; + + uint32_t neighbor_activity_duration; + boolean_t neighbor_activity_flag; + + stw_tmr_t neighbor_init_ack_tmr; + stw_tmr_t neighbor_update_ack_tmr; + stw_tmr_t neighbor_activity_tmr; + stw_tmr_t neighbor_update_interval_tmr; + stw_tmr_t neighbor_term_ack_tmr; + +} dlep_context_neighbor_t; + + + + +extern uint16_t +dlep_get_next_neighbor_id(void); + +extern void +dlep_neighbor_init(dlep_context_neighbor_t *p2neighbor); + +extern void +dlep_neighbor_clear(dlep_context_neighbor_t *p2neighbor); + +extern void +dlep_neighbor_display(dlep_context_neighbor_t *p2neighbor); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_context_neighbor_management.c b/dlep_radio_ipv6/dlep_context_neighbor_management.c new file mode 100644 index 0000000..fb1303f --- /dev/null +++ b/dlep_radio_ipv6/dlep_context_neighbor_management.c @@ -0,0 +1,476 @@ +/*---------------------------------------------------------------------- + * dlep_context_neighbor_management.c + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" + + +static uint32_t local_id = 5000; + + +/* + * Porting: The implementation of the functions in this file can be + * changed to platform specific resource management APIs, such as + * AVL or RB trees. + */ + + +/* + * function to meter a local id + */ +static uint32_t +dlep_get_next_local_id (void) +{ + local_id++; + if (!local_id) { + local_id++; + } + return (local_id); +} + + +/** + * NAME + * dlep_allocate_session + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * dlep_context_neighbor_t + * *dlep_neighbor_allocate(dlep_context_peer_t *p2peer, + * uint8_t *mac_address) + * + * DESCRIPTION + * Allocates a neighbor context block for a new neighbor. The + * neighbor context is set to defaults and put in the database. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * mac_address - This is a pointer the MAC address assigned + * to the neighbor. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * A pointer to the newly allocated neighbor context. + * NULL is returned if the allocation failed. + * + */ +dlep_context_neighbor_t +*dlep_neighbor_allocate (dlep_context_peer_t *p2peer, + uint8_t *mac_address) +{ +printf("dlep_neighbor_allocate\n"); + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + return (NULL); + } + + if (!mac_address) { + return (NULL); + } + + p2ctx = NULL; + p2ctx = malloc(sizeof(dlep_context_neighbor_t)); + if (!p2ctx) { + DLEP_DEBUG("%s-%u Error: No resource for new neighbor block \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return (NULL); + } + + dlep_neighbor_init(p2ctx); + + p2ctx->p2peer = p2peer; + + p2ctx->local_id = dlep_get_next_local_id(); + + /* The sequence number must be used to correlate the + * ACKs with the original request. + */ + p2ctx->sequence = 0; + + mac_copy_address(p2ctx->mac_address, mac_address); + + /* + * insert the new context in the list + */ + p2ctx->p2next_neighbor = p2peer->neighbor_list; + p2peer->neighbor_list = p2ctx; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Allocated local id=%u neighbor %p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->local_id, + p2ctx); + } + + return (p2ctx); +} + + +/** + * NAME + * dlep_neighbor_remove + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * void + * dlep_neighbor_remove(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t **p2neighbor) + * + * DESCRIPTION + * This function removes the neighbor context block from + * the nodes database. Dynamically allocated memory + * must be freed prior to removing a neighbor. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context. + * + * p2neighbor - A pointer to the neighbor context block pointer + * + * OUTPUT PARAMETERS + * p2neighbor - updated. + * + * RETURN VALUE + * none + * + */ +void +dlep_neighbor_remove (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t **p2neighbor) +{ +printf("dlep_neighbor_remove\n"); + dlep_context_neighbor_t *p2previous; + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + DLEP_DEBUG("%s-%u peer context null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return; + } + + p2ctx = p2peer->neighbor_list; + + if (!p2ctx) { + DLEP_DEBUG("%s-%u Empty neighbor list \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return; + } + + if (p2ctx == *p2neighbor) { + p2peer->neighbor_list = p2ctx->p2next_neighbor; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u deallocating local id=%u %p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->local_id, + p2ctx); + } + + /* now free the block */ + free(p2ctx); + + *p2neighbor = NULL; + return; + } + + p2previous = p2peer->neighbor_list; + p2ctx = p2previous->p2next_neighbor; + + while (p2ctx) { + + if (p2ctx == *p2neighbor) { + p2previous->p2next_neighbor = p2ctx->p2next_neighbor; + + if (dlep_debug_flags & DLEP_NEIGHBOR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u deallocating local id=%u %p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->local_id, + p2ctx); + } + + free(p2ctx); + + *p2neighbor = NULL; + break; + + } else { + /* walk the list */ + p2previous = p2ctx; + p2ctx = p2ctx->p2next_neighbor; + } + } + return; +} + + +/** + * NAME + * dlep_get_neighbor_by_local_id + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * dlep_context_neighbor_t + * *dlep_get_neighbor_by_local_id(dlep_context_peer_t *p2peer, + * uint32_t local_id) + * + * DESCRIPTION + * This function searches the database for the specified local ID + * and returns the neighbor context pointer. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context + * + * local_id - The local ID to locate + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * A pointer to the neighbor context. + * NULL is returned if the neighbor was not found. + * + */ +dlep_context_neighbor_t +*dlep_get_neighbor_by_local_id (dlep_context_peer_t *p2peer, + uint32_t local_id) +{ +printf("dlep_get_neighbor_by_local_id\n"); + dlep_context_neighbor_t *result; + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + DLEP_DEBUG("%s-%u null peer context \n", + DEBUG_FUNCTION, + DEBUG_LINE); + return (NULL); + } + + result = NULL; + + p2ctx = p2peer->neighbor_list; + while (p2ctx) { + + if (p2ctx->local_id == local_id) { + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_neighbor; + } + } + return (result); +} + + +/** + * NAME + * dlep_get_neighbor_by_mac_address + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * dlep_context_neighbor_t + * *dlep_get_neighbor_by_mac_address(dlep_context_peer_t *p2peer, + * uint8_t *p2mac_address) + * + * DESCRIPTION + * This function searches the database for the specified MAC address + * and returns the neighbor context pointer. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context + * + * p2mac_address - the MAC to locate + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * A pointer to the neighbor context. + * NULL is returned if the neighbor was not found. + * + */ +dlep_context_neighbor_t +*dlep_get_neighbor_by_mac_address (dlep_context_peer_t *p2peer, + uint8_t *p2mac_address) +{ +printf("dlep_get_neighbor_by_mac_address\n"); + dlep_context_neighbor_t *result; + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + return (NULL); + } + + result = NULL; + + p2ctx = p2peer->neighbor_list; + while (p2ctx) { + + if (mac_compare_address(p2ctx->mac_address, p2mac_address)) { +// printf("\n Checking MAC in the MAC LIST"); + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_neighbor; + } + } +// printf("\n Not preset MAC in the MAC list"); + return (result); +} + + +/** + * NAME + * dlep_neighbor_deallocate_all + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * void + * dlep_neighbor_deallocate_all(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function removes and frees all neighbor context blocks + * tied to this node. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_neighbor_deallocate_all (dlep_context_peer_t *p2peer) + +{ +printf("dlep_neighbor_deallocate_all\n"); + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + return; + } + + /* + * Now free each block + */ + while (p2peer->neighbor_list) { + p2ctx = p2peer->neighbor_list; + + /* clear and stop processing */ + dlep_neighbor_clear(p2ctx); + + p2peer->neighbor_list = p2ctx->p2next_neighbor; + free(p2ctx); + } + + /* + * Nullify the node's neighbor list + */ + p2peer->neighbor_list = NULL; + return; +} + + +/** + * NAME + * dlep_neighbor_list_all + * + * SYNOPSIS + * #include "dlep_context_neighbor_management.h" + * void + * dlep_neighbor_list_all(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function displays all established neighbors on + * the peer to stdout. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_neighbor_list_all (dlep_context_peer_t *p2peer) +{ +printf("dlep_neighbor_list_all\n"); + dlep_context_neighbor_t *p2ctx; + + if (!p2peer) { + return; + } + + p2ctx = p2peer->neighbor_list; + while (p2ctx) { + dlep_neighbor_display(p2ctx); + p2ctx = p2ctx->p2next_neighbor; + } + printf("\n"); + return; +} + + diff --git a/dlep_radio_ipv6/dlep_context_neighbor_management.h b/dlep_radio_ipv6/dlep_context_neighbor_management.h new file mode 100644 index 0000000..200121a --- /dev/null +++ b/dlep_radio_ipv6/dlep_context_neighbor_management.h @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------- + * dlep_context_neighbor_management.h + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONTEXT_SESSION_MANAGEMENT_H__ +#define __DLEP_CONTEXT_SESSION_MANAGEMENT_H__ + +#include "dlep_context_neighbor.h" +#include "dlep_context_peer.h" + + +extern dlep_context_neighbor_t +*dlep_neighbor_allocate(dlep_context_peer_t *p2peer, + uint8_t *mac_address); + +extern void +dlep_neighbor_remove(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t **p2context); + +extern dlep_context_neighbor_t +*dlep_get_neighbor_by_local_id(dlep_context_peer_t *p2peer, + uint32_t local_id); + +extern dlep_context_neighbor_t +*dlep_get_neighbor_by_mac_address(dlep_context_peer_t *p2peer, + uint8_t *mac_address); + +extern void +dlep_neighbor_deallocate_all(dlep_context_peer_t *p2peer); + +extern void +dlep_neighbor_list_all(dlep_context_peer_t *p2peer); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_context_peer.c b/dlep_radio_ipv6/dlep_context_peer.c new file mode 100644 index 0000000..4bc7f00 --- /dev/null +++ b/dlep_radio_ipv6/dlep_context_peer.c @@ -0,0 +1,482 @@ +/*---------------------------------------------------------------------- + * dlep_context_peer.c -- Routines to manage the peer context data + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "stw_system_timer.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_config.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_peer.h" + + +extern void +dlep_fsm_destroy(dlep_context_peer_t *p2peer); + +extern void +dlep_fsm_create(dlep_context_peer_t *p2peer); + + + +/* Meters a locally unique ID for nodes */ +static uint32_t peer_id_meter = 0; + + +/* + * API to increment seq ID + */ +uint16_t +get_next_sequence_number (dlep_context_peer_t *p2peer) +{ + if (!p2peer) { + return (0); + } + + p2peer->sequence++; + if (!p2peer->sequence) { + p2peer->sequence++; + } + return (p2peer->sequence); +} + + + +/* + * Local API to meter peer IDs + */ +static uint32_t +get_next_peer_id (void) +{ + peer_id_meter++; + if (!peer_id_meter) { + peer_id_meter++; + } + return (peer_id_meter); +} + +/* Below two init functions are added for DLEPv7 */ + +/* + * init optional signal data + */ +static uint32_t init_optional_signal(void) { + + uint32_t opt_signal = 0; + + opt_signal |= (~(~0 << (RFC5444_MAX_MESSAGE_CODE - 1))); + + opt_signal &= (~(1 << (RFC5444_MSG_PEER_UPDATE_RES -1))); + opt_signal &= (~(1 << (RFC5444_MSG_PEER_UPDATE_REQ -1))); + opt_signal &= (~(1 << (RFC5444_MSG_LINK_CHAR_RES -1))); + opt_signal &= (~(1 << (RFC5444_MSG_LINK_CHAR_REQ -1))); + + return opt_signal; +} + +/* + * init optional data item + */ +static uint32_t init_optional_data_item(void) { + + uint32_t opt_data = 0; + + opt_data |= (~(~0 << (RFC5444_MAX_DATA_ITEM - 1))); + + + opt_data &= (~(1 << (RFC5444_TLV_LINK_RESOURCES_METRIC_RX - 1))); + opt_data &= (~(1 << (RFC5444_TLV_LINK_RESOURCES_METRIC_TX - 1))); + opt_data &= (~(1 << (RFC5444_TLV_LINK_RLQ_METRIC_TX -1))); + opt_data &= (~(1 << (RFC5444_TLV_LINK_RLQ_METRIC_RX -1))); + opt_data &= (~(1 << (RFC5444_TLV_CREDIT_WINDOW_STATUS -1))); + opt_data &= (~(1 << (RFC5444_TLV_CREDIT_GRANT -1))); + opt_data &= (~(1 << (RFC5444_TLV_CREDIT_REQUEST -1))); + opt_data &= (~(1 << (RFC5444_TLV_VENDOR_EXTENSION -1))); + opt_data &= (~(1 << (RFC5444_TLV_IPV4_ATTACHED_SUBNET -1))); + opt_data &= (~(1 << (RFC5444_TLV_IPV6_ATTACHED_SUBNET -1))); + + return opt_data; +} + +/** + * NAME + * dlep_peer_init + * + * SYNOPSIS + * #include "dlep_context_peer.h" + * void + * dlep_peer_init(dlep_config_t *p2config, + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function initializes the peer context data after the + * peer has been allocated. The function copies the configuration + * parameters to the peer context. This prevents changes to + * configuration parameters occuring while the protocol is + * active. + * + * INPUT PARAMETERS + * p2config - A pointer to the configuration data + * + * p2peer - A pointer to the peer context + * + * OUTPUT PARAMETERS + * p2peer - updated + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_init (dlep_config_t *p2config, dlep_context_peer_t *p2peer) +{ + if (!p2config || !p2peer) { + return; + } + + p2peer->p2config = p2config; + + /* + * The next_node pointer and the IPv4:Port are already present + */ + p2peer->peer_id = get_next_peer_id(); + + p2peer->sequence = 0; + p2peer->router_id = 0; + p2peer->client_id = 0; + + p2peer->expected_peer_offer_sequence = 0; + p2peer->expected_peer_term_ack_sequence = 0; + p2peer->expected_peer_update_response_sequence = 0; + + p2peer->status_code = RFC5444_SUCCESS; + + strcpy(p2peer->peer_type_description, "no peer description"); + p2peer->peer_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH] = '\0'; + + + p2peer->peer_term_ack_tmo = + p2config->peer_term_ack_tmo; + p2peer->peer_term_missed_ack_threshold = + p2config->peer_term_missed_ack_threshold; + + p2peer->peer_heartbeat_interval = + p2config->peer_heartbeat_interval; + p2peer->peer_heartbeat_missed_threshold = + p2config->peer_heartbeat_missed_threshold; + + p2peer->neighbor_up_ack_tmo = + p2config->neighbor_up_ack_tmo; + p2peer->neighbor_up_missed_ack_threshold = + p2config->neighbor_up_missed_ack_threshold; + + p2peer->neighbor_update_interval_tmo = + p2config->neighbor_update_interval_tmo; + + p2peer->neighbor_activity_timer = + p2config->neighbor_activity_timer; + + p2peer->neighbor_down_ack_tmo = + p2config->neighbor_down_ack_tmo; + p2peer->neighbor_down_missed_ack_threshold = + p2config->neighbor_down_missed_ack_threshold; + + + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + ipv4_zero_address(&p2peer->update_ipv4_address); + + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + ipv6_zero_address(&p2peer->update_ipv6_address); + + + /* + * This is the number of times the timer has + * expired waiting on the ack msg. + */ + p2peer->peer_offer_timeout_count = 0; + p2peer->peer_heartbeat_timeout_count = 0; + p2peer->peer_term_ack_timeout_count = 0; + + /* + * pointer to a single linked list of neighbors associated + * with this node. + */ + p2peer->neighbor_list = NULL; + + p2peer->fsm_handle = NULL; + dlep_fsm_create(p2peer); + + /* + * init optional data and signal item + */ + p2peer->optional_signal = init_optional_signal(); + p2peer->optional_data_item = init_optional_data_item(); + + stw_system_timer_prepare(&p2peer->peer_offer_tmr); + stw_system_timer_prepare(&p2peer->peer_heartbeat_tmr); + stw_system_timer_prepare(&p2peer->peer_term_ack_tmr); + + return; +} + + +/** + * NAME + * dlep_peer_clear + * + * SYNOPSIS + * #include "dlep_context_peer.h" + * void + * dlep_peer_clear(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function should be called as part of the work + * needed to tear down a node. + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer data + * structure to be freed. + * + * OUTPUT PARAMETERS + * p2peer - cleared + * + * RETURN VALUE + * None + * + */ +void +dlep_peer_clear (dlep_context_peer_t *p2peer) +{ + RC_STW_t rc; + + if (!p2peer) { + printf("%s-%u peer pointer null \n", + DEBUG_FUNCTION, DEBUG_LINE); + return; + } + + rc = stw_system_timer_stop(&p2peer->peer_offer_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + rc = stw_system_timer_stop(&p2peer->peer_heartbeat_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + rc = stw_system_timer_stop(&p2peer->peer_term_ack_tmr); + if (rc != RC_STW_OK) { + DLEP_DEBUG("%s-%u peer_id=%u rc_stw rc=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + rc); + } + + p2peer->peer_id = 0; + p2peer->peer_udp_port = 0; + p2peer->peer_tcp_port = 0; + + dlep_fsm_destroy(p2peer); + return; +} + + +/** + * NAME + * dlep_peer_display + * + * SYNOPSIS + * #include "dlep_context_peer.h" + * void + * dlep_peer_display(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function displays the peer node data + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_short_display (dlep_context_peer_t *p2peer) +{ + if (!p2peer) { + return; + } + + printf("\nDLEP Local Client %u \n", + p2peer->peer_id); + + /* printf(" Client ID=%u \n", + p2peer->client_id); + + printf(" Router ID=%u \n", + p2peer->router_id); */ + + printf(" Peer Description=%s \n", + p2peer->peer_type_description); + + printf(" Peer UDP port=%u \n", + p2peer->peer_udp_port); + + printf(" Peer TCP port=%u \n", + p2peer->peer_tcp_port); + + ipv4_print_address(" Peer IPv4", + &p2peer->peer_ipv4); + + ipv6_print_address(" Peer IPv6", + &p2peer->peer_ipv6); + + return; +} + + +/** + * NAME + * dlep_peer_display + * + * SYNOPSIS + * #include "dlep_context_peer.h" + * void + * dlep_peer_display(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function displays the peer node data + * + * INPUT PARAMETERS + * p2peer - This is a pointer to the peer data + * structure to be freed. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_display (dlep_context_peer_t *p2peer) +{ + if (!p2peer) { + return; + } + + printf("\nDLEP Local Client %u \n", + p2peer->peer_id); + + /* printf(" Client ID=%u \n", + p2peer->client_id); + + printf(" Router ID=%u \n", + p2peer->router_id); */ + + printf(" Peer Description=%s \n", + p2peer->peer_type_description); + + printf(" Peer UDP port=%u \n", + p2peer->peer_udp_port); + + printf(" Peer TCP port=%u \n", + p2peer->peer_tcp_port); + + ipv4_print_address(" Peer IPv4", + &p2peer->peer_ipv4); + + ipv6_print_address(" Peer IPv6", + &p2peer->peer_ipv6); + + /* printf(" router offer timeout count=%u \n", + p2peer->peer_offer_timeout_count); */ + + printf(" peer heartbeat missed count=%u \n", + p2peer->peer_heartbeat_timeout_count); + + /* printf(" peer term ack missed count=%u \n", + p2peer->peer_term_ack_timeout_count); */ + + printf(" peer term ack missed threshold=%u \n", + p2peer->peer_term_missed_ack_threshold); + + printf(" neighbor_up_ack_tmo=%u milliseconds \n", + p2peer->neighbor_up_ack_tmo); + + printf(" neighbor_up_missed_ack_threshold=%u \n", + p2peer->neighbor_up_missed_ack_threshold); + + printf(" neighbor_update_interval_tmo=%u milliseconds \n", + p2peer->neighbor_update_interval_tmo); + + printf(" neighbor_activity_timer=%u \n", + p2peer->neighbor_activity_timer); + + printf(" neighbor_down_ack_tmo=%u milliseconds \n", + p2peer->neighbor_down_ack_tmo); + + printf(" neighbor_down_missed_ack_threshold=%u \n", + p2peer->neighbor_down_missed_ack_threshold); + + printf(" Metrics:\n"); + printf(" RLQ TX=%u <0-100>", p2peer->rlq_tx); + printf(" RLQ RX=%u <0-100> \n", p2peer->rlq_rx); + printf(" Resources =%u <0-100>", p2peer->resources); + printf(" Latency=%llu milliseconds \n", p2peer->latency); + printf(" CDR TX=%llu bps ", p2peer->cdr_tx); + printf(" CDR RX=%llu bps \n", p2peer->cdr_rx); + printf(" MDR TX=%llu bps ", p2peer->mdr_tx); + printf(" MDR RX=%llu bps \n", p2peer->mdr_rx); + printf(" MTU=%u \n",p2peer->mtu); + + return; +} + + diff --git a/dlep_radio_ipv6/dlep_context_peer.h b/dlep_radio_ipv6/dlep_context_peer.h new file mode 100644 index 0000000..d256572 --- /dev/null +++ b/dlep_radio_ipv6/dlep_context_peer.h @@ -0,0 +1,230 @@ +/*---------------------------------------------------------------------- + * dlep_context_peer.h -- routines to manage the peer context data + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONTEXT_PEER_H__ +#define __DLEP_CONTEXT_PEER_H__ + +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" + +#include "rfc5444_scratch_pad.h" + +#include "dlep_config.h" +#include "dlep_context_neighbor.h" + + +#define ERROR_STRING_LENGTH ( 32 ) + + + +/* + * Defines the data used to manage a node + */ +typedef struct context_peer_t_ { + struct context_peer_t_ *p2next_peer; + + /* a locally unique ID for display and user I/F */ + uint32_t peer_id; + + /* DLEP IDs */ + uint32_t router_id; + uint32_t client_id; + + /* link to the configuration data */ + dlep_config_t *p2config; + + /* + * incremented with each peer and neighbor message + * transmitted + */ + uint16_t sequence; + + /* expected seq set when the modem init is sent */ + uint16_t expected_peer_offer_sequence; + + /* expected seq set when the peer term is sent */ + uint16_t expected_peer_term_ack_sequence; + + /* expected seq set when the peer update is sent */ + uint16_t expected_peer_update_response_sequence; + + /* + * If the return code is non-zero, an error occurred + * and the Return Status TLV will be inserted when a + * response is built. + */ + uint16_t status_code; + + char peer_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH+1]; + + /* + * peer ip address info to uniquely discriminate nodes + */ +#if 0 + uint16_t peer_port; +#endif + uint16_t peer_udp_port; + uint16_t peer_tcp_port; + ipv4_address_t peer_ipv4; + ipv6_address_t peer_ipv6; + + struct sockaddr_in msg_addr; + struct sockaddr_in6 msg6_addr; + + socklen_t msg_sock_len; + + ipv4_address_t ipv4_address; + ipv6_address_t ipv6_address; + + + ipv4_address_t ipv4_attached_subnet; + // ipv6_address_t ipv6_attached_subnet; + + uint32_t peer_term_ack_tmo; + uint32_t peer_term_missed_ack_threshold; + + uint32_t peer_heartbeat_interval; + uint32_t peer_heartbeat_missed_threshold; + + /* + * peer_update addresses + * update layer 3 addresses for the sim + */ + uint8_t update_ipv4_operation; + ipv4_address_t update_ipv4_address; + + uint8_t update_ipv6_operation; + ipv6_address_t update_ipv6_address; + + + uint32_t neighbor_up_ack_tmo; + uint32_t neighbor_up_missed_ack_threshold; + + /* + * used by the client to drive periodic updates + * in milliseconds + */ + uint32_t neighbor_update_interval_tmo; + + uint32_t neighbor_activity_timer; + + uint32_t neighbor_down_ack_tmo; + uint32_t neighbor_down_missed_ack_threshold; + + + /* + * Peer Link-wide RF metrics + */ + uint16_t peer_supported_metrics; + + uint8_t rlq_rx; /* 0-poor, 100-good */ + uint8_t rlq_tx; /* 0-poor, 100-good */ + uint8_t resources_rx; /* 0 -100% */ + uint8_t resources_tx; /* 0 -100% */ + uint8_t resources; /* added for v27 */ + uint64_t latency; /* millisec */ + uint64_t cdr_rx; /* bps */ + uint64_t cdr_tx; /* bps */ + uint64_t mdr_tx; /* bps */ + uint64_t mdr_rx; /* bps */ + uint32_t eft; /* millisec */ + uint16_t mtu; /* added for v27 */ + /* + * Adding optional and data signal + */ + uint32_t optional_signal; + uint32_t optional_data_item; + + /* + * A few peer state working variables + */ + uint32_t peer_offer_timeout_count; + uint32_t peer_heartbeat_timeout_count; + uint32_t peer_term_ack_timeout_count; + + /* + * The list of neighbors associated with this node. + * For simplicity, this is a linked list. If the + * number of neighbors per peer is small, this is + * not a problem. If the numbers increase we can + * go to a hasher. + */ + dlep_context_neighbor_t *neighbor_list; + + /* + * peer state machine handle + */ + void *fsm_handle; + + stw_tmr_t peer_offer_tmr; + stw_tmr_t peer_heartbeat_tmr; + stw_tmr_t peer_term_ack_tmr; + + /* + * When a received message is parsed, its contents are + * parsed here. The data is then passed to the state + * machine where it is processed relative to the + * state for correctness. + */ + rfc5444_packet_scratch_pad_t packet_scratch_pad; + rfc5444_message_scratch_pad_t message_scratch_pad; + + uint32_t ttl; + +} dlep_context_peer_t; + + + +extern uint16_t +get_next_sequence_number(dlep_context_peer_t *p2peer); + +extern void +dlep_peer_init(dlep_config_t *p2config, dlep_context_peer_t *p2peer); + +extern void +dlep_peer_clear(dlep_context_peer_t *p2peer); + +extern void +dlep_peer_short_display(dlep_context_peer_t *p2peer); + +extern void +dlep_peer_display(dlep_context_peer_t *p2peer); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_context_peer_management.c b/dlep_radio_ipv6/dlep_context_peer_management.c new file mode 100644 index 0000000..808e291 --- /dev/null +++ b/dlep_radio_ipv6/dlep_context_peer_management.c @@ -0,0 +1,499 @@ +/*---------------------------------------------------------------------- + * dlep_context_node_management.c + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include + +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" + + +/* + * List anchor for the local nodes + */ +static dlep_context_peer_t *p2peer_list = NULL; + + +/** + * NAME + * dlep_allocate_node + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * dlep_context_peer_t + * *dlep_peer_allocate(ipv4_address_t *p2ipv4, uint16_t udp_port, tcp_port) + * + * DESCRIPTION + * Allocates a context block for a new node. The context + * block is set to defaults and put on the list. The IPv4 + * address and the port uniquely discriminate the node. + * + * INPUT PARAMETERS + * p2ipv4 - This is a pointer to the IPv4 address structure. + * + * udp_port - This is the udp port for the node. + * + * tcp_port - This is the tcp port for the node. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * A pointer to the newly allocated nod context. + * NULL is returned if the block could not be allocated. + * + */ +dlep_context_peer_t +*dlep_peer_allocate (ipv6_address_t *p2ipv6, ipv4_address_t *p2ipv4, uint16_t udp_port, uint16_t tcp_port) +{ + dlep_context_peer_t *p2ctx; + + p2ctx = NULL; + p2ctx = malloc(sizeof(dlep_context_peer_t)); + if (!p2ctx) { + DLEP_DEBUG("%s-%u Error: No resources for new peer context block \n", + DEBUG_FUNCTION, + DEBUG_LINE); + + return (NULL); + } + ipv6_copy_address(&p2ctx->peer_ipv6, p2ipv6); + ipv4_copy_address(&p2ctx->peer_ipv4, p2ipv4); + p2ctx->peer_udp_port = udp_port; + p2ctx->peer_tcp_port = tcp_port; + + + + /* + * jam the new peer context in the list + */ + p2ctx->p2next_peer = p2peer_list; + p2peer_list = p2ctx; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Allocated peer block %p \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx); + } + + return (p2ctx); +} + +/** + * NAME + * dlep_peer_remove + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_remove(dlep_context_peer_t **p2peer) + * + * DESCRIPTION + * This function removes a peer context block from the database. + * All dynamically allocate resources must be freed prior to + * removing a node. + * + * INPUT PARAMETERS + * p2peer - A pointer to the peer context block pointer + * + * OUTPUT PARAMETERS + * p2peer - nulled + * + * RETURN VALUE + * No return code + * The callers pointer is NULLed. If there was a problem, the + * callers peer context pointer is not updated. + * + */ +void +dlep_peer_remove (dlep_context_peer_t **p2peer) +{ + dlep_context_peer_t *p2previous; + dlep_context_peer_t *p2ctx; + + if (!p2peer_list) { + return; + } + + p2ctx = p2peer_list; + if (p2ctx == *p2peer) { + p2peer_list = p2ctx->p2next_peer; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u deallocating \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->peer_id); + } + + /* now free the block and update the caller's pointer */ + free(p2ctx); + *p2peer = NULL; + return; + } + + p2previous = p2peer_list; + p2ctx = p2previous->p2next_peer; + + while (p2ctx) { + if (p2ctx == *p2peer) { + p2previous->p2next_peer = p2ctx->p2next_peer; + + if (dlep_debug_flags & DLEP_PEER_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u deallocating \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->peer_id); + } + + /* now free the block and update the caller's pointer */ + free(p2ctx); + *p2peer = NULL; + break; + + } else { + /* walk the list */ + p2previous = p2ctx; + p2ctx = p2ctx->p2next_peer; + } + } + return; +} + + +/** + * NAME + * dlep_get_peer_by_peer_id + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * dlep_context_peer_t + * *dlep_get_peer_by_peer_id(uint16_t peer_id) + * + * DESCRIPTION + * This function searches the database for the specified peer ID + * and returns the context block pointer. + * + * INPUT PARAMETERS + * peer_id - The locally unique peer ID to look up + * + * RETURN VALUE + * A pointer to the peer context block. + * NULL is returned if the peer was not found. + * + */ +dlep_context_peer_t +*dlep_get_peer_by_peer_id (uint16_t peer_id) +{ + dlep_context_peer_t *result; + dlep_context_peer_t *p2ctx; + + result = NULL; + p2ctx = p2peer_list; + while (p2ctx) { + + if (p2ctx->peer_id == peer_id) { + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_peer; + } + } + return (result); +} + + +/** + * NAME + * dlep_peer_get_by_ipv4 + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * dlep_context_peer_t + * *dlep_peer_get_by_ipv4(ipv4_address_t *p2ipv4, + * uint16_t port) + * + * DESCRIPTION + * This function returns the pointer to the peer context block. + * + * INPUT PARAMETERS + * p2ipv4 - This is a pointer to the IPv4 address to locate + * + * port - This is the port used by the peer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * The pointer to the peer context block. + * NULL is returned if the peer context is not located. + * + */ +dlep_context_peer_t +*dlep_peer_get_by_ipv4 (ipv4_address_t *p2ipv4, uint16_t udp_port, uint16_t tcp_port) +{ + dlep_context_peer_t *result; + dlep_context_peer_t *p2ctx; + + if (!p2ipv4) { + return (NULL); + } + + result = NULL; + p2ctx = p2peer_list; + while (p2ctx) { + + if (ipv4_compare_address(&p2ctx->peer_ipv4, p2ipv4) && + p2ctx->peer_udp_port == udp_port && + p2ctx->peer_tcp_port == tcp_port) { + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_peer; + } + } + return (result); +} + + +/* dlep_peer_get_by_ipv6 */ //added for ipv6 + +dlep_context_peer_t +*dlep_peer_get_by_ipv6 (ipv6_address_t *p2ipv6, uint16_t udp_port, uint16_t tcp_port) +{ + dlep_context_peer_t *result; + dlep_context_peer_t *p2ctx; + + if (!p2ipv6) { + return (NULL); + } + + result = NULL; + p2ctx = p2peer_list; + while (p2ctx) { + + if (ipv6_compare_address(&p2ctx->peer_ipv6, p2ipv6) && + p2ctx->peer_udp_port == udp_port && + p2ctx->peer_tcp_port == tcp_port) { + result = p2ctx; + break; + + } else { + /* walk the list */ + p2ctx = p2ctx->p2next_peer; + } + } + return (result); +} + + + + +/** + * NAME + * dlep_peer_deallocate_all + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_deallocate_all(void) + * + * DESCRIPTION + * This function removes and frees all peer context blocks. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_deallocate_all (void) +{ + dlep_context_peer_t *p2ctx; + dlep_context_peer_t *p2free; + + p2ctx = p2peer_list; + while (p2ctx) { + p2free = p2ctx; + + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2ctx->peer_id); + } + + /* walk the list */ + p2ctx = p2ctx->p2next_peer; + free(p2free); + } + p2peer_list = NULL; + return; +} + +/** + * NAME + * dlep_peer_short_list_all + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_short_list_all(void) + * + * DESCRIPTION + * This function generates a short list of all peers. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_short_list_all (void) +{ + dlep_context_peer_t *p2ctx; + + p2ctx = p2peer_list; + while (p2ctx) { + dlep_peer_short_display(p2ctx); + p2ctx = p2ctx->p2next_peer; + } + printf("\n"); + return; +} + + +/** + * NAME + * dlep_peer_list_all + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_list_all(void) + * + * DESCRIPTION + * This function generates a list of all peers. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_list_all (void) +{ + dlep_context_peer_t *p2ctx; + + p2ctx = p2peer_list; + while (p2ctx) { + dlep_peer_display(p2ctx); + p2ctx = p2ctx->p2next_peer; + } + printf("\n"); + return; +} + + +/** + * NAME + * dlep_peer_neighbor_list_all + * + * SYNOPSIS + * #include "dlep_context_peer_management.h" + * void + * dlep_peer_neighbor_list_all(void) + * + * DESCRIPTION + * This function generates a list of all neighbors associated + * with each node + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_peer_neighbor_list_all (void) +{ + dlep_context_peer_t *p2ctx; + + p2ctx = p2peer_list; + while (p2ctx) { + dlep_peer_short_display(p2ctx); + + dlep_neighbor_list_all(p2ctx); + p2ctx = p2ctx->p2next_peer; + } + printf("\n"); + return; +} + + diff --git a/dlep_radio_ipv6/dlep_context_peer_management.h b/dlep_radio_ipv6/dlep_context_peer_management.h new file mode 100644 index 0000000..def1a93 --- /dev/null +++ b/dlep_radio_ipv6/dlep_context_peer_management.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------- + * dlep_context_peer_management.h + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_CONTEXT_PEER_MANAGEMENT_H__ +#define __DLEP_CONTEXT_PEER_MANAGEMENT_H__ + +#include "dlep_context_peer.h" + + +extern dlep_context_peer_t +*dlep_peer_allocate(ipv6_address_t *p2ipv6, ipv4_address_t *p2ipv4, uint16_t udp_port, uint16_t tcp_port); + +extern void +dlep_peer_remove(dlep_context_peer_t **p2peer); + +extern dlep_context_peer_t +*dlep_peer_get_by_ipv4(ipv4_address_t *p2ipv4, uint16_t udp_port, uint16_t tcp_port); + +extern dlep_context_peer_t +*dlep_peer_get_by_ipv6(ipv6_address_t *p2ipv6, uint16_t udp_port, uint16_t tcp_port); + +extern dlep_context_peer_t +*dlep_get_peer_by_peer_id(uint16_t peer_id); + +extern void +dlep_peer_short_list_all(void); + +extern void +dlep_peer_list_all(void); + +extern void +dlep_peer_neighbor_list_all(void); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_debug.c b/dlep_radio_ipv6/dlep_debug.c new file mode 100644 index 0000000..44cf032 --- /dev/null +++ b/dlep_radio_ipv6/dlep_debug.c @@ -0,0 +1,255 @@ +/*------------------------------------------------------------------ + * dlep_debug.c -- debug flag support for DLEP + * + * August 2010, Bo Berry + * + * Copyright (c) 2008, 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *----------------------------------------------------------------- + */ + +#include "dlep_debug.h" + +/* + * debug flags + */ +uint32_t dlep_debug_flags = 0; + + +/** + * NAME + * dlep_debug_set_flag + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_set_flag(uint32_t *p2debug_flags, uint32_t mask) + * + * DESCRIPTION + * Sets specific debug flags + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to component debug flags. + * + * mask - bit mask indicating which flags to set. + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + * NOTES + * If p2debug_flags is null, no operation takes place. + * If mask is (-1), all flags will be set. + * If mask is 0, no operation takes place. + * + */ +void +dlep_debug_set_flag (uint32_t *p2debug_flags, uint32_t mask) +{ + if (p2debug_flags) { + if (mask) { + *p2debug_flags |= mask; + } + } + return; +} + + +/** + * NAME + * dlep_debug_clear_flag + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_clear_flag(uint32_t *p2debug_flags, uint32_t mask) + * + * DESCRIPTION + * Clears specific debug flag(s) + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to the component debug flags. + * + * mask - bit mask indicating which flags to clear. + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + * NOTES + * If p2debug_flags is null, no operation takes place. + * If mask is (-1), all flags will be cleared. + * If mask is 0, no operation takes place. + * + */ +void +dlep_debug_clear_flag (uint32_t *p2debug_flags, uint32_t mask) +{ + if (p2debug_flags) { + if (mask) { + *p2debug_flags &= ~mask; + } + } + return; +} + + +/** + * NAME + * dlep_debug_is_flag_set + * + * SYNOPSIS + * #include "dlep_debug.h" + * boolean_t + * dlep_debug_is_flag_set(uint32_t debug_flags, uint32_t mask) + * + * DESCRIPTION + * Returns the status of debug flag(s) + * + * INPUT PARAMETERS + * debug_flags - Component debugs. + * + * mask - debug flag(s). + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE flag(s) set + * FALSE flag(s) clear + * + * EXAMPLES + * dlep_debug_is_flag_set(&component_flags, SOME_DEBUG) + * + * dlep_debug_is_flag_set(&component_flags, (SOME_DEBUG | ANOTHER_DEBUG) ) + * + */ +boolean_t +dlep_debug_is_flag_set (uint32_t debug_flags, uint32_t flag) +{ + return ( ((debug_flags & flag) ? TRUE : FALSE) ); +} + + +/** + * NAME + * dlep_debug_set_all + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_set_all(uint32_t *p2debug_flags) + * + * DESCRIPTION + * This function should be used to set all debugs. + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to component debug flags. + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + */ +void +dlep_debug_set_all (uint32_t *p2debug_flags) +{ + if (p2debug_flags) { + *p2debug_flags = DLEP_DEBUG_ALL_FLAGS; + } + return; +} + +/** + * NAME + * dlep_debug_clear_all + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_clear_all(uint32_t *p2debug_flags) + * + * DESCRIPTION + * This function should be used to clear all debugs. + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to component debug flags. + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + */ +void +dlep_debug_clear_all (uint32_t *p2debug_flags) +{ + if (p2debug_flags) { + *p2debug_flags = 0; + } + return; +} + + +/** + * NAME + * dlep_debug_init + * + * SYNOPSIS + * #include "dlep_debug.h" + * void + * dlep_debug_int(uint32_t *p2debug_flags, uint32_t initial_mask) + * + * DESCRIPTION + * Init the debug flagss. + * + * INPUT PARAMETERS + * p2debug_flags - Pointer to component debug flags. + * + * initial_mask + * + * OUTPUT PARAMETERS + * p2debug_flags - Flags are updated + * + * RETURN VALUE + * none + * + */ +void +dlep_debug_init (uint32_t *p2debug_flags, uint32_t initial_mask) +{ + if (p2debug_flags) { + *p2debug_flags = initial_mask; + } + return; +} + + diff --git a/dlep_radio_ipv6/dlep_debug.h b/dlep_radio_ipv6/dlep_debug.h new file mode 100644 index 0000000..3262893 --- /dev/null +++ b/dlep_radio_ipv6/dlep_debug.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------- + * dlep_debug.h -- Debug flags and supporting macros + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_DEBUG_H__ +#define __DLEP_DEBUG_H__ + +#include "safe_types.h" + +extern uint32_t dlep_debug_flags; + + + +/* + * Use these macros to abstract the preprocessor + * so internal information is not displayed in + * debugs. + */ +#define ENABLE_FUNCTION_AND_LINE + +#ifdef ENABLE_FUNCTION_AND_LINE +#define DEBUG_FILE __FILE__ +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ +#define DEBUG_DATE __DATE__ +#define DEBUG_TIME __TIME__ +#else +#define DEBUG_FILE " " +#define DEBUG_FUNCTION " " +#define DEBUG_LINE 0 +#define DEBUG_DATE " " +#define DEBUG_TIME " " +#endif + + +/* + * abstracted for porting + */ +#define DLEP_DEBUG printf + + +/* + * surgical debug flags for DLEP. + */ +#define DLEP_DEBUG_ALL_FLAGS ( -1 ) + +#define DLEP_ERROR_TRACE_FLAG ( 0x01 ) +#define DLEP_UDP_TRACE_FLAG ( 0x02 ) + +#define DLEP_INCOMING_TRACE_FLAG ( 0x04 ) +#define DLEP_OUTGOING_TRACE_FLAG ( 0x08 ) + +#define DLEP_PEER_TRACE_FLAG ( 0x10 ) +#define DLEP_NEIGHBOR_TRACE_FLAG ( 0x20 ) + +#define DLEP_METRICS_TRACE_FLAG ( 0x40 ) +#define DLEP_SCRATCH_TRACE_FLAG ( 0x80 ) +#define DLEP_DECODER_TRACE_FLAG ( 0x100 ) + + + +extern void dlep_debug_set_flag(uint32_t *p2debug_flags, uint32_t mask); + +extern void dlep_debug_clear_flag(uint32_t *p2debug_flags, uint32_t mask); + +extern boolean_t dlep_debug_is_flag_set(uint32_t debug_flags, uint32_t mask); + +extern void dlep_debug_set_all(uint32_t *p2debug_flags); + +extern void dlep_debug_clear_all(uint32_t *p2debug_flags); + +extern void dlep_debug_init(uint32_t *p2debug_flags, uint32_t mask); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_debug_cli.c b/dlep_radio_ipv6/dlep_debug_cli.c new file mode 100644 index 0000000..402b9f2 --- /dev/null +++ b/dlep_radio_ipv6/dlep_debug_cli.c @@ -0,0 +1,334 @@ +/*------------------------------------------------------------------ + * dlep_debug_cli.c -- DLEP debug CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "safe_types.h" +#include "cli.h" + +#include "rfc5444_types.h" + +#include "dlep_debug.h" +#include "dlep_debug_cli.h" + + +/* + * directory record + * + * static cli_record_t debug_dir; + */ + +/* + * allocate command records + */ +static cli_record_t debug_show_mask_cmd; +static cli_record_t debug_set_mask_cmd; +static cli_record_t debug_clear_mask_cmd; +static cli_record_t debug_enable_all_cmd; +static cli_record_t debug_disable_all_cmd; + + + + +/** + ** debug commands + **/ +static void +cli_debug_show_mask (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("peer_debug_show - displays enabled debugging levels \n"); + printf("\n"); + return; + } + + printf(" error - %s \n", + ((dlep_debug_flags&DLEP_ERROR_TRACE_FLAG)?"On":"Off")); + + printf(" udp - %s \n", + ((dlep_debug_flags&DLEP_UDP_TRACE_FLAG)?"On":"Off")); + + printf(" incoming - %s \n", + ((dlep_debug_flags&DLEP_INCOMING_TRACE_FLAG)?"On":"Off")); + + printf(" outgoing - %s \n", + ((dlep_debug_flags&DLEP_OUTGOING_TRACE_FLAG)?"On":"Off")); + + printf(" peer - %s \n", + ((dlep_debug_flags&DLEP_PEER_TRACE_FLAG)?"On":"Off")); + + printf(" neighbor - %s \n", + ((dlep_debug_flags&DLEP_NEIGHBOR_TRACE_FLAG)?"On":"Off")); + + printf(" metrics - %s \n", + ((dlep_debug_flags&DLEP_METRICS_TRACE_FLAG)?"On":"Off")); + + printf(" scratch - %s \n", + ((dlep_debug_flags&DLEP_SCRATCH_TRACE_FLAG)?"On":"Off")); + + printf(" decoder - %s \n", + ((dlep_debug_flags&DLEP_DECODER_TRACE_FLAG)?"On":"Off")); + + printf("\n"); + return; +} + + + +static void +cli_debug_set_mask (uint32_t argc, char *argv[]) +{ + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("debug_set [error|udp|incoming|outgoing|packet|peer|" + "neighbor|metrics|scratch|decoder] \n"); + printf("where \n"); + printf(" error - enables the error debug trace \n"); + printf(" udp - enables debug trace of the udp send-receive \n"); + + printf(" incoming - enables debug trace of incoming packets \n"); + printf(" outgoing - enables debug trace of outgoing packets \n"); + printf(" packet - enables both incoming and outgoing packet " + "trace \n"); + + printf(" peer - enables peer specific debug trace \n"); + printf(" neighbor - enables neighbor specific debug trace \n"); + + printf(" metrics - enables neighbor metrics trace \n"); + printf(" scratch - enables scratch pad trace \n"); + printf(" decoder - enables debug trace of TLV validation \n"); + + printf("\n"); + return; + } + + if (!strcmp(argv[1], "error")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_ERROR_TRACE_FLAG); + + } else if (!strcmp(argv[1], "udp")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_UDP_TRACE_FLAG); + + } else if (!strcmp(argv[1], "incoming")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_INCOMING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "outgoing")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_OUTGOING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "packet")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_INCOMING_TRACE_FLAG); + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_OUTGOING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "peer")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_PEER_TRACE_FLAG); + + } else if (!strcmp(argv[1], "neighbor")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_NEIGHBOR_TRACE_FLAG); + + } else if (!strcmp(argv[1], "metrics")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_METRICS_TRACE_FLAG); + + } else if (!strcmp(argv[1], "scratch")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_SCRATCH_TRACE_FLAG); + + } else if (!strcmp(argv[1], "decoder")) { + dlep_debug_set_flag(&dlep_debug_flags, + DLEP_DECODER_TRACE_FLAG); + } else { + printf("Invalid debug flag, <%s> \n", argv[1]); + } + return; +} + + +static void +cli_debug_clear_mask (uint32_t argc, char *argv[]) +{ + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + + printf("debug_clear [error|udp|incoming|outgoing|packet|peer|neighbor|" + "metrics|scratch|decoder] \n"); + printf("where \n"); + printf(" error - disables the error debug trace \n"); + printf(" udp - disables debug trace for udp operations \n"); + + printf(" incoming - disables debug trace of incoming packets \n"); + printf(" outgoing - disables debug trace of outgoing packets \n"); + printf(" packet - enables both incoming and outgoing packet " + "trace \n"); + + printf(" peer - disables peer specific debug trace \n"); + printf(" neighbor - disables neighbor specific debug trace \n"); + + printf(" metrics - disables neighbor metrics trace \n"); + printf(" scratch - disables scratch pad trace \n"); + printf(" decoder - disables debug trace of TLV validation \n"); + + printf("\n"); + return; + } + + if (!strcmp(argv[1], "error")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_ERROR_TRACE_FLAG); + + } else if (!strcmp(argv[1], "udp")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_UDP_TRACE_FLAG); + + } else if (!strcmp(argv[1], "incoming")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_INCOMING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "outgoing")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_OUTGOING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "packet")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_INCOMING_TRACE_FLAG); + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_OUTGOING_TRACE_FLAG); + + } else if (!strcmp(argv[1], "peer")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_PEER_TRACE_FLAG); + + } else if (!strcmp(argv[1], "neighbor")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_NEIGHBOR_TRACE_FLAG); + + } else if (!strcmp(argv[1], "metrics")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_METRICS_TRACE_FLAG); + + } else if (!strcmp(argv[1], "scratch")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_SCRATCH_TRACE_FLAG); + + } else if (!strcmp(argv[1], "decoder")) { + dlep_debug_clear_flag(&dlep_debug_flags, + DLEP_DECODER_TRACE_FLAG); + } + return; +} + + +static void +cli_debug_enable_all (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("debug_enable - enables all debugs \n"); + printf("\n"); + return; + } + dlep_debug_flags = (-1); + printf(" all peer debugs enabled \n"); + return; +} + + +static void +cli_debug_disable_all (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("debug_disable - disables all debugs \n"); + printf("\n"); + return; + } + dlep_debug_flags = (0); + printf(" all peer debugs disabled \n"); + return; +} + + +/** + * NAME + * dlep_debug_cli_init + * + * SYNOPSIS + * void + * dlep_debug_cli_init() + * + * DESCRIPTION + * Registers the dlep debug commands with the cli + * facility. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_debug_cli_init (void) +{ + RC_CLI_t rc; + + /* + * Create directory and commands + **rc = cli_mkdir("peer", &cli_debug_dir, &debug_dir); + */ + + /* debug commands */ + rc = cli_mkcmd("debug_show", cli_debug_show_mask, + &cli_debug_dir, &debug_show_mask_cmd); + + rc = cli_mkcmd("debug_set", cli_debug_set_mask, + &cli_debug_dir, &debug_set_mask_cmd); + + rc = cli_mkcmd("debug_clear", cli_debug_clear_mask, + &cli_debug_dir, &debug_clear_mask_cmd); + + rc = cli_mkcmd("debug_enable", cli_debug_enable_all, + &cli_debug_dir, &debug_enable_all_cmd); + + rc = cli_mkcmd("debug_disable", cli_debug_disable_all, + &cli_debug_dir, &debug_disable_all_cmd); + + return; +} + + diff --git a/dlep_radio_ipv6/dlep_debug_cli.h b/dlep_radio_ipv6/dlep_debug_cli.h new file mode 100644 index 0000000..1245a9b --- /dev/null +++ b/dlep_radio_ipv6/dlep_debug_cli.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------- + * dlep_debug_cli.h -- debug cli prototypes for DLEP + * + * October 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_DEBUG_CLI_H__ +#define __DLEP_DEBUG_CLI_H__ + + +extern void +dlep_debug_cli_init(void); + +#endif + diff --git a/dlep_radio_ipv6/dlep_message_builder.c b/dlep_radio_ipv6/dlep_message_builder.c new file mode 100644 index 0000000..5345be3 --- /dev/null +++ b/dlep_radio_ipv6/dlep_message_builder.c @@ -0,0 +1,2419 @@ +/*---------------------------------------------------------------------- + * dlep_message_builder.c -- Routines to build the DLEP messages + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "packet_dump.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_encoder_tlv.h" +#include "rfc5444_encoder.h" + +#include "dlep_sim_options.h" +#include "dlep_debug.h" +#include "dlep_porter.h" +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" +#include "rfc5444_experimental_tlv.h" + +#include "dlep_message_builder.h" +#include "dlep_client_timer.h" + +extern int TCP_READY; +extern int init; + +/* + * Local API to increment a sequence number. Sequence numbers + * are simply request-response correlators. They are not + * checked for 'sequencing' or lost messages. The originator + * determines the sequence number so it can correlate the + * response. + */ +static uint16_t +dlep_get_next_sequence_number (uint16_t sequence_number) +{ +printf("dlep_get_next_sequence_number\n"); + sequence_number++; + if (!sequence_number) { + sequence_number++; + } + return (sequence_number); +} + + +/** + * NAME + * send_dlep_attached_peer_discovery + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_attached_peer_discovery( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a attached peer discovery message + * from the radio to the router to initiate the discovery process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_attached_peer_discovery (dlep_context_peer_t *p2peer) +{ +printf("send_dlep_attached_peer_discovery\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + TCP_READY = 0; +// printf("\n INSIDE send_dlep_attached_peer_discovery "); + p2es = rfc5444_encoder_packet_start(); + + /* Adding message header */ + rfc5444_encoder_message_block_start(p2es, + RFC5444_SIG_ATT_PEER_DISCOVERY); + + packet_dump("OUTGOING-", + p2es->packet_ptr, + 1); + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_detached_peer_discovery + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_detached_peer_discovery( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a detached peer discovery message + * from the radio to the router to initiate the discovery process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_detached_peer_discovery (dlep_context_peer_t *p2peer) +{ +printf("send_dlep_detached_peer_discovery\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + /* + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); +*/ + +// added for D5 + +rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_DET_PEER_DISCOVERY); + +/* This function call to add message lenth */ + +#if 0 +rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); +#endif +#if 0 + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +/* + // added for testing, will remove it +// rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_DET_PEER_DISCOVERY); + */ + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + p2peer->expected_peer_offer_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + +#endif + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + /* optional */ + rfc5444_peer_tlv(p2es, p2config->local_type_description); +#if 0 + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); +#if 0 + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#endif + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_peer_offer + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_offer(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer offer message + * from the router to the radio in response to the + * peer attached/detached discovery message. This + * confirms discovery. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_offer (dlep_context_peer_t *p2peer) +{ +printf("send_dlep_peer_offer\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + p2es = rfc5444_encoder_packet_start(); + + /* Adding Message header */ + + rfc5444_encoder_signal_block_start(p2es, + RFC5444_SIG_PEER_OFFER, + DLEP_SIGNAL_FLAGS); + + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_ipv4_connection_point_tlv(p2es, p2config->local_tcp_port, + &p2config->local_ipv4); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending peer offer : \n"); + printf(" signal code=%u RFC5444_SIG_PEER_OFFER \n", + RFC5444_SIG_PEER_OFFER); + } + + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + + /* Oppening TCP socket */ +// dlep_tcp_porter_open(p2config); + + rfc5444_encoder_free(p2es); + + return; +} + + + /** + * NAME + * send_dlep_peer_init + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_init( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer init message + * from the radio to the router to initiate the TCP synchronization process. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ + void + send_dlep_peer_init (dlep_context_peer_t *p2peer) + { +printf("send_dlep_peer_init\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_INIT_REQ); + + /* required */ + rfc5444_version_tlv(p2es, + RFC5444_DLEP_MAJOR_VERSION, + RFC5444_DLEP_MINOR_VERSION); + + rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); + + rfc5444_link_metric_mdr_rx_tlv(p2es, 100000000); + p2peer->mdr_rx=100000000; + + rfc5444_link_metric_mdr_tx_tlv(p2es, 100000000); + p2peer->mdr_tx=100000000; + + rfc5444_link_metric_cdr_rx_tlv(p2es, 100000000); + p2peer->cdr_rx=100000000; + rfc5444_link_metric_cdr_tx_tlv(p2es, 250); + p2peer->cdr_tx =250; + + rfc5444_link_metric_latency_tlv1(p2es, 250); + p2peer->latency = 250; + + rfc5444_link_metric_resources_tx_tlv(p2es, 100); + p2peer->resources_tx = 100; + rfc5444_link_metric_resources_rx_tlv(p2es, 100); + p2peer->resources_rx = 100; + + rfc5444_link_metric_rlq_rx_tlv(p2es, 100); + p2peer->rlq_rx = 100; + rfc5444_link_metric_rlq_tx_tlv(p2es, 100); + p2peer->rlq_tx = 100; + + + + /* optional */ + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#if 0 + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + + + printf("\n CALLING dlep_tcp_connect"); +#endif + +#if 0 + dlep_tcp_connect(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); +#endif + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + /* Setting this flag inorder for dlep_tcp_receive to get called after tcp connect + * and first dlep_tcp_send is called inorder to avoid infinite call in loop. + */ + TCP_READY = 1; + + rfc5444_encoder_free(p2es); +// printf("\n PEER INIT REQUEST Sent"); + + return; +} + + /** + * NAME + * send_dlep_peer_init_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_init( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer init message response + * from the radio to the router. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ + void + send_dlep_peer_init_ack (dlep_context_peer_t *p2peer) + { +printf("send_dlep_peer_init_ack\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_INIT_RES); + if(init == 1) { + p2peer->status_code = RFC5444_REQUEST_DENIED; + } + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_peer_tlv(p2es, p2config->local_type_description); + + rfc5444_heartbeat_interval_tlv(p2es, p2config->peer_heartbeat_interval); + + rfc5444_link_metric_mdr_rx_tlv(p2es, 100000000); + p2peer->mdr_rx=100000000; + + rfc5444_link_metric_mdr_tx_tlv(p2es, 100000000); + p2peer->mdr_tx=100000000; + + rfc5444_link_metric_cdr_rx_tlv(p2es, 100000000); + p2peer->cdr_rx=100000000; + + rfc5444_link_metric_cdr_tx_tlv(p2es, 100000000); + p2peer->cdr_tx = 100000000; + + rfc5444_link_metric_latency_tlv1(p2es, 250); + p2peer->latency = 250; + + /* rfc5444_link_metric_latency_tlv(p2es, 250); + p2peer->latency = 250; */ + + rfc5444_link_metric_rlq_rx_tlv(p2es, 100); + p2peer->rlq_rx = 100; + + rfc5444_link_metric_rlq_tx_tlv(p2es, 100); + p2peer->rlq_tx = 100; + + rfc5444_link_metric_resources_tlv(p2es, 100); + p2peer->resources = 100; + + rfc5444_mtu_tlv(p2es, 100); + p2peer->mtu = 100; + + + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2config->local_ipv6); + ipv6_zero_address(&p2peer->ipv6_address); + + // rfc5444_ipv6_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + rfc5444_ipv6_subnet_tlv (p2es, RFC5444_EXISTING_ADD_ADDRESS, 64, &p2config->local_ipv6); + rfc5444_encoder_message_block_end(p2es); + + + /* + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2config->local_ipv4); + ipv4_zero_address(&p2peer->ipv4_address); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + rfc5444_encoder_message_block_end(p2es); +*/ + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } +#if 0 + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + + + printf("\n CALLING dlep_tcp_connect"); +#endif + +#if 0 + dlep_tcp_connect(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); +#endif + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Session initialization response : \n"); + printf(" Message code=%u RFC5444_MSG_PEER_INIT_RES\n",RFC5444_MSG_PEER_INIT_RES); + + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + /* Setting this flag inorder for dlep_tcp_receive to get called after tcp connect + * and first dlep_tcp_send is called inorder to avoid infinite call in loop. + */ + TCP_READY = 1; + + rfc5444_encoder_free(p2es); + + return; +} + + +/** + * NAME + * send_dlep_peer_heartbeat + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_heartbeat( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer heartbeat to + * maintain a persistent presence with the peer. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_heartbeat (dlep_context_peer_t *p2peer) +{ +printf("send_dlep_peer_heartbeat\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + +// printf("\n INSIDE send_dlep_peer_heartbeat"); + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_HEARTBEAT); + +#if 0 + /* + * Get a unique sequence number + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); +#if 0 +#ifdef MULTIPLE_PEER_MESSAGES_PACKED + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_HEARTBEAT); + + /* + * Get a unique sequence number + * HB does not have an ACK, so the sequence number is not important. + */ + p2peer->sequence = + dlep_get_next_sequence_number(p2peer->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); +#endif +#endif + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + /* if (TCP_READY ) { + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + } else { // Else send with UDP socket if heartbeat sent before TCP connection. + dlep_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + } */ + + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending heartbeat message : \n"); + printf(" Message code=%u RFC5444_MSG_PEER_HEARTBEAT\n", + RFC5444_MSG_PEER_HEARTBEAT); + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_peer_update_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_update_request( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer update message + * from the router to the radio. It is used to indicate + * a new layer 3 address or the removal of a layer 3 + * address. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_update_request (dlep_context_peer_t *p2peer) +{ +printf("send_dlep_peer_update_request\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_UPDATE_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = dlep_get_next_sequence_number(p2peer->sequence); + p2peer->expected_peer_update_response_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + if (p2peer->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2peer->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2peer->update_ipv4_operation, + &p2peer->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + else if (p2peer->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2peer->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2peer->update_ipv6_operation, + &p2peer->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } +#if 0 + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_link_metric_mdr_rx_tlv(p2es, p2peer->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2peer->mdr_tx); + rfc5444_link_metric_cdr_rx_tlv(p2es, p2peer->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2peer->cdr_tx); + rfc5444_link_metric_latency_tlv1(p2es, p2peer->latency); + rfc5444_link_metric_resources_tlv(p2es, p2peer->resources); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2peer->rlq_tx); + rfc5444_link_metric_rlq_rx_tlv(p2es, p2peer->rlq_rx); + rfc5444_mtu_tlv(p2es, p2peer->mtu); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session update request :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_UPDATE_REQ\n", + RFC5444_MSG_PEER_UPDATE_REQ); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + + return; +} + + +/** + * NAME + * send_dlep_peer_update_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_update_response( + * dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer update response message + * from the radio to the router. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_update_response (dlep_context_peer_t *p2peer) +{ +printf("send_dlep_peer_update_response\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_UPDATE_RES); +#if 0 + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_status_tlv(p2es, p2peer->status_code); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session update response :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_UPDATE_RES\n", + RFC5444_MSG_PEER_UPDATE_RES); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_peer_termination + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_termination(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer termination message + * from the router to the radio or from the radio to the + * router to termiante the association. As result all + * neighbor neighbors are also terminated. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_termination (dlep_context_peer_t *p2peer) +{ +printf("send_dlep_peer_termination\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2peer->sequence = dlep_get_next_sequence_number( + p2peer->sequence); + p2peer->expected_peer_offer_sequence = p2peer->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +// printf("\n Adding Status TLV"); + rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + rfc5444_encoder_message_block_end(p2es); +#endif +#ifdef MULTIPLE_PEER_MESSAGES_PACKED + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_REQ); + + /* + * acks will not align with incremented sequence + * + * p2peer->sequence = dlep_get_next_sequence_number( + * p2peer->sequence); + * p2peer->expected_peer_offer_sequence = p2peer->sequence; + */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2peer->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session termination :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_TERM_REQ\n", + RFC5444_MSG_PEER_TERM_REQ); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_peer_termination_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_peer_termination_ack(dlep_context_peer_t *p2peer) + * + * DESCRIPTION + * This function is used to send a peer termination ACK + * message from the router to the radio or from the radio + * to the router in response to the peer terminate request. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_peer_termination_ack (dlep_context_peer_t *p2peer) +{ +printf("send_dlep_peer_termination_ack\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + + if (!p2peer) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_PEER_TERM_RES); +#if 0 + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + +// rfc5444_status_tlv(p2es, p2peer->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending session termination message :\n"); + printf(" Message code=%u RFC5444_MSG_PEER_TERM_RES\n", + RFC5444_MSG_PEER_TERM_REQ); + } + + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_up + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_up(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor up message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_up (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_up\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + printf("sending nei up\n"); + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_REQ); + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* add the IPv4 address if there is one to add */ + if (p2neighbor->ipv4_address.v4_addr.v4_addr32) { + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv4_address); + ipv4_zero_address(&p2neighbor->ipv4_address); + } + + /* add the IPv6 address if there is one to add */ + else if(p2neighbor->ipv6_address.v6_addr.v6_addr16[0] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[1] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[2] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[3] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[4] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[5] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[6] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[7]) + { + + printf("sending ipv6 address\n"); + + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv6_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + //rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + + + rfc5444_encoder_message_block_end(p2es); +#if 0 +//ifdef MULTIPLE_NEIGHBOR_MESSAGES_PACKED + /**** neighbor down ****/ + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_term_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + /**** neighbor up ****/ + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_init_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + /* add the IPv4 address if there is one to add */ + if (p2neighbor->ipv4_address.v4_addr.v4_addr32) { + rfc5444_ipv4_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv4_address); + ipv4_zero_address(&p2neighbor->ipv4_address); + } + + /* add the IPv6 address if there is one to add */ + if (p2neighbor->ipv6_address.v6_addr.v6_addr16[0] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[1] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[2] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[3] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[4] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[5] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[6] || + p2neighbor->ipv6_address.v6_addr.v6_addr16[7]) + { + rfc5444_ipv6_address_tlv(p2es, + RFC5444_EXISTING_ADD_ADDRESS, + &p2neighbor->ipv6_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + } + + rfc5444_link_metric_mdr_tlv(p2es, p2neighbor->mdr); + + rfc5444_link_metric_cdr_tlv(p2es, p2neighbor->cdr); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); +#endif + + rfc5444_encoder_packet_end(p2es); + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination up:\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_UP_REQ\n", + RFC5444_MSG_NEIGHBOR_UP_REQ); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_up_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_up_ack(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor up ack message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_up_ack (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_up_ack\n"); + rfc5444_encoder_state_t *p2es; + + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_UP_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); +#if 0 + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_metrics + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_metrics(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor metrics message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context with the + * metrics data set + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_metrics (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_metrics\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); +#if 0 + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + } +#endif + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + rfc5444_ipv6_subnet_tlv(p2es, + p2neighbor->update_ipv6_operation, p2neighbor->ipv6_subnet_prefix,&p2neighbor->update_ipv6_subnet_address); + p2neighbor->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination update to metrics:\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_METRICS\n", + RFC5444_MSG_NEIGHBOR_METRICS); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + +void +send_dlep_neighbor_credit_grant_req (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_credit_grant_req\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); + +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + +#if 0 + /* + * Get a unique sequence number */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_credit_grand_request_tlv(p2es, p2neighbor->cgr); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + + /* + * start the ack timer. Using same neighbor_up_ack_tmo Neighbor Up Time. + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_update_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_update_ack_tmr, + (void *)p2neighbor); + + return; +} + + +void +send_dlep_neighbor_credit_reject (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_credit_reject\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); + + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_METRICS); + + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_rx_tlv(p2es, p2neighbor->resources_tx); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_address_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_address_request(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a peer heartbeat. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_address_request (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_address_request\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_ADDRESS_REQ); + + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = + dlep_get_next_sequence_number(p2neighbor->sequence); + p2neighbor->expected_neighbor_address_response_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (p2neighbor->update_ipv4_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv4_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv4_address_tlv(p2es, + p2neighbor->update_ipv4_operation, + &p2neighbor->update_ipv4_address); + p2peer->update_ipv4_operation = RFC5444_NO_ADDRESS; + } + + if (p2neighbor->update_ipv6_operation == RFC5444_EXISTING_ADD_ADDRESS || + p2neighbor->update_ipv6_operation == RFC5444_DROP_ADDRESS) { + rfc5444_ipv6_address_tlv(p2es, + p2neighbor->update_ipv6_operation, + &p2neighbor->update_ipv6_address); + p2peer->update_ipv6_operation = RFC5444_NO_ADDRESS; + } + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_rx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_rx); + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + + rfc5444_ipv4_attached_subnet_tlv(p2es, RFC5444_EXISTING_ADD_ADDRESS); + + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_address_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_address_response(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor address response. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_address_response (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_address_response\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_ADDRESS_RES); + + /* + * echo the neighbor sequence number + */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + + rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_down + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_down(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor down message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_down (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_down\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_REQ); +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = dlep_get_next_sequence_number( + p2neighbor->sequence); + p2neighbor->expected_neighbor_term_ack_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + +// rfc5444_status_tlv(p2es, p2neighbor->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination down :\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_DOWN_REQ\n", + RFC5444_MSG_NEIGHBOR_DOWN_REQ); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_down_ack + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_down_ack(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a neighbor down ack message. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_down_ack (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_down_ack \n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_NEIGHBOR_DOWN_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_status_tlv(p2es, p2neighbor->status_code); + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination down response :\n"); + printf(" Message code=%u RFC5444_MSG_NEIGHBOR_DOWN_RES\n", + RFC5444_MSG_NEIGHBOR_DOWN_RES); + + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_link_char_request + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_link_char_request(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor, + * uint64_t cdr, + * uint16_t latency) + * + * DESCRIPTION + * This function is used to send a link characteristic message from + * the server to the client. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * cdr - requested data rate + * + * latency - maximum latency requested + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_link_char_request (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor, + uint64_t cdr, + uint64_t latency) +{ +printf("send_dlep_neighbor_link_char_request\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_LINK_CHAR_REQ); + +#if 0 + /* + * Get a unique sequence number and save a copy for the + * acknowledgement + */ + p2neighbor->sequence = + dlep_get_next_sequence_number(p2neighbor->sequence); + p2neighbor->expected_neighbor_link_char_response_sequence = + p2neighbor->sequence; + + rfc5444_encoder_message_block_add_sequence_number(p2es, + p2neighbor->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + if (cdr) { + rfc5444_link_metric_cdr_tx_tlv(p2es, cdr); + rfc5444_link_metric_cdr_rx_tlv(p2es, cdr); + } + + + if (latency) { + rfc5444_link_metric_latency_tlv1(p2es, latency); + } + +// rfc5444_encoder_tlv_block_end(p2es); + + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + +/** + * NAME + * send_dlep_neighbor_link_char_response + * + * SYNOPSIS + * #include "dlep_message_builder.h" + * void + * send_dlep_neighbor_link_char_response(dlep_context_peer_t *p2peer, + * dlep_context_neighbor_t *p2neighbor) + * + * DESCRIPTION + * This function is used to send a link characteristic response from + * the client to the server. + * + * INPUT PARAMETERS + * p2peer - The pointer to the peer context data + * + * p2neighbor - pointer to the neighbor context + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +send_dlep_neighbor_link_char_response (dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor) +{ +printf("send_dlep_neighbor_link_char_response\n"); + rfc5444_encoder_state_t *p2es; + dlep_config_t *p2config; + rfc5444_message_scratch_pad_t *scratch_pad; + + if (!p2peer) { + return; + } + + if (!p2neighbor) { + return; + } + + p2config = p2peer->p2config; + scratch_pad = &p2peer->message_scratch_pad; + + p2es = rfc5444_encoder_packet_start(); +#if 0 + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_PACKET); + + rfc5444_identification_tlv(p2es, + p2peer->router_id, + p2peer->client_id, + p2config->peer_heartbeat_interval); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_start(p2es, + RFC5444_MSG_LINK_CHAR_RES); +#if 0 + /* echo the sequence number */ + rfc5444_encoder_message_block_add_sequence_number(p2es, + scratch_pad->sequence); + + rfc5444_encoder_tlv_block_start(p2es, + RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); +#endif + rfc5444_mac_address_tlv(p2es, p2neighbor->mac_address); + + rfc5444_link_metric_mdr_rx_tlv(p2es, p2neighbor->mdr_tx); + rfc5444_link_metric_mdr_tx_tlv(p2es, p2neighbor->mdr_tx); + + rfc5444_link_metric_cdr_rx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_cdr_tx_tlv(p2es, p2neighbor->cdr_tx); + + rfc5444_link_metric_latency_tlv1(p2es, p2neighbor->latency); + + rfc5444_link_metric_resources_tlv(p2es, p2neighbor->resources); + + rfc5444_link_metric_rlq_rx_tlv(p2es, p2neighbor->rlq_rx); + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_mtu_tlv(p2es, p2neighbor->mtu); + +#if 0 + rfc5444_link_metric_resources_rx_tlv(p2es, p2neighbor->resources_tx); + + rfc5444_link_metric_rlq_tx_tlv(p2es, p2neighbor->rlq_tx); + + rfc5444_encoder_tlv_block_end(p2es); +#endif + rfc5444_encoder_message_block_end(p2es); + + rfc5444_encoder_packet_end(p2es); + + if (dlep_debug_flags & DLEP_OUTGOING_TRACE_FLAG) { + packet_dump("OUTGOING-", + p2es->packet_ptr, + p2es->packet_length); + } + + if (dlep_debug_flags & DLEP_SCRATCH_TRACE_FLAG) { + printf("Sending Destination link char response :\n"); + printf(" Message code=%u FC5444_MSG_LINK_CHAR_RES\n", + RFC5444_MSG_LINK_CHAR_RES); + } + + dlep_tcp_send(p2config, p2peer, + p2es->packet_ptr, p2es->packet_length); + + rfc5444_encoder_free(p2es); + return; +} + + diff --git a/dlep_radio_ipv6/dlep_message_builder.h b/dlep_radio_ipv6/dlep_message_builder.h new file mode 100644 index 0000000..faa037b --- /dev/null +++ b/dlep_radio_ipv6/dlep_message_builder.h @@ -0,0 +1,133 @@ +/*---------------------------------------------------------------------- + * dlep_message_builder.h -- Routines to build the DLEP messages + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_MESSAGE_BUILDER_H__ +#define __DLEP_MESSAGE_BUILDER_H__ + +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" + + + +/* + * Router-Radio Level Mesages + */ + +extern void +send_dlep_attached_peer_discovery(dlep_context_peer_t *p2peer); + +extern void +send_dlep_detached_peer_discovery(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_offer(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_init(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_init_ack(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_heartbeat(dlep_context_peer_t *p2peer); + + +extern void +send_dlep_peer_update_request(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_update_response(dlep_context_peer_t *p2peer); + + +extern void +send_dlep_peer_termination(dlep_context_peer_t *p2peer); + +extern void +send_dlep_peer_termination_ack(dlep_context_peer_t *p2peer); + + +/* + * Neighbor Level Mesages + */ + +extern void +send_dlep_neighbor_up(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_up_ack(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_metrics(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_credit_grant_req(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_credit_reject(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_address_request(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_address_response(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + +extern void +send_dlep_neighbor_down(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_down_ack(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_dlep_neighbor_link_char_request(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor, + uint64_t cdr, + uint64_t latency); + + +extern void +send_dlep_neighbor_link_char_response(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + + + +#endif + diff --git a/dlep_radio_ipv6/dlep_porter.c b/dlep_radio_ipv6/dlep_porter.c new file mode 100644 index 0000000..90472c1 --- /dev/null +++ b/dlep_radio_ipv6/dlep_porter.c @@ -0,0 +1,1148 @@ +/*---------------------------------------------------------------------- + * dlep_porter.c -- APIs for UDP socket use + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include "safe_types.h" +#include "dlep_debug.h" +#include "dlep_config.h" +#include "dlep_context_peer.h" +#include "dlep_porter.h" + + + +// ADDED FOR DEBUG +// #include + +#define MSG_MIN_LEN ( 4 ) +#define MSG_MAX_LEN ( 1400 ) + +extern int TCP_READY; + +extern int TCP_CLIENT_READY; +extern int errno; + +/** + * NAME + * dlep_porter_init + * + * SYNOPSIS + * void + * dlep_porter_init(dlep_config_t *p2config) + * + * DESCRIPTION + * This function is used to initialize the transport data prior + * to allocating resources. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * None. + * + */ +void +dlep_porter_init (dlep_config_t *p2config) +{ + if (!p2config) { + return; + } + + return; +} + + +void +dlep_tcp_porter_open(dlep_config_t *p2config) + +{ + int status; + int status_6; + + if (!p2config) { + return; + } + + /* At this stage open tcp socket alone in order to use in + * select system call later. */ + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Opening the tcp socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + // p2config->dlep_tcp_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + + p2config->dlep_tcp_sockfd = socket(AF_INET6, SOCK_STREAM, 0); + +// added for debug +// fcntl(p2config->dlep_tcp_sockfd, F_SETFL, O_NONBLOCK); + if (p2config->dlep_tcp_sockfd < 0) { + DLEP_DEBUG("%s-%u Error: not able to open TCP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + exit (0); + } + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Binding the tcp socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } +/* + memset(&p2config->dlep_addr, 0, sizeof(struct sockaddr_in)); + p2config->dlep_addr.sin_family = AF_INET; + p2config->dlep_addr.sin_port = htons(p2config->local_tcp_port); + p2config->dlep_addr.sin_addr.s_addr = INADDR_ANY; +*/ + memset(&p2config->dlep_addr6, 0, sizeof(struct sockaddr_in6)); + p2config->dlep_addr6.sin6_family = AF_INET6; + p2config->dlep_addr6.sin6_port = htons(p2config->local_tcp_port); + p2config->dlep_addr6.sin6_addr = in6addr_any ; + + status = bind(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2config->dlep_addr6, + sizeof(struct sockaddr_in6)); +/* + status_6 = bind(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2config->dlep_addr6, + sizeof(struct sockaddr_in6)); +*/ + if (status < 0) { + + printf("\n not able to bind"); + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: not able to bind TCP " + "socket to port %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2config->local_tcp_port); + } + exit (0); + } + printf("\n waiting connect from router\n"); + status = listen(p2config->dlep_tcp_sockfd,5); + + if (status) { + perror("ERROR on listen"); + exit(2); + } +/* + p2config->client_lenght = sizeof(p2config->client); + p2config->dlep_tcp_client_sockfd = accept(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2config->client, &p2config->client_lenght); + + if (p2config->dlep_tcp_client_sockfd < 0) { + perror("ERROR on accept"); + exit(1); + } + + + printf(" dlep_tcp_sockfd after accept =%d",p2config->dlep_tcp_client_sockfd); + + TCP_READY = 1; +*/ + +#if 0 + int sockfd, newsockfd, portno, clilen; + char buffer[256]; + struct sockaddr_in serv_addr, cli_addr; + int n; + + /* First call to socket() function */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (sockfd < 0) + { + perror("ERROR opening socket"); + exit(1); + } + + /* Initialize socket structure */ + bzero((char *) &serv_addr, sizeof(serv_addr)); + portno = 5001; + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = INADDR_ANY; + serv_addr.sin_port = htons(portno); + + /* Now bind the host address using bind() call.*/ + if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + perror("ERROR on binding"); + exit(1); + } + + /* Now start listening for the clients, here process will + * go in sleep mode and will wait for the incoming connection + */ + + listen(sockfd,5); + clilen = sizeof(cli_addr); + + /* Accept actual connection from the client */ + newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen); + if (newsockfd < 0) + { + perror("ERROR on accept"); + exit(1); + } + + /* If connection is established then start communicating */ + bzero(buffer,256); + // n = read( newsockfd,buffer,255 ); + + if (n < 0) + { + perror("ERROR reading from socket"); + exit(1); + } + + printf("Here is the message: %s\n",buffer); + + /* Write a response to the client */ +// n = write(newsockfd,"I got your message",18); + + if (n < 0) + { + perror("ERROR writing to socket"); + exit(1); + } + + return 0; +#endif + return; + +} + + +/** + * NAME + * dlep_porter_open + * + * SYNOPSIS + * void + * dlep_porter_open(dlep_config_t *p2config) + * + * DESCRIPTION + * This function is used to open and bind to a local + * socket fd. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * None. + * + */ +void +dlep_porter_open (dlep_config_t *p2config) +{ + int status; + struct addrinfo *resmulti; + + if (!p2config) { + return; + } + p2config->reuse = 1; + +// if (p2config->start_on_discovery) { + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Opening the UDP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + // p2config->dlep_udp_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + + p2config->dlep_udp_sockfd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); + + if (p2config->dlep_udp_sockfd < 0) { + DLEP_DEBUG("%s-%u Error: not able to open UDP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + exit (0); + } + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Binding the UDP socket \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + if(setsockopt(p2config->dlep_udp_sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&p2config->reuse, sizeof(p2config->reuse)) < 0) + { + perror("Setting SO_REUSEADDR error"); + close(p2config->dlep_udp_sockfd); + exit(1); + } +/* + memset(&p2config->dlep_addr, 0, sizeof(struct sockaddr_in)); + p2config->dlep_addr.sin_family = AF_INET; + p2config->dlep_addr.sin_port = htons(p2config->local_udp_port); + p2config->dlep_addr.sin_addr.s_addr = htonl(INADDR_ANY); +*/ + memset(&p2config->dlep_addr6, 0, sizeof(struct sockaddr_in6)); + p2config->dlep_addr6.sin6_family = AF_INET6; + p2config->dlep_addr6.sin6_port = htons(p2config->local_udp_port); + p2config->dlep_addr6.sin6_addr = in6addr_any; + +/* + status = bind(p2config->dlep_udp_sockfd, + (struct sockaddr *)&p2config->dlep_addr, + sizeof(struct sockaddr_in)); +*/ + status = bind(p2config->dlep_udp_sockfd, + (struct sockaddr *)&p2config->dlep_addr6, + sizeof(struct sockaddr_in6)); + + if (status < 0) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: not able to bind UDP " + "socket to port %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2config->local_udp_port); + } + exit (0); + } + + //p2config->group.imr_multiaddr.s_addr = inet_addr("224.1.0.31"); +// p2config->group.imr_interface.s_addr = INADDR_ANY; +// p2config->group.imr_interface.s_addr = inet_addr("20.1.1.4"); + // p2config->group.imr_interface.s_addr = inet_addr(p2config->local_ipv4_dot); +/* + if(setsockopt(p2config->dlep_udp_sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char *)&p2config->group, sizeof(p2config->group)) < 0) + { + perror("Adding multicast group error"); + close(p2config->dlep_udp_sockfd); + exit(1); + } else { + printf("Adding multicast group...OK.\n"); + } +*/ + // p2config->group6.ipv6mr_multiaddr = inet_pton("FF02:0:0:0:0:0:0:7"); +/* memcpy(&p2config->group6.ipv6mr_multiaddr,&(((struct sockaddr_in6 *)addr)->sin6_addr), + sizeof(struct in6_addr));*/ + // getaddrinfo("ff02::7", NULL, NULL, &resmulti); + // memset(&p2config->group6,0,sizeof(p2config->group6)); + // memcpy(&p2config->group6.ipv6mr_multiaddr,&(((struct sockaddr_in6 *))->sin6_addr), + // sizeof(struct p2config->group6.ipv6mr_multiaddr)); + //p2config->group6.ipv6mr_multiaddr = + //p2config->group6.ipv6mr_multiaddr = ((sockaddr_in6*)resmulti->ai_addr)->sin6_addr; + //inet_pton(AF_INET6, resmulti, p2config->group6.ipv6mr_multiaddr); + // p2config->group6.ipv6mr_interface = in6addr_any; + + inet_pton(AF_INET6, "FF02:0:0:0:0:0:1:7", &p2config->group6); + + if(setsockopt(p2config->dlep_udp_sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, + (char *)&p2config->group6, sizeof(p2config->group6)) < 0) + { + perror("Adding multicast group error"); + close(p2config->dlep_udp_sockfd); + exit(1); + } else { + printf("Adding multicast group...OK.\n"); + } + + return; +} + + + + +// dlep_tcp_connect // +void +dlep_tcp_connect (dlep_config_t *p2config, + dlep_context_peer_t *p2peer, + void *msg, + uint32_t length) +{ + int status; + // int status_6; + if (!p2config) { + return; + } + + + // memset(&p2peer->msg_addr, 0, sizeof(struct sockaddr_in)); + memset(&p2peer->msg6_addr, 0, sizeof(struct sockaddr_in6)); + + // p2peer->msg_addr.sin_family = AF_INET; + p2peer->msg6_addr.sin6_family = AF_INET6; + + // p2peer->msg_addr.sin_port = htons(p2peer->peer_tcp_port); + p2peer->msg6_addr.sin6_port = htonl(p2peer->peer_tcp_port); + //p2peer->msg_addr.sin_addr.s_addr = htonl(p2peer->peer_ipv4.v4_addr.v4_addr32); + // p2peer->msg_addr.sin_addr.s_addr = p2peer->peer_ipv4.v4_addr.v4_addr32; + // p2peer->msg_addr6.sin6_addr.s6_addr32 = htonl(p2peer->peer_ipv6.v6_addr.v6_addr32); + +#if 0 + p2peer->msg6_addr.sin6_addr.s6_addr32[0] = p2peer->peer_ipv6.v6_addr.v6_addr32[0]; + p2peer->msg6_addr.sin6_addr.s6_addr32[1] = p2peer->peer_ipv6.v6_addr.v6_addr32[1]; + p2peer->msg6_addr.sin6_addr.s6_addr32[2] = p2peer->peer_ipv6.v6_addr.v6_addr32[2]; + p2peer->msg6_addr.sin6_addr.s6_addr32[3] = p2peer->peer_ipv6.v6_addr.v6_addr32[3]; +#endif + +//vinod + p2peer->msg6_addr.sin6_addr.s6_addr16[0] = p2peer->peer_ipv6.v6_addr.v6_addr16[0]; + p2peer->msg6_addr.sin6_addr.s6_addr16[1] = p2peer->peer_ipv6.v6_addr.v6_addr16[1]; + p2peer->msg6_addr.sin6_addr.s6_addr16[2] = p2peer->peer_ipv6.v6_addr.v6_addr16[2]; + p2peer->msg6_addr.sin6_addr.s6_addr16[3] = p2peer->peer_ipv6.v6_addr.v6_addr16[3]; + p2peer->msg6_addr.sin6_addr.s6_addr16[4] = p2peer->peer_ipv6.v6_addr.v6_addr16[4]; + p2peer->msg6_addr.sin6_addr.s6_addr16[5] = p2peer->peer_ipv6.v6_addr.v6_addr16[5]; + p2peer->msg6_addr.sin6_addr.s6_addr16[6] = p2peer->peer_ipv6.v6_addr.v6_addr16[6]; + p2peer->msg6_addr.sin6_addr.s6_addr16[7] = p2peer->peer_ipv6.v6_addr.v6_addr16[7]; + + +printf("Connecting the TCP socket \n"); +/* + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Connecting the TCP socket \n", + DEBUG_FUlNCTION, + DEBUG_LINE); + } +*/ + + status = connect(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2peer->msg6_addr, + sizeof(struct sockaddr_in6)); +/* + status_6 = connect(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2peer->msg6_addr, + sizeof(struct sockaddr_in6)); +*/ + if (status < 0) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: not able to connect to TCP " + "socket to port %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_tcp_port); + } +// exit (0); + printf("\n Do Manual start once server ready "); + } + + + +// listen(32, p2config->dlep_sockfd); + return; +} + + +/** + * NAME + * dlep_udp_receive + * + * SYNOPSIS + * int + * dlep_udp_receive(dlep_config_t *p2config, + * struct sockaddr_in *rcvd_msg_addr, + * socklen_t *rcvd_msg_socket_length, + * void *msg, + * uint32_t length) + * + * DESCRIPTION + * This function is used to receive a UDP message. + * This is a blocking call. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * rcvd_msg_addr - pointer to the receive socket data + * + * rcvd_socket_length - pointer to the receive socket length + * + * msg - pointer to the message buffer to receive the data + * + * length - Maximum number of bytes to receive, that + * the buffer can hold. + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * number of bytes read + * <= 0 error condition + * + */ +int +dlep_udp_receive (dlep_config_t *p2config, + struct sockaddr_in6 *rcvd_msg_addr, + socklen_t *rcvd_socket_length, + void *msg, + uint32_t length) +{ + int num_bytes; + + if (!p2config) { + return (0); + } + + if (!msg) { + return (0); + } + + if (length < MSG_MIN_LEN || length > MSG_MAX_LEN) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: msg length invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (0); + } + + /* + * Since we use the sig_alarm, we must handle + * interrupting the recv_from. + */ + *rcvd_socket_length = sizeof(struct sockaddr); + num_bytes = -1; + while (num_bytes < 0) { + num_bytes = recvfrom(p2config->dlep_udp_sockfd, + msg, + length, + MSG_WAITALL, + (struct sockaddr *)rcvd_msg_addr, + rcvd_socket_length); + + if (num_bytes < 0) { + if (errno == EINTR) { + continue; + } + + perror("recvfrom: udp failed "); + memset(msg, 0 , 128); + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: recv_from error = %d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + num_bytes); + } + + } else { + rcvd_msg_addr->sin6_port = htons(rcvd_msg_addr->sin6_port); + + p2config->client_udp_6.sin6_port = htons(rcvd_msg_addr->sin6_port); + p2config->client_udp_6.sin6_addr = rcvd_msg_addr->sin6_addr; + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Received from !!!!!!%s at port %u %u bytes \n", + DEBUG_FUNCTION, + DEBUG_LINE, + // inet_ntoa( rcvd_msg_addr->sin6_addr), + // inet_ntoa( p2config->client_udp.sin_addr), + rcvd_msg_addr->sin6_port, + htons(p2config->client_udp_6.sin6_port), + num_bytes); + } + break; + } + } + + + return (num_bytes); +} + + +// dlep_udp_receive_6 // + +int +dlep_udp_receive_6 (dlep_config_t *p2config, + struct sockaddr_in6 *rcvd_msg_addr, + socklen_t *rcvd_socket_length, + void *msg, + uint32_t length) +{ + int num_bytes; + + if (!p2config) { + return (0); + } + + if (!msg) { + return (0); + } + + if (length < MSG_MIN_LEN || length > MSG_MAX_LEN) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: msg length invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (0); + } + + /* + * Since we use the sig_alarm, we must handle + * interrupting the recv_from. + */ + *rcvd_socket_length = sizeof(struct sockaddr); + num_bytes = -1; + while (num_bytes < 0) { + num_bytes = recvfrom(p2config->dlep_udp_sockfd, + msg, + length, + MSG_WAITALL, + (struct sockaddr *)rcvd_msg_addr, + rcvd_socket_length); + + if (num_bytes < 0) { + if (errno == EINTR) { + continue; + } + + perror("recvfrom: udp failed "); + memset(msg, 0 , 128); + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: recv_from error = %d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + num_bytes); + } + + } else { + rcvd_msg_addr->sin6_port = htons(rcvd_msg_addr->sin6_port); + + p2config->client_udp_6.sin6_port = htons(rcvd_msg_addr->sin6_port); + p2config->client_udp_6.sin6_addr = rcvd_msg_addr->sin6_addr; + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Received from !!!!!!%s at port %u %u bytes \n", + DEBUG_FUNCTION, + DEBUG_LINE, + //inet_ntoa(rcvd_msg_addr->sin_addr), + // inet_ntoa(p2config->client_udp_6.sin6_addr), + //rcvd_msg_addr->sin_port, + htons(p2config->client_udp_6.sin6_port), + num_bytes); + } + break; + } + } + + return (num_bytes); +} + + + + +/** + * NAME + * dlep_tcp_receive + * + * SYNOPSIS + * int + * dlep_tcp_receive(dlep_config_t *p2config, + * struct sockaddr_in *rcvd_msg_addr, + * socklen_t *rcvd_msg_socket_length, + * void *msg, + * uint32_t length) + * + * DESCRIPTION + * This function is used to receive a TCP message. + * This is a blocking call. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * rcvd_msg_addr - pointer to the receive socket data + * + * rcvd_socket_length - pointer to the receive socket length + * + * msg - pointer to the message buffer to receive the data + * + * length - Maximum number of bytes to receive, that + * the buffer can hold. + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * number of bytes read + * <= 0 error condition + * + */ +int +dlep_tcp_receive (dlep_config_t *p2config, + struct sockaddr_in6 *rcvd_msg_addr, + socklen_t *rcvd_socket_length, + void *msg, + uint32_t length) +{ + int num_bytes; + //static int count; + int bytes_read ,bytes_left, fd; + unsigned short msg_len = 0; + char msg_hdr[4]; + char *buf_ptr; + + bytes_read = bytes_left = 0; + buf_ptr = msg_hdr; + + if (!p2config) { + + printf("\n INNN config"); + return (0); + } + fd = p2config->dlep_tcp_client_sockfd; + + + if (!msg) { + return (0); + } + + if (length < MSG_MIN_LEN || length > MSG_MAX_LEN) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: msg length invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (0); + } + + /* + * Since we use the sig_alarm, we must handle + * interrupting the recv_from. + */ + //*rcvd_socket_length = sizeof(struct sockaddr); + //num_bytes = -1; +#if 0 + while (num_bytes < 0) { + num_bytes = recvfrom(p2config->dlep_tcp_client_sockfd, + msg, + length, + MSG_WAITALL, + (struct sockaddr *)rcvd_msg_addr, + rcvd_socket_length); + + if (num_bytes < 0) { + if (errno == EINTR) { + continue; + } + count++; + if (count < 6) + perror("recvfrom: tcp failed "); + memset(msg, 0 , 128); + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: recv_from error = %d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + num_bytes); + } + + } else { + // rcvd_msg_addr->sin_port = htons(rcvd_msg_addr->sin_port); + + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Received from %s at port %u %u bytes \n", + DEBUG_FUNCTION, + DEBUG_LINE, + inet_ntoa(rcvd_msg_addr->sin6_addr), + rcvd_msg_addr->sin6_port, + num_bytes); + } + break; + } + } +#endif +#define MSG_HDR_SIZE 4 + bytes_read = recv(fd, msg_hdr, MSG_HDR_SIZE, MSG_PEEK); + /* fall through case where bytes_read == MSG_HDR_SIZE */ + buf_ptr++; + buf_ptr++; + +#define GETSHORT(ptr) ((unsigned char *)ptr)[0] << 8 | ((unsigned char *)ptr)[1] +// #define GETSHORT(ptr) (*((unsigned short *) (ptr))) + msg_len = GETSHORT(buf_ptr); + + /* Read the full message */ + msg_len += MSG_HDR_SIZE; + bytes_left = msg_len; + + + while (bytes_left > 0) { + bytes_read = recv(fd, msg, bytes_left, 0); + if (bytes_read == 0) { + close(p2config->dlep_tcp_client_sockfd); + TCP_CLIENT_READY = 0; + } +/* + uint8_t *ptr = msg; + int len = bytes_read; + for(;len!=0; --len) { + printf("%x",*ptr); + } +*/ + if(bytes_read < 0) { + return (-1); + } + + //*length += bytes_read; + msg += bytes_read; + bytes_left -= bytes_read; + } + num_bytes = msg_len - bytes_left; + +// return (MANET_INFRA_SUCCESS); + return (num_bytes); +} + + +// dlep_tcp_receive_6 // +int +dlep_tcp_receive_6 (dlep_config_t *p2config, + struct sockaddr_in6 *rcvd_msg_addr, + socklen_t *rcvd_socket_length, + void *msg, + uint32_t length) +{ + int num_bytes; + //static int count; + int bytes_read ,bytes_left, fd; + unsigned short msg_len = 0; + char msg_hdr[4]; + char *buf_ptr; + + bytes_read = bytes_left = 0; + buf_ptr = msg_hdr; + + if (!p2config) { + + printf("\n INNN config"); + return (0); + } + fd = p2config->dlep_tcp_client_sockfd; + + + if (!msg) { + return (0); + } + + if (length < MSG_MIN_LEN || length > MSG_MAX_LEN) { + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: msg length invalid \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (0); + } + +#define MSG_HDR_SIZE 4 + bytes_read = recv(fd, msg_hdr, MSG_HDR_SIZE, MSG_PEEK); + /* fall through case where bytes_read == MSG_HDR_SIZE */ + buf_ptr++; + buf_ptr++; + +#define GETSHORT(ptr) ((unsigned char *)ptr)[0] << 8 | ((unsigned char *)ptr)[1] +// #define GETSHORT(ptr) (*((unsigned short *) (ptr))) + msg_len = GETSHORT(buf_ptr); + + /* Read the full message */ + msg_len += MSG_HDR_SIZE; + bytes_left = msg_len; + + + while (bytes_left > 0) { + bytes_read = recv(fd, msg, bytes_left, 0); + if (bytes_read == 0) { + close(p2config->dlep_tcp_client_sockfd); + TCP_CLIENT_READY = 0; + } + + if(bytes_read < 0) { + return (-1); + } + + //*length += bytes_read; + msg += bytes_read; + bytes_left -= bytes_read; + } + num_bytes = msg_len - bytes_left; + +// return (MANET_INFRA_SUCCESS); + return (num_bytes); +} + + + +/** + * NAME + * dlep_udp_send + * + * SYNOPSIS + * void + * dlep_send(dlep_config_t *p2config, + * dlep_context_peer_t *p2peer, + * void *msg, + * uint32_t length) + * + * DESCRIPTION + * This function is used to send a UDP mesage. + * + * INPUT PARAMETERS + * p2config - pointer to the config data + * + * p2peer - pointer to the peer context + * + * msg - Pointer to the message to be sent + * + * length - Number of bytes in mesage to send + * + * OUTPUT PARAMETERS + * None. + * + * RETURN VALUE + * None. + * + */ +void +dlep_send (dlep_config_t *p2config, + dlep_context_peer_t *p2peer, + void *msg, + uint32_t length) +{ + int send_bytes; + int send_bytes_6; + + if (!p2peer) { + return; + } + + if (!msg) { + return; + } + +// perror("send: udp "); + + // memset(&p2peer->msg_addr, 0, sizeof(struct sockaddr_in)); + memset(&p2peer->msg6_addr, 0, sizeof(struct sockaddr_in6)); + // p2peer->msg_addr.sin_family = AF_INET; +// Debug + p2peer->msg6_addr.sin6_family = AF_INET6; + + // p2peer->msg_addr.sin_port = htons(p2peer->peer_udp_port); + p2peer->msg6_addr.sin6_port = htons(p2peer->peer_udp_port); + //p2peer->msg_addr.sin_addr.s_addr = htonl(p2peer->peer_ipv4.v4_addr.v4_addr32); + // p2peer->msg_addr.sin_addr.s_addr = p2peer->peer_ipv4.v4_addr.v4_addr32; + +#if 0 + p2peer->msg6_addr.sin6_addr.s6_addr32[0] = p2peer->peer_ipv6.v6_addr.v6_addr32[0]; + p2peer->msg6_addr.sin6_addr.s6_addr32[1] = p2peer->peer_ipv6.v6_addr.v6_addr32[1]; + p2peer->msg6_addr.sin6_addr.s6_addr32[2] = p2peer->peer_ipv6.v6_addr.v6_addr32[2]; + p2peer->msg6_addr.sin6_addr.s6_addr32[3] = p2peer->peer_ipv6.v6_addr.v6_addr32[3]; +#endif +//vinod + p2peer->msg6_addr.sin6_addr.s6_addr16[0] = p2peer->peer_ipv6.v6_addr.v6_addr16[0]; + p2peer->msg6_addr.sin6_addr.s6_addr16[1] = p2peer->peer_ipv6.v6_addr.v6_addr16[1]; + p2peer->msg6_addr.sin6_addr.s6_addr16[2] = p2peer->peer_ipv6.v6_addr.v6_addr16[2]; + p2peer->msg6_addr.sin6_addr.s6_addr16[3] = p2peer->peer_ipv6.v6_addr.v6_addr16[3]; + p2peer->msg6_addr.sin6_addr.s6_addr16[4] = p2peer->peer_ipv6.v6_addr.v6_addr16[4]; + p2peer->msg6_addr.sin6_addr.s6_addr16[5] = p2peer->peer_ipv6.v6_addr.v6_addr16[5]; + p2peer->msg6_addr.sin6_addr.s6_addr16[6] = p2peer->peer_ipv6.v6_addr.v6_addr16[6]; + p2peer->msg6_addr.sin6_addr.s6_addr16[7] = p2peer->peer_ipv6.v6_addr.v6_addr16[7]; + + + send_bytes = sendto(p2config->dlep_udp_sockfd, + msg, + length, + 0, + //(struct sockaddr *)&p2peer->msg_addr, + (struct sockaddr *)&p2config->client_udp, + sizeof(struct sockaddr_in6)); + +/* send_bytes_6 = sendto(p2config->dlep_udp_sockfd, + msg, + length, + 0, + //(struct sockaddr *)&p2peer->msg_addr, + (struct sockaddr *)&p2config->client_udp_6, + sizeof(struct sockaddr_in6)); +*/ + if (send_bytes < 0) { + perror("sendto: udp failed "); + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u send to %s at " + "port %d bytes=%d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + // inet_ntoa(p2peer->msg6_addr.sin6_addr), + p2peer->peer_udp_port, + send_bytes); + } + } else { + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sent iiiii to %s at " + "port %d bytes=%d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + //inet_ntoa(p2peer->msg_addr.sin_addr), + // inet_ntoa(p2config->client_udp_6.sin6_addr), + //p2peer->peer_udp_port, + htons(p2config->client_udp_6.sin6_port), + send_bytes); + } + } + + return; +} + + + + +void +dlep_tcp_send (dlep_config_t *p2config, + dlep_context_peer_t *p2peer, + void *msg, + uint32_t length) +{ + int send_bytes; + int send_bytes_6; + uint32_t ttl = 255; + + if (!p2peer) { + return; + } + + if (!msg) { + return; + } + + perror("send: tcp "); + + + memset(&p2peer->msg6_addr, 0, sizeof(struct sockaddr_in6)); + + p2peer->msg6_addr.sin6_family = AF_INET6; + + p2peer->msg6_addr.sin6_port = htons(p2peer->peer_tcp_port); + +#if 0 + p2peer->msg6_addr.sin6_addr.s6_addr32[0] = p2peer->peer_ipv6.v6_addr.v6_addr32[0]; + p2peer->msg6_addr.sin6_addr.s6_addr32[1] = p2peer->peer_ipv6.v6_addr.v6_addr32[1]; + p2peer->msg6_addr.sin6_addr.s6_addr32[2] = p2peer->peer_ipv6.v6_addr.v6_addr32[2]; + p2peer->msg6_addr.sin6_addr.s6_addr32[3] = p2peer->peer_ipv6.v6_addr.v6_addr32[3]; +#endif +//vinod + p2peer->msg6_addr.sin6_addr.s6_addr16[0] = p2peer->peer_ipv6.v6_addr.v6_addr16[0]; + p2peer->msg6_addr.sin6_addr.s6_addr16[1] = p2peer->peer_ipv6.v6_addr.v6_addr16[1]; + p2peer->msg6_addr.sin6_addr.s6_addr16[2] = p2peer->peer_ipv6.v6_addr.v6_addr16[2]; + p2peer->msg6_addr.sin6_addr.s6_addr16[3] = p2peer->peer_ipv6.v6_addr.v6_addr16[3]; + p2peer->msg6_addr.sin6_addr.s6_addr16[4] = p2peer->peer_ipv6.v6_addr.v6_addr16[4]; + p2peer->msg6_addr.sin6_addr.s6_addr16[5] = p2peer->peer_ipv6.v6_addr.v6_addr16[5]; + p2peer->msg6_addr.sin6_addr.s6_addr16[6] = p2peer->peer_ipv6.v6_addr.v6_addr16[6]; + p2peer->msg6_addr.sin6_addr.s6_addr16[7] = p2peer->peer_ipv6.v6_addr.v6_addr16[7]; + + + + if (p2peer->ttl) { + if(setsockopt(p2config->dlep_tcp_client_sockfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + (char *)&p2peer->ttl, sizeof(p2peer->ttl)) < 0) + { + perror("Setting IPV6_UNICAST_HOPS error TTL"); + close(p2config->dlep_tcp_client_sockfd); + exit(1); + } + } + + send_bytes = sendto(p2config->dlep_tcp_client_sockfd, + msg, + length, + 0, + (struct sockaddr *)&p2config->client_6, + sizeof(struct sockaddr_in6)); + /* send_bytes_6 = sendto(p2config->dlep_tcp_client_sockfd, + msg, + length, + 0, + (struct sockaddr *)&p2config->client, + sizeof(struct sockaddr_in6)); +*/ + if (send_bytes < 0) { + perror("sendto: tcp failed "); + if (dlep_debug_flags & DLEP_ERROR_TRACE_FLAG) { + DLEP_DEBUG("%s-%u Error: peer_id=%u send to %s at " + "port %d bytes=%d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + p2peer->peer_tcp_port, + send_bytes); + } + } else { + if (dlep_debug_flags & DLEP_UDP_TRACE_FLAG) { + DLEP_DEBUG("%s-%u peer_id=%u sent to %s at " + "port %d bytes=%d \n", + DEBUG_FUNCTION, + DEBUG_LINE, + p2peer->peer_id, + htons(p2config->client_6.sin6_port), + send_bytes); + } + } + if (p2peer->ttl) { + p2peer->ttl = 0; + if(setsockopt(p2config->dlep_tcp_client_sockfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + (char *)&ttl, sizeof(ttl)) < 0) + { + perror("Setting IPV6_UNICAST_HOPS error"); + close(p2config->dlep_tcp_client_sockfd); + exit(1); + } + } + + return; +} diff --git a/dlep_radio_ipv6/dlep_porter.h b/dlep_radio_ipv6/dlep_porter.h new file mode 100644 index 0000000..d285e2a --- /dev/null +++ b/dlep_radio_ipv6/dlep_porter.h @@ -0,0 +1,117 @@ +/*---------------------------------------------------------------------- + * dlep_porter.h -- APIs for UDP socket use + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_PORTER_H__ +#define __DLEP_PORTER_H__ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "safe_types.h" +#include "dlep_config.h" + +#include "dlep_context_peer.h" + + +extern void +dlep_porter_init(dlep_config_t *p2config); + + +extern void +dlep_porter_open(dlep_config_t *p2config); + +extern void +dlep_tcp_porter_open(dlep_config_t *p2config); + + +extern void +dlep_tcp_open(dlep_config_t *p2config); + + +extern void +dlep_tcp_connect(dlep_config_t *p2config, + dlep_context_peer_t *p2ctx, + void *msg, + uint32_t length); + + +extern int +dlep_udp_receive(dlep_config_t *p2config, + struct sockaddr_in6 *rcvd_msg_addr, + socklen_t *rcvd_msg_socket_length, + void *msg, + uint32_t length); + +extern int +dlep_udp_receive_6(dlep_config_t *p2config, + struct sockaddr_in6 *rcvd_msg_addr, + socklen_t *rcvd_msg_socket_length, + void *msg, + uint32_t length); + +extern int +dlep_tcp_receive(dlep_config_t *p2config, + struct sockaddr_in6 *rcvd_msg_addr, + socklen_t *rcvd_msg_socket_length, + void *msg, + uint32_t length); + +extern int +dlep_tcp_receive_6(dlep_config_t *p2config, + struct sockaddr_in6 *rcvd_msg_addr, + socklen_t *rcvd_msg_socket_length, + void *msg, + uint32_t length); + + +extern void +dlep_send(dlep_config_t *p2config, + dlep_context_peer_t *p2ctx, + void *msg, + uint32_t length); + +extern void +dlep_tcp_send(dlep_config_t *p2config, + dlep_context_peer_t *p2ctx, + void *msg, + uint32_t length); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_server_neighbor_fsm.h b/dlep_radio_ipv6/dlep_server_neighbor_fsm.h new file mode 100644 index 0000000..a0faed7 --- /dev/null +++ b/dlep_radio_ipv6/dlep_server_neighbor_fsm.h @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------- + * dlep_server_neighbor_fsm.h -- server neighbor state machine + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_SERVER_SESSION_FSM_H__ +#define __DLEP_SERVER_SESSION_FSM_H__ + +#include "safe_types.h" +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" + + +/* + * normalized server events for neighbors + */ +typedef enum { + neighbor_init_e = 0, + neighbor_update_metrics_e, + neighbor_update_addr_req_e, + neighbor_term_user_req_e, + neighbor_term_e, + neighbor_term_ack_e, + neighbor_down_ack_tmo_e, + neighbor_link_char_res_e, +} dlep_server_neighbor_events_e; + + +/* + * normalized server states + */ +typedef enum { + neighbor_initializing_s = 0, + neighbor_update_s, + neighbor_terminating_s, +} dlep_server_neighbor_states_e; + + + + +extern uint32_t +dlep_server_neighbor_fsm_get_state( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_server_neighbor_fsm_show_counter( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_server_neighbor_fsm_show_state_table( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_server_neighbor_fsm_show_history( + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_server_neighbor_fsm_engine(uint32_t normalized_event, + dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_neighbor_fsm_destroy(dlep_context_neighbor_t *p2neighbor); + + +extern void +dlep_neighbor_fsm_create(dlep_context_neighbor_t *p2neighbor); + + +#endif + diff --git a/dlep_radio_ipv6/dlep_sim_options.h b/dlep_radio_ipv6/dlep_sim_options.h new file mode 100644 index 0000000..4d6cf73 --- /dev/null +++ b/dlep_radio_ipv6/dlep_sim_options.h @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------- + * dlep_sim_options.h -- Sim build options + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_SIM_OPTIONS_H__ +#define __DLEP_SIM_OPTIONS_H__ + +/* + * This file defines several build #defines that can be used to + * change the behavior of the simulator code for testing, etc. + */ + + +/** + ** Enable the definition of this macro to pack multiple + ** peer messages in a packet. + ** + ** #define MULTIPLE_PEER_MESSAGES_PACKED ( 1 ) + **/ +// #define MULTIPLE_PEER_MESSAGES_PACKED ( 1 ) + + +/** + ** Enable the definition of this macro to pack multiple + ** neighbor messages in a packet. + ** + ** #define MULTIPLE_NEIGHBOR_MESSAGES_PACKED ( 1 ) + **/ +//#define MULTIPLE_NEIGHBOR_MESSAGES_PACKED ( 1 ) + + +/** + ** Enable the insertion of the experimental TLVs for testing + ** + ** #define EXPERIMENTAL_TLVS ( 1 ) + **/ +// #define EXPERIMENTAL_TLVS ( 1 ) + + +/* + * defintion of this macro will enable dynamic + * metrics during periodic updates for testing. + * + * #define DYNAMIC_METRICS_ENABLED + */ +//#define DYNAMIC_METRICS_ENABLED + + + + +#endif + diff --git a/dlep_radio_ipv6/dlep_source_cli.c b/dlep_radio_ipv6/dlep_source_cli.c new file mode 100644 index 0000000..fb745a1 --- /dev/null +++ b/dlep_radio_ipv6/dlep_source_cli.c @@ -0,0 +1,143 @@ +/*------------------------------------------------------------------ + * dlep_source_cli.c -- source CLI commands + * + * October 2011, Bo Berry + * + * Copyright (c) 2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#include "cli.h" + +#include "dlep_source_cli.h" +//SENDIL +#include "sim_dlep_radio_cli.h" + + + +/* + * directory record + */ +cli_record_t cli_source_dir; + + +/* + * allocate command records + */ +static cli_record_t source_command_cmd; + + + +/** + ** source commands + **/ + +static void +source_commands (uint32_t argc, char *argv[]) +{ + FILE *fp; + +#define MAX_INPUT_LENGTH ( 512 ) + char input_string[MAX_INPUT_LENGTH]; + + + if (argv[1] && *argv[1] == '?') { + printf("source_commands - source commands from the file\n"); + printf("\n"); + printf(" - the file that contains commands being sourced \n"); + printf("\n"); + return; + } + + printf("sourcing file %s \n", argv[1]); + + fp = fopen(argv[1], "r"); + if (!fp) { + printf("Error: problem opening source file: %s\n", + argv[1]); + return; + } + + while (fgets(input_string, MAX_INPUT_LENGTH, fp)) { + if (input_string[0] == '\0') { + continue; + } else if (input_string[0] == '#') { + continue; + } + + dlep_cli_engine(input_string); + } + + return; +} + + + +/** + * NAME + * dlep_source_cli_init + * + * SYNOPSIS + * void + * dlep_source_cli_init() + * + * DESCRIPTION + * Registers the dlep source command with the cli + * facility. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_source_cli_init (void) +{ + RC_CLI_t rc; + + /* + * Create directory and commands + */ + rc = cli_mkdir("source", NULL, &cli_source_dir); + + + rc = cli_mkcmd("source_commands", + source_commands, + &cli_source_dir, + &source_command_cmd); + + return; +} + diff --git a/dlep_radio_ipv6/dlep_source_cli.h b/dlep_radio_ipv6/dlep_source_cli.h new file mode 100644 index 0000000..99bf642 --- /dev/null +++ b/dlep_radio_ipv6/dlep_source_cli.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------- + * dlep_source_cli.h -- source cli commands + * + * August 2011, Bo Berry + * + * Copyright (c) 2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __DLEP_SOURCE_CLI_H__ +#define __DLEP_SOURCE_CLI_H__ + + +extern void +dlep_source_cli_init(void); + +#endif + diff --git a/dlep_radio_ipv6/fsm.c b/dlep_radio_ipv6/fsm.c new file mode 100644 index 0000000..7330838 --- /dev/null +++ b/dlep_radio_ipv6/fsm.c @@ -0,0 +1,790 @@ +/*------------------------------------------------------------------ + * fsm.c -- Finite State Machine + * + * February 2005, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "fsm.h" + + +/* + * These are the maximum states and events that fsm uses + * for sizing during create. + */ +#define FSM_MAX_STATES ( 64 ) +#define FSM_MAX_EVENTS ( 64 ) + + + +/** + * NAME + * fsm_display_table + * + * SYNOPSIS + * #include "fsm.h" + * void + * fsm_display_table(fsm_t *fsm) + * + * DESCRIPTION + * Displays the designated state machine table to console. + * + * INPUT PARAMETERS + * fsm - handle to fsm + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +fsm_display_table (fsm_t *fsm) +{ +printf("fsm_display_table\n"); + uint32_t i; + uint32_t j; + state_tuple_t *state_ptr; + event_tuple_t *event_ptr; + + state_description_t *p2state_description; + event_description_t *p2event_description; + + if (fsm == NULL) { + return; + } + + if (fsm->tag != FSM_TAG) { + return; + } + + p2state_description = fsm->state_description_table; + p2event_description = fsm->event_description_table; + + printf("\nFSM: %s \n", fsm->fsm_name); + printf(" number_states = %d\n", fsm->number_states); + printf(" number_events = %d\n", fsm->number_events); + printf(" curr_state = %s\n", + p2state_description[fsm->curr_state].description ); + printf("\n"); + + /* + * For the normalized state table, list the normalized + * events and state transitions. + */ + for (i=0; inumber_states; i++) { + + state_ptr = &fsm->state_table[i]; + + printf(" State: %s \n", + p2state_description[state_ptr->state_id].description); + printf(" Event / Next State \n"); + printf("----------------------------\n"); + + for (j=0; jnumber_events; j++) { + + event_ptr = &state_ptr->p2event_tuple[j]; + + /* + * Display the name of the state associated with the next state. + */ + printf(" %u-%s / %s \n", + j, + p2event_description[j].description, + p2state_description[event_ptr->next_state].description); + } + printf("\n"); + } + printf("\n"); + return; +} + + +/** + * NAME + * fsm_show_history + * + * SYNOPSIS + * #include "fsm.h' + * void + * fsm_show_history(fsm_t *fsm) + * + * DESCRIPTION + * Displays history of the state transitions. + * + * INPUT PARAMETERS + * *fsm - handle of the state machine + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +fsm_show_history (fsm_t *fsm) +{ + uint32_t i, j; + fsm_history_t *history_ptr; + + state_description_t *p2state_description; + event_description_t *p2event_description; + + if (fsm == NULL) { + return; + } + + if (fsm->tag != FSM_TAG) { + return; + } + + p2state_description = fsm->state_description_table; + p2event_description = fsm->event_description_table; + + printf("\nFSM: %s History \n", fsm->fsm_name); + printf("Current State / Event / New State / rc \n"); + printf("------------------------------------------------\n"); + + j = fsm->history_index; + for (i=0; ihistory[i]; + + if (history_ptr->stateID == FSM_NULL_STATE_ID) { + continue; + } + + printf(" %u-%s / %u-%s / %u-%s / %u\n", + history_ptr->prevStateID, + p2state_description[history_ptr->prevStateID].description, + history_ptr->eventID, + p2event_description[history_ptr->eventID].description, + history_ptr->stateID, + p2state_description[history_ptr->stateID].description, + history_ptr->handler_rc); + + if (j==0) { + j=FSM_HISTORY; + } + j--; + } + + printf("\n"); + return; +} + + +/** + * NAME + * fsm_get_state + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_get_state(fsm_t *fsm, uint32_t*p2state) + * + * DESCRIPTION + * Function to return the current state. + * + * INPUT PARAMETERS + * *fsm - state machine handle + * + * p2state - Pointer to a state variable to be updated. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_get_state (fsm_t *fsm, uint32_t *p2state) +{ + if (fsm == NULL) { + return (RC_FSM_NULL); + } + + if (fsm->tag != FSM_TAG) { + return (RC_FSM_INVALID_HANDLE); + } + + *p2state = fsm->curr_state; + return (RC_FSM_OK); +} + + +/** + * NAME + * fsm_set_exception_state + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_set_exception_state(fsm_t *fsm, + * uint32_t exception_state) + * + * DESCRIPTION + * To be called from an event handler to alter + * the next state from the event table when an + * exception has been detected + * + * INPUT PARAMETERS + * *fsm - state machine handle + * + * exception_state - New state to be transitioned + * when the event handler returns. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_set_exception_state (fsm_t *fsm, uint32_t exception_state) +{ + if (fsm == NULL) { + return (RC_FSM_NULL); + } + + if (fsm->tag != FSM_TAG) { + return (RC_FSM_INVALID_HANDLE); + } + + /* + * Change the state of this FSM to the requested state. + */ + if (exception_state > fsm->number_states-1) { + return (RC_FSM_INVALID_STATE); + } + + fsm->exception_state = exception_state; + fsm->exception_state_indicator = TRUE; + return (RC_FSM_OK); +} + + +/** + * NAME + * fsm_destroy + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_destroy(fsm_t **fsm) + * + * DESCRIPTION + * Destroys the specified state machine. + * + * INPUT PARAMETERS + * fsm - pointer to fsm handle + * + * OUTPUT PARAMETERS + * fsm - is nulled + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_destroy (fsm_t **fsm) +{ + fsm_t *p2fsm; + + if (fsm == NULL) { + return (RC_FSM_NULL); + } + + p2fsm = *fsm; + if (p2fsm->tag != FSM_TAG) { + return (RC_FSM_INVALID_HANDLE); + } + + free(p2fsm->history); + *fsm = NULL; + free(p2fsm); + return (RC_FSM_OK); +} + + +/** + * NAME + * fsm_create + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_create(fsm_t **fsm, + * char *name, + * uint32_t initial_state, + * state_description_t *state_description_table, + * event_description_t *event_description_table, + * state_tuple_t *state_table) + * + * DESCRIPTION + * Creates and initializes a state machine. The + * initial state is specified by the user. + * + * INPUT PARAMETERS + * fsm pointer to fsm handle to be returned + * once created + * + * name pointer to fsm name + * + * initial_state Initial start state + * + * state_description_table + * Pointer to the user table which + * provides a description of each state. + * The table is used when displaying + * state info to the console. + * + * event_description_table + * Pointer to the user table which + * provides a description of each event. + * The table is used when displaying + * state info to the console. + * + * state_table Pointer to user defined state + * table. The state table is indexed + * by the normalized state ID, 0, 1, ... + * Each state table tuple must reference + * an event table. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_create (fsm_t **fsm, + char *name, + uint32_t initial_state, + state_description_t *state_description_table, + event_description_t *event_description_table, + state_tuple_t *state_table) +{ + fsm_t *temp_fsm; + uint32_t i; + uint32_t j; + state_tuple_t *state_ptr; + event_tuple_t *event_ptr; + + if (fsm == NULL) { + return (RC_FSM_NULL); + } + + if (state_description_table == NULL) { + printf("\n Description table == NULL"); + return (RC_FSM_INVALID_STATE_TABLE); + } + + if (event_description_table == NULL) { + + printf("\n event table == NULL"); + return (RC_FSM_INVALID_EVENT_TABLE); + } + + if (state_table == NULL) { + + printf("\n state_table == NULL"); + return (RC_FSM_INVALID_STATE_TABLE); + } + + + /* + * allocate memory to manage state machine + */ + temp_fsm = (fsm_t *)malloc( sizeof(fsm_t) ); + if (temp_fsm == NULL) { + printf("ME1\n"); + return (RC_FSM_NO_RESOURCES); + } + + /* + * default a name if needed + */ + if (name) { + strncpy(temp_fsm->fsm_name, name, FSM_NAME_LEN); + } else { + strncpy(temp_fsm->fsm_name, "State Machine", FSM_NAME_LEN); + } + + /* + * initialize fsm config parms + */ + temp_fsm->tag = FSM_TAG; /* for sanity cchecks */ + + temp_fsm->curr_state = initial_state; + temp_fsm->next_state = initial_state; + temp_fsm->exception_state_indicator = FALSE; + + /* save the event description table */ + temp_fsm->state_description_table = state_description_table; + temp_fsm->event_description_table = event_description_table; + + /* save the pointer to the state table */ + temp_fsm->state_table = state_table; + + /* + * Find the size of the state table + */ + temp_fsm->number_states = 0; + for (i=0; inumber_states++; + } else { + free(temp_fsm); + + printf("\n IN FSM invalied state tABLE"); + return (RC_FSM_INVALID_STATE_TABLE); + } + } else { + break; + } + } + if (temp_fsm->number_states < 1 || + temp_fsm->number_states > FSM_MAX_STATES-1) { + free(temp_fsm); + printf("ME2\n"); + return (RC_FSM_INVALID_STATE_TABLE); + } +#if 0 + printf("number states=%u \n", temp_fsm->number_states); +#endif + + /* + * check zero based range for state + */ + if (initial_state > temp_fsm->number_states-1) { + free(temp_fsm); + printf("ME3\n"); + return (RC_FSM_INVALID_STATE); + } + + + /* + * Find the size of the event table + */ + temp_fsm->number_events = 0; + for (i=0; inumber_events++; + } + if (temp_fsm->number_events < 1 || + temp_fsm->number_events > FSM_MAX_EVENTS-1) { + free(temp_fsm); + printf("ME5\n"); + return (RC_FSM_INVALID_EVENT_TABLE); + } +#if 0 + printf("number events=%u \n", temp_fsm->number_events); +#endif + + /* + * Now verify the state table - event table relationships and + * that the IDs are normalized. + */ + for (i=0; inumber_states; i++) { + state_ptr = &temp_fsm->state_table[i]; + + event_ptr = state_ptr->p2event_tuple; + + for (j=0; jnumber_events; j++) { +#if 0 + printf(" %u eventID=%u \n", + j, + event_ptr[j].eventID); +#endif + if (j != event_ptr[j].eventID) { + free(temp_fsm); + printf("ME6\n"); + return (RC_FSM_INVALID_EVENT_TABLE); + } + } + } + + /* + * allocate memory for history + */ + temp_fsm->history = malloc(FSM_HISTORY * sizeof(fsm_history_t)); + if (temp_fsm->history == NULL) { + free(temp_fsm); + printf("ME7\n"); + return (RC_FSM_NO_RESOURCES); + } + + /* + * initialize history buffer + */ + temp_fsm->history_index = 0; + for (i=0; ihistory[i].prevStateID = FSM_NULL_STATE_ID; + temp_fsm->history[i].stateID = FSM_NULL_STATE_ID; + temp_fsm->history[i].eventID = FSM_NULL_EVENT_ID; + temp_fsm->history[i].handler_rc = RC_FSM_NULL; + } + + /* return handle to the user */ + *fsm = temp_fsm; + return (RC_FSM_OK); +} + + +/* + * internal routine to record a state transition history + */ +static void +fsm_record_history (fsm_t *fsm, + uint32_t normalized_event, + uint32_t nextState, + RC_FSM_t handler_rc) +{ + fsm_history_t *history_ptr; + + /* + * get next index to record a little history + */ + fsm->history_index = (fsm->history_index+1)%FSM_HISTORY; + + /* + * Get a local pointer to the history buffer to populate + */ + history_ptr = &fsm->history[fsm->history_index]; + + history_ptr->prevStateID = fsm->curr_state; + history_ptr->stateID = nextState; + history_ptr->eventID = normalized_event; + history_ptr->handler_rc = handler_rc; + return; +} + + +/** + * NAME + * fsm_engine + * + * SYNOPSIS + * #include "fsm.h" + * RC_FSM_t + * fsm_engine(fsm_t *fsm, + * uint32_t normalized_event, + * void *p2event_buffer, + * void *p2parm) + * + * DESCRIPTION + * Drives a state machine defined by normalized event + * and a states. + * + * INPUT PARAMETERS + * *fsm state machine handle + * + * normalized_event the event id to process + * + * *p2event pointer to the raw event which + * is driving the event. This is + * passed through to the handler. + * + * *p2parm pointer parameter that is simply + * passed through to each event + * handler. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + * + */ +RC_FSM_t +fsm_engine (fsm_t *fsm, + uint32_t normalized_event, + void *p2event_buffer, + void *p2parm) +{ +printf("fsm_engine\n"); + event_tuple_t *event_ptr; + event_cb_t event_handler; + RC_FSM_t rc; + + /* + * verify pointers & handles are valid + */ + + if (fsm == NULL) { + + printf("\n RETURN 2 DEBUG "); + return (RC_FSM_NULL); + } + + if (fsm->tag != FSM_TAG) { + + printf("\n RETURN 3 DEBUG "); + return (RC_FSM_INVALID_HANDLE); + } + + /* + * verify that "event id" is valid: [0-(number_events-1)] + */ + if (normalized_event > fsm->number_events-1) { + fsm_record_history(fsm, normalized_event, + fsm->curr_state, RC_FSM_INVALID_EVENT); + printf("\n RETURN 4 DEBUG "); + return (RC_FSM_INVALID_EVENT); + } + + /* + * Index into the state table to get to the event table + * so we can get the next state and the event handler. + */ + event_ptr = + &fsm->state_table[fsm->curr_state].p2event_tuple[normalized_event]; + + /* + * If the handler was NULL then we have a quiet event , + * no processing possible. + */ + event_handler = event_ptr->event_handler; + if (event_handler == NULL) { + fsm_record_history(fsm, + normalized_event, + event_ptr->next_state, + RC_FSM_INVALID_EVENT_HANDLER); + printf("\n RETURN 5 DEBUG "); + return (RC_FSM_OK); + } + + printf(" "); + rc = (*event_handler)(p2event_buffer, p2parm); + + /* + * Event handler wants to stop processing events. There is no access + * to the fsm data structure in case the state machine has ended. + */ + if (rc == RC_FSM_STOP_PROCESSING) { + printf("\n RETURN 6 DEBUG "); + return (rc); + } + + /* + * If the return code is not OK, simply record the + * result without a state change. + */ + if (rc != RC_FSM_OK) { + fsm_record_history(fsm, normalized_event, + event_ptr->next_state, rc); + return (rc); + } + + /* + * If the exception state indicator is set, use the exception + * state provided by the event handler. This is an unexpected + * state transition. Else use the event table next state. + */ + if (fsm->exception_state_indicator) { + /* + * event handler detected an exception to the state transition + */ + fsm->exception_state_indicator = FALSE; + fsm->next_state = fsm->exception_state; + + } else { + /* + * we have a valid event table transition + */ + fsm->next_state = event_ptr->next_state; + } + + /* + * Validate the next state from the event table + * knowing that the event id is 0,1,2,... + * Then use the event id to directly index into the state + * table to set the next state. + */ + if (fsm->next_state > (fsm->number_states-1)) { + fsm_record_history(fsm, + normalized_event, + fsm->next_state, + RC_FSM_INVALID_STATE); + rc = RC_FSM_INVALID_STATE; + + } else { + + /* record a bit of history. */ + fsm_record_history(fsm, + normalized_event, + fsm->next_state, + rc); + + /* + * and update the current state completing the transition + */ + fsm->curr_state = fsm->next_state; + } + return (rc); +} + diff --git a/dlep_radio_ipv6/fsm.h b/dlep_radio_ipv6/fsm.h new file mode 100644 index 0000000..59f2c9a --- /dev/null +++ b/dlep_radio_ipv6/fsm.h @@ -0,0 +1,340 @@ +/*------------------------------------------------------------------ + * fsm.h - Finite State Machine definitions + * + * February 2005, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __FSM_H__ +#define __FSM_H__ + +#include "safe_types.h" + + +/* + * return codes utilized by the fsm APIs and + * user event handlers + */ +typedef enum { + /* indicates success - state change */ + RC_FSM_OK = 0, + + /* indicates that the fsm handle was NULL */ + RC_FSM_NULL, + + /* indicates that the fsm handle pointed to somethinf else! */ + RC_FSM_INVALID_HANDLE, + + RC_FSM_INVALID_EVENT_HANDLER, + + /* indicates that an error was found in the state table */ + RC_FSM_INVALID_STATE_TABLE, + + /* indicates that the next state was out of bounds */ + RC_FSM_INVALID_STATE, + + /* indicates that an error was found in the event table */ + RC_FSM_INVALID_EVENT_TABLE, + + /* indicates that the next event was out of bounds */ + RC_FSM_INVALID_EVENT, + + /* indicates that there was no memory available */ + RC_FSM_NO_RESOURCES, + + /* event handler indicating that the event can be + * ignored, no transition + */ + RC_FSM_IGNORE_EVENT, + + /* event handler indicating that the state machine is + * being deallocated and no further access to the fsm + * strucutre should be made - history + */ + RC_FSM_STOP_PROCESSING, +} RC_FSM_t; + + + +#define FSM_NULL_STATE_ID ( -1 ) +#define FSM_NULL_EVENT_ID ( -1 ) + + +/* + * typedef RC_FSM_t (*event_cb_t)(void *p2event, void *p2parm) + * + * DESCRIPTION + * Provides typedef for the event handler functions. + * + * Once the state's normalized event ID and index has been + * determined, the associated event call-back is invoked + * to effect the state processing and transition. + * + * INPUT PARAMETERS + * p2event pointer to the raw event to be processed + * by the event handler. + * + * p2parm pointer parameter that is simply + * passed through from fsm_engine to each + * event handler. + * + * RETURN VALUE + * RC_FSM_OK + * error otherwise + */ +typedef RC_FSM_t (*event_cb_t)(void *p2event, void *p2parm); + + +/* + * User provided Normalized Event Description Table. + * + * An Example + * typedef enum { + * start_init_e = 0, + * init_rcvd_e, + * init_tmo_e, + * init_ack_e, + * start_term_e, + * term_rcvd_e, + * term_ack_e, + * } session_events_e; + * + * static event_description_t normalized_event_table[] = + * {{start_init_e, "Start Session Init"}, + * {init_rcvd_e, "Session Init"}, + * {init_tmo_e, "Session Init ACK TMO"}, + * {init_ack_e, "Session Init ACK"}, + * {start_term_e, "Start Session Termination"}, + * {term_rcvd_e, "Session Terminate"}, + * {term_ack_e, "Session Terminate ACK"}, + * {FSM_NULL_EVENT_ID, NULL}}; / required to end table / + * + */ +typedef struct { + uint32_t event_id; + char *description; +} event_description_t; + + +/* + * User provided Normalized State DESCRIPTION Table. + * + * An example + * typedef enum { + * idle_s = 0, + * wait_for_init_ack_s, + * established_s, + * wait_for_term_ack_s, + * } demo_states_e; + * + * static state_description_t normalized_state_table[] = + * {{start_init_e, "Start Session Init"}, + * {idle_s, Idle State"}, + * {wait_for_init_ack_s, "Wait for Init Ack State"}, + * {established_s, "Established State"}, + * {wait_for_term_ack_s, "Wait for Terminate Ack State"}, + * {FSM_NULL_STATE_ID, NULL}}; / required to end table / + * + */ +typedef struct { + uint32_t state_id; + char *description; +} state_description_t; + + + +/* + * User provided Event Table - one table per state is + * required. The table must have an entry for each + * normalized event, ordered from 0 - n. + * + * event_id is the normalized value. + * + * event_handler is the user provided call-back function that is + * invoked to handle the event and effect the state transition. + * If the event_handler is NULL, no processing is + * associated with the event - no state transition. + * + * next_state is the next state as result of the event. It is + * possible that a state transition associated with an event + * remain in the current state. + * + * An example: + * static event_tuple_t state_wait_for_init_ack_events[] = + * {{start_init_e, event_ignore, wait_for_init_ack_s}, + * {init_rcvd_e, event_ignore, wait_for_init_ack_s}, + * {init_tmo_e, event_init_ack_tmo, wait_for_init_ack_s}, + * {init_ack_e, event_init_ack_rcvd, established_s}, + * {start_term_e, event_term_rcvd, wait_for_term_ack_s}, + * {term_rcvd_e, event_term_rcvd, idle_s}, + * {term_ack_e, event_ignore, wait_for_term_ack_s}}; + */ +typedef struct { + uint32_t eventID; /* normalized event id */ + event_cb_t event_handler; /* if NULL==no transaction processing */ + uint32_t next_state; /* normalized next state - can be + * the same state */ +} event_tuple_t; + + +/* + * User provided Normalized State Table. This table represents all + * the states and the event table associated with each state. + * + * An example: + * static state_tuple_t demo_state_table[] = + * {{idle_s, state_idle_events}, + * {wait_for_init_ack_s, state_wait_for_init_ack_events}, + * {established_s, state_established_events}, + * {wait_for_term_ack_s, state_wait_for_term_ack_events}, + * {FSM_NULL_STATE_ID, NULL}}; / requied to end table / + */ +typedef struct { + uint32_t state_id; + event_tuple_t *p2event_tuple; +} state_tuple_t; + + +/* + * Historical record of state changes + */ +typedef struct { + uint32_t number; + uint32_t prevStateID; + uint32_t stateID; + uint32_t eventID; + RC_FSM_t handler_rc; +} fsm_history_t; + + +#define FSM_HISTORY ( 64 ) + +/* + * Finite State Machine structure + * + */ +#define FSM_TAG ( 0xba5eba11 ) +#define FSM_NAME_LEN ( 32 ) + +typedef struct { + /* for fsm validation */ + uint32_t tag; + + uint32_t curr_state; + uint32_t next_state; + + /* + * This is set by an event handle to cover an excpetion + * state transition that is different from the event + * table next state transition. + */ + uint32_t exception_state; + boolean_t exception_state_indicator; + + char fsm_name[FSM_NAME_LEN]; + + /* number states in table */ + uint32_t number_states; + + /* number events in each state-event table */ + uint32_t number_events; + + /* debug and trace flags*/ + uint32_t flags; + + /* pointer to the state table */ + state_tuple_t *state_table; + + /* description of normalized states and events */ + state_description_t *state_description_table; + event_description_t *event_description_table; + + /* starts at 0 and wraps */ + uint32_t history_index; + /* memory is malloc'ed to record history */ + fsm_history_t *history; +} fsm_t; + + +/* + * show state machine table + */ +extern void +fsm_display_table(fsm_t *fsm); + + +/* + * shows state machine history + */ +extern void +fsm_show_history(fsm_t *fsm); + + +/* get state */ +extern RC_FSM_t +fsm_get_state(fsm_t *fsm, uint32_t *p2state); + + +/* + * allows event handler to update the next state based upon + * an unexpected condition when processing the event. + */ +extern RC_FSM_t +fsm_set_exception_state(fsm_t *fsm, uint32_t exception_state); + + +/* + * destroy a state machine + */ +extern RC_FSM_t +fsm_destroy(fsm_t **fsm); + + +/* + * create and config a state machine + */ +extern RC_FSM_t +fsm_create(fsm_t **fsm, + char *fsm_name, + uint32_t initial_state, + state_description_t *state_description_table, + event_description_t *event_description_table, + state_tuple_t *state_table); + + +/* + * API to drive a state machine + */ +extern RC_FSM_t +fsm_engine(fsm_t *fsm, + uint32_t normalized_event, + void *p2event_bufer, + void *p2parm); + + +#endif /* __FSM_H__ */ + diff --git a/dlep_radio_ipv6/fuzz_dlep_cli.h b/dlep_radio_ipv6/fuzz_dlep_cli.h new file mode 100644 index 0000000..1da0faf --- /dev/null +++ b/dlep_radio_ipv6/fuzz_dlep_cli.h @@ -0,0 +1,40 @@ +/*------------------------------------------------------------------ + * fuzz_dlep_cli.h -- fuzz CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __FUZZ_DLEP_CLI_H__ +#define __FUZZ_DLEP_CLI_H__ + + +extern +void fuzz_dlep_cli_init(void); + +#endif + diff --git a/dlep_radio_ipv6/fuzz_encoder_tlv.h b/dlep_radio_ipv6/fuzz_encoder_tlv.h new file mode 100644 index 0000000..d5d462b --- /dev/null +++ b/dlep_radio_ipv6/fuzz_encoder_tlv.h @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------- + * fuzz_encoder_tlv.h -- routine prototypes to encode TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __FUZZ_ENCODER_TLV_H__ +#define __FUZZ_ENCODER_TLV_H__ + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_encoder.h" + + + +extern uint8_t +*fuzz_identification_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t router_id, + uint32_t client_id, + uint8_t heartbeat_interval); + +extern uint8_t +*fuzz_version_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t version_major, + uint16_t version_minor); + + +extern uint8_t +*fuzz_peer_tlv(rfc5444_encoder_state_t *p2encoder_state, + char *peer_type_string); + + +extern uint8_t +*fuzz_mac_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t mac_address[]); + + +extern uint8_t +*fuzz_ipv4_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv4_address_t *ipv4); + +extern uint8_t +*fuzz_ipv6_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv6_address_t *ipv6_dest_addr); + + +extern uint8_t +*fuzz_link_metric_mdr_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr); + +extern uint8_t +*fuzz_link_metric_cdr_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr); + +extern uint8_t +*fuzz_link_metric_latency_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t latency); + +extern uint8_t +*fuzz_link_metric_resources_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources); + +extern uint8_t +*fuzz_link_metric_rlq_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq); + +extern uint8_t +*fuzz_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t termination_code); + + +extern uint8_t +*fuzz_datarate_request_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t requested_cdr); + + +extern uint8_t +*fuzz_datarate_request_ack_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t requested_cdr, + uint32_t granted_cdr); + +#endif + + diff --git a/dlep_radio_ipv6/fuzz_message_builder.h b/dlep_radio_ipv6/fuzz_message_builder.h new file mode 100644 index 0000000..db76512 --- /dev/null +++ b/dlep_radio_ipv6/fuzz_message_builder.h @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------- + * fuzz_message_builder.h -- Routines to build fuzzed DLEP messages + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __FUZZ_MESSAGE_BUILDER_H__ +#define __FUZZ_MESSAGE_BUILDER_H__ + +#include "dlep_context_peer.h" +#include "dlep_context_neighbor.h" + + + +/* + * Router-Radio Level Mesages + */ + +extern void +send_fuzz_attached_peer_discovery(dlep_context_peer_t *p2peer); + +extern void +send_fuzz_detached_peer_discovery(dlep_context_peer_t *p2peer); + +extern void +send_fuzz_peer_offer(dlep_context_peer_t *p2peer); + + +extern void +send_fuzz_peer_heartbeat(dlep_context_peer_t *p2peer); + + +extern void +send_fuzz_peer_update_request(dlep_context_peer_t *p2peer); + +extern void +send_fuzz_peer_update_response(dlep_context_peer_t *p2peer); + + +extern void +send_fuzz_peer_terminate(dlep_context_peer_t *p2peer); + +extern void +send_fuzz_peer_terminate_ack(dlep_context_peer_t *p2peer); + + +/* + * Neighbor Level Mesages + */ + +extern void +send_fuzz_neighbor_up(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_up_ack(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_metrics(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_address_request(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_address_response(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + +extern void +send_fuzz_neighbor_down(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_down_ack(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + +extern void +send_fuzz_neighbor_link_char_request(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor, + uint64_t cdr, + uint64_t latency); + + +extern void +send_fuzz_neighbor_link_char_response(dlep_context_peer_t *p2peer, + dlep_context_neighbor_t *p2neighbor); + + + +#endif + diff --git a/dlep_radio_ipv6/fuzz_packet.c b/dlep_radio_ipv6/fuzz_packet.c new file mode 100644 index 0000000..352b899 --- /dev/null +++ b/dlep_radio_ipv6/fuzz_packet.c @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------- + * fuzz_packet.c -- Routines to read a fuzzed packet file + * + * October 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "safe_types.h" +#include "fuzz_packet.h" + + +#define FUZZ_PACKET_LENGTH ( 2048 ) + + +/** + * NAME + * fuzz_packet_load + * + * DESCRIPTION + * This function reads the designated file that contains + * a fuzzed DLEP packet. The fuzzed packet is used for testing. + * + * INPUT PARAMETERS + * + * OUTPUT PARAMETERS + * + * RETURN VALUE + * length - number of bytes in packet + * + */ +uint32_t +fuzz_packet_load (char *fuzzy_filename, uint8_t *p2packet) +{ + uint32_t i; + uint32_t key_index; + uint32_t line_count; + + FILE *fp; + + +#define MAX_INPUT_LENGTH ( 512 ) + char directed_filename[MAX_INPUT_LENGTH]; + char input_string[MAX_INPUT_LENGTH]; + +#define ARGC_MAX ( 8 ) + uint32_t argc; + char *argv[ARGC_MAX]; + + + if (!fuzzy_filename || !p2packet) { + return (0); + } + + strcpy(directed_filename, "fuzzy_dir/"); + strcat(directed_filename, fuzzy_filename); + + fp = fopen(directed_filename, "r"); + if (!fp) { + printf("Error: problem opening fuzzed file: %s\n", + directed_filename); + return (0); + } + + key_index = 0; + line_count = 0; + while (fgets(input_string, MAX_INPUT_LENGTH, fp)) { + line_count++; + + if (input_string[0] == '\0') { + continue; + } else if (input_string[0] == '#') { + continue; + } + + argv[0] = strtok(input_string, " ,\t\n"); + /* empty line */ + if (argv[0] == NULL) { + continue; + } + p2packet[key_index] = strtoul(argv[0], NULL, 16); + key_index++; + + argc = 1; + for (i=1; i +#include + +#include "ipv4_address.h" + + +/** + * NAME + * ipv4_print_address + * + * SYNOPSIS + * #include "man_ipv4_address.h" + * void + * ipv4_print_address(char *p2label, + * ipv4_address_t *ipv4_src_addr) + * + * DESCRIPTION + * Use this function to printf an IPv4 address in dot-decimal + * notation. + * + * INPUT PARAMETERS + * p2label - label to be printed + * ipv4_src_addr - pointer to the IPv4 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +ipv4_print_address (char *p2label, ipv4_address_t *ipv4_src_addr) +{ + if (!ipv4_src_addr) { + return; + } + + if (p2label) { + printf("%s %d.%d.%d.%d \n", + p2label, + ipv4_src_addr->v4_addr.v4_addr8[3], + ipv4_src_addr->v4_addr.v4_addr8[2], + ipv4_src_addr->v4_addr.v4_addr8[1], + ipv4_src_addr->v4_addr.v4_addr8[0]); + + } else { + printf("IPv4: %d.%d.%d.%d \n", + ipv4_src_addr->v4_addr.v4_addr8[3], + ipv4_src_addr->v4_addr.v4_addr8[2], + ipv4_src_addr->v4_addr.v4_addr8[1], + ipv4_src_addr->v4_addr.v4_addr8[0]); + } + + return; +} + + +/** + * NAME + * ipv4_dot_decimal2digits + * + * SYNOPSIS + * #include "man_ipv4_address.h" + * void + * ipv4_dot_decimal2digits(ipv4_address_t *ipv4_dest_addr, + * char *input) + * + * DESCRIPTION + * This function converts an IPv4 dot-decimal notation, + * such as 192.168.1.1, into binary. + * + * INPUT PARAMETERS + * ipv4_dest_addr - pointer to the IPv4 address + * + * input - pointer to the Ascii IPv4 string + * + * OUTPUT PARAMETERS + * ipv4_dest_addr - updated with the IPv4 address + * + * RETURN VALUE + * None + * + * EXAMPLES + * ipv4_dest_addr->v4_addr.v4_addr8[3] = 192; + * ipv4_dest_addr->v4_addr.v4_addr8[2] = 168; + * ipv4_dest_addr->v4_addr.v4_addr8[1] = 1; + * ipv4_dest_addr->v4_addr.v4_addr8[0] = 1; + * + * If there is an error, the remaining ipv4[i] are 0. + * + */ +void +ipv4_dot_decimal2digits (ipv4_address_t *ipv4_dest_addr, char *input) +{ + char *ptr; + + if (!ipv4_dest_addr) { + return; + } + + ipv4_zero_address(ipv4_dest_addr); + + if (!input) { + return; + } + + /* most significant */ + ipv4_dest_addr->v4_addr.v4_addr8[3] = strtoul(input, &ptr, 10); + if (*ptr != '.') { + return; + } + ptr++; + ipv4_dest_addr->v4_addr.v4_addr8[2] = strtoul(ptr, &ptr, 10); + if (*ptr != '.') { + return; + } + ptr++; + ipv4_dest_addr->v4_addr.v4_addr8[1] = strtoul(ptr, &ptr, 10); + if (*ptr != '.') { + return; + } + ptr++; + ipv4_dest_addr->v4_addr.v4_addr8[0] = strtoul(ptr, NULL, 10); + + return; +} + + diff --git a/dlep_radio_ipv6/ipv4_address.h b/dlep_radio_ipv6/ipv4_address.h new file mode 100644 index 0000000..2532b42 --- /dev/null +++ b/dlep_radio_ipv6/ipv4_address.h @@ -0,0 +1,398 @@ +/*------------------------------------------------------------------ + * ipv4_address.h -- Miscellaneous IPv4 Address Support Routines + * + * July 2008, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __IPV4_ADDRESS_H__ +#define __IPV4_ADDRESS_H__ + +#include "safe_types.h" +#include "network_order.h" + + + +/* + * IPv4 Address Notations + * + * Dot Decimal: 192.0.2.235 + * + * Hexidecimal: 0xC00002EB + * + * + * Classless Inter-Domain Routing (CIDR) + * + * CIDR ranges for private networks: + * + * Number of Classful Largest + * NAME Address range addresses DESCRIPTION CIDR block + *--------------------------------------------------------------------- + * 24-bit 10.0.0.0 – + * 10.255.255.255 16,777,216 Single Class A 10.0.0.0/8 + * 20-bit 172.16.0.0 – + * 172.31.255.255 1,048,576 16 contiguous Class + * B blocks 172.16.0.0/12 + * 16-bit 192.168.0.0 – + * 192.168.255.255 65,536 Contiguous range of + * 256 class C blocks 192.168.0.0/16 + * + * Link-local addressing + * Address block edfined in RFC3330 for the special use in + * link-local addressing. These addresses are only valid on the link, + * such as a local network segment or point-to-point connection, that + * a host is connected to. + * Range: 169.254.0.0/16 + * + * Local-host (local loopback) + * Addresses within this range are internal to the lost and should + * never appear outside the host computer. Packets sent to this + * address are returned as incoming packets on the same virtual + * network device. + * Range: 127.0.0.0 – 127.255.255.255 (127.0.0.0/8 in CIDR notation) + * + */ + + + +/* + * IPv4 Multicast Addresses: 224.0.0.0 thru 239.255.255.255 + * The multicast addresses from 224.0.0.0 to 224.0.0.255 are reserved for + * multicast routing information. Application programs should use multicast + * addresses outside this range. + */ +#define IPV4_MULTICAST_LOW ( 0xE0000000 ) +#define IPV4_MULTICAST_HIGH ( 0xEF000000 ) + + + +/* + * IPv4 length values + */ +#define IPV4_ADDR_STRING_LEN ( 16 ) +#define IPV4_ADDR_LEN_IN_BITS ( 32 ) +#define IPV4_ADDR_LEN_IN_BYTES ( 4 ) +#define IPV4_ADDR_LEN_IN_LONGS ( 1 ) + + +/* + * IPv4 Address Type (32 bits) + */ +typedef struct ipv4_address_ { + union { + uint8_t v4_addr8[IPV4_ADDR_LEN_IN_BYTES]; + uint32_t v4_addr32; + } v4_addr; +} ipv4_address_t; + + + + +/** + * NAME + * ipv4_put_address + * + * SYNOPSIS + * static inline uint8_t + * *ipv4_put_address(uint8_t *mp, ipv4_address_t *ipv4_src_addr) + * + * DESCRIPTION + * Use this function to copy the source IPv4 address to the + * destination pointer mp. + * + * INPUT PARAMETERS + * mp - destination buffer pointer + * + * ipv4_src_addr - pointer to the source address + * + * OUTPUT PARAMETERS + * mp - updated + * + * RETURN VALUE + * Pointer to the next byte in the destination space, mp + * + */ +static inline uint8_t +*ipv4_put_address (uint8_t *mp, ipv4_address_t *ipv4_src_addr) +{ + if (!ipv4_src_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_PUTLONG(mp, ipv4_src_addr->v4_addr.v4_addr32); + mp = mp + sizeof(ipv4_address_t); + + return (mp); +} + + +/** + * NAME + * ipv4_get_address + * + * SYNOPSIS + * static inline uint8_t + * *ipv4_get_address(ipv4_address_t *ipv4_dest_addr, uint8_t *mp) + * + * DESCRIPTION + * Use this function to copy an IPv4 address from the buffer + * pointer mp to the destination ipv4_dest_addr. + * + * INPUT PARAMETERS + * ipv4_dest_addr - destination pointer to receive the IPv4 address + * + * mp - source pointer to copy from + * + * OUTPUT PARAMETERS + * ipv4_dest_addr - updated + * + * RETURN VALUE + * Pointer to the next byte in the source space, mp + * + */ +static inline uint8_t +*ipv4_get_address (ipv4_address_t *ipv4_dest_addr, uint8_t *mp) +{ + if (!ipv4_dest_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_GETLONG(mp, ipv4_dest_addr->v4_addr.v4_addr32); + mp = mp + sizeof(ipv4_address_t); + + return (mp); +} + + +/** + * NAME + * ipv4_address_is_multicast + * + * SYNOPSIS + * static inline boolean_t + * ipv4_address_is_multicast(ipv4_address_t *ipv4_addr) + * + * DESCRIPTION + * Use this function determine if the IPv4 address is multicast. + * + * INPUT PARAMETERS + * ipv4_addr pointer to the IPv4 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes, it is a multicast address + * FALSE - nope! + * + */ +static inline boolean_t +ipv4_address_is_multicast (ipv4_address_t *ipv4_addr) +{ + ipv4_address_t ipv4_multicast; + + if (!ipv4_addr) { + return (FALSE); + } + + ipv4_multicast.v4_addr.v4_addr32 = + ipv4_addr->v4_addr.v4_addr32 & 0xFF000000; + + if (ipv4_multicast.v4_addr.v4_addr32 >= IPV4_MULTICAST_LOW && + ipv4_multicast.v4_addr.v4_addr32 <= IPV4_MULTICAST_HIGH) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * ipv4_address_to_broadcast + * + * SYNOPSIS + * static inline ipv4_address_t + * ipv4_address_to_broadcast(ipv4_address_t *ipv4_addr) + * ipv4_address_t *ipv4_subnet, + * ipv4_address_t *ipv4_broadcast) + * + * DESCRIPTION + * This function returns a broadcast address given an + * IPv4 address and its subnet. + * + * INPUT PARAMETERS + * ipv4_addr - pointer to the IPv4 address + * + * ipv4_subnet - pointer to the IPv4 subnet mask + * + * ipv4_broadcast - pointer to the IPv4 subnet mask + * + * OUTPUT PARAMETERS + * ipv4_broadcast - updated + * + * RETURN VALUE + * IPv4 broadcast address + * + */ +static inline boolean_t +ipv4_address_to_broadcast (ipv4_address_t *ipv4_addr, + ipv4_address_t *ipv4_subnet, + ipv4_address_t *ipv4_broadcast) +{ + if (!ipv4_addr || !ipv4_subnet || ipv4_broadcast) { + return (FALSE); + } + + ipv4_broadcast->v4_addr.v4_addr32 = + (ipv4_addr->v4_addr.v4_addr32 | + (~ipv4_subnet->v4_addr.v4_addr32)); + return (TRUE); +} + + +/** + * NAME + * ipv4_zero_address + * + * SYNOPSIS + * static inline void + * ipv4_zero_address(ipv4_address_t *ipv4_addr) + * + * DESCRIPTION + * This function can be used to zero an IPv4 address. + * + * INPUT PARAMETERS + * ipv4_addr - pointer to the IPV4 address + * + * OUTPUT PARAMETERS + * ipv4_addr - zeroed + * + * RETURN VALUE + * none + * + */ +static inline void +ipv4_zero_address (ipv4_address_t *ipv4_addr) +{ + if (!ipv4_addr) { + return; + } + + ipv4_addr->v4_addr.v4_addr32 = 0; + return; +} + + +/** + * NAME + * ipv4_compare_address + * + * SYNOPSIS + * static inline boolean_t + * ipv4_compare_address(ipv4_address_t ipv4_dest_addr, + * ipv4_address_t ipv4_src_addr) + * + * DESCRIPTION + * This function can be used to compare two IPv4 addresses. + * + * INPUT PARAMETERS + * ipv4_dest_addr - pointer to the destination IPV4 address + * + * ipv4_src_addr - pointer to the source IPV4 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE == equal + * FALSE == not equal + * + */ +static inline boolean_t +ipv4_compare_address (ipv4_address_t *ipv4_dest_addr, + ipv4_address_t *ipv4_src_addr) +{ + if (ipv4_dest_addr->v4_addr.v4_addr32 == + ipv4_src_addr->v4_addr.v4_addr32) { + return (TRUE); + } else { + return (FALSE); + } +} + + + +/** + * NAME + * ipv4_copy_address + * + * SYNOPSIS + * static inline void + * ipv4_copy_address(ipv4_address_t *ipv4_dest_addr, + * ipv4_address_t *ipv4_src_addr) + * + * DESCRIPTION + * Use this function to compare two IPv4 addresses + * + * INPUT PARAMETERS + * ipv4_dest_addr - pointer to the destination IPv4 address + * + * ipv4_src_addr - pointer to the src IPv4 address + * + * OUTPUT PARAMETERS + * ipv4_dest_addr - updated + * + * RETURN VALUE + * none + * + */ +static inline void +ipv4_copy_address (ipv4_address_t *ipv4_dest_addr, + ipv4_address_t *ipv4_src_addr) +{ + if (!ipv4_dest_addr || !ipv4_src_addr) { + return; + } + + ipv4_dest_addr->v4_addr.v4_addr32 = ipv4_src_addr->v4_addr.v4_addr32; + return; +} + + + +extern void +ipv4_print_address(char *p2label, ipv4_address_t *ipv4_src_addr); + +extern void +ipv4_dot_decimal2digits(ipv4_address_t *ipv4_dest_addr, char *input); + +extern void +ipv4_dot_hex2digits(ipv4_address_t *ipv4_dest_addr, char *input); + +#endif + diff --git a/dlep_radio_ipv6/ipv6_address.c b/dlep_radio_ipv6/ipv6_address.c new file mode 100644 index 0000000..14c4dd0 --- /dev/null +++ b/dlep_radio_ipv6/ipv6_address.c @@ -0,0 +1,211 @@ +/*---------------------------------------------------------------------- + * ipv6_address.c -- Miscellaneous IPv6 Address Support Routines + * + * June 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include + +#include "ipv6_address.h" + + +/** + * NAME + * ipv6_print_address + * + * SYNOPSIS + * #include "man_ipv6_address.h" + * void + * ipv6_print_address(char *p2label, + * ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to print an IPv6 address + * + * INPUT PARAMETERS + * p2label - label to be printed + * + * ipv6_src_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +ipv6_print_address (char *p2label, ipv6_address_t *ipv6_src_addr) +{ + if (!ipv6_src_addr) { + return; + } + char str[130]; + if (p2label) { + printf("%s %04x:%04x:%04x:%04x%04x:%04x:%04x:%04x \n", + p2label, + ipv6_src_addr->v6_addr.v6_addr16[0], + ipv6_src_addr->v6_addr.v6_addr16[1], + ipv6_src_addr->v6_addr.v6_addr16[2], + ipv6_src_addr->v6_addr.v6_addr16[3], + ipv6_src_addr->v6_addr.v6_addr16[4], + ipv6_src_addr->v6_addr.v6_addr16[5], + ipv6_src_addr->v6_addr.v6_addr16[6], + ipv6_src_addr->v6_addr.v6_addr16[7]); + + + } else { + sprintf(str,"IPv6: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", + ipv6_src_addr->v6_addr.v6_addr8[0], + ipv6_src_addr->v6_addr.v6_addr8[1], + ipv6_src_addr->v6_addr.v6_addr8[2], + ipv6_src_addr->v6_addr.v6_addr8[3], + ipv6_src_addr->v6_addr.v6_addr8[4], + ipv6_src_addr->v6_addr.v6_addr8[5], + ipv6_src_addr->v6_addr.v6_addr8[6], + ipv6_src_addr->v6_addr.v6_addr8[7], + ipv6_src_addr->v6_addr.v6_addr8[8], + ipv6_src_addr->v6_addr.v6_addr8[9], + ipv6_src_addr->v6_addr.v6_addr8[10], + ipv6_src_addr->v6_addr.v6_addr8[11], + ipv6_src_addr->v6_addr.v6_addr8[12], + ipv6_src_addr->v6_addr.v6_addr8[13], + ipv6_src_addr->v6_addr.v6_addr8[14], + ipv6_src_addr->v6_addr.v6_addr8[15]); + } +#if 0 + printf("ipv6_print_address expanded v6 is %s\n",str); +#endif + + return; +} + +void expand_ipv6_addr(char ipv6_addr[],ipv6_address_t *ipv6_src_addr) +{ + + sprintf(ipv6_addr,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + ipv6_src_addr->v6_addr.v6_addr8[0], + ipv6_src_addr->v6_addr.v6_addr8[1], + ipv6_src_addr->v6_addr.v6_addr8[2], + ipv6_src_addr->v6_addr.v6_addr8[3], + ipv6_src_addr->v6_addr.v6_addr8[4], + ipv6_src_addr->v6_addr.v6_addr8[5], + ipv6_src_addr->v6_addr.v6_addr8[6], + ipv6_src_addr->v6_addr.v6_addr8[7], + ipv6_src_addr->v6_addr.v6_addr8[8], + ipv6_src_addr->v6_addr.v6_addr8[9], + ipv6_src_addr->v6_addr.v6_addr8[10], + ipv6_src_addr->v6_addr.v6_addr8[11], + ipv6_src_addr->v6_addr.v6_addr8[12], + ipv6_src_addr->v6_addr.v6_addr8[13], + ipv6_src_addr->v6_addr.v6_addr8[14], + ipv6_src_addr->v6_addr.v6_addr8[15]); + + printf("expanded v6 is %s\n",ipv6_addr); + +} + + + + + +/** + * NAME + * ipv6_ascii2digits + * + * SYNOPSIS + * #include "man_ipv6_address.h" + * void + * ipv6_ascii2digits(ipv6_address_t *ipv6_dest_addr, + * char *input) + * + * DESCRIPTION + * This function converts an ascii notation, + * 11111111:22222222:33333333:44444444 + * IPv6 address into binary. + * + * INPUT PARAMETERS + * ipv6_dest_addr - pointer to the IPv6 address + * + * input - pointer to the string + * + * OUTPUT PARAMETERS + * ipv6_dest_addr - updated + * + * RETURN VALUE + * none + * + * EXAMPLES + * ipv6_dest_addr->v6_addr.v6_addr32[0] = 11111111; + * ipv6_dest_addr->v6_addr.v6_addr32[1] = 22222222; + * ipv6_dest_addr->v6_addr.v6_addr32[2] = 33333333; + * ipv6_dest_addr->v6_addr.v6_addr32[3] = 44444444; + * + * If there is an error, the remaining ipv6[i] are 0. + * + */ +void +ipv6_ascii2digits (ipv6_address_t *ipv6_dest_addr, char *input) +{ + uint32_t i; + char *ptr; + +#if 0 + printf("input v6 for ipv6_ascii2digits %s\n",input); +#endif + + if (!ipv6_dest_addr) { + return; + } + + /* zero the users ipv6 */ + ipv6_zero_address(ipv6_dest_addr); + + if (!input) { + return; + } + + ipv6_dest_addr->v6_addr.v6_addr16[0] = strtoul(input, &ptr, 16); + if (*ptr != ':') { + return; + } + ptr++; + + for (i=1; i<7; i++) { + ipv6_dest_addr->v6_addr.v6_addr16[i] = strtoul(ptr, &ptr, 16); + if (*ptr != ':') { + return; + } + ptr++; + } + ipv6_dest_addr->v6_addr.v6_addr16[7] = strtoul(ptr, NULL, 16); + + return; +} + diff --git a/dlep_radio_ipv6/ipv6_address.h b/dlep_radio_ipv6/ipv6_address.h new file mode 100644 index 0000000..92fdaf6 --- /dev/null +++ b/dlep_radio_ipv6/ipv6_address.h @@ -0,0 +1,478 @@ +/*------------------------------------------------------------------ + * ipv6_address.h -- Miscellaneous IPv6 Address Support Routines + * + * July 2008, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __IPV6_ADDRESS_H__ +#define __IPV6_ADDRESS_H__ + +#include "safe_types.h" +#include "network_order.h" + + +/* + * (few) IPv6 Address Definition + * + * 2001:0db8:3c4d:0015:0000:0000:abcd:ef12 + * ______________|____|___________________ + * global prefix subnet Interface ID + * + * IPv6 Address Ranges + * IPv6 Prefix Allocation + * -------------------------------------- + * 0000::/8 Reserved by IETF + * 2000::/3 Global Unicast + * FC00::/7 Unique Local Unicast + * FE80::/10 Link Local Unicast + * FF00::/8 Multicast + */ + + +/* defined for 32-bit overlay */ +#define IPV6_GLOBAL_PREFIX ( 0x20000000 ) /* 2000::/3 */ +#define IPV6_MULTICAST_PREFIX ( 0xFF000000 ) /* ff00::/8 */ +#define IPV6_UNIQUE_LOCAL_PREFIX ( 0xFC000000 ) /* fc00::/7 */ +#define IPV6_LINK_LOCAL_PREFIX ( 0xFE800000 ) /* fe80::/1 */ +#define IPV6_LINK_LOCAL_LOOPBACK_SUFFIX ( 0x0001 ) /* ::1/128 */ + + +/* + * IPv6 length values and prefixes + * + * http://www.iana.org/assignments/ipv6-multicast-addresses/ + * http://en.wikipedia.org/wiki/IPv6 + */ +#define IPV6_ADDR_STRING_LEN ( 42 ) +#define IPV6_ADDR_LEN_IN_BITS ( 128 ) +#define IPV6_ADDR_LEN_IN_BYTES ( 16 ) +#define IPV6_ADDR_LEN_IN_SHORTS ( 8 ) +#define IPV6_ADDR_LEN_IN_LONGS ( 4 ) + + + +/* + * IPv6 Address Type (128 bits) + */ +typedef struct ipv6_address_ { + union { + uint8_t v6_addr8[IPV6_ADDR_LEN_IN_BYTES]; + uint16_t v6_addr16[IPV6_ADDR_LEN_IN_SHORTS]; + uint32_t v6_addr32[IPV6_ADDR_LEN_IN_LONGS]; + } v6_addr; +} ipv6_address_t; + + + +/** + * NAME + * ipv6_put_address + * + * SYNOPSIS + * static inline uint8_t + * *ipv6_put_address(uint8_t *mp, ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to copy the source IPv6 address to the + * destination pointer mp. + * + * INPUT PARAMETERS + * mp - destination buffer pointer + * + * ipv6_src_addr - ponter to the source IPv6 address + * + * OUTPUT PARAMETERS + * mp - updated + * + * RETURN VALUE + * Pointer to the next byte in the destination space, mp + * + */ +//vinod + +static inline uint8_t +*ipv6_put_address (uint8_t *mp, ipv6_address_t *ipv6_src_addr) +{ + if (!ipv6_src_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_PUTSHORT(mp, ipv6_src_addr->v6_addr.v6_addr16[0]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(mp, ipv6_src_addr->v6_addr.v6_addr16[1]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(mp, ipv6_src_addr->v6_addr.v6_addr16[2]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(mp, ipv6_src_addr->v6_addr.v6_addr16[3]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(mp, ipv6_src_addr->v6_addr.v6_addr16[4]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(mp, ipv6_src_addr->v6_addr.v6_addr16[5]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(mp, ipv6_src_addr->v6_addr.v6_addr16[6]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(mp, ipv6_src_addr->v6_addr.v6_addr16[7]); + mp = mp + sizeof(uint16_t); + + return (mp); +} + + +/** + * NAME + * ipv6_get_address + * + * SYNOPSIS + * static inline uint8_t + * *ipv6_get_address(ipv6_address_t *ipv6_dest_addr, uint8_t *mp) + * + * DESCRIPTION + * Use this function to copy an IPv6 address from the buffer + * pointer mp to the destination ipv6_dest_addr. + * + * INPUT PARAMETERS + * ipv6_dest_addr - destination pointer to receive the IPv6 address + * + * mp - source pointer to copy from + * + * OUTPUT PARAMETERS + * ipv6_dest_addr - updated + * + * RETURN VALUE + * Pointer to the next byte in the source space, mp + * + */ +static inline uint8_t +*ipv6_get_address (ipv6_address_t *ipv6_dest_addr, uint8_t *mp) +{ + if (!ipv6_dest_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr16[0]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr16[1]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr16[2]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr16[3]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr16[4]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr16[5]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr16[6]); + mp = mp + sizeof(uint16_t); + + NETWORK_ORDER_GETLONG(mp, ipv6_dest_addr->v6_addr.v6_addr16[7]); + mp = mp + sizeof(uint16_t); + + return (mp); +} + +/** + * NAME + * ipv6_zero_address + * + * SYNOPSIS + * static inline void + * ipv6_zero_address(ipv6_address_t *ipv6_dest_addr) + * + * DESCRIPTION + * Use this function to zero an IPv6 address + * A zero address is reserved by the IETF. + * + * INPUT PARAMETERS + * ipv6_dest_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * ipv6_dest_addr - zeroed + * + * RETURN VALUE + * none + * + */ +static inline void +ipv6_zero_address (ipv6_address_t *ipv6_dest_addr) +{ + if (!ipv6_dest_addr) { + return; + } + + ipv6_dest_addr->v6_addr.v6_addr32[0] = 0; + ipv6_dest_addr->v6_addr.v6_addr32[1] = 0; + ipv6_dest_addr->v6_addr.v6_addr32[2] = 0; + ipv6_dest_addr->v6_addr.v6_addr32[3] = 0; + return; +} + + +/** + * NAME + * ipv6_address_is_global + * + * SYNOPSIS + * static inline boolean_t + * ipv6_address_is_global(ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to determine if the IPv6 address is global. + * 2000::/3 Global Unicast + * + * INPUT PARAMETERS + * ipv6_src_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes + * FALSE - nope! + * + */ +static inline boolean_t +ipv6_address_is_global (ipv6_address_t *ipv6_src_addr) +{ + + if (IPV6_GLOBAL_PREFIX == + (ipv6_src_addr->v6_addr.v6_addr32[0] & IPV6_GLOBAL_PREFIX)) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * ipv6_address_is_multicast + * + * SYNOPSIS + * static inline boolean_t + * ipv6_address_is_multicast(ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to determine if the IPv6 address is multicast. + * FF00::/8 Multicast + * + * INPUT PARAMETERS + * ipv6_src_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes + * FALSE - nope! + * + */ +static inline boolean_t +ipv6_address_is_multicast (ipv6_address_t *ipv6_src_addr) +{ + + if (IPV6_MULTICAST_PREFIX == + (ipv6_src_addr->v6_addr.v6_addr16[0] & IPV6_MULTICAST_PREFIX)) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * ipv6_address_is_linklocal + * + * SYNOPSIS + * static inline boolean_t + * ipv6_address_is_linklocal(ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to determine if the IPv6 address is link local. + * FE80::/10 Link Local Unicast + * + * INPUT PARAMETERS + * ipv6_src_addr - pointer to the IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes + * FALSE - nope! + * + */ +static inline boolean_t +ipv6_address_is_linklocal (ipv6_address_t *ipv6_src_addr) +{ + if (IPV6_LINK_LOCAL_PREFIX == + (ipv6_src_addr->v6_addr.v6_addr16[0] & IPV6_LINK_LOCAL_PREFIX)) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * static inline boolean_t + * ipv6_compare_address(ipv6_address_t *ipv6_dest_addr, + * ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to compare two IPv6 addresses + * + * INPUT PARAMETERS + * ipv6_dest_addr - pointer to the destination IPv6 address + * + * ipv6_src_addr - pointer to the src IPv6 address + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - addresses equal + * FALSE - not equal + * + */ +static inline boolean_t +ipv6_compare_address (ipv6_address_t *ipv6_dest_addr, + ipv6_address_t *ipv6_src_addr) +{ + if (!ipv6_dest_addr || !ipv6_src_addr) { + return (FALSE); + } + + if (ipv6_dest_addr->v6_addr.v6_addr16[0] == + ipv6_src_addr->v6_addr.v6_addr16[0] && + ipv6_dest_addr->v6_addr.v6_addr16[1] == + ipv6_src_addr->v6_addr.v6_addr16[1] && + ipv6_dest_addr->v6_addr.v6_addr16[2] == + ipv6_src_addr->v6_addr.v6_addr16[2] && + ipv6_dest_addr->v6_addr.v6_addr16[3] == + ipv6_src_addr->v6_addr.v6_addr16[3] && + ipv6_dest_addr->v6_addr.v6_addr16[4] == + ipv6_src_addr->v6_addr.v6_addr16[4] && + ipv6_dest_addr->v6_addr.v6_addr16[5] == + ipv6_src_addr->v6_addr.v6_addr16[5] && + ipv6_dest_addr->v6_addr.v6_addr16[6] == + ipv6_src_addr->v6_addr.v6_addr16[6] && + ipv6_dest_addr->v6_addr.v6_addr16[7] == + ipv6_src_addr->v6_addr.v6_addr16[7]) { + + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * ipv6_copy_address + * + * SYNOPSIS + * static inline void + * ipv6_copy_address(ipv6_address_t *ipv6_dest_addr, + * ipv6_address_t *ipv6_src_addr) + * + * DESCRIPTION + * Use this function to compare two IPv6 addresses + * + * INPUT PARAMETERS + * ipv6_dest_addr - pointer to the destination IPv6 address + * + * ipv6_src_addr - pointer to the src IPv6 address + * + * OUTPUT PARAMETERS + * ipv6_dest_addr - updated + * + * RETURN VALUE + * none + * + */ +static inline void +ipv6_copy_address (ipv6_address_t *ipv6_dest_addr, + ipv6_address_t *ipv6_src_addr) +{ + if (!ipv6_dest_addr || !ipv6_src_addr) { + return; + } + + /* Due to byter ordering issue ,I have added v6 addr in following way */ + + int i; + ipv6_dest_addr->v6_addr.v6_addr16[0] = + ipv6_src_addr->v6_addr.v6_addr16[0]; + ipv6_dest_addr->v6_addr.v6_addr16[1] = + ipv6_src_addr->v6_addr.v6_addr16[1]; + ipv6_dest_addr->v6_addr.v6_addr16[2] = + ipv6_src_addr->v6_addr.v6_addr16[2]; + ipv6_dest_addr->v6_addr.v6_addr16[3] = + ipv6_src_addr->v6_addr.v6_addr16[3]; + ipv6_dest_addr->v6_addr.v6_addr16[4] = + ipv6_src_addr->v6_addr.v6_addr16[4]; + ipv6_dest_addr->v6_addr.v6_addr16[5] = + ipv6_src_addr->v6_addr.v6_addr16[5]; + ipv6_dest_addr->v6_addr.v6_addr16[6] = + ipv6_src_addr->v6_addr.v6_addr16[6]; + ipv6_dest_addr->v6_addr.v6_addr16[7] = + ipv6_src_addr->v6_addr.v6_addr16[7]; +#if 0 + for(i = 0; i<=7 ; i++) + printf("ipv6_copied_address is %x\n",ipv6_src_addr->v6_addr.v6_addr16[i]); +#endif + + + return; +} + + + +extern void +ipv6_print_address(char *p2label, ipv6_address_t *ipv6_src_addr); + +extern void +ipv6_ascii2digits(ipv6_address_t *ipv6_dest_addr, char *input); + +#endif + diff --git a/dlep_radio_ipv6/mac_address.c b/dlep_radio_ipv6/mac_address.c new file mode 100644 index 0000000..f6fab64 --- /dev/null +++ b/dlep_radio_ipv6/mac_address.c @@ -0,0 +1,169 @@ +/*---------------------------------------------------------------------- + * mac_address.c -- MAC Address Support Routines + * + * January 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "mac_address.h" + + +/** + * NAME + * mac_print_address + * + * SYNOPSIS + * #include "man_mac_address.h" + * void + * mac_print_address (char *p2label, uint8_t mac[]) + * + * DESCRIPTION + * This function can be used to print the MAC address. If + * the p2label is non-NULL, the label prefixes the MAC. + * + * INPUT PARAMETERS + * p2label - Pointer to the label + * + * mac - Pointer to the mac address array + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +mac_print_address (char *p2label, uint8_t mac[]) +{ + if (p2label) { + printf("%s %02x:%02x:%02x:%02x:%02x:%02x \n", + p2label, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + } else { + printf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x \n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + return; +} + + +/** + * NAME + * mac_ascii2digits + * + * SYNOPSIS + * #include "man_mac_address.h" + * void + * mac_ascii2digits(uint8_t mac_dest_addr[], char *input) + * + * DESCRIPTION + * This function converts an ascii notation, 12:34:56:78:90:ab + * MAC address into an array. + * + * INPUT PARAMETERS + * mac_dest_addr - Pointer to the mac address array + * + * input - pointer the string + * + * OUTPUT PARAMETERS + * mac_dest_addr - updated + * + * RETURN VALUE + * none + * + * EXAMPLES + * mac_dest_addr[0] = 12; + * mac_dest_addr[1] = 34; + * mac_dest_addr[2] = 56; + * mac_dest_addr[3] = 78; + * mac_dest_addr[4] = 90; + * mac_dest_addr[5] = ab; + * + * If there is an error, the remaining mac[i] are 0. + * + */ +void +mac_ascii2digits (uint8_t mac_dest_addr[], char *input) +{ + uint32_t i; + uint8_t digit; + uint32_t maci; + + if (!mac_dest_addr) { + return; + } + + /* zero the users mac array */ + for (i=0; i= '0' && input[i] <='9') { + digit = (input[i] - '0') * (16); + } else if (input[i] >= 'a' && input[i] <='f') { + digit = (input[i] - 'a' + 10) * (16); + } else if (input[i] >= 'A' && input[i] <='F') { + digit = (input[i] - 'A' + 10) * (16); + } else { + return; + } + + i++; + if (input[i] >= '0' && input[i] <='9') { + digit += (input[i] - '0'); + } else if (input[i] >= 'a' && input[i] <='f') { + digit += (input[i] - 'a' + 10); + } else if (input[i] >= 'A' && input[i] <='F') { + digit += (input[i] - 'A' + 10); + } else { + return; + } + + mac_dest_addr[maci] = digit; + + i++; + if (input[i] != ':') { + return; + } + + maci++; + } + + return; +} + diff --git a/dlep_radio_ipv6/mac_address.h b/dlep_radio_ipv6/mac_address.h new file mode 100644 index 0000000..92e2f38 --- /dev/null +++ b/dlep_radio_ipv6/mac_address.h @@ -0,0 +1,361 @@ +/*---------------------------------------------------------------------- + * mac_address.h + * + * January 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __MAC_ADDRESS_H__ +#define __MAC_ADDRESS_H__ + +#include "safe_types.h" +#include "network_order.h" + + +/* + * MAC in string Dot Notation: 11:22:33:44:55:66 + */ +#define MAC_DOT_LEN_IN_BYTES ( 18 ) + +/* + * MAC in byte array[] + */ +#define MAC_ADDR_LEN_IN_BYTES ( 6 ) + + + +/** + * NAME + * mac_put_address + * + * SYNOPSIS + * static inline uint8_t + * *mac_put_address(uint8_t *mp, uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to copy the source MAC address to + * the destination pointer mp, in network order. + * + * INPUT PARAMETERS + * mp - destination buffer pointer + * + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTNPUT PARAMETERS + * mp - updated + * + * RETURN VALUE + * Pointer to the next byte in the destination space, mp + * + */ +static inline uint8_t +*mac_put_address (uint8_t *mp, uint8_t *mac_src_addr) +{ + if (!mac_src_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[0]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[1]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[2]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[3]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[4]); + mp++; + NETWORK_ORDER_PUTBYTE(mp, mac_src_addr[5]); + mp++; + + return (mp); +} + + +/** + * NAME + * mac_get_address + * + * SYNOPSIS + * static inline uint8_t + * *mac_get_address(uint8_t *mac_dest_addr, uint8_t *mp) + * + * DESCRIPTION + * Use this function to copy a network ordered MAC address from + * the pointer mp to the destination array mac_dest_addr[]. + * + * INPUT PARAMETERS + * mac_dest_addr - pointer to the destination mac address, 6-bytes + * + * mp - source pointer to copy from + * + * OUTPUT PARAMETERS + * mac_dest_addr - updated + * + * RETURN VALUE + * Pointer to the next byte in the source space, mp + * + */ +static inline uint8_t +*mac_get_address (uint8_t *mac_dest_addr, uint8_t *mp) +{ + if (!mac_dest_addr || !mp) { + return (mp); + } + + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[0]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[1]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[2]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[3]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[4]); + mp++; + NETWORK_ORDER_GETBYTE(mp, mac_dest_addr[5]); + mp++; + + return (mp); +} + + +/** + * NAME + * mac_zero_address + * + * SYNOPSIS + * static inline void + * mac_zero_address(uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to zero a MAC address. + * + * INPUT PARAMETERS + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTPUT PARAMETERS + * mac_src_addr - updated + * + * RETURN VALUE + * None + * + */ +static inline void +mac_zero_address (uint8_t *mac_src_addr) +{ + if (!mac_src_addr) { + return; + } + + mac_src_addr[0] = 0; + mac_src_addr[1] = 0; + mac_src_addr[2] = 0; + mac_src_addr[3] = 0; + mac_src_addr[4] = 0; + mac_src_addr[5] = 0; + return; +} + + +/** + * NAME + * mac_set_to_broadcast + * + * SYNOPSIS + * static inline void + * mac_set_to_broadcast(uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to set the MAC address to the broadcast address. + * + * INPUT PARAMETERS + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTPUT PARAMETERS + * mac_src_addr - updated + * + * RETURN VALUE + * None + * + */ +static inline void +mac_set_to_broadcast (uint8_t *mac_src_addr) +{ + if (!mac_src_addr) { + return; + } + + mac_src_addr[0] = 0xFF; + mac_src_addr[1] = 0xFF; + mac_src_addr[2] = 0xFF; + mac_src_addr[3] = 0xFF; + mac_src_addr[4] = 0xFF; + mac_src_addr[5] = 0xFF; + return; +} + + +/** + * NAME + * mac_is_broadcast + * + * SYNOPSIS + * static inline boolean_t + * mac_is_broadcast(uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to determine if this is a broadcast MAC address + * + * INPUT PARAMETERS + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - yes + * FALSE - no + * + */ +static inline boolean_t +mac_is_broadcast (uint8_t *mac_src_addr) +{ + if (!mac_src_addr) { + return (FALSE); + } + + if (mac_src_addr[0] == 0xFF && + mac_src_addr[1] == 0xFF && + mac_src_addr[2] == 0xFF && + mac_src_addr[3] == 0xFF && + mac_src_addr[4] == 0xFF && + mac_src_addr[5] == 0xFF) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * mac_compare_address + * + * SYNOPSIS + * static inline boolean_t + * mac_compare_address(uint8_t *mac_dest_addr, + * uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to compare two MAC addresses + * + * INPUT PARAMETERS + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * mac_dest_addr - pointer to the destination mac address, 6-bytes + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE - addresses equal + * FALSE - not equal + * + */ +static inline boolean_t +mac_compare_address (uint8_t *mac_dest_addr, + uint8_t *mac_src_addr) +{ + if (!mac_dest_addr || !mac_src_addr) { + return (FALSE); + } + + if (mac_dest_addr[0] == mac_src_addr[0] && + mac_dest_addr[1] == mac_src_addr[1] && + mac_dest_addr[2] == mac_src_addr[2] && + mac_dest_addr[3] == mac_src_addr[3] && + mac_dest_addr[4] == mac_src_addr[4] && + mac_dest_addr[5] == mac_src_addr[5]) { + return (TRUE); + } else { + return (FALSE); + } +} + + +/** + * NAME + * mac_copy_address + * + * SYNOPSIS + * static inline void + * mac_copy_address(uint8_t *mac_dest_addr, + * uint8_t *mac_src_addr) + * + * DESCRIPTION + * Use this function to copy a MAC address + * + * INPUT PARAMETERS + * mac_dest_addr - pointer to the destination mac address, 6-bytes + * + * mac_src_addr - pointer to the source mac address, 6-bytes + * + * OUTPUT PARAMETERS + * mac_dest_addr - updated + * + * RETURN VALUE + * none + * + */ +static inline void +mac_copy_address (uint8_t *mac_dest_addr, + uint8_t *mac_src_addr) +{ + if (!mac_dest_addr || !mac_src_addr) { + return; + } + + mac_dest_addr[0] = mac_src_addr[0]; + mac_dest_addr[1] = mac_src_addr[1]; + mac_dest_addr[2] = mac_src_addr[2]; + mac_dest_addr[3] = mac_src_addr[3]; + mac_dest_addr[4] = mac_src_addr[4]; + mac_dest_addr[5] = mac_src_addr[5]; + return; +} + + + +extern void +mac_print_address(char *p2label, uint8_t mac[]); + +extern void +mac_ascii2digits(uint8_t mac_dest_addr[], char *input); + +#endif + diff --git a/dlep_radio_ipv6/network_order.h b/dlep_radio_ipv6/network_order.h new file mode 100644 index 0000000..4506afa --- /dev/null +++ b/dlep_radio_ipv6/network_order.h @@ -0,0 +1,235 @@ +/*---------------------------------------------------------------------- + * network_order.h -- macros to deal with byte order + * + * January 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __NETWORK_ORDER_H__ +#define __NETWORK_ORDER_H__ + +#include + + +/* + * Network Order is the transmission of the most significant byte first, + * or big-endian. + * http://en.wikipedia.org/wiki/Endianness + * + * Little-Endian architectures, the low-order byte of a word is stored + * in the lowest address in memory. + * + * Big-Endian architectures, the high-order byte of a word is stored + * in the lowest address in memory. + * + * Porting, it may be necessary to modify these functions based upon your + * platform. + * + * 16-bits + * LSB ----------------> MSB Big Endian + * | Byte1 | Byte0 | + * MSB <---------------- LSB Little Endian + * + * 32-bits + * LSB --------------------------------> MSB Big Endian + * | Byte3 | Byte2 | Byte1 | Byte0 | + * MSB <-------------------------------- LSB Little Endian + * + */ + +/* + * Define the macro for processor order to network order + * + * PowerPC, 680x0 + * #define __BIG_ENDIAN__ + * #define __BIG_ENDIAN_TO_FROM_NETWORK__ + * + * x86, x64 + * Note: MAC gcc defines the __LITTLE_ENDIAN__ macro + * #define __LITTLE_ENDIAN__ + * #define __LITTLE_ENDIAN_TO_FROM_NETWORK__ + */ + +#define __LITTLE_ENDIAN_TO_FROM_NETWORK__ + + +/* 8-bit moves */ +#undef NETWORK_ORDER_GETCHAR +#define NETWORK_ORDER_GETCHAR(ptr, value) { \ + (value) = *((char *)ptr); \ +} + +#undef NETWORK_ORDER_PUTCHAR +#define NETWORK_ORDER_PUTCHAR(ptr, value) { \ + *((char *)ptr) = (char)(value); \ +} + + +/* unsigned 8-bit moves */ +#undef NETWORK_ORDER_GETBYTE +#define NETWORK_ORDER_GETBYTE(ptr, value) { \ + (value) = *((uint8_t *)ptr); \ +} + +#undef NETWORK_ORDER_PUTBYTE +#define NETWORK_ORDER_PUTBYTE(ptr, value) { \ + *((uint8_t *)ptr) = (uint8_t)(value); \ +} + + +#if defined __LITTLE_ENDIAN_TO_FROM_NETWORK__ + +/* 16-bit moves */ +#undef NETWORK_ORDER_GETSHORT +#define NETWORK_ORDER_GETSHORT(ptr, value) { \ + (value) = *((uint8_t *)ptr + 0); \ + (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); \ +} + + +#undef NETWORK_ORDER_PUTSHORT +#define NETWORK_ORDER_PUTSHORT(ptr, value) { \ + *((uint8_t *)ptr + 0) = (uint8_t)((value) >> 8); \ + *((uint8_t *)ptr + 1) = (uint8_t)(value); \ +} + + +/* 32-bit moves */ +#undef NETWORK_ORDER_GETLONG +#define NETWORK_ORDER_GETLONG(ptr, value) { \ + (value) = *((uint8_t *)ptr + 0); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 2); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 3); \ +} + +#undef NETWORK_ORDER_PUTLONG +#define NETWORK_ORDER_PUTLONG(ptr, value) { \ + *((uint8_t *)ptr + 0) = (uint8_t) ((value) >> 24); \ + *((uint8_t *)ptr + 1) = (uint8_t) ((value) >> 16); \ + *((uint8_t *)ptr + 2) = (uint8_t) ((value) >> 8); \ + *((uint8_t *)ptr + 3) = (uint8_t) (value); \ +} + + + +/* 64-bit moves */ +#undef NETWORK_ORDER_GETLLONG +#define NETWORK_ORDER_GETLLONG(ptr, value) { \ + (value) = *((uint8_t *)ptr + 0); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 2); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 3); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 4); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 5); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 6); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 7); \ +} + +#undef NETWORK_ORDER_PUTLLONG +#define NETWORK_ORDER_PUTLLONG(ptr, value) { \ + *((uint8_t *)ptr + 0) = (uint8_t) ((value) >> 56); \ + *((uint8_t *)ptr + 1) = (uint8_t) ((value) >> 48); \ + *((uint8_t *)ptr + 2) = (uint8_t) ((value) >> 40); \ + *((uint8_t *)ptr + 3) = (uint8_t) ((value) >> 32); \ + *((uint8_t *)ptr + 4) = (uint8_t) ((value) >> 24); \ + *((uint8_t *)ptr + 5) = (uint8_t) ((value) >> 16); \ + *((uint8_t *)ptr + 6) = (uint8_t) ((value) >> 8); \ + *((uint8_t *)ptr + 7) = (uint8_t) (value); \ +} + + +#elif defined __BIG_ENDIAN_TO_FROM_NETWORK__ + +/* 16-bit moves */ +#undef NETWORK_ORDER_GETSHORT +#define NETWORK_ORDER_GETSHORT(ptr, value) { \ + (value) = *((uint8_t *)ptr + 1); \ + (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 0); \ +} + + +#undef NETWORK_ORDER_PUTSHORT +#define NETWORK_ORDER_PUTSHORT(ptr, value) { \ + *((uint8_t *)ptr + 1) = (uint8_t)((value) >> 8); \ + *((uint8_t *)ptr + 0) = (uint8_t)(value); \ +} + + +/* 32-bit moves */ +#undef NETWORK_ORDER_GETLONG +#define NETWORK_ORDER_GETLONG(ptr, value) { \ + (value) = *((uint8_t *)ptr + 3); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 2); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 0); \ +} + +#undef NETWORK_ORDER_PUTLONG +#define NETWORK_ORDER_PUTLONG(ptr, value) { \ + *((uint8_t *)ptr + 3) = (uint8_t) ((value) >> 24); \ + *((uint8_t *)ptr + 2) = (uint8_t) ((value) >> 16); \ + *((uint8_t *)ptr + 1) = (uint8_t) ((value) >> 8); \ + *((uint8_t *)ptr + 0) = (uint8_t) (value); \ +} + + +/* 64-bit moves */ +#undef NETWORK_ORDER_GETLLONG +#define NETWORK_ORDER_GETLLONG(ptr, value) { \ + (value) = *((uint8_t *)ptr + 7); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 6); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 5); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 4); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 3); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 2); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 1); (value) <<= 8; \ + (value) |= *((uint8_t *)ptr + 0); \ +} + +#undef NETWORK_ORDER_PUTLLONG +#define NETWORK_ORDER_PUTLLONG(ptr, value) { \ + *((uint8_t *)ptr + 7) = (uint8_t) ((value) >> 56); \ + *((uint8_t *)ptr + 6) = (uint8_t) ((value) >> 48); \ + *((uint8_t *)ptr + 5) = (uint8_t) ((value) >> 40); \ + *((uint8_t *)ptr + 4) = (uint8_t) ((value) >> 32); \ + *((uint8_t *)ptr + 3) = (uint8_t) ((value) >> 24); \ + *((uint8_t *)ptr + 2) = (uint8_t) ((value) >> 16); \ + *((uint8_t *)ptr + 1) = (uint8_t) ((value) >> 8); \ + *((uint8_t *)ptr + 0) = (uint8_t) (value); \ +} + + +#else +#error CPU endianness not defined. +#endif + +#endif + + diff --git a/dlep_radio_ipv6/packet_dump.c b/dlep_radio_ipv6/packet_dump.c new file mode 100644 index 0000000..3e29ca1 --- /dev/null +++ b/dlep_radio_ipv6/packet_dump.c @@ -0,0 +1,125 @@ +/*------------------------------------------------------------------ + * packet_dump.c -- hex display of packet data + * + * Copyright (c) 2009, 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *----------------------------------------------------------------- + */ + +#include + +#include "packet_dump.h" + + +/** + * NAME + * packet_dump + * + * SYNOPSIS + * #include "packet_dump.h" + * void + * packet_dump(char *p2label, + * void *ptr, + * uint32_t number_bytes) + * + * DESCRIPTION + * This function displays a packet to facilitate + * debug and integration. + * + * INPUT PARAMETERS + * p2label - Pointer to a string label, such as IN or OUT + * + * ptr - Pointer to the message + * + * number_bytes - Number of bytes to display + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + * EXAMPLE + * OUTGOING- 0x04 0x00 0x0c 0x01 0x10 0x09 0x0a 0x00 + * OUTGOING- 0x00 0x03 0xe8 0x00 0x00 0x04 0x57 0x0a + * OUTGOING- 0x13 0x00 0x15 0x00 0x03 0x00 0x0d 0x04 + * OUTGOING- 0x10 0x06 0x11 0x22 0x33 0x44 0x55 0x66 + * OUTGOING- 0x0c 0x10 0x01 0x00 + * + * + */ +void +packet_dump (char *p2label, + void *ptr, + uint32_t number_bytes) +{ + uint8_t *p; + uint32_t i; + + if (ptr == NULL) { + return; + } + +/* + * no minimum balance required to open an account! + */ +#if 0 +#define MIN_NUMBER_OF_BYTES ( 16 ) + if (number_bytes < MIN_NUMBER_OF_BYTES) { + return; + } +#endif + +/* + * put a limit on it + */ +#define MAX_NUMBER_OF_BYTES ( 512 ) + if (number_bytes > MAX_NUMBER_OF_BYTES) { + number_bytes = MAX_NUMBER_OF_BYTES; + } + + /* + * Loop across the data, displaying in lines. + */ +#define MAX_BYTES_PER_LINE ( 8 ) + + p = (uint8_t *)ptr; + for (i=0; i +#include +#include + +#include "safe_types.h" +#include "network_order.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_packet_header.h" + +#include "rfc5444_decoder.h" +#include "dlep_client_peer_fsm.h" + +#define RFC5444_DEBUG printf +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ + + +/* + * Set - block open + * Clear - block closed + */ +#define DECODER_STATE_PACKET ( 0x01 ) +#define DECODER_STATE_MESSAGE ( 0x02 ) +#define DECODER_STATE_TLV ( 0x04 ) + + +static rfc5444_decoder_message_fv_t message_parser_fv; + +/* + * We add one to the max to account for the 0 based array. The + * TLV code is the index straight-up. 0--invalid, 1-255 valid. + */ +static rfc5444_decoder_tlv_fv_t tlv_decoder_fv[RFC5444_MAX_TLV_CODE+1]; + + +/* + * The undefined TLV decoder! Steps over undefined TLVs. + */ +static rfc5444_rc_t +rfc5444_undefined_tlv_decoder ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint8_t tlv_flags; + uint8_t tlv8_length; + uint16_t tlv16_length; + + printf("\n Not supported TLV "); + if (p2decoder_state->tlv_block_length >= sizeof(uint8_t)) { + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_flags); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + } else { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + if (tlv_flags & + (THASTYPEEXT | THASSINGLEINDEX | THASMULTIINDEX | THASMULTIVALUE)) { + if (verbose) { + RFC5444_DEBUG("ERROR: %s-%u tlv code=%u flags=0x%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_flags); + } + return (RC_RFC5444_INVALID_TLV_FLAG); + } + + tlv16_length = 0; + if (tlv_flags & THASVALUE) { + if (tlv_flags & THASEXTLEN) { + if (p2decoder_state->tlv_block_length >= sizeof(uint16_t)) { + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, + tlv16_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->tlv_block_length -= sizeof(uint16_t); + } else { + if (verbose) { + RFC5444_DEBUG("ERROR: %s-%u tlv code=%u flags=0x%0x" + " tlv16_length=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_flags, + tlv16_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + } else { + if (p2decoder_state->tlv_block_length >= sizeof(uint8_t)) { + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, + tlv8_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + tlv16_length = tlv8_length; + } else { + if (verbose) { + RFC5444_DEBUG("ERROR: %s-%u tlv code=%u flags=0x%0x" + " tlv16_length=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_flags, + tlv16_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + } + + if (p2decoder_state->tlv_block_length >= tlv16_length) { + p2decoder_state->tlv_block_length -= tlv16_length; + } else { + tlv16_length = p2decoder_state->tlv_block_length; + p2decoder_state->tlv_block_length = 0; + if (verbose) { + RFC5444_DEBUG("ERROR: %s-%u tlv code=%u flags=0x%0x" + " tlv16_length=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_flags, + tlv16_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + RFC5444_DEBUG("%s-%u tlv block length %u bytes \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv16_length); + } + + p2decoder_state->parse_ptr += tlv16_length; + return (RC_RFC5444_OK); +} + + + +/* + * An internal function to manage TLV block decoding + */ +static rfc5444_rc_t +rfc5444_decoder_parse_tlv_block ( + uint8_t *base_ptr, + uint32_t block_len, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_code; + uint8_t tlv_len; + rfc5444_rc_t rc; + dlep_context_peer_t *p2peer; + + p2peer = context_ptr; + + /* + * The tlv_block_length does not include the + */ + rc = RC_RFC5444_OK; + while ((p2decoder_state->message_block_length) > 2){ + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_code); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= sizeof(uint16_t); + + if (dlep_client_fsm_get_state(p2peer)) { + if (!(p2peer->optional_data_item & (1 << (tlv_code - 1)))) { + printf("\n Optional data TLV %d ignore", tlv_code); + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_len); + p2decoder_state->message_block_length -= (tlv_len + 1); + p2decoder_state->parse_ptr += (tlv_len + 1); + continue; + } + } + + /* + * note that tlv_codes are the index into the vector + * table of decoders. 0--invalid, 254--max. + * now invoke the specific TLV parser + */ + rc = (*tlv_decoder_fv[tlv_code])(tlv_code, + p2decoder_state, + context_ptr, + verbose); + if (rc != RC_RFC5444_OK) { + break; + } + + } + + + return (rc); +} + + +/** + * NAME + * rfc5444_decoder_packet + * + * SYNOPSIS + * rfc5444_rc_t + * *rfc5444_decoder_packet(uint8_t *packet_ptr, + * uint32_t packet_len, + * void *context_ptr, + * boolean_t verbose) + * + * DESCRIPTION + * This function is used to allocate and initialize the + * decoder state variable and then decode the packet. + * + * INPUT PARAMETERS + * packet_ptr - a pointer to the packet to be parsed + * + * packet_len - the number of bytes in the packet + * + * context_ptr - a pointer passed through to the users + * parsing routine + * + * verbose - TRUE enables debug + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - packet successfully parsed + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_packet (uint8_t *packet_ptr, + uint32_t packet_len, + void *context_ptr, + boolean_t verbose) +{ + rfc5444_decoder_state_t *p2decoder_state; + rfc5444_rc_t rc; + dlep_context_peer_t *p2peer; + uint32_t dlep_signal_flag; + int signal = FALSE; + + p2peer = context_ptr; + + if (!packet_ptr) { + return (RC_RFC5444_NULL_POINTER); + } + // printf("Decoder packet reaching here\n"); + /* verify the packet length is in the ball park */ + if (packet_len < RFC5444_MIN_PACKET_LEN || + packet_len > RFC5444_MAX_PACKET_LEN) { + return (RC_RFC5444_INVALID_PACKET_LENGTH); + } + + p2decoder_state = malloc(sizeof(rfc5444_decoder_state_t)); + if (!p2decoder_state) { + return (RC_RFC5444_NO_RESOURCES); + } + + /* parse_ptr is the working buffer pointer */ + p2decoder_state->parse_ptr = packet_ptr; + + /*checking this is signal or message */ + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr,dlep_signal_flag); + if(dlep_signal_flag == 0x444C4550) { + signal = TRUE; + } + //printf("signal value is %d\n",signal); + + /* packet_length is the working length to parse */ + p2decoder_state->packet_length = packet_len; + + /* save the original packet pointer */ + p2decoder_state->packet_ptr = packet_ptr; + + // p2decoder_state->packet_flags = 0; + + p2decoder_state->message_block_length = 0; +// p2decoder_state->message_block_flags = 0; + +// p2decoder_state->tlv_block_length = 0; +// p2decoder_state->tlv_block_base = NULL; + + /* + * Notes on parsing - the parse_ptr is incremented to + * keep up with the next byte position to parse while + * the packet_len is decremented to track how many bytes + * to parse remain. + * If an error occurs, parsing stops and the remainder + * of the packet is discarded. It is too difficult to + * unwind and still maintain packet integrity to continue. + */ + + /* + * Loop through messages + */ + + if (p2decoder_state->packet_length < (2 * sizeof(uint8_t))) { + /** user must release the packet **/ + free(p2decoder_state); + return (RC_RFC5444_INVALID_PACKET_LENGTH); + } + + + if (signal) { + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->packet_length -= sizeof(uint32_t); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, + p2decoder_state->message_block_code); + + if(p2decoder_state->message_block_code > 20 ) { + if(verbose) { + RFC5444_DEBUG("%s-%u Error: message feature " + "not supported \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + + /** user must release the packet **/ + free(p2decoder_state); + return (RC_RFC5444_INVALID_MESSAGE_LENGTH); + } + + /* if (dlep_client_fsm_get_state(p2peer)) { + if (!(p2peer->optional_signal & (1 << (p2decoder_state->message_block_code - 1)))) { + printf("\n Optional termination needed"); + } + } */ + + +/* NEED TO ADD MESSAGE VALIDATION */ + + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->packet_length -= sizeof(uint16_t); + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, + p2decoder_state->message_block_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->packet_length -= sizeof(uint16_t); + + + /* decode the TLV block if present */ + + if (p2decoder_state->message_block_length > 2) { + rc = rfc5444_decoder_parse_tlv_block( + p2decoder_state->tlv_block_base, + p2decoder_state->message_block_length, + p2decoder_state, + context_ptr, + verbose); + if (rc != RC_RFC5444_OK) { + if (verbose) { + RFC5444_DEBUG("%s-%u Error: tlv parser error %u-%s \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rc, + rfc5444_rc2string(rc)); + } + printf("\n lenth of message %d",p2decoder_state->message_block_length); + free(p2decoder_state); + return (rc); + } + } //END + /* + * now process the message + */ + (*message_parser_fv)(p2decoder_state->message_block_code, + p2decoder_state->seq_num, + context_ptr,signal); + + + /** user must release the buffer **/ + free(p2decoder_state); + + return (RC_RFC5444_OK); +} + + + +/** + * NAME + * rfc5444_decoder_free + * + * SYNOPSIS + * uint8_t + * *rfc5444_decoder_free( + * rfc5444_decoder_state_t *p2decoder_state) + * + * DESCRIPTION + * This function is used to release all resources associated with + * the decoding a packet. + * + * INPUT PARAMETERS + * rfc5444_decoder_state - This is a pointer to the decoder + * state variable to be freed. + * + * OUTPUT PARAMETERS + * rfc5444_decoder_state - contents and resources are freed + * + * RETURN VALUE + * none + * + */ +void +rfc5444_decoder_free (rfc5444_decoder_state_t *p2decoder_state) +{ + if (!p2decoder_state) { + return; + } + + if (p2decoder_state->packet_ptr) { + free(p2decoder_state->packet_ptr); + p2decoder_state->packet_ptr = NULL; + } + free(p2decoder_state); + return; +} + + +/** + * NAME + * rfc5444_decoder_tlv_register_cb + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_decoder_tlv_register_cb( + * uint8_t tlv_code, + * rfc5444_decoder_tlv_fv_t users_tlv_decoder) + * + * DESCRIPTION + * This function must be called to register a decoder for the + * specified RFC5444 TLV code. If there is a decoder already + * registered, the registration fails as the previous registration + * must be unregistered first. + * + * INPUT PARAMETERS + * tlv_code - The TLV code to be registered + * + * users_tlv_decoder - The user's TLV decoder function + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_tlv_register_cb ( + uint16_t tlv_code, + rfc5444_decoder_tlv_fv_t users_tlv_decoder) +{ + if (tlv_decoder_fv[tlv_code] != &rfc5444_undefined_tlv_decoder) { + /* someone is already registered */ + return (RC_RFC5444_STATE_ERROR); + } + + /* bind the new tlv decoder call-back */ + tlv_decoder_fv[tlv_code] = users_tlv_decoder; + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_decoder_tlv_unregister_cb + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_decoder_tlv_unregister_cb( + * uint8_t tlv_code) + * + * DESCRIPTION + * This function must be called to unregister a RFC5444 TLV decoder. + * The default decoder is installed for the TLV code. + * + * INPUT PARAMETERS + * tlv_code - The TLV code to be unregistered + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_tlv_unregister_cb (uint16_t tlv_code) +{ + tlv_decoder_fv[tlv_code] = &rfc5444_undefined_tlv_decoder; + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_decoder_init + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_decoder_init(void) + * + * DESCRIPTION + * This function must be called to initialize the decode prior to + * its use. Users may register specific TLV decoders after the + * initializatin. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_init (rfc5444_decoder_message_fv_t mp) +{ + uint32_t i; + + /*user call back to process a message */ + message_parser_fv = mp; + + for (i=0; i<(RFC5444_MAX_TLV_CODE+1); i++) { + tlv_decoder_fv[i] = &rfc5444_undefined_tlv_decoder; + } + + return (RC_RFC5444_OK); +} + diff --git a/dlep_radio_ipv6/rfc5444_decoder.h b/dlep_radio_ipv6/rfc5444_decoder.h new file mode 100644 index 0000000..d713e8d --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_decoder.h @@ -0,0 +1,130 @@ +/*------------------------------------------------------------------ + * rfc5444_decoder.h -- packet decoding routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + *------------------------------------------------------------------ + */ + +#ifndef ___RFC5444_DECODER__ +#define ___RFC5444_DECODER__ + +#include "safe_types.h" +#include "rfc5444_types.h" + +#include "rfc5444_scratch_pad.h" + +/* + * This is the structure type used to manage the decoding + * and parsing of the packet. + */ +/* D5 EDIT + * using packet_ptr, parse_ptr, packet_length and message block... + * remaining structure members need to remove + */ + +typedef struct { + uint8_t *packet_ptr; + + uint8_t *parse_ptr; + uint16_t packet_length; + + uint8_t packet_flags; + uint16_t seq_num; + + uint8_t message_block_code; + uint8_t message_block_flags; + uint16_t message_block_length; + + uint8_t *tlv_block_base; + uint8_t tlv_block_length; + +} rfc5444_decoder_state_t; + + +/* + * TLV decoder call-back type- must be provided by the user + * for each TLV processed by the protocol. + */ +typedef rfc5444_rc_t (*rfc5444_decoder_tlv_fv_t)( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *scratch_pad, + boolean_t verbose); + + +/* + * message decoder call-back type- must be provided + * by the user for his protocol. + */ +typedef void (*rfc5444_decoder_message_fv_t)( + uint16_t message_code, + uint16_t sequence_number, + void *context_ptr, int signal); + + +/* + * packet decoder call-back type- must be provided + * by the user for his protocol. + */ +typedef void (*rfc5444_decoder_packet_fv_t)( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *scratch_pad); + + + + +/* register a user tlv parser */ +extern rfc5444_rc_t +rfc5444_decoder_tlv_register_cb(uint16_t tlv_code, + rfc5444_decoder_tlv_fv_t users_tlv_decoder); + + +/* unregister a user's tlv parser, restoring the null parser */ +extern rfc5444_rc_t +rfc5444_decoder_tlv_unregister_cb(uint16_t tlv_code); + + +extern rfc5444_rc_t +rfc5444_decoder_packet(uint8_t *bufptr, + uint32_t buflen, + void *context_ptr, + boolean_t verbose); + + +/* release resources after decoding a packet */ +extern void +rfc5444_decoder_free(rfc5444_decoder_state_t *p2decoder_state); + + +/* required before use */ +extern rfc5444_rc_t +rfc5444_decoder_init(rfc5444_decoder_message_fv_t mp); + +#endif + diff --git a/dlep_radio_ipv6/rfc5444_decoder_tlv.c b/dlep_radio_ipv6/rfc5444_decoder_tlv.c new file mode 100644 index 0000000..17cc351 --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_decoder_tlv.c @@ -0,0 +1,1553 @@ +/*------------------------------------------------------------------ + * rfc5444_decoder_tlv.c -- decode DLEP RFC5444 TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "safe_types.h" +#include "network_order.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_decoder.h" + +#include "dlep_context_peer.h" + +#include "rfc5444_decoder_tlv.h" + +#define RFC5444_DEBUG printf +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ + +/* D5 EDIT */ + +/* + * Identification + */ +#if 0 +static rfc5444_rc_t +rfc5444_decoder_identification_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + uint16_t tlv_length; + uint32_t router_id; + uint32_t client_id; + uint8_t heartbeat_interval; + + dlep_context_peer_t *p2peer; + rfc5444_packet_scratch_pad_t *packet_scratch_pad; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + packet_scratch_pad = &p2peer->packet_scratch_pad; + message_scratch_pad = &p2peer->message_scratch_pad; + + // NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_flags); + // p2decoder_state->parse_ptr += sizeof(uint8_t); + // p2decoder_state->tlv_block_length -= sizeof(uint8_t); + + // if (tlv_flags != RFC5444_TLV_IDENTIFICATION_FLAGS) { + // return (RC_RFC5444_INVALID_TLV_FLAG); + // } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); +// p2decoder_state->tlv_block_length -= sizeof(uint8_t); +// p2decoder_state->message_block_length -= p2decoder_state->tlv_block_length ; + p2decoder_state->message_block_length -= tlv_length; + if (tlv_length != RFC5444_TLV_IDENTIFICATION_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, heartbeat_interval); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, router_id); + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->tlv_block_length -= sizeof(uint32_t); + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, client_id); + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->tlv_block_length -= sizeof(uint32_t); + + packet_scratch_pad->router_id = router_id; + packet_scratch_pad->router_id_present = TRUE; + + packet_scratch_pad->client_id = client_id; + packet_scratch_pad->client_id_present = TRUE; + + packet_scratch_pad->peer_heartbeat_interval = heartbeat_interval; + packet_scratch_pad->peer_heartbeat_interval_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s \n" + " router_id=%u client_id=%u " + "heartbeat_interval=%u seconds \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + router_id, + client_id, + heartbeat_interval); + } + return (RC_RFC5444_OK); +} + +#endif +/* + * Version + */ +static rfc5444_rc_t +rfc5444_decoder_version_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_version_tlv\n"); + uint16_t tlv_length; + uint16_t major_version; + uint16_t minor_version; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + if (tlv_length != RFC5444_TLV_VERSION_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, major_version); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, minor_version); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->major_version = major_version; + message_scratch_pad->major_version_present = TRUE; + + message_scratch_pad->minor_version = minor_version; + message_scratch_pad->minor_version_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s DLEP version=%u.%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + major_version, + minor_version); + } + return (RC_RFC5444_OK); +} + + +/* + * Peer Type + */ +static rfc5444_rc_t +rfc5444_decoder_peer_type_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc_decoder_peer_type_tlv\n"); + uint16_t tlv_length; + char *desc; + uint8_t *p2description; + uint32_t i; + uint8_t tlv_flags; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length > RFC5444_TLV_PEER_TYPE_MAX_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_flags); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + /* if (tlv_flags != RFC5444_TLV_PEER_TYPE_FLAGS) { + printf("suriya tlv flag of peer not matching\n"); + return (RC_RFC5444_INVALID_TLV_FLAG); + } */ + + + if (tlv_length) { + desc = message_scratch_pad->peer_type_description; + p2description = p2decoder_state->parse_ptr; + + for (i=0; iparse_ptr = p2description; + } + + if (verbose) { + RFC5444_DEBUG("%s-%u %s %s \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + p2peer->peer_type_description); + } + return (RC_RFC5444_OK); +} + + +/* + * MAC address + */ +static rfc5444_rc_t +rfc5444_decoder_mac_address_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_mac_address_tlv\n"); + uint16_t tlv_length; + // uint16_t mac_addr[MAC_ADDR_LEN_IN_BYTES]; + uint8_t mac_addr[MAC_ADDR_LEN_IN_BYTES]; + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + if (tlv_length != RFC5444_TLV_MAC_ADDRESS_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + + p2decoder_state->parse_ptr = mac_get_address(mac_addr, + p2decoder_state->parse_ptr); + + mac_copy_address(message_scratch_pad->mac_address, mac_addr); + message_scratch_pad->mac_address_present = TRUE; + + return (RC_RFC5444_OK); +} + + +/* + * IPv4 address + */ +static rfc5444_rc_t +rfc5444_decoder_ipv4_address_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_ipv4_address_tlv\n"); + uint16_t tlv_length; + uint8_t operation; + ipv4_address_t ipv4_addr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != (RFC5444_TLV_IPV4_ADDRESS_LENGTH)) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + /** account for all parameters **/ + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, operation); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + p2decoder_state->parse_ptr = ipv4_get_address(&ipv4_addr, + p2decoder_state->parse_ptr); + + ipv4_copy_address(&message_scratch_pad->ipv4_address, &ipv4_addr); + + message_scratch_pad->ipv4_address_present = TRUE; + message_scratch_pad->ipv4_operation = operation; + + + if (verbose) { + ipv4_print_address("IPv4 Addr", &ipv4_addr); + RFC5444_DEBUG("%s-%u %s operation=%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + operation); + } + return (RC_RFC5444_OK); +} + +/* + * IPv4 attached subnet + */ +static rfc5444_rc_t +rfc5444_decoder_ipv4_attached_subnet_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_ipv4_attached_subnet_tlv\n"); + uint16_t tlv_length; + uint8_t operation; + ipv4_address_t ipv4_addr; + uint8_t subnetmask; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + + } + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != (RFC5444_TLV_IPV4_ATTACHED_SUBNET_LENGTH)) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + /** account for all parameters **/ + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, operation); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + p2decoder_state->parse_ptr = ipv4_get_address(&ipv4_addr, + p2decoder_state->parse_ptr); + + ipv4_copy_address(&message_scratch_pad->ipv4_address, &ipv4_addr); + + message_scratch_pad->ipv4_address_present = TRUE; + message_scratch_pad->ipv4_operation = operation; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, subnetmask); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + + if (verbose) { + ipv4_print_address("IPv4 Addr", &ipv4_addr); + RFC5444_DEBUG("%s-%u %s operation=%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + operation); + } + return (RC_RFC5444_OK); +} + + +/* + * IPv6 address + */ +static rfc5444_rc_t +rfc5444_decoder_ipv6_address_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc544_decoder_ipv6_address_tlv\n"); + uint16_t tlv_length; + uint8_t operation; + ipv6_address_t ipv6_addr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != RFC5444_TLV_IPV6_ADDRESS_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + /** account for all parameters **/ + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, operation); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + p2decoder_state->parse_ptr = ipv6_get_address(&ipv6_addr, + p2decoder_state->parse_ptr); + + message_scratch_pad->ipv6_address_present = TRUE; + message_scratch_pad->ipv6_operation = operation; + + ipv6_copy_address(&message_scratch_pad->ipv6_address, &ipv6_addr); + + p2decoder_state->parse_ptr += sizeof(uint8_t); + if (verbose) { + ipv6_print_address("IPv6 Addr", &ipv6_addr); + RFC5444_DEBUG("%s-%u operation=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + operation); + } + return (RC_RFC5444_OK); +} + + +/* + * MDR TX Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_mdr_tx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_mdr_tx_tlv\n"); + uint16_t tlv_length; + uint64_t mdr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_MDR_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, mdr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->mdr_tx = mdr; + message_scratch_pad->mdr_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s mdr tx=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + mdr); + } + return (RC_RFC5444_OK); +} + +/* + * MDR RX + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_mdr_rx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_mdr_rx_tlv\n"); + uint16_t tlv_length; + uint64_t mdr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_MDR_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, mdr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->mdr_rx = mdr; + message_scratch_pad->mdr_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s mdr rx=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + mdr); + } + return (RC_RFC5444_OK); +} + + +/* + * CDR_TX Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_cdr_tx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_cdr_tx_tlv\n"); + uint16_t tlv_length; + uint64_t cdr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_CDR_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, cdr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->cdr_tx = cdr; + message_scratch_pad->cdr_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s cdr tx =%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + cdr); + } + return (RC_RFC5444_OK); +} + +/* + * CDR_RX Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_cdr_rx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_cdr_rx_tlv\n"); + uint16_t tlv_length; + uint64_t cdr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_CDR_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, cdr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->cdr_rx = cdr; + message_scratch_pad->cdr_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s cdr rx=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + cdr); + } + return (RC_RFC5444_OK); +} + + + + +/* + * Latency Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_latency_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ + +printf("rfc5444_decoder_link_metric_latency_tlv\n"); + uint16_t tlv_length; + uint64_t latency; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, latency); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->latency = latency; + message_scratch_pad->latency_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s latency=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + latency); + } + return (RC_RFC5444_OK); +} + + +/* + * Resource Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_resources_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_resources_tlv\n"); + uint16_t tlv_length; + uint8_t resources; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, resources); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + message_scratch_pad->resources = resources; + message_scratch_pad->resources_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s resources=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + resources); + } + return (RC_RFC5444_OK); +} + + +/* + * Resources Link Metric TX + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_resources_tx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_resources_tx_tlv\n"); + uint16_t tlv_length; + uint8_t resources; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, resources); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + message_scratch_pad->resources_tx = resources; + message_scratch_pad->resources_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s resources tx=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + resources); + } + return (RC_RFC5444_OK); +} + + +/* + * Resources Link Metric RX + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_resources_rx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_resoureces_rx_tlv\n"); + uint16_t tlv_length; + uint8_t resources; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, resources); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= tlv_length; + message_scratch_pad->resources_rx = resources; + message_scratch_pad->resources_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s resources rx =%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + resources); + } + return (RC_RFC5444_OK); +} + + + +/* + * RLQ Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_rlq_tx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_rlq_tx_tlv\n"); + uint16_t tlv_length; + uint16_t rlq; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RLQ_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, rlq); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->rlq_tx = rlq; + message_scratch_pad->rlq_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s rlq tx=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + rlq); + } + return (RC_RFC5444_OK); +} + +/* + * RLQ RX Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_rlq_rx_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_rlq_rx_tlv\n"); + uint16_t tlv_length; + uint16_t rlq; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_RLQ_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, rlq); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->rlq_rx = rlq; + message_scratch_pad->rlq_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s rlq rx=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + rlq); + } + return (RC_RFC5444_OK); +} + +/* + * MTU Link Metric + */ +static rfc5444_rc_t +rfc5444_decoder_link_metric_mtu_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_link_metric_mtu_tlv\n"); + uint16_t tlv_length; + uint16_t mtu; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_MTU_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, mtu); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->mtu = mtu; + message_scratch_pad->mtu_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s rlq rx=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + mtu); + } + return (RC_RFC5444_OK); +} + + +/* + * Peer Status + */ +static rfc5444_rc_t +rfc5444_decoder_status_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_status_tlv\n"); + uint16_t tlv_length; + uint8_t status_code; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, status_code); + p2decoder_state->parse_ptr += tlv_length; + + message_scratch_pad->status_code = status_code; + message_scratch_pad->status_code_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s status_code=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + status_code); + } + return (RC_RFC5444_OK); +} + +/*eft decoder */ +static rfc5444_rc_t +rfc5444_decoder_eft_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_eft_tlv\n"); + uint16_t tlv_length; + uint32_t eft; + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_LINK_METRIC_EFT_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, eft); + p2decoder_state->parse_ptr += sizeof(uint32_t); + + message_scratch_pad->eft = eft; + if (verbose) { + RFC5444_DEBUG("%s-%u %s eft=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + eft); + } + return (RC_RFC5444_OK); +} + +/* port TLV decoder */ +static rfc5444_rc_t +rfc5444_decoder_port_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_port_tlv\n"); + uint16_t tlv_length; + uint16_t port; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_PORT_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, port); + p2decoder_state->parse_ptr += sizeof(uint16_t); + + message_scratch_pad->port = port; + p2peer->peer_tcp_port = port; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s port=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + port); + } + return (RC_RFC5444_OK); +} + +/* credit_window_status_tlv */ + +static rfc5444_rc_t +rfc5444_decoder_credit_window_status_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_credit_window_status_tlv\n"); + uint16_t tlv_length; + uint64_t mrw; + uint64_t rrw; + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_CREDIT_WINDOW_STATUS_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLLONG(p2decoder_state->parse_ptr, mrw); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + NETWORK_ORDER_GETLLONG(p2decoder_state->parse_ptr, rrw); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->mrw = mrw; + message_scratch_pad->rrw = rrw; + message_scratch_pad->cws_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s rrw=%llu mrw =%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + rrw, mrw); + } + return (RC_RFC5444_OK); +} + +/* credit grand */ + +static rfc5444_rc_t +rfc5444_decoder_credit_grand_request_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_credit_grand_request_tlv\n"); + uint16_t tlv_length; + uint64_t cgr; + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_CREDIT_GRANT_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLLONG(p2decoder_state->parse_ptr, cgr); + p2decoder_state->parse_ptr += sizeof(uint64_t); + + message_scratch_pad->cgr = cgr; + if (verbose) { + RFC5444_DEBUG("%s-%u %s Credit grand req=%llu \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + cgr); + } + return (RC_RFC5444_OK); +} + +/*credit_request tlv */ +static rfc5444_rc_t +rfc5444_decoder_credit_request_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_credit_request_tlv\n"); + uint16_t tlv_length; + uint8_t cr; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + + if (tlv_length != RFC5444_TLV_CREDIT_REQUEST_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, cr); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + /* cr should be zero... add check later */ + + message_scratch_pad->credit_req_present = TRUE; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s Credit req=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + cr); + } + return (RC_RFC5444_OK); +} + +static rfc5444_rc_t +rfc5444_decoder_heartbeat_interval_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_heartbeat_interval_tlv\n"); + uint16_t tlv_length; + uint32_t hbt; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->message_block_length -= (tlv_length + 1); + if (tlv_length != 4) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, hbt); + p2decoder_state->parse_ptr += sizeof(uint32_t); + message_scratch_pad->hbt = hbt; + + if (verbose) { + RFC5444_DEBUG("%s-%u %s Heart beat interval =%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + hbt); + } + + return (RC_RFC5444_OK); +} + +/* Below TLV functions are added for DLEPv7 */ +static rfc5444_rc_t +rfc5444_decoder_optinal_signal_supported_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_optinal_signal_supported_tlv\n"); + uint16_t tlv_length; + uint8_t opt_signals; + uint8_t i; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint8_t); +#if 0 + if (tlv_length != RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } +#endif + for (i = 0; i < RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED_LENGTH ; i++) { + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, opt_signals); + p2decoder_state->parse_ptr += sizeof(uint8_t); + + if(opt_signals) { + p2peer->optional_signal |= (1 << (opt_signals -1)); + } + + if (verbose) { + RFC5444_DEBUG("%s-%u %s dlepv7 optional_signal =%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + opt_signals); + } + } + + return (RC_RFC5444_OK); + +} + +static rfc5444_rc_t +rfc5444_decoder_optinal_data_item_supported_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *context_ptr, + boolean_t verbose) +{ +printf("rfc5444_decoder_optional_data_item_supported_tlv"); + uint16_t tlv_length; + uint8_t opt_data_item; + uint8_t i; + + dlep_context_peer_t *p2peer; + rfc5444_message_scratch_pad_t *message_scratch_pad; + + p2peer = context_ptr; + if (!p2peer) { + return (RC_RFC5444_NULL_POINTER); + } + + message_scratch_pad = &p2peer->message_scratch_pad; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->message_block_length -= (tlv_length + 1); + p2decoder_state->parse_ptr += sizeof(uint8_t); +#if 0 + if (tlv_length != RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED_LENGTH) { + return (RC_RFC5444_INVALID_TLV_LENGTH); + } +#endif + for (i = 0; i < tlv_length ; i++) { + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, opt_data_item); + + p2decoder_state->parse_ptr += sizeof(uint8_t); + if (opt_data_item) { + p2peer->optional_data_item |= (1 << (opt_data_item -1)); + + } + + if (verbose) { + RFC5444_DEBUG("%s-%u %s dlepv7 opt_data_item =%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + opt_data_item); + } + } + return (RC_RFC5444_OK); +} + +/** + * NAME + * rfc5444_decoder_tlv_init + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_decoder_tlv_init(void) + * + * DESCRIPTION + * This function must be called to register the TLV decoders. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_decoder_tlv_init (void) +{ +#if 0 + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_IDENTIFICATION, + &rfc5444_decoder_identification_tlv); +#endif + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_VERSION, + &rfc5444_decoder_version_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_PEER_TYPE, + &rfc5444_decoder_peer_type_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_MAC_ADDRESS, + &rfc5444_decoder_mac_address_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_IPV4_ADDRESS, + &rfc5444_decoder_ipv4_address_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_IPV4_ATTACHED_SUBNET, + &rfc5444_decoder_ipv4_attached_subnet_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_IPV6_ADDRESS, + &rfc5444_decoder_ipv6_address_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_MDR_METRIC_TX, + &rfc5444_decoder_link_metric_mdr_tx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_MDR_METRIC_RX, + &rfc5444_decoder_link_metric_mdr_rx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_CDR_METRIC_TX, + &rfc5444_decoder_link_metric_cdr_tx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_CDR_METRIC_RX, + &rfc5444_decoder_link_metric_cdr_rx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_LATENCY_METRIC, + &rfc5444_decoder_link_metric_latency_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RESOURCES_METRIC_RX, + &rfc5444_decoder_link_metric_resources_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RESOURCES_METRIC_TX, + &rfc5444_decoder_link_metric_resources_tx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RESOURCES_METRIC_RX, + &rfc5444_decoder_link_metric_resources_rx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RLQ_METRIC_TX, + &rfc5444_decoder_link_metric_rlq_tx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_RLQ_METRIC_RX, + &rfc5444_decoder_link_metric_rlq_rx_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_MTU, + &rfc5444_decoder_link_metric_mtu_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_PORT, + &rfc5444_decoder_port_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_LINK_EFT_METRIC, + &rfc5444_decoder_eft_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_CREDIT_WINDOW_STATUS, + &rfc5444_decoder_credit_window_status_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_CREDIT_GRANT, + &rfc5444_decoder_credit_grand_request_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_CREDIT_REQUEST, + &rfc5444_decoder_credit_request_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_HEARTBEAT_INTERVAL, + &rfc5444_decoder_heartbeat_interval_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_STATUS, + &rfc5444_decoder_status_tlv); + +/* Below TLV functions are added for DLEPv7 */ + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED, + &rfc5444_decoder_optinal_signal_supported_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED, + &rfc5444_decoder_optinal_data_item_supported_tlv); + + return (RC_RFC5444_OK); +} diff --git a/dlep_radio_ipv6/rfc5444_decoder_tlv.h b/dlep_radio_ipv6/rfc5444_decoder_tlv.h new file mode 100644 index 0000000..bf96982 --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_decoder_tlv.h @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------ + * rfc5444_decoder_tlv.h -- + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + *------------------------------------------------------------------ + */ + +#ifndef __RFC5444_DECODER_TLV__ +#define __RFC5444_DECODER_TLV__ + +#include "safe_types.h" +#include "rfc5444_types.h" + + + +extern rfc5444_rc_t +rfc5444_decoder_tlv_init(void); + + +#endif + + diff --git a/dlep_radio_ipv6/rfc5444_encoder.c b/dlep_radio_ipv6/rfc5444_encoder.c new file mode 100644 index 0000000..2a1cac3 --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_encoder.c @@ -0,0 +1,750 @@ +/*------------------------------------------------------------------ + * rfc5444_encoder.c -- RFC 5444 message encoding APIs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +/* + * Basic strucuture to format one or more messages in + * a RFC 5444 formatted packet. + * + * p2es = rfc5444_encoder_packet_start(); + * rfc5444_encoder_tlv_block_start(p2es, + * RFC5444_TLV_BLOCK_CONTEXT_PACKET); + * ... TLVs... + * rfc5444_encoder_tlv_block_end(p2es); + * + * rfc5444_encoder_message_block_start(p2es, + * RFC5444_MSG_NEIGHBOR_METRICS); + * + * p2neighbor->sequence = dlep_get_next_sequence_number( + * p2neighbor->sequence); + * + * rfc5444_encoder_message_block_add_sequence_number(p2es, + * p2neighbor->sequence); + * + * rfc5444_encoder_tlv_block_start(p2es, + * RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + * ... TLVs... + * rfc5444_encoder_tlv_block_end(p2es); + * rfc5444_encoder_message_block_end(p2es); + * + * rfc5444_encoder_message_block_start(p2es, + * RFC5444_MSG_NEIGHBOR_METRICS); + * + * p2neighbor->sequence = dlep_get_next_sequence_number( + * p2neighbor->sequence); + * + * rfc5444_encoder_message_block_add_sequence_number(p2es, + * p2neighbor->sequence); + * + * rfc5444_encoder_tlv_block_start(p2es, + * RFC5444_TLV_BLOCK_CONTEXT_MESSAGE); + * ... TLVs... + * rfc5444_encoder_tlv_block_end(p2es); + * rfc5444_encoder_message_block_end(p2es); + * + * rfc5444_encoder_packet_end(p2es); + */ + + +#include +#include +#include + +#include "safe_types.h" +#include "network_order.h" + +#include "rfc5444_types.h" +#include "rfc5444_packet_header.h" +#include "rfc5444_utils.h" + +#include "packet_dump.h" +#include "rfc5444_encoder.h" + + +#define RFC5444_DEBUG printf +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ + + + +/* + * Set - block open + * Clear - block closed + */ +#define ENCODER_STATE_PACKET ( 0x01 ) +#define ENCODER_STATE_MESSAGE ( 0x02 ) +#define ENCODER_STATE_TLV ( 0x04 ) + + +/** + * NAME + * rfc5444_encoder_packet_start + * + * SYNOPSIS + * rfc5444_encoder_state_t + * *rfc5444_encoder_packet_start(void) + * + * DESCRIPTION + * This function is used to allocate and initialize the + * encoder state variable. A packet buffer is also allocated + * and attached to the encoded state. As the packet is + * formatted, adding TLVs, the encoder variables are adjusted. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * Returns a pointer to the encoder state variable that + * must be passed to the encoding routines. + * + * NULL is returned if there was an error. + * + */ +rfc5444_encoder_state_t +*rfc5444_encoder_packet_start (void) +{ +printf("rfc5444_encoder_packet_start\n"); + uint8_t *ptr; + uint8_t *dest; + boolean_t verbose = FALSE; + + rfc5444_encoder_state_t *p2encoder_state; + + p2encoder_state = malloc(sizeof(rfc5444_encoder_state_t)); + if (!p2encoder_state) { + if (verbose) { + RFC5444_DEBUG("%s-%u Error: no encoder resources \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (NULL); + } + +/* port - may use a platform specific buffer allocation routine */ +#define MSG_BUFFER ( 1400 ) + ptr = malloc(MSG_BUFFER); + if (!ptr) { + if (verbose) { + RFC5444_DEBUG("%s-%u Error: no buffer resources \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + free(p2encoder_state); + return (NULL); + } + /* make space for packet header */ + dest = ptr; +#if 0 + NETWORK_ORDER_PUTBYTE(dest, 0); + dest += sizeof(uint8_t); +#endif + + /* save the working buffer pointer */ + p2encoder_state->buildit_ptr = dest; + + /* save the buffer pointer needed when complete */ + p2encoder_state->packet_ptr = ptr; + + /* update packet flags once the completed */ + p2encoder_state->p2packet_flags = ptr; + p2encoder_state->packet_flags = 0; + + /* completed packet length */ + p2encoder_state->packet_length = 0; + + p2encoder_state->p2message_block_length = NULL; + p2encoder_state->message_block_length = 0; + p2encoder_state->message_block_flags = 0; + + p2encoder_state->p2tlv_block_length = NULL; + p2encoder_state->tlv_block_length = 0; + + /* set packet open for business */ + p2encoder_state->state_flags = ENCODER_STATE_PACKET; + printf("state=0x%0x \n", p2encoder_state->state_flags); + + return (p2encoder_state); +} + + +/** + * NAME + * rfc5444_encoder_packet_add_sequence_number + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_packet_add_sequence_number( + * rfc5444_encoder_state_t *p2encoder_state, + * uint16_t sequence_number) + * + * DESCRIPTION + * This function is used to insert the packet sequence number + * into the packet header when it is desired. The phasseqnum + * flag is set. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * sequence_number - The sequence number to be added to the + * packet. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_packet_add_sequence_number ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t sequence_number) +{ +printf("rfc5444_encoder_packet_add_sequence_number\n"); + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (p2encoder_state->state_flags != ENCODER_STATE_PACKET) { + /* packet must be open */ + return (RC_RFC5444_STATE_ERROR); + } + + if (verbose) { + RFC5444_DEBUG("%s-%u sequence number %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + sequence_number); + } + + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, + sequence_number); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + /* set the phasseqnum flag */ + p2encoder_state->packet_flags |= PHASSEQNUM; + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_packet_end + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_packet_end( + * rfc5444_encoder_state_t *p2encoder_state) + * + * DESCRIPTION + * This function is used after all messages and TLVs have been + * added to the packet to complete the packet formatting, + * making the packet ready for transmission. The final packet + * length is computed and all arears are set. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_packet_end ( + rfc5444_encoder_state_t *p2encoder_state) +{ +printf("rfc5444_encoder_packet_end\n"); + uint16_t length; + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + if (verbose) { + RFC5444_DEBUG("%s-%u Error: encoder null \n", + DEBUG_FUNCTION, + DEBUG_LINE); + } + return (RC_RFC5444_NULL_POINTER); + } + + /* compute the final packet length */ + length = p2encoder_state->buildit_ptr - + p2encoder_state->packet_ptr; + p2encoder_state->packet_length = length; + if (verbose) { + RFC5444_DEBUG("%s-%u packet length=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + length); + } + + + printf("\n Finding total length of packet::::%d ", + p2encoder_state->packet_length); + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_free + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_free( + * rfc5444_encoder_state_t *p2encoder_state) + * + * DESCRIPTION + * This function is used to release all resources associated with + * the encoder state. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable to be freed. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents and resources are freed + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_free (rfc5444_encoder_state_t *p2encoder_state) +{ +printf("rfc5444_encoder_free\n"); + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (p2encoder_state->packet_ptr) { + free(p2encoder_state->packet_ptr); + p2encoder_state->packet_ptr = NULL; + } + free(p2encoder_state); + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_signal_block_start + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_signal_block_start( + * rfc5444_encoder_state_t *p2encoder_state, + * uint16_t message_code) + * + * DESCRIPTION + * This function is used to append a new message + * to the packet being formatted. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * message_code - The code of the message to be appended. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_signal_block_start ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t message_code, uint32_t dlep_signal_flags) +{ +printf("rfc5444_encoder_signal_block_start\n"); + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + // p2encoder_state->message_block_base = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTLONG(p2encoder_state->buildit_ptr, dlep_signal_flags); + p2encoder_state->buildit_ptr += sizeof(uint32_t); + + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, message_code); +// printf(" Added message code =%d",message_code); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + p2encoder_state->p2message_block_length = p2encoder_state->buildit_ptr; + + p2encoder_state->message_block_length = 0; + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, 0); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_message_block_start + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_message_block_start( + * rfc5444_encoder_state_t *p2encoder_state, + * uint16_t message_code) + * + * DESCRIPTION + * This function is used to append a new message + * to the packet being formatted. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * message_code - The code of the message to be appended. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_message_block_start ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t message_code) +{ +printf("rfc5444_encoder_message_block_start\n"); + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + // p2encoder_state->message_block_base = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, message_code); +// printf(" Added message code =%d",message_code); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + p2encoder_state->p2message_block_length = p2encoder_state->buildit_ptr; + + p2encoder_state->message_block_length = 0; + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, 0); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_message_block_add_sequence_number + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_message_block_add_sequence_number( + * rfc5444_encoder_state_t *p2encoder_state, + * uint16_t sequence_number) + * + * DESCRIPTION + * This function is used to insert the message sequence number + * into the message header when it is desired. The mhasseqnum + * flag is set. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * sequence_number - The sequence number to be inserted. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_message_block_add_sequence_number ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t sequence_number) +{ +printf("rfc5444_encoder_message_block_add_sequence_number\n"); + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (!(p2encoder_state->state_flags & ENCODER_STATE_MESSAGE)) { + /* message block is not open */ + return (RC_RFC5444_STATE_ERROR); + } + + if (verbose) { + RFC5444_DEBUG("%s-%u sequence number %u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + sequence_number); + } + + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, sequence_number); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + /* set the mhasseqnum flag */ + p2encoder_state->message_block_flags |= MHASSEQNUM; + + return(RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_message_block_end + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_message_block_end( + * rfc5444_encoder_state_t *p2encoder_state) + * + * DESCRIPTION + * This function is used after all parameters have been + * added to the message to complete the message formatting. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_message_block_end ( + rfc5444_encoder_state_t *p2encoder_state) +{ +printf("rfc5444_encoder_message_block_end\n"); + uint16_t length; + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + length = p2encoder_state->buildit_ptr - + p2encoder_state->p2message_block_length - sizeof(uint16_t); +// printf(" \n Adding total TLV length %d",length); + + // need not keep + p2encoder_state->message_block_length = length; + + /* go back to update the message block length */ + NETWORK_ORDER_PUTSHORT(p2encoder_state->p2message_block_length, length); + + if (verbose) { + printf("%s-%u message block size=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + length); + } + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_tlv_block_start + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_tlv_block_start( + * rfc5444_encoder_state_t *p2encoder_state, + * uint32_t block_indicator) + * + * DESCRIPTION + * This function is used to open a new TLV block in the + * packet header or the message body. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * block_indicator - This enum indicates where the TLV + * block is being appended: + * RFC5444_TLV_BLOCK_CONTEXT_PACKET + * RFC5444_TLV_BLOCK_CONTEXT_MESSAGE + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_tlv_block_start ( + rfc5444_encoder_state_t *p2encoder_state, + uint32_t block_indicator) +{ +printf("rfc5444_encoder_tlv_block_start\n"); + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (p2encoder_state->state_flags & ENCODER_STATE_TLV) { + /* TLV block already open */ + return (RC_RFC5444_STATE_ERROR); + } + + /* set the packet header TLV present bit */ + if (block_indicator == RFC5444_TLV_BLOCK_CONTEXT_PACKET) { + if (p2encoder_state->state_flags == ENCODER_STATE_PACKET) { + p2encoder_state->packet_flags |= PHASTLV; + } else { + return (RC_RFC5444_STATE_ERROR); + } + + } else if (block_indicator == RFC5444_TLV_BLOCK_CONTEXT_MESSAGE) { + if (p2encoder_state->state_flags & ENCODER_STATE_MESSAGE) { + /* do nothing */ + } else { + return (RC_RFC5444_STATE_ERROR); + } + } else { + return (RC_RFC5444_INVALID_BLOCK_INDICATOR); + } + + if (verbose) { + RFC5444_DEBUG("%s-%u adding %s TLV block \n", + DEBUG_FUNCTION, + DEBUG_LINE, + ((block_indicator == RFC5444_TLV_BLOCK_CONTEXT_PACKET) ? + "packet" : "message") ); + } + + /* save the ptr to update the TLV block length */ + p2encoder_state->p2tlv_block_length = p2encoder_state->buildit_ptr; + + p2encoder_state->tlv_block_length = 0; + NETWORK_ORDER_PUTSHORT(p2encoder_state->buildit_ptr, 0); + p2encoder_state->buildit_ptr += sizeof(uint16_t); + + /* mark the TLV block open */ + p2encoder_state->state_flags |= ENCODER_STATE_TLV; + + return (RC_RFC5444_OK); +} + + +/** + * NAME + * rfc5444_encoder_tlv_block_end + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_encoder_tlv_block_end( + * rfc5444_encoder_state_t *p2encoder_state) + * + * DESCRIPTION + * This function must be used to close a TLV block. + * + * INPUT PARAMETERS + * p2encoder_state - This is a pointer to the encoder + * state variable for the packet being formatted. + * + * OUTPUT PARAMETERS + * p2encoder_state - contents updated + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + * + */ +rfc5444_rc_t +rfc5444_encoder_tlv_block_end ( + rfc5444_encoder_state_t *p2encoder_state) +{ + uint16_t length; + boolean_t verbose = FALSE; + + if (!p2encoder_state) { + return (RC_RFC5444_NULL_POINTER); + } + + if (!(p2encoder_state->state_flags & ENCODER_STATE_TLV)) { + /* tlv block not open */ + return (RC_RFC5444_STATE_ERROR); + } + + /* compute the final packet length, accounting for the length itself */ + length = p2encoder_state->buildit_ptr - + p2encoder_state->p2tlv_block_length - sizeof(uint16_t); + p2encoder_state->tlv_block_length = length; + + /* go back to update the TLV block length */ + NETWORK_ORDER_PUTSHORT(p2encoder_state->p2tlv_block_length, length); + + if (verbose) { + RFC5444_DEBUG("%s-%u tlv block size=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + length); + } + + p2encoder_state->state_flags &= ~ENCODER_STATE_TLV; + + return (RC_RFC5444_OK); +} + + diff --git a/dlep_radio_ipv6/rfc5444_encoder.h b/dlep_radio_ipv6/rfc5444_encoder.h new file mode 100644 index 0000000..0d6d6cc --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_encoder.h @@ -0,0 +1,129 @@ +/*------------------------------------------------------------------ + * rfc5444_encoder.h -- RFC5444 message encoding routines + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef ___RFC5444_ENCODER__ +#define ___RFC5444_ENCODER__ + +#include "safe_types.h" +#include "rfc5444_types.h" + + +#define RFC5444_TLV_BLOCK_CONTEXT_PACKET ( 3 ) +#define RFC5444_TLV_BLOCK_CONTEXT_MESSAGE ( 5 ) + + +/* + * This is the structure type used to manage the encoding of + * the packet-message and TLVs. + */ +typedef struct { + uint32_t *dlep_sig_flags; + + uint32_t state_flags; + + uint8_t *buildit_ptr; + + uint8_t *packet_ptr; + + uint8_t *p2packet_flags; + uint8_t packet_flags; + + uint16_t packet_length; + + uint8_t *message_block_base; + uint8_t *p2message_block_flags; + uint8_t message_block_flags; + + uint8_t *p2message_block_length; + uint16_t message_block_length; + + uint8_t *tlv_block_base; + uint8_t *p2tlv_block_length; + uint8_t tlv_block_length; + +} rfc5444_encoder_state_t; + + + + +extern rfc5444_encoder_state_t +*rfc5444_encoder_packet_start(void); + + +extern rfc5444_rc_t +rfc5444_encoder_packet_add_sequence_number( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t sequence_number); + + +extern rfc5444_rc_t +rfc5444_encoder_packet_end( + rfc5444_encoder_state_t *p2encoder_state); + + +extern rfc5444_rc_t +rfc5444_encoder_free(rfc5444_encoder_state_t *p2encoder_state); + + +extern rfc5444_rc_t +rfc5444_encoder_message_block_start( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t message_code); + +extern rfc5444_rc_t +rfc5444_encoder_signal_block_start ( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t message_code, uint32_t dlep_signal_flags); + + +extern rfc5444_rc_t +rfc5444_encoder_message_block_add_sequence_number( + rfc5444_encoder_state_t *p2encoder_state, + uint16_t sequence_number); + + +extern rfc5444_rc_t +rfc5444_encoder_message_block_end( + rfc5444_encoder_state_t *p2encoder_state); + + +extern rfc5444_rc_t +rfc5444_encoder_tlv_block_start( + rfc5444_encoder_state_t *p2encoder_state, + uint32_t block_indicator); + + +extern rfc5444_rc_t +rfc5444_encoder_tlv_block_end( + rfc5444_encoder_state_t *p2encoder_state); + + +#endif diff --git a/dlep_radio_ipv6/rfc5444_encoder_tlv.c b/dlep_radio_ipv6/rfc5444_encoder_tlv.c new file mode 100644 index 0000000..d560e35 --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_encoder_tlv.c @@ -0,0 +1,1500 @@ +/*---------------------------------------------------------------------- + * rfc5444_encoder_tlv.c -- routines to encode TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "network_order.h" + +#include "rfc5444_types.h" +#include "rfc5444_encoder.h" +#include "rfc5444_encoder_tlv.h" + + +/** + * NAME + * rfc5444_identification_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_identification_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint32_t router_id, + * uint32_t client_id, + * uint8_t heartbeat_interval) + * + * DESCRIPTION + * Call this function to add the indentification TLV + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * router_id - indicates the router ID of the DLEP neighbor, set to + * '0' when unknown. + * + * client_id - indicates the client ID of the DLEP neighbor, set to + * '0' when unknown. + * + * heartbeat_interval - An 8-bit, unsigned value specifiying + * the peer-to-peer heartbeat interval. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | HB Intrvl | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Router ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | Client ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +#define RFC5444_TLV_IDENTIFICATION 255 + uint8_t +*rfc5444_identification_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t router_id, + uint32_t client_id, + uint8_t heartbeat_interval) +{ +printf("rfc5444_identification_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IDENTIFICATION); + dest += sizeof(uint8_t); + // if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IDENTIFICATION_FLAGS); + dest += sizeof(uint8_t); + // endif + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IDENTIFICATION_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, heartbeat_interval); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLONG(dest, router_id); + dest += sizeof(uint32_t); + + NETWORK_ORDER_PUTLONG(dest, client_id); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/** + * NAME + * rfc5444_version_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_version_tlv(rfc5444_encoder_state_t *p2encoder_state, + * uint16_t version_major, + * uint16_t version_minor) + * + * DESCRIPTION + * Call this function to insert the RFC5444 version TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * version_major - Major version of the client or router protocol. + * + * version_minor - Minor version of the client or router protocol. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Major Ver | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Major Ver | Minor Version | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + uint8_t +*rfc5444_version_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t version_major, + uint16_t version_minor) +{ +printf("rfc5444_version_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VERSION); + dest += sizeof(uint8_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VERSION_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VERSION_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTSHORT(dest, version_major); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, version_minor); + dest += sizeof(uint16_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/* port TLV */ + + uint8_t +*rfc5444_port_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t port) +{ +printf("rfc5444_port_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_PORT); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_PORT_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTSHORT(dest, port); + dest += sizeof(uint16_t); + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* CREDIT WINDOW STATUS TLV */ + uint8_t +*rfc5444_credit_window_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mrw, uint64_t rrw) +{ +printf("rfc5444_credit_window_status_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_WINDOW_STATUS); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_WINDOW_STATUS_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLLONG(dest, mrw); + dest += sizeof(uint64_t); + + NETWORK_ORDER_PUTLLONG(dest, rrw); + dest += sizeof(uint64_t); + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* CREDIT GRAND REQUEST */ + + uint8_t +*rfc5444_credit_grand_request_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cgr) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest,RFC5444_TLV_CREDIT_GRANT ); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_GRANT_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLLONG(dest, cgr); + dest += sizeof(uint64_t); + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* CREDIT REQUEST */ + uint8_t +*rfc5444_credit_request_tlv(rfc5444_encoder_state_t *p2encoder_state) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest,RFC5444_TLV_CREDIT_REQUEST); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_REQUEST_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, 0); + dest += sizeof(uint8_t); + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* TLV_HEATBEAT_INTERVAL */ + + +uint8_t +*rfc5444_heartbeat_interval_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t hbt) +{ + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest,RFC5444_TLV_HEARTBEAT_INTERVAL); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_HEARTBEAT_INTERVAL_LENGTH); + dest += sizeof(uint16_t); + /* convert to milliseconds */ + hbt = hbt * 1000; + + NETWORK_ORDER_PUTLONG(dest, hbt); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + +/** + * NAME + * rfc5444_peer_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_peer_tlv(rfc5444_encoder_state_t *p2encoder_state, + * char *peer_type_string) + * + * DESCRIPTION + * Call this function to add the return code TLV + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * peer_type_string - non-NULL terminated string + * identifier. <= 80 characters. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Peer Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Peer Type String (non-NULL terminated) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-.... + * + */ + uint8_t +*rfc5444_peer_tlv(rfc5444_encoder_state_t *p2encoder_state, + char *peer_type_string) +{ +printf("rfc5444_peer_tlv\n"); + uint8_t *ptr; + uint8_t length; + uint8_t *dest; + uint32_t i; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_PEER_TYPE); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_PEER_TYPE_FLAGS); + dest += sizeof(uint8_t); +#endif + ptr = dest; + NETWORK_ORDER_PUTSHORT(dest, 1); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_PEER_TYPE_FLAGS); + dest += sizeof(uint8_t); + + length = 1; + for (i=0; (*peer_type_string) && ibuildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_mac_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_mac_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t mac_address[]) + * + * DESCRIPTION + * Call this function to insert the remote MAC address TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * mac_address - the remote router MAC address. The MAC + * is used to uniquely address all neighbor messages. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | MAC Addr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Remote Router MAC Continued (32-bit) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | MAC Addr | + * +-+-+-+-+-+-+-+-+ + * + */ + uint8_t +*rfc5444_mac_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t mac_address[]) +{ +printf("rfc5444_mac_address_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MAC_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_MAC_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MAC_ADDRESS_LENGTH); + dest += sizeof(uint16_t); + + dest = mac_put_address(dest, mac_address); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_ipv4_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_ipv4_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t operation, + * ipv4_address_t ipv4) + * + * DESCRIPTION + * Call this function to insert the IPv4 TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * operation - indicates the operation to be applied + * on the IPv4 address + * RFC5444_EXISTING_NEW_ADDRESS + * RFC5444_WITHDRAW_ADDRESS + * + * ipv4 - the address + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | operation | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | IPv4 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*rfc5444_ipv4_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv4_address_t *ipv4) +{ +printf("rfc5444_ipv4_address_tlv"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV4_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV4_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV4_ADDRESS_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv4_put_address(dest, ipv4); + + /* NETWORK_ORDER_PUTBYTE(dest, 24); + dest += sizeof(uint8_t); */ + + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_ipv6_address_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_ipv6_address_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t operation, + * ipv6_address_t *ipv6_addr) + * + * DESCRIPTION + * Call this function to insert the IPv4 TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * operation - indicates the operation to be applied + * on the IPv4 address + * RFC5444_EXISTING_NEW_ADDRESS + * RFC5444_WITHDRAW_ADDRESS + * + * ipv6_addr - the address + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | operation | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | IPv6 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | IPv6 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 12 | IPv6 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 16 | IPv6 Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + uint8_t +*rfc5444_ipv6_address_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv6_address_t *ipv6_addr) +{ +printf("rfc5444_ipv6_address_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV6_ADDRESS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV6_ADDRESS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV6_ADDRESS_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv6_put_address(dest, ipv6_addr); + + /* NETWORK_ORDER_PUTBYTE(dest, 64); + dest += sizeof(uint8_t); */ + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_link_metric_mdr_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_mdr_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t mdr) + * + * DESCRIPTION + * Call this function to insert the maximum datarate TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * mdr - the maximum theoretical data rate, in bits per + * second (bps), achieved on the link. When + * metrics are reported, the maximum data rate + * MUST be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | MDR | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | MDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | MDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ + uint8_t +*rfc5444_link_metric_mdr_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr) +{ +printf("rfc5444_link_metric_mdr_tx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_MDR_METRIC_TX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_MDR_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_MDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, mdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + uint8_t +*rfc5444_link_metric_mdr_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr) +{ +printf("rfc5444_link_metric_mdr_rx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_MDR_METRIC_RX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_MDR_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_MDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, mdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + +/** + * NAME + * rfc5444_link_metric_cdr_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_cdr_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t cdr) + * + * DESCRIPTION + * Call this function to insert the current datarate TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * cdr - the current data rate, in bits per second + * (bps), achieved on the link. If there is no + * distinction between maximum and current + * data rate, current data rate SHOULD be set + * equal to the maximum data rate. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | CDR | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | CDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 8 | CDR contd | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*rfc5444_link_metric_cdr_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr) +{ +printf("rfc5444_link_metric_cdr_tx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_CDR_METRIC_TX); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_CDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, cdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*rfc5444_link_metric_latency_tlv1 (rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency) +{ +printf("rfc5444_link_metric_latency_tlv1\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_LATENCY_METRIC); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, latency); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); + +} + +uint8_t +*rfc5444_link_metric_cdr_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr) +{ +printf("rfc5444_link_metric_cdr_rx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_CDR_METRIC_RX); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_CDR_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_CDR_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLLONG(dest, cdr); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/** + * NAME + * rfc5444_link_metric_latency_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_latency_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint64_t latency) + * + * DESCRIPTION + * Call this function to insert the latency TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * latency - the transmission delay that a packet + * encounters as it is transmitted over the link. + * This is reported in absolute delay, in + * milliseconds. If latency cannot be calculated, + * a value of 0 should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Latency | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 4 | Latency | + * +-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*rfc5444_link_metric_latency_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency) +{ +printf("rfc5444_link_metric_latency_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_LATENCY_METRIC); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_LATENCY_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLONG(dest, latency); + dest += sizeof(uint64_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/** + * NAME + * rfc5444_link_metric_resources_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t resources) + * + * DESCRIPTION + * Call this function to insert the resources TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * resources - a percentage, 0-100, representing the amount + * of remaining resources, such as battery power. + * If resources cannot be calculated, a value of + * 100 should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Resources | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*rfc5444_link_metric_resources_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources) +{ +printf("rfc5444_link_metric_resources_tx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RESOURCES_METRIC_TX); + dest += sizeof(uint8_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, resources); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +uint8_t +*rfc5444_link_metric_resources_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources) +{ +printf("rfc5444_link_metric_resources_rx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RESOURCES_METRIC_RX); + dest += sizeof(uint8_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, resources); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*rfc5444_link_metric_resources_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources) +{ +printf("rfc5444_link_metric_resources_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RESOURCES_METRIC); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, resources); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/** + * NAME + * rfc5444_link_metric_rlq_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_link_metric_rq_tlv( + * rfc5444_encoder_state_t *p2encoder_state, + * uint8_t rlq) + * + * DESCRIPTION + * Call this function to insert the RLQ TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * rlq - a non-dimensional number, 0-100, representing + * the relative link quality. A value of 100 + * represents a link of the highest quality. If + * the RLQ cannot be calculated, a value of 100 + * should be reported. + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | RLQ | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +uint8_t +*rfc5444_link_metric_rlq_tx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq) +{ +printf("rfc5444_link_metric_rlq_tx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RLQ_METRIC_TX); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RLQ_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, rlq); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*rfc5444_link_metric_rlq_rx_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq) +{ +printf("rfc5444_link_metric_rlq_rx_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_RLQ_METRIC_RX); + dest += sizeof(uint16_t); + +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_LINK_METRIC_RLQ_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, rlq); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/* + * MTU + */ +uint8_t +*rfc5444_mtu_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint16_t mtu) +{ +printf("rfc5444_mtu_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MTU); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_MTU_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, mtu); + dest += sizeof(uint16_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* + * eft + */ +uint8_t +*rfc5444_link_metric_eft_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t eft) +{ +printf("rfc5444_link_metric_eft_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_EFT_METRIC); + dest += sizeof(uint8_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_RLQ_FLAGS); + dest += sizeof(uint8_t); +#endif + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_METRIC_EFT_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLONG(dest, eft); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/** + * NAME + * rfc5444_status_tlv + * + * SYNOPSIS + * uint8_t + * *rfc5444_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + * uint8_t status_code) + * + * DESCRIPTION + * Call this function to insert the peer status TLV. + * + * INPUT PARAMETERS + * p2es - pointer to the encoder state variable + * + * status_code - protocol status code reflecting success + * of previous request + * + * OUTPUT PARAMETERS + * p2es - updated + * + * RETURNS + * The pointer to the byte immediately following the TLV. + * + * NOTES + * + * Most Least + * Byte Significant Bit Significant Bit + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * 0 | TLV Code | Flags | Length | Status Code | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +uint8_t +*rfc5444_status_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t status_code) +{ +printf("rfc5444_status_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_STATUS); + dest += sizeof(uint16_t); +#if 0 + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_STATUS_FLAGS); + dest += sizeof(uint8_t); +#endif + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_STATUS_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, status_code); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* Below TLV functions are added for DLEPv7 */ + +uint8_t +*rfc5444_ipv4_attached_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, uint8_t operation) + +{ +printf("rfc5444_ipv4_attached_subnet_tlv\n"); + uint8_t *dest; + char subnet[16]; + char local_ipv4_dot[IPV4_ADDR_STRING_LEN] = "255.255.255.0"; + ipv4_address_t ipv4_subnet_addr; + + ipv4_dot_decimal2digits(&ipv4_subnet_addr, local_ipv4_dot); + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV4_ATTACHED_SUBNET); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV4_ATTACHED_SUBNET_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv4_put_address(dest, &ipv4_subnet_addr); + + NETWORK_ORDER_PUTBYTE(dest, 24); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + uint8_t +*rfc5444_ipv6_attached_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, + ipv6_address_t *ipv6_subnet_addr) +{ +printf("rfc5444_ipv6_attached_subnet_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV6_ADDRESS); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, (RFC5444_TLV_IPV6_ATTACHED_SUBNET_LENGTH)); + dest += sizeof(uint8_t); + + dest = ipv6_put_address(dest, ipv6_subnet_addr); + + NETWORK_ORDER_PUTBYTE(dest, 64); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +/* Suriya added for testing purpose */ +//vinod +/* +*rfc5444_ipv6_subnet_tlv_surya (rfc5444_encoder_state_t *p2encoder_state,uint8_t operation, +uint8_t subnet,ipv6_address_t *ipv6_subnet_addr) +*/ + + uint8_t +*rfc5444_ipv6_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state,uint8_t operation, +uint8_t subnet,ipv6_address_t *ipv6_subnet_addr ) +{ +printf("rfc5444_ipv6_subnet_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV6_ATTACHED_SUBNET); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV6_ATTACHED_SUBNET_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, operation); + dest += sizeof(uint8_t); + + dest = ipv6_put_address(dest, ipv6_subnet_addr); + + NETWORK_ORDER_PUTBYTE(dest, subnet); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + + uint8_t +*rfc5444_optinal_signal_supported_tlv (rfc5444_encoder_state_t *p2encoder_state) +{ +printf("rfc5444_optional_signal_supported_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED_LENGTH); + dest += sizeof(uint8_t); + + /* Reserved bit */ + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_MSG_PEER_UPDATE_RES); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest,RFC5444_MSG_PEER_UPDATE_REQ); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_MSG_LINK_CHAR_RES); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest,RFC5444_MSG_LINK_CHAR_REQ); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + +uint8_t +*rfc5444_optinal_data_item_supported_tlv (rfc5444_encoder_state_t *p2encoder_state) +{ +printf("rfc5444_optional_data_item_supported_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED_LENGTH); + dest += sizeof(uint8_t); + + /* Reserved bit */ + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RESOURCES_METRIC_RX); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RESOURCES_METRIC_TX); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RLQ_METRIC_TX); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_LINK_RLQ_METRIC_RX); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_WINDOW_STATUS); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_GRANT); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_CREDIT_REQUEST); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VENDOR_EXTENSION); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV4_ATTACHED_SUBNET); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV6_ATTACHED_SUBNET); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + uint8_t +*rfc5444_vendor_extension_tlv (rfc5444_encoder_state_t *p2encoder_state) +{ +printf("rfc5444_vendor_extension_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VENDOR_EXTENSION); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_VENDOR_EXTENSION_LENGTH); + dest += sizeof(uint8_t); + + /* Reserved bit */ + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0x00); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, VENDOR_OUI_LENGTH); + dest += sizeof(uint8_t); + +/* Vendor OUI */ + NETWORK_ORDER_PUTBYTE(dest, 0xAB); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, 0xBC); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, 0xCD); + dest += sizeof(uint8_t); + +/* Device type*/ + NETWORK_ORDER_PUTSHORT(dest, 0xBABE); + dest += sizeof(uint16_t); + +/*PAYLOAD in TLV format*/ + NETWORK_ORDER_PUTBYTE(dest, VENDOR_SPECIFIC_PAYLOAD_TYPE); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, VENDOR_SPECIFIC_PAYLOAD_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, 0xEF); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0xDC); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0xBA); + dest += sizeof(uint8_t); + NETWORK_ORDER_PUTBYTE(dest, 0xBD); + dest += sizeof(uint8_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} +/* + * ipv4 connection point tlv + * + */ +uint8_t +*rfc5444_ipv4_connection_point_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint16_t port, + ipv4_address_t *ipv4) +{ +printf("rfc5444_ipv4_connection_point_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_IPV4_CONNECTION_POINT); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTSHORT(dest, (RFC5444_TLV_IPV4_CONNECTION_POINT_LENGTH)); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_IPV4_CONNECTION_POINT_FLAGS); + dest += sizeof(uint8_t); + + dest = ipv4_put_address(dest, ipv4); + + NETWORK_ORDER_PUTSHORT(dest, port); + dest += sizeof(uint16_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + diff --git a/dlep_radio_ipv6/rfc5444_encoder_tlv.h b/dlep_radio_ipv6/rfc5444_encoder_tlv.h new file mode 100644 index 0000000..a50eb45 --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_encoder_tlv.h @@ -0,0 +1,197 @@ +/*---------------------------------------------------------------------- + * rfc5444_encoder_tlv.h -- routine prototypes to encode TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __RFC5444_ENCODER_TLV_H__ +#define __RFC5444_ENCODER_TLV_H__ + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_encoder.h" + + + +extern uint8_t +*rfc5444_identification_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t router_id, + uint32_t client_id, + uint8_t heartbeat_interval); + +extern uint8_t +*rfc5444_version_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t version_major, + uint16_t version_minor); + + +extern uint8_t +*rfc5444_peer_tlv(rfc5444_encoder_state_t *p2encoder_state, + char *peer_type_string); + + +extern uint8_t +*rfc5444_mac_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t mac_address[]); + + +extern uint8_t +*rfc5444_ipv4_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv4_address_t *ipv4); + +extern uint8_t +*rfc5444_ipv6_address_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, + ipv6_address_t *ipv6_dest_addr); + + +extern uint8_t +*rfc5444_link_metric_mdr_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr); + +extern uint8_t +*rfc5444_link_metric_mdr_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mdr); + +extern uint8_t +*rfc5444_link_metric_cdr_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr); +extern uint8_t +*rfc5444_link_metric_latency_tlv1(rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency); + +extern uint8_t +*rfc5444_link_metric_cdr_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cdr); + +extern uint8_t +*rfc5444_link_metric_latency_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t latency); + +extern uint8_t +*rfc5444_link_metric_resources_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources); + +extern uint8_t +*rfc5444_link_metric_resources_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources); + +extern uint8_t +*rfc5444_link_metric_rlq_tx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq); + +extern uint8_t +*rfc5444_link_metric_rlq_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t rlq); + +extern uint8_t +*rfc5444_link_metric_eft_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t eft); + + +extern uint8_t +*rfc5444_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t termination_code); + + +extern uint8_t +*rfc5444_datarate_request_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t requested_cdr); + + +extern uint8_t +*rfc5444_datarate_request_ack_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t requested_cdr, + uint32_t granted_cdr); +extern uint8_t +*rfc5444_port_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t port); +extern uint8_t +*rfc5444_credit_window_status_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t mrw, uint64_t rrw); +extern uint8_t +*rfc5444_credit_grand_request_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint64_t cgr); +extern uint8_t +*rfc5444_credit_request_tlv(rfc5444_encoder_state_t *p2encoder_state); + +extern uint8_t +*rfc5444_heartbeat_interval_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t hbt); + + +/* Below TLV functions are added for DLEPv7 */ + +extern uint8_t +*rfc5444_ipv4_attached_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation); + +//vinod + +extern uint8_t +*rfc5444_ipv6_attached_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, + ipv6_address_t *ipv6_subnet); + + +//vinod +extern uint8_t +*rfc5444_ipv6_subnet_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint8_t operation, uint8_t subnet,ipv6_address_t *ipv6_subnet_addr); + + +/* Below TLV functions are added for DLEPv27 */ +extern uint8_t +*rfc5444_link_metric_resources_rx_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint8_t resources); + +extern uint8_t +*rfc5444_mtu_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint16_t mtu); + +extern uint8_t +*rfc5444_ipv4_connection_point_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint16_t port, + ipv4_address_t *ipv4); + +extern uint8_t +*rfc5444_optinal_signal_supported_tlv (rfc5444_encoder_state_t *p2encoder_state); + +extern uint8_t +*rfc5444_optinal_data_item_supported_tlv (rfc5444_encoder_state_t *p2encoder_state); + +extern uint8_t +*rfc5444_vendor_extension_tlv (rfc5444_encoder_state_t *p2encoder_state); + + +#endif + + diff --git a/dlep_radio_ipv6/rfc5444_experimental_tlv.c b/dlep_radio_ipv6/rfc5444_experimental_tlv.c new file mode 100644 index 0000000..7778d39 --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_experimental_tlv.c @@ -0,0 +1,264 @@ +/*------------------------------------------------------------------ + * rfc5444_experimental_tlv.c -- routines for standard TLVs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "safe_types.h" +#include "network_order.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_decoder.h" + +#include "rfc5444_experimental_tlv.h" + + + +#define RFC5444_TLV_EXPER_8 ( 253 ) +#define RFC5444_TLV_EXPER_8_LENGTH ( 4 ) + +#define RFC5444_TLV_EXPER_16 ( 254 ) +#define RFC5444_TLV_EXPER_16_LENGTH ( 4 ) + + +#define RFC5444_DEBUG printf +#define DEBUG_FUNCTION __FUNCTION__ +#define DEBUG_LINE __LINE__ + + + +/* + * RFC 5444 defines TLVs as + * + * := + * + * ? + * (?)? + * (?)? + * + * This is referred to as the T-F-L-V format. The + * field is used to describe the length field size, 8-bits + * or 16-bits as well as the presence of the value or not. + * + * The standard TLV encoding does not specify the + * field. The flag field is not needed as the tlv_code itself + * describes the value by definition of the code itself. + * http://en.wikipedia.org/wiki/Type-length-value + * + * This file experiments with the standard TLV format + * in RFC5444 formatting. It is also a good test for + * the decoder. + */ + +/* + * Experimental 8-bit length + */ +uint8_t +*rfc5444_exper_8_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t parameter) +{ +printf("rfc5444_exper_8_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_EXPER_8); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_EXPER_8_LENGTH); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTLONG(dest, parameter); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/* + * Experimental 16-bit length + */ +uint8_t +*rfc5444_exper_16_tlv (rfc5444_encoder_state_t *p2encoder_state, + uint32_t parameter) +{ +printf("rfc5444_exper_16_tlv\n"); + uint8_t *dest; + + dest = p2encoder_state->buildit_ptr; + + NETWORK_ORDER_PUTBYTE(dest, RFC5444_TLV_EXPER_16); + dest += sizeof(uint8_t); + + NETWORK_ORDER_PUTSHORT(dest, RFC5444_TLV_EXPER_16_LENGTH); + dest += sizeof(uint16_t); + + NETWORK_ORDER_PUTLONG(dest, parameter); + dest += sizeof(uint32_t); + + p2encoder_state->buildit_ptr = dest; + return (dest); +} + + +/* + * Experimental 8-bit length field decoder + */ +static rfc5444_rc_t +rfc5444_decoder_exper_8_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *scratch_pad, + boolean_t verbose) +{ +printf("rfc5444_decoder_exper_8_tlv\n"); + uint8_t tlv_length; + uint32_t parameter; + + NETWORK_ORDER_GETBYTE(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint8_t); + p2decoder_state->tlv_block_length -= sizeof(uint8_t); + + if (tlv_length != RFC5444_TLV_EXPER_8_LENGTH) { + if (verbose) { + RFC5444_DEBUG("%s-%u ERROR: invalid length tlv_code=%u " + "len=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, parameter); + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->tlv_block_length -= sizeof(uint32_t); + + if (verbose) { + RFC5444_DEBUG("%s-%u %s parameter=0x%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + parameter); + } + return (RC_RFC5444_OK); +} + + +/* + * Experimental 16-bit length field decoder + */ +static rfc5444_rc_t +rfc5444_decoder_exper_16_tlv ( + uint16_t tlv_code, + rfc5444_decoder_state_t *p2decoder_state, + void *scratch_pad, + boolean_t verbose) +{ +printf("rfc5444_decoder_exper_16_tlv\n"); + uint16_t tlv_length; + uint32_t parameter; + + NETWORK_ORDER_GETSHORT(p2decoder_state->parse_ptr, tlv_length); + p2decoder_state->parse_ptr += sizeof(uint16_t); + p2decoder_state->tlv_block_length -= sizeof(uint16_t); + + if (tlv_length != RFC5444_TLV_EXPER_16_LENGTH) { + if (verbose) { + RFC5444_DEBUG("%s-%u ERROR: invalid length tlv_code=%u " + "len=%u \n", + DEBUG_FUNCTION, + DEBUG_LINE, + tlv_code, + tlv_length); + } + return (RC_RFC5444_INVALID_TLV_LENGTH); + } + + NETWORK_ORDER_GETLONG(p2decoder_state->parse_ptr, parameter); + p2decoder_state->parse_ptr += sizeof(uint32_t); + p2decoder_state->tlv_block_length -= sizeof(uint32_t); + + if (verbose) { + RFC5444_DEBUG("%s-%u %s parameter=0x%0x \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rfc5444_tlv_code2string(tlv_code), + parameter); + } + return (RC_RFC5444_OK); +} + + +/* + * + * NAME + * rfc5444_experimental_tlv_init + * + * SYNOPSIS + * rfc5444_rc_t + * rfc5444_experimental_tlv_init(void) + * + * DESCRIPTION + * This function must be called to register the experimental + * TLV decoders. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_RFC5444_OK - success + * error otherwise + *- + */ +rfc5444_rc_t +rfc5444_experimental_tlv_init (void) +{ + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_EXPER_8, + &rfc5444_decoder_exper_8_tlv); + + rfc5444_decoder_tlv_register_cb(RFC5444_TLV_EXPER_16, + &rfc5444_decoder_exper_16_tlv); + + return (RC_RFC5444_OK); +} + + diff --git a/dlep_radio_ipv6/rfc5444_experimental_tlv.h b/dlep_radio_ipv6/rfc5444_experimental_tlv.h new file mode 100644 index 0000000..65a4b32 --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_experimental_tlv.h @@ -0,0 +1,56 @@ +/*------------------------------------------------------------------ + * rfc5444_experimental_tlv.h -- prototypes for stndard TLV APIs + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + *------------------------------------------------------------------ + */ + +#ifndef __RFC5444_EXPERIMENTAL_TLV__ +#define __RFC5444_EXPERIMENTAL_TLV__ + +#include "safe_types.h" +#include "rfc5444_types.h" +#include "rfc5444_encoder.h" + + +extern uint8_t +*rfc5444_exper_8_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t parameter); + + +extern uint8_t +*rfc5444_exper_16_tlv(rfc5444_encoder_state_t *p2encoder_state, + uint32_t parameter); + + +extern rfc5444_rc_t +rfc5444_experimental_tlv_init(void); + +#endif + + diff --git a/dlep_radio_ipv6/rfc5444_packet_header.c b/dlep_radio_ipv6/rfc5444_packet_header.c new file mode 100644 index 0000000..3d9853c --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_packet_header.c @@ -0,0 +1,179 @@ +/*------------------------------------------------------------------ + * rfc5444_packet_header.c -- + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include + +#include "safe_types.h" +#include "network_order.h" + +#include "rfc5444_packet_header.h" + + + +#define RFC5444_VERSION ( 0 ) + +/* + * This will change when authentication is supported. + */ +#define RFC5444_PACKET_FLAGS ( 2 ) + + +/* + * RFC5444 Control Header + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+ + * | | | + * | Vers | Flags | + * | | | + * +-+-+-+-+-+-+-+-+ + * + */ +#define RFC5444_PACKET_HDR_VERSION_MASK ( 0xF0 ) +#define RFC5444_PACKET_HDR_VERSION_SHIFT ( 4 ) + +#define RFC5444_PACKET_HDR_FLAGS_MASK ( 0x0F ) +#define RFC5444_PACKET_HDR_FLAGS_SHIFT ( 0 ) + + + +/** + * NAME + * rfc5444_add_packet_header + * + * SYNOPSIS + * uint8_t + * *rfc5444_add_packet_header(uint8_t *dest) + * + * DESCRIPTION + * Call this function to add the RFC5444 packet header + * when constructing a message. + * + * INPUT PARAMETERS + * dest - pointer to where the RFC5444 header is placed + * + * OUTPUT PARAMETERS + * dest - buffer is modified with the packet header + * + * RETURN VALUES + * Pointer to data area just beyond the newly added + * RFC5444 header. + * + * NOTES + * ASSUME all pointers are valid + */ +uint8_t +*rfc5444_add_packet_header (uint8_t *dest, uint8_t flags) +{ +printf("rfc5444_add_packet_header\n"); + uint8_t rfc5444_header; + + /* all fields are defaulted to zero */ + rfc5444_header = 0; + + rfc5444_header = (flags & RFC5444_PACKET_HDR_FLAGS_MASK); + + rfc5444_header |= ((RFC5444_VERSION << RFC5444_PACKET_HDR_VERSION_SHIFT) & + RFC5444_PACKET_HDR_VERSION_MASK); + + rfc5444_header |= rfc5444_header; + + NETWORK_ORDER_PUTBYTE(dest, rfc5444_header); + dest += sizeof(uint8_t); + return (dest); +} + + +/** + * NAME + * rfc5444_parse_packet_header + * + * SYNOPSIS + * uint8_t + * *rfc5444_parse_packet_header(uint8_t *msg, + * uint8_t *packet_flags, + * + * DESCRIPTION + * Call this function to extract the RFC5444 packet header + * fields when a message is received. + * + * INPUT PARAMETERS + * msg - pointer to the beginning of the RFC5444 message + * + * rsvrd - pointer to the reserved field + * + * rf0 - pointer to the rf0 flag + * + * OUTPUT PARAMETERS + * rsvrd - updated + * + * rf0 - updated + * + * RETURN VALUES: + * Pointer to data area just beyond the newly parsed + * RFC5444 header. + * NULL if the version is not supported. + * + * NOTES + * ASSUME all pointers are valid + * + */ +uint8_t +*rfc5444_parse_packet_header (uint8_t *msg, + uint8_t *packet_header_flags) +{ +printf("rfc5444_parse_packet_header\n"); + uint8_t rfc5444_packet_header; + uint8_t rfc5444_version; + + *packet_header_flags = 0; + + NETWORK_ORDER_GETBYTE(msg, rfc5444_packet_header); + + rfc5444_version = ((rfc5444_packet_header & + RFC5444_PACKET_HDR_VERSION_MASK) >> + RFC5444_PACKET_HDR_VERSION_SHIFT); + + if (rfc5444_version == RFC5444_VERSION) { + *packet_header_flags = ((rfc5444_packet_header & + RFC5444_PACKET_HDR_FLAGS_MASK) >> + RFC5444_PACKET_HDR_FLAGS_SHIFT); + + msg += sizeof(uint8_t); + } else { + msg = NULL; + } + + return (msg); +} + + diff --git a/dlep_radio_ipv6/rfc5444_packet_header.h b/dlep_radio_ipv6/rfc5444_packet_header.h new file mode 100644 index 0000000..3b1f34a --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_packet_header.h @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------ + * rfc5444_packet_header.h -- + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __RFC5444_PACKET_HEADER_H__ +#define __RFC5444_PACKET_HEADER_H__ + +#include "safe_types.h" + + +extern uint8_t +*rfc5444_add_packet_header(uint8_t *dest, + uint8_t packet_header_flags); + + +extern uint8_t +*rfc5444_parse_packet_header(uint8_t *msg, + uint8_t *packet_header_flags); + + +#endif + diff --git a/dlep_radio_ipv6/rfc5444_scratch_pad.c b/dlep_radio_ipv6/rfc5444_scratch_pad.c new file mode 100644 index 0000000..857d27a --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_scratch_pad.c @@ -0,0 +1,384 @@ +/*---------------------------------------------------------------------- + * rfc5444_scratch_pad.c -- Routines to manage parsed data + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include +#include +#include + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_scratch_pad.h" + + +/** + * NAME + * rfc5444_show_packet_scratch_pad + * + * SYNOPSIS + * #include "rfc5444_scratch_pad.h" + * void + * rfc5444_show_packet_scratch_pad( + * rfc5444_packet_scratch_pad_t *scratch_pad) + * + * DESCRIPTION + * This function is used to display the packet scratch pad + * to facilitate debugging and integration. + * + * INPUT PARAMETERS + * pkt_scratch_pad - This is a pointer to the packet scratch + * pad area + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +rfc5444_show_packet_scratch_pad ( + rfc5444_packet_scratch_pad_t *pkt_scratch_pad) +{ +printf("rfc5444_show_packet_scratch_pad\n"); + if (!pkt_scratch_pad) { + return; + } + + printf("\nPacket Scratch Pad \n"); + + if (pkt_scratch_pad->sequence_present) { + printf(" sequence number=%u \n", + pkt_scratch_pad->sequence); + } + + if (pkt_scratch_pad->router_id_present) { + printf(" router id=%u \n", + pkt_scratch_pad->router_id); + } + + if (pkt_scratch_pad->client_id_present) { + printf(" client id=%u \n", + pkt_scratch_pad->client_id); + } + + if (pkt_scratch_pad->peer_heartbeat_interval_present) { + printf(" peer heartbeat interval=%u seconds \n", + pkt_scratch_pad->peer_heartbeat_interval); + } + + return; +} + + +/** + * NAME + * rfc5444_show_message_scratch_pad + * + * SYNOPSIS + * #include "rfc5444_scratch_pad.h" + * void + * rfc5444_show_message_scratch_pad( + * rfc5444_message_scratch_pad_t *scratch_pad) + * + * DESCRIPTION + * This function is used to display the message scratch pad to + * facilitate debugging and ntegration. + * + * INPUT PARAMETERS + * msg_scratch_pad - This is a pointer to the message scratch + * pad area + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +rfc5444_show_message_scratch_pad ( + rfc5444_message_scratch_pad_t *msg_scratch_pad) +{ +printf("rfc5444_show_message_scratch_pad\n"); + if (!msg_scratch_pad) { + return; + } + + printf("Message Scratch Pad \n"); + + printf(" message code=%u %s \n", + msg_scratch_pad->message_code, + rfc5444_message_code2string(msg_scratch_pad->message_code)); + + /* if (msg_scratch_pad->sequence_present) { + printf(" sequence number=%u \n", + msg_scratch_pad->sequence); + } */ + + if (msg_scratch_pad->major_version_present || + msg_scratch_pad->minor_version_present) { + printf(" DLEP version=%u.%u \n", + msg_scratch_pad->major_version, + msg_scratch_pad->minor_version); + } + + if (msg_scratch_pad->status_code_present) { + printf(" status code=%u \n", + msg_scratch_pad->status_code); + } + + if (msg_scratch_pad->mac_address_present) { + mac_print_address(" MAC=", msg_scratch_pad->mac_address); + } + + if (msg_scratch_pad->ipv4_address_present) { + printf(" IPv4 operation=%u \n", + msg_scratch_pad->ipv4_operation); + ipv4_print_address(" IPv4", &msg_scratch_pad->ipv4_address); + } + + if (msg_scratch_pad->ipv6_address_present) { + printf(" IPv6 operation=%u \n", + msg_scratch_pad->ipv6_operation); + ipv6_print_address(" IPv6", &msg_scratch_pad->ipv6_address); + } + + if (msg_scratch_pad->rlq_present) { + printf(" rlq tx=%u percent \n", + msg_scratch_pad->rlq_tx); + + printf(" rlq rx=%u percent \n", + msg_scratch_pad->rlq_rx); + } + + if (msg_scratch_pad->resources_present) { + printf(" resources =%u percent\n", + msg_scratch_pad->resources); + + } + + if (msg_scratch_pad->latency_present) { + printf(" latency=%llu milliseconds \n", + msg_scratch_pad->latency); + } + + if (msg_scratch_pad->cdr_present) { + printf(" cdr tx=%llu bps \n", + msg_scratch_pad->cdr_tx); + + printf(" cdr rx=%llu bps \n", + msg_scratch_pad->cdr_rx); + } + + if (msg_scratch_pad->mdr_present) { + printf(" mdr tx=%llu bps\n", + msg_scratch_pad->mdr_tx); + + printf(" mdr rx=%llu bps\n", + msg_scratch_pad->mdr_rx); + } + + if (msg_scratch_pad->mtu_present) { + printf(" mtu=%u \n", + msg_scratch_pad->mtu); + } + + return; +} + + +/** + * NAME + * rfc5444_scrub_packet_scratch_pad + * + * SYNOPSIS + * #include "rfc5444_scratch_pad.h" + * void + * rfc5444_scrub_packet_scratch_pad( + * rfc5444_packet_scratch_pad_t *pkt_scratch_pad) + * + * DESCRIPTION + * This function is used to scrub the packet scratch pad + * prior to parsing a RFC5444 packet. + * + * INPUT PARAMETERS + * scratch_pad - This is a pointer to the scratch pad area + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +rfc5444_scrub_packet_scratch_pad ( + rfc5444_packet_scratch_pad_t *pkt_scratch_pad) +{ +printf("rfc5444_srcub_packet_scratch\n"); + if (!pkt_scratch_pad) { + return; + } + + pkt_scratch_pad->sequence = 0; + pkt_scratch_pad->sequence_present = FALSE; + + pkt_scratch_pad->router_id = 0; + pkt_scratch_pad->router_id_present = FALSE; + + pkt_scratch_pad->client_id = 0; + pkt_scratch_pad->client_id_present = FALSE; + + pkt_scratch_pad->peer_heartbeat_interval = 0; + pkt_scratch_pad->peer_heartbeat_interval_present = FALSE; + + return; +} + +#if 0 +/* Below two init functions are added for DLEPv7 */ +static uint32_t init_optional_signal(void) { + + uint32_t opt_signal = 0; + + opt_signal |= (~(~0 << (RFC5444_MAX_MESSAGE_CODE - 1))); + + opt_signal &= (~(1 << RFC5444_MSG_PEER_UPDATE_RES)); + opt_signal &= (~(1 << RFC5444_MSG_LINK_CHAR_RES)); + + return opt_signal; +} + +static uint32_t init_optional_data_item(void) { + + uint32_t opt_data = 0; + + opt_data |= (~(~0 << (RFC5444_MAX_DATA_ITEM - 1))); + + opt_data &= (~(1 << RFC5444_TLV_LINK_RESOURCES_METRIC_RX)); + opt_data &= (~(1 << RFC5444_TLV_LINK_RESOURCES_METRIC_TX)); + opt_data &= (~(1 << RFC5444_TLV_CREDIT_WINDOW_STATUS)); + opt_data &= (~(1 << RFC5444_TLV_CREDIT_GRANT)); + opt_data &= (~(1 << RFC5444_TLV_CREDIT_REQUEST)); + opt_data &= (~(1 << RFC5444_TLV_VENDOR_EXTENSION)); + opt_data &= (~(1 << RFC5444_TLV_IPV4_ATTACHED_SUBNET)); + opt_data &= (~(1 << RFC5444_TLV_IPV6_ATTACHED_SUBNET)); + + return opt_data; +} +#endif +/** + * NAME + * rfc5444_scrub_message_scratch_pad + * + * SYNOPSIS + * #include "rfc5444_scratch_pad.h" + * void + * rfc5444_scrub_message_scratch_pad( + * rfc5444_message_scratch_pad_t *msg_scratch_pad) + * + * DESCRIPTION + * This function is used to scrub the message scratch pad + * prior to parsing a RFC5444 message. + * + * INPUT PARAMETERS + * scratch_pad - This is a pointer to the scratch pad area + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +rfc5444_scrub_message_scratch_pad ( + rfc5444_message_scratch_pad_t *msg_scratch_pad) +{ + if (!msg_scratch_pad) { + return; + } + + msg_scratch_pad->message_code = 0; + + msg_scratch_pad->major_version = 0; + msg_scratch_pad->major_version_present = FALSE; + + msg_scratch_pad->minor_version = 0; + msg_scratch_pad->minor_version_present = FALSE; + + msg_scratch_pad->sequence = 0; + msg_scratch_pad->sequence_present = FALSE; + + msg_scratch_pad->status_code = 0; + msg_scratch_pad->status_code_present = 0; + + mac_zero_address(msg_scratch_pad->mac_address); + msg_scratch_pad->mac_address_present = FALSE; + + ipv4_zero_address(&msg_scratch_pad->ipv4_address); + msg_scratch_pad->ipv4_address_present = FALSE; + + ipv6_zero_address(&msg_scratch_pad->ipv6_address); + msg_scratch_pad->ipv6_address_present = FALSE; + + strcpy(msg_scratch_pad->peer_type_description, " "); + msg_scratch_pad->peer_type_description[ + RFC5444_TLV_PEER_TYPE_MAX_LENGTH]='\0'; + + msg_scratch_pad->rlq_tx = 0; + msg_scratch_pad->rlq_rx = 0; + msg_scratch_pad->rlq_present = FALSE; + + msg_scratch_pad->resources = 0; + msg_scratch_pad->resources_present = FALSE; + + msg_scratch_pad->latency = 0; + msg_scratch_pad->latency_present = FALSE; + + msg_scratch_pad->cdr_tx = 0; + msg_scratch_pad->cdr_rx = 0; + msg_scratch_pad->cdr_present = FALSE; + + msg_scratch_pad->mdr_tx = 0; + msg_scratch_pad->mdr_rx = 0; + msg_scratch_pad->mdr_present = FALSE; + + msg_scratch_pad->mtu = 0; + msg_scratch_pad->mtu_present = FALSE; + +#if 0 +/* Below code is added for DLEPv7 */ + msg_scratch_pad->dlepv7_optional_signal = init_optional_signal(); + msg_scratch_pad->dlepv7_optional_data_item = init_optional_data_item(); +#endif + return; +} diff --git a/dlep_radio_ipv6/rfc5444_scratch_pad.h b/dlep_radio_ipv6/rfc5444_scratch_pad.h new file mode 100644 index 0000000..19656ae --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_scratch_pad.h @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------- + * rfc5444_scratch_pad.h -- data to manage parsed data + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __RFC5444_SCRATCH_PAD_H__ +#define __RFC5444_SCRATCH_PAD_H__ + +#include "safe_types.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" + +#include "rfc5444_types.h" + + + +/* + * message scratch pad - when a message is parsed, its + * data is first saved here so the peer or neighbor can + * be looked up. The required and optional TLVs can + * also be managed. + */ +typedef struct { + uint16_t sequence; + boolean_t sequence_present; + + uint32_t router_id; + boolean_t router_id_present; + + uint32_t client_id; + boolean_t client_id_present; + + uint8_t peer_heartbeat_interval; + boolean_t peer_heartbeat_interval_present; + +} rfc5444_packet_scratch_pad_t; + + + +/* + * message scratch pad - when a message is parsed, its + * data is first saved here so the peer or neighbor can + * be looked up. The required and optional TLVs can + * also be managed. + */ +typedef struct { + uint16_t message_code; + + uint16_t sequence; + boolean_t sequence_present; + + uint8_t major_version; + boolean_t major_version_present; + + uint8_t minor_version; + boolean_t minor_version_present; + + uint16_t status_code; + boolean_t status_code_present; + + uint8_t mac_address[MAC_ADDR_LEN_IN_BYTES]; + boolean_t mac_address_present; + + ipv4_address_t ipv4_address; + ipv4_address_t ipv4_attached_subnet; + uint8_t ipv4_operation; + boolean_t ipv4_address_present; + + ipv6_address_t ipv6_address; + ipv6_address_t ipv6_attached_subnet; + uint8_t ipv6_operation; + boolean_t ipv6_address_present; + + char peer_type_description[RFC5444_TLV_PEER_TYPE_MAX_LENGTH+1]; + + /* metrics */ + boolean_t rlq_present; + uint8_t rlq_tx; + uint8_t rlq_rx; + + boolean_t resources_present; + uint8_t resources_tx; + uint8_t resources_rx; + uint8_t resources; /* addded for v27 */ + + boolean_t latency_present; + uint64_t latency; + + boolean_t cdr_present; + uint64_t cdr_tx; + uint64_t cdr_rx; + + boolean_t mdr_present; + uint64_t mdr_tx; + uint64_t mdr_rx; + + uint16_t port; + uint32_t eft; + + boolean_t cws_present; + uint64_t mrw; + uint64_t rrw; + uint64_t cgr; + + boolean_t credit_req_present; + + uint32_t hbt; + + boolean_t mtu_present; + uint16_t mtu; /* added for v27 */ + +#if 0 + uint32_t dlepv7_optional_signal; + uint32_t dlepv7_optional_data_item; +#endif + +} rfc5444_message_scratch_pad_t; + + +extern void +rfc5444_show_packet_scratch_pad( + rfc5444_packet_scratch_pad_t *pkt_scratch_pad); + +extern void +rfc5444_show_message_scratch_pad( + rfc5444_message_scratch_pad_t *msg_scratch_pad); + +extern void +rfc5444_scrub_packet_scratch_pad( + rfc5444_packet_scratch_pad_t *pkt_scratch_pad); + +extern void +rfc5444_scrub_message_scratch_pad( + rfc5444_message_scratch_pad_t *msg_scratch_pad); + +#endif + + diff --git a/dlep_radio_ipv6/rfc5444_types.h b/dlep_radio_ipv6/rfc5444_types.h new file mode 100644 index 0000000..f57b0b2 --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_types.h @@ -0,0 +1,292 @@ +/*------------------------------------------------------------------ + * rfc5444_types.h -- RFC5444 types + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef ___RFC5444_TYPES__ +#define ___RFC5444_TYPES__ + + +#include "rfc5444_api_rc.h" + + + +#define SECONDS_TO_MILLISECONDS ( 1000 ) + + + +/* reasonable bounds for good measure */ +#define RFC5444_MIN_PACKET_LEN ( 3 ) +#define RFC5444_MAX_PACKET_LEN ( 1400 ) + +#define RFC5444_MIN_MESSAGE_LEN ( 3 ) +#define RFC5444_MAX_MESSAGE_LEN ( 500 ) + + + +/* + * packet header flag definitions + */ +#define PHASSEQNUM ( 0x08 ) /* ignored */ +#define PHASTLV ( 0x04 ) + +/* + * message header flag definitions + */ +#define MHASHORIG ( 0x80 ) /* not supported */ +#define MHASHOPLIMIT ( 0x40 ) /* not supported */ +#define MHASHOPCOUNT ( 0x20 ) /* not supported */ +#define MHASSEQNUM ( 0x10 ) +#define MHASADDRLEN ( 0x03 ) /* not supported */ + +/* + * TLV flag definitions + */ +#define THASTYPEEXT ( 0x80 ) /* not supported */ +#define THASSINGLEINDEX ( 0x40 ) /* not supported */ +#define THASMULTIINDEX ( 0x20 ) /* not supported */ +#define THASVALUE ( 0x10 ) +#define THASEXTLEN ( 0x08 ) +#define THASMULTIVALUE ( 0x04 ) /* not supported */ + + +/* + * Signal header flags + */ +#define DLEP_SIGNAL_FLAGS (0x444C4550) + +/* + * Status codes used in the Status TLV. + */ +typedef enum { + RFC5444_SUCCESS = 0, + RFC5444_ERROR, + RFC5444_REQUEST_DENIED = 2, + RFC5444_MSG_UNKNOWN = 128, + RFC5444_MSG_UNEXPECTED = 129, + RFC5444_INVALID_DATA = 130, + RFC5444_INVALID_DESTINATION = 131, + RFC5444_MSG_TIMEOUT = 132, +} rfc5444_status_code_type_t; + + +/* + * The max value for RLQ and Resources + */ +#define RFC5444_100_PERCENT ( 100 ) + +/* DLEP version implemented and supported */ +#define RFC5444_DLEP_MAJOR_VERSION ( 1 ) +#define RFC5444_DLEP_MINOR_VERSION ( 7 ) + + +/* + * When the TLV vector table is allocated, we add one to + * the max to account for the 0 based array. The TLV + * code is the index straight-up. 0--invalid, 1-255 valid. + */ +#define RFC5444_MAX_TLV_CODE ( 255 ) + + +/* + * RFC5444 TLV Codes + ***FIX - TLV codes to be defined with IANA + */ +typedef enum { + RFC5444_TLV_RESERVED = 0, + RFC5444_TLV_STATUS = 1, + RFC5444_TLV_IPV4_CONNECTION_POINT = 2, + RFC5444_TLV_IPV6_CONNECTION_POINT = 3, + RFC5444_TLV_PEER_TYPE = 4, + RFC5444_TLV_HEARTBEAT_INTERVAL = 5, + RFC5444_TLV_EXTENSION_SUPPORTED = 6, + + RFC5444_TLV_MAC_ADDRESS = 7, + RFC5444_TLV_IPV4_ADDRESS = 8, + RFC5444_TLV_IPV6_ADDRESS = 9, + RFC5444_TLV_IPV4_ATTACHED_SUBNET = 10, + RFC5444_TLV_IPV6_ATTACHED_SUBNET = 11, + + RFC5444_TLV_LINK_MDR_METRIC_RX = 12, + RFC5444_TLV_LINK_MDR_METRIC_TX = 13, + RFC5444_TLV_LINK_CDR_METRIC_RX = 14, + RFC5444_TLV_LINK_CDR_METRIC_TX = 15, + RFC5444_TLV_LINK_LATENCY_METRIC = 16, + RFC5444_TLV_LINK_RESOURCES_METRIC = 17, + RFC5444_TLV_LINK_RLQ_METRIC_RX = 18, + RFC5444_TLV_LINK_RLQ_METRIC_TX = 19, + + RFC5444_TLV_MTU = 20, + + RFC5444_MAX_DATA_ITEM = 21, + /* added to avoid build error of 27 since existing v7 needs below */ + RFC5444_TLV_VERSION, + RFC5444_TLV_PORT, + RFC5444_TLV_LINK_RESOURCES_METRIC_RX , + RFC5444_TLV_LINK_RESOURCES_METRIC_TX , + RFC5444_TLV_LINK_EFT_METRIC , + RFC5444_TLV_CREDIT_WINDOW_STATUS , + RFC5444_TLV_CREDIT_GRANT , + RFC5444_TLV_CREDIT_REQUEST , + RFC5444_TLV_VENDOR_EXTENSION, + RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED , + RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED , +} rfc5444_tlv_t; + + +/* + * Flag values used to encode and decode TLVs + */ +#define RFC5444_TLV_IDENTIFICATION_FLAGS ( 0x10 ) +#define RFC5444_TLV_VERSION_FLAGS ( 0x10 ) +#define RFC5444_TLV_PEER_TYPE_FLAGS ( 0x00 ) + +#define RFC5444_TLV_MAC_ADDRESS_FLAGS ( 0x10 ) +#define RFC5444_TLV_IPV4_ADDRESS_FLAGS ( 0x10 ) +#define RFC5444_TLV_IPV6_ADDRESS_FLAGS ( 0x10 ) + +#define RFC5444_TLV_LINK_METRIC_MDR_FLAGS ( 0x10 ) +#define RFC5444_TLV_LINK_METRIC_CDR_FLAGS ( 0x10 ) +#define RFC5444_TLV_LINK_METRIC_LATENCY_FLAGS ( 0x10 ) +#define RFC5444_TLV_LINK_METRIC_RESOURCES_FLAGS ( 0x10 ) +#define RFC5444_TLV_LINK_METRIC_RLQ_FLAGS ( 0x10 ) + +#define RFC5444_TLV_STATUS_FLAGS ( 0x10 ) +#define RFC5444_TLV_IPV4_CONNECTION_POINT_FLAGS ( 0x00 ) + +/* + * Lengths (bytes) used to encode and decode TLVs + */ +#define RFC5444_TLV_IDENTIFICATION_LENGTH ( 9 ) +#define RFC5444_TLV_VERSION_LENGTH ( 4 ) + + /* string length <= 80 */ +#define RFC5444_TLV_PEER_TYPE_MAX_LENGTH ( 160 ) + +#define RFC5444_TLV_MAC_ADDRESS_LENGTH ( 6 ) +#define RFC5444_TLV_IPV4_ADDRESS_LENGTH ( 5 ) /* + operation */ +#define RFC5444_TLV_IPV6_ADDRESS_LENGTH ( 17 ) /* + operation */ + +#define RFC5444_TLV_LINK_METRIC_MDR_LENGTH ( 8 ) +#define RFC5444_TLV_LINK_METRIC_CDR_LENGTH ( 8 ) +#define RFC5444_TLV_LINK_METRIC_LATENCY_LENGTH ( 8 ) +#define RFC5444_TLV_LINK_METRIC_RESOURCES_LENGTH ( 1 ) +#define RFC5444_TLV_LINK_METRIC_RLQ_LENGTH ( 1 ) +#define RFC5444_TLV_LINK_METRIC_EFT_LENGTH ( 4 ) +#define RFC5444_TLV_PORT_LENGTH ( 2 ) +#define RFC5444_TLV_CREDIT_WINDOW_STATUS_LENGTH ( 16 ) +#define RFC5444_TLV_STATUS_LENGTH ( 1 ) +#define RFC5444_TLV_CREDIT_GRANT_LENGTH ( 8 ) +#define RFC5444_TLV_CREDIT_REQUEST_LENGTH ( 1 ) +#define RFC5444_TLV_HEARTBEAT_INTERVAL_LENGTH ( 4 ) +#define RFC5444_TLV_MTU_LENGTH ( 2 ) +#define RFC5444_TLV_IPV4_CONNECTION_POINT_LENGTH ( 7 ) + +/* Below TLV's length are added for DLEPv7 */ +#define RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED_LENGTH ( 6 ) +#define RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED_LENGTH ( 12 ) +/* +Length (3) + OUI length(1) + VENDOR OUI (3 octets) ++ DEVICE TYPE (2) + PAYLOAD length (6 (T + L + V) = 15 +*/ +#define RFC5444_TLV_VENDOR_EXTENSION_LENGTH ( 15 ) +#define RFC5444_TLV_IPV4_ATTACHED_SUBNET_LENGTH ( 6 ) +#define RFC5444_TLV_IPV6_ATTACHED_SUBNET_LENGTH ( 18 ) + +/* For VENDOR EXTENSION TLV in DLEPv7 */ +#define VENDOR_OUI_LENGTH ( 3 ) +#define VENDOR_SPECIFIC_PAYLOAD_TYPE ( 30 ) +#define VENDOR_SPECIFIC_PAYLOAD_LENGTH 4 + +/* + * IPv4/6 addresses can be added or dropped by the + * RFC5444_MSG_NEIGHBOR_ADDRESS message. + */ +#define RFC5444_NO_ADDRESS ( 0x02 ) /* added to avoid error */ +#define RFC5444_EXISTING_ADD_ADDRESS ( 0x01 ) +#define RFC5444_DROP_ADDRESS ( 0x00 ) + + + + +/* + * RFC5444 Router-Radio Message codes + ***FIX - message codes to be defined with IANA + */ + +typedef enum { + RFC5444_SIG_RESERVED = 0, + + RFC5444_SIG_ATT_PEER_DISCOVERY, + + RFC5444_SIG_PEER_OFFER, + + RFC5444_MAX_SIGNAL_CODE +} rfc5444_sig_type_t; + +typedef enum { + RFC5444_MSG_RESERVED = 0, + + RFC5444_MSG_PEER_INIT_REQ, + RFC5444_MSG_PEER_INIT_RES, + + + RFC5444_MSG_PEER_UPDATE_REQ, + RFC5444_MSG_PEER_UPDATE_RES, + + RFC5444_MSG_PEER_TERM_REQ, + RFC5444_MSG_PEER_TERM_RES, + + RFC5444_MSG_NEIGHBOR_UP_REQ, + RFC5444_MSG_NEIGHBOR_UP_RES, + + RFC5444_MSG_NEIGHBOR_ANNOUNCE_REQ, + RFC5444_MSG_NEIGHBOR_ANNOUNCE_RES, + + RFC5444_MSG_NEIGHBOR_DOWN_REQ, + RFC5444_MSG_NEIGHBOR_DOWN_RES, + + RFC5444_MSG_NEIGHBOR_METRICS, + + RFC5444_MSG_LINK_CHAR_REQ, + RFC5444_MSG_LINK_CHAR_RES, + + RFC5444_MSG_PEER_HEARTBEAT, + + RFC5444_MAX_MESSAGE_CODE, + /* added to avoid build errors */ + RFC5444_MSG_DET_PEER_DISCOVERY, + RFC5444_MSG_NEIGHBOR_ADDRESS_REQ, + RFC5444_MSG_NEIGHBOR_ADDRESS_RES, + +} rfc5444_msg_type_t; + + +#endif + diff --git a/dlep_radio_ipv6/rfc5444_utils.c b/dlep_radio_ipv6/rfc5444_utils.c new file mode 100644 index 0000000..6c515db --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_utils.c @@ -0,0 +1,400 @@ +/*---------------------------------------------------------------------- + * rfc5444_utils.c -- RFC5444 utils + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#include + +#include "safe_types.h" +#include "rfc5444_types.h" + +#include "rfc5444_utils.h" + + +/** + * NAME + * r2rc2string + * + * SYNOPSIS + * #include "rfc5444_utils.h" + * char + * *rfc5444_rc2string(uint32_t rc) + * + * DESCRIPTION + * This function converts a RFC5444 return code to a string + * for display. + * + * INPUT PARAMETERS + * rc - The return code to be converted to a string + * + * OUTPUT PARAMETERS + * None + * + * RETURN VALUE + * A pointer to a string description of the return code + * + */ +char +*rfc5444_rc2string (uint32_t rc) +{ +printf("rfc5444_rc2string\n"); + char *p2text; + + switch (rc) { + + case RC_RFC5444_OK: + p2text = "RC_RFC5444_OK"; + break; + + case RC_RFC5444_NULL_POINTER: + p2text = "RC_RFC5444_NULL_POINTER"; + break; + + case RC_RFC5444_NO_RESOURCES: + p2text = "RC_RFC5444_NO_RESOURCES"; + break; + + case RC_RFC5444_STATE_ERROR: + p2text = "RC_RFC5444_STATE_ERROR"; + break; + + case RC_RFC5444_VERSION_ERROR: + p2text = "RC_RFC5444_VERSION_ERROR"; + break; + + case RC_RFC5444_INVALID_PACKET_HEADER: + p2text = "RC_RFC5444_INVALID_PACKET_HEADER"; + break; + + case RC_RFC5444_INVALID_PACKET_LENGTH: + p2text = "RC_RFC5444_INVALID_PACKET_LENGTH"; + break; + + case RC_RFC5444_INVALID_BLOCK_INDICATOR: + p2text = "RC_RFC5444_INVALID_BLOCK_INDICATOR"; + break; + + case RC_RFC5444_INVALID_MESSAGE_FLAG: + p2text = "RC_RFC5444_INVALID_MESSAGE_FLAG"; + break; + + case RC_RFC5444_INVALID_MESSAGE_MAL: + p2text = "RC_RFC5444_INVALID_MESSAGE_MAL"; + break; + + case RC_RFC5444_INVALID_MESSAGE_LENGTH: + p2text = "RC_RFC5444_INVALID_MESSAGE_LENGTH"; + break; + + case RC_RFC5444_INVALID_MESSAGE_SEQUENCE: + p2text = "RC_RFC5444_INVALID_MESSAGE_SEQUENCE"; + break; + + case RC_RFC5444_INVALID_MESSAGE_CODE: + p2text = "RC_RFC5444_INVALID_MESSAGE_CODE"; + break; + + case RC_RFC5444_INVALID_TLV_BLOCK_LENGTH: + p2text = "RC_RFC5444_INVALID_TLV_BLOCK_LENGTH"; + break; + + case RC_RFC5444_UNKNOWN_TLV_CODE: + p2text = "RC_RFC5444_UNKNOWN_TLV_CODE"; + break; + + case RC_RFC5444_INVALID_TLV_FLAG: + p2text = "RC_RFC5444_INVALID_TLV_FLAG"; + break; + + case RC_RFC5444_INVALID_TLV_LENGTH: + p2text = "RC_RFC5444_INVALID_TLV_LENGTH"; + break; + + default: + p2text = "RFC5444_UNKNOWN_RETURN_CODE"; + break; + } + return (p2text); +} + + +/** + * NAME + * rfc5444_tlv_code2string + * + * SYNOPSIS + * #include "rfc5444_utils.h" + * char + * *rfc5444_tlv_code2string(uint8_t tlv_code) + * + * DESCRIPTION + * This function converts a RFC5444 TLV code to a string + * for display. + * + * INPUT PARAMETERS + * tlv_code - The code to be converted to a string + * + * OUTPUT PARAMETERS + * None + * + * RETURN VALUE + * A pointer to a string description of the TLV code + * + */ +char +*rfc5444_tlv_code2string (uint16_t tlv_code) +{ +printf("rfc5444_tlv_code2string\n"); + char *p2text; + + switch (tlv_code) { +#if 0 + case RFC5444_TLV_IDENTIFICATION: + p2text = "RFC5444_TLV_IDENTIFICATION"; + break; +#endif + case RFC5444_TLV_VERSION: + p2text = "RFC5444_TLV_VERSION"; + break; + + case RFC5444_TLV_PORT: + p2text = "RFC5444_TLV_PORT"; + break; + + case RFC5444_TLV_PEER_TYPE: + p2text = "RFC5444_TLV_PEER_TYPE"; + break; + + case RFC5444_TLV_MAC_ADDRESS: + p2text = "RFC5444_TLV_MAC_ADDRESS"; + break; + + case RFC5444_TLV_IPV4_ADDRESS: + p2text = "RFC5444_TLV_IPV4_ADDRESS"; + break; + + case RFC5444_TLV_IPV6_ADDRESS: + p2text = "RFC5444_TLV_IPV6_ADDRESS"; + break; + + case RFC5444_TLV_LINK_MDR_METRIC_TX: + p2text = "RFC5444_TLV_LINK_MDR_TX_METRIC"; + break; + + case RFC5444_TLV_LINK_MDR_METRIC_RX: + p2text = "RFC5444_TLV_LINK_MDR_RX_METRIC"; + break; + + case RFC5444_TLV_LINK_CDR_METRIC_TX: + p2text = "RFC5444_TLV_LINK_CDR_TX_METRIC"; + break; + + case RFC5444_TLV_LINK_CDR_METRIC_RX: + p2text = "RFC5444_TLV_LINK_CDR_RX_METRIC"; + break; + + case RFC5444_TLV_LINK_LATENCY_METRIC: + p2text = "RFC5444_TLV_LINK_LATENCY_METRIC"; + break; + + case RFC5444_TLV_LINK_RESOURCES_METRIC_TX: + p2text = "RFC5444_TLV_LINK_RESOURCES_TX_METRIC"; + break; + + case RFC5444_TLV_LINK_RESOURCES_METRIC_RX: + p2text = "RFC5444_TLV_LINK_RESOURCES_RX_METRIC"; + break; + + case RFC5444_TLV_LINK_RLQ_METRIC_TX: + p2text = "RFC5444_TLV_LINK_RLQ_METRIC"; + break; + + case RFC5444_TLV_LINK_RLQ_METRIC_RX: + p2text = "RFC5444_TLV_LINK_RLQ_RX_METRIC"; + break; + + case RFC5444_TLV_HEARTBEAT_INTERVAL: + p2text = "RFC5444_TLV_HEARTBEAT_INTERVAL"; + break; + + case RFC5444_TLV_STATUS: + p2text = "RFC5444_TLV_STATUS"; + break; + + case RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED: + p2text = "RFC5444_TLV_OPTIONAL_SIGNAL_SUPPORTED"; + break; + + case RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED: + p2text = "RFC5444_TLV_OPTIONAL_DATA_ITEM_SUPPORTED"; + break; + + case RFC5444_TLV_VENDOR_EXTENSION: + p2text = "RFC5444_TLV_VENDOR_EXTENSION"; + break; + + case RFC5444_TLV_IPV4_ATTACHED_SUBNET: + p2text = "RFC5444_TLV_IPV4_ATTACHED_SUBNET"; + break; + + case RFC5444_TLV_IPV6_ATTACHED_SUBNET: + p2text = "RFC5444_TLV_IPV6_ATTACHED_SUBNET"; + break; + + /* added for dlepv 27 */ + + case RFC5444_TLV_LINK_RESOURCES_METRIC: + p2text = "RFC5444_TLV_LINK_RESOURCES_METRIC"; + break; + + case RFC5444_TLV_MTU: + p2text = "RFC5444_TLV_MTU"; + break; + + default: + p2text = "RFC5444_UNKNOWN_TLV_CODE"; + break; + } + return (p2text); +} + + +/** + * NAME + * rfc5444_message_code2string + * + * SYNOPSIS + * #include "rfc5444_utils.h" + * char + * *rfc5444_message_code2string(uint8_t message_code) + * + * DESCRIPTION + * This function converts a RFC5444 message code to a string + * for display. + * + * INPUT PARAMETERS + * message_code - The message code to be converted to a string + * + * OUTPUT PARAMETERS + * None + * + * RETURN VALUE + * A pointer to a string description of the message code + * + */ +char +*rfc5444_message_code2string (uint16_t message_code) +{ +printf("rfc5444_message_code2string"); + char *p2text; + + switch (message_code) { + /* case RFC5444_SIG_ATT_PEER_DISCOVERY: + p2text = "RFC5444_SIG_ATT_PEER_DISCOVERY"; + break; */ + + case RFC5444_MSG_DET_PEER_DISCOVERY: + p2text = "RFC5444_MSG_DET_PEER_DISCOVERY"; + break; + + /* case RFC5444_SIG_PEER_OFFER: + p2text = "RFC5444_SIG_PEER_OFFER"; + break; */ + + case RFC5444_MSG_PEER_INIT_REQ: + p2text = "RFC5444_MSG_PEER_INIT_REQ"; + break; + + case RFC5444_MSG_PEER_INIT_RES: + p2text = "RFC5444_MSG_PEER_INIT_RES"; + break; + + case RFC5444_MSG_PEER_HEARTBEAT: + p2text = "RFC5444_MSG_PEER_HEARTBEAT"; + break; + + case RFC5444_MSG_PEER_UPDATE_REQ: + p2text = "RFC5444_MSG_PEER_UPDATE_REQ"; + break; + + case RFC5444_MSG_PEER_UPDATE_RES: + p2text = "RFC5444_MSG_PEER_UPDATE_RES"; + break; + + case RFC5444_MSG_PEER_TERM_REQ: + p2text = "RFC5444_MSG_PEER_TERM_REQ"; + break; + + case RFC5444_MSG_PEER_TERM_RES: + p2text = "RFC5444_MSG_PEER_TERM_RES"; + break; + + case RFC5444_MSG_NEIGHBOR_UP_REQ: + p2text = "RFC5444_MSG_NEIGHBOR_UP_REQ"; + break; + + case RFC5444_MSG_NEIGHBOR_UP_RES: + p2text = "RFC5444_MSG_NEIGHBOR_UP_RES"; + break; + + case RFC5444_MSG_NEIGHBOR_DOWN_REQ: + p2text = "RFC5444_MSG_NEIGHBOR_DOWN_REQ"; + break; + + case RFC5444_MSG_NEIGHBOR_DOWN_RES: + p2text = "RFC5444_MSG_NEIGHBOR_DOWN_RES"; + break; + + case RFC5444_MSG_NEIGHBOR_METRICS: + p2text = "RFC5444_MSG_NEIGHBOR_METRICS"; + break; + + case RFC5444_MSG_NEIGHBOR_ADDRESS_REQ: + p2text = "RFC5444_MSG_NEIGHBOR_ADDRESS_REQ"; + break; + + case RFC5444_MSG_NEIGHBOR_ADDRESS_RES: + p2text = "RFC5444_MSG_NEIGHBOR_ADDRESS_RES"; + break; + + case RFC5444_MSG_LINK_CHAR_REQ: + p2text = "RFC5444_MSG_LINK_CHAR_REQ"; + break; + + case RFC5444_MSG_LINK_CHAR_RES: + p2text = "RFC5444_MSG_LINK_CHAR_RES"; + break; + + default: + p2text = "RFC5444_UNKNOWN_MESSAGE_CODE"; + break; + } + return (p2text); +} + diff --git a/dlep_radio_ipv6/rfc5444_utils.h b/dlep_radio_ipv6/rfc5444_utils.h new file mode 100644 index 0000000..bce8a1e --- /dev/null +++ b/dlep_radio_ipv6/rfc5444_utils.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------- + * rfc5444_utils.h -- utility prototypes + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +#ifndef __RFC5444_UTILS_H__ +#define __RFC5444_UTILS_H__ + +#include "safe_types.h" + + +extern char *rfc5444_rc2string(uint32_t rc); + +extern char *rfc5444_tlv_code2string(uint16_t tlv_code); + +extern char *rfc5444_message_code2string(uint16_t message_code); + +#endif + diff --git a/dlep_radio_ipv6/runtime_environment.h b/dlep_radio_ipv6/runtime_environment.h new file mode 100644 index 0000000..5971b60 --- /dev/null +++ b/dlep_radio_ipv6/runtime_environment.h @@ -0,0 +1,41 @@ +/*------------------------------------------------------------------ + * runtime_environment.h -- Abstractions + * + * Februrary 2002, Bo Berry + * + * Copyright (c) 2002-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __RUNTIME_ENVIRONMENT_H__ +#define __RUNTIME_ENVIRONMENT_H__ + + +#define LOCK_INTERRUPTS() +#define UNLOCK_INTERRUPTS() + + +#endif + diff --git a/dlep_radio_ipv6/safe_limits.h b/dlep_radio_ipv6/safe_limits.h new file mode 100644 index 0000000..b028026 --- /dev/null +++ b/dlep_radio_ipv6/safe_limits.h @@ -0,0 +1,195 @@ +/*------------------------------------------------------------------ + * safe_limits.h + * + * February 2009, Bo Berry + * + * Copyright (c) 2009-2011 by Cisco Systems + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __SAFE_LIMITS__ +#define __SAFE_LIMITS__ + +/* + * Abstract header file for portability. + */ + + +/* + * ANSI C - number of bits by type + */ +#ifndef CHAR_BIT +#define CHAR_BIT ( 8 ) +#endif + +#ifndef BYTE_BIT +#define BYTE_BIT ( 8 ) +#endif + +#ifndef SHORT_BIT +#define SHORT_BIT ( 16 ) +#endif + +#ifndef INT_BIT +#define INT_BIT ( 32 ) +#endif + +#ifndef LONG_BIT +// #define LONG_BIT ( 32 ) +#define LONG_BIT ( 64 ) +#endif + +#ifndef LONG_LONG_BIT +#define LONG_LONG_BIT ( 64 ) +#endif + +#ifndef POINTER_BIT +#define POINTER_BIT ( 64 ) +#endif + + + +#ifndef BYTE_MAX +#define BYTE_MAX ( 255 ) +#endif + +#ifndef SCHAR_MAX +#define SCHAR_MAX ( 127 ) +#define SCHAR_MIN ( -SCHAR_MAX - 1 ) +#endif + +#ifndef CHAR_MAX +#define CHAR_MAX ( 127 ) +#define CHAR_MIN ( -CHAR_MAX - 1 ) +#endif + +#ifndef UCHAR_MAX +#define UCHAR_MAX ( 0xff ) +#endif + +#ifndef SHRT_MAX +#define SHRT_MAX ( 32767 ) +#define SHRT_MIN ( -SHRT_MAX - 1 ) +#endif + +#ifndef USHRT_MAX +#define USHRT_MAX ( 0xffff ) +#endif + +#ifndef INT_MAX +#define INT_MAX ( 2147483647 ) +#define INT_MIN ( -INT_MAX - 1 ) +#endif + +#ifndef UINT_MAX +#define UINT_MAX ( 0xffffffff ) +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX ( 9223372036854775807 ) +#define LLONG_MIN ( -LLONG_MAX - 1 ) +#endif + +#ifndef ULLONG_MAX +#define ULLONG_MAX ( 0xffffffffffffffff ) +#endif + + +#if LONG_BIT == INT_BIT + +#ifndef LONG_MAX +#define LONG_MAX ( INT_MAX) +#define LONG_MIN ( -LONG_MAX - 1 ) +#endif + +#ifndef ULONG_MAX +#define ULONG_MAX ( UINT_MAX ) +#endif + +#else + +#ifndef LONG_MAX +#define LONG_MAX ( LLONG_MAX) +#define LONG_MIN ( -LONG_MAX - 1 ) +#endif + +#ifndef ULONG_MAX +#define ULONG_MAX ( ULLONG_MAX ) +#endif + +#endif + + +#ifndef INT8_MIN +#define INT8_MIN ( SCHAR_MIN ) +#endif + +#ifndef INT8_MAX +#define INT8_MAX ( SCHAR_MAX ) +#endif + +#ifndef UINT8_MAX +#define UINT8_MAX ( UCHAR_MAX ) +#endif + +#ifndef INT16_MIN +#define INT16_MIN ( SHRT_MIN ) +#endif + +#ifndef INT16_MAX +#define INT16_MAX ( SHRT_MAX ) +#endif + +#ifndef UINT16_MAX +#define UINT16_MAX ( USHRT_MAX ) +#endif + +#ifndef INT32_MIN +#define INT32_MIN ( INT_MIN ) +#endif + +#ifndef INT32_MAX +#define INT32_MAX ( INT_MAX ) +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX ( UINT_MAX ) +#endif + +#ifndef INT64_MIN +#define INT64_MIN ( LLONG_MIN ) +#endif + +#ifndef INT64_MAX +#define INT64_MAX ( LLONG_MAX ) +#endif + +#ifndef UINT64_MAX +#define UINT64_MAX ( ULLONG_MAX ) +#endif + + +#endif /* __SAFE_LIMITS__ */ + diff --git a/dlep_radio_ipv6/safe_types.h b/dlep_radio_ipv6/safe_types.h new file mode 100644 index 0000000..eafaa0a --- /dev/null +++ b/dlep_radio_ipv6/safe_types.h @@ -0,0 +1,139 @@ +/*------------------------------------------------------------------ + * safe_types.h + * + * March 2007, Bo Berry + * + * Copyright (c) 2007-2011 by Cisco Systems, Inc + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __SAFE_TYPES__ +#define __SAFE_TYPES__ + +#include + +#include "safe_limits.h" + + +/* + * Abstract header file for portability. + */ + +#ifndef TRUE +#define TRUE ( 1 ) +#endif + +#ifndef FALSE +#define FALSE ( 0 ) +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#ifndef boolean_t +typedef unsigned char boolean_t; +#endif + + + +#ifndef int8_t +typedef signed char int8_t; +#endif + +#ifndef int16_t +typedef short int16_t; +#endif + +#ifndef int32_t +typedef int int32_t; +#endif + +#ifndef uchar_t +typedef unsigned char uchar_t; +#endif + +#ifndef uint8_t +typedef unsigned char uint8_t; +#endif + +#ifndef uint16_t +typedef unsigned short uint16_t; +#endif + +#ifndef uint32_t +typedef unsigned int uint32_t; +#endif + +#ifndef uint64_t +//typedef unsigned long long uint64_t; +#endif + +#if 0 +#if POINTER_BIT == 64 +#ifndef intptr_t; +typedef long long intptr_t; +#endif + +#ifndef uintptr_t; +typedef unsigned long long uintptr_t; +#endif + +#else + +#ifndef intptr_t; +typedef signed int intptr_t; +#endif +#ifndef uintptr_t; +typedef unsigned int uintptr_t; +#endif + +#endif +#endif + + +#ifndef ushort +typedef unsigned short ushort; +#endif + +#ifndef int_t +typedef int int_t; +#endif + +#ifndef uint_t +typedef unsigned int uint_t; +#endif + +#ifndef ulong +typedef unsigned long ulong; +#endif + +#ifndef ulonglong +typedef unsigned long long ullong; +#endif + + +#endif /* __SAFE_TYPES__ */ + diff --git a/dlep_radio_ipv6/sim_dlep_radio.c b/dlep_radio_ipv6/sim_dlep_radio.c new file mode 100644 index 0000000..ae45a8b --- /dev/null +++ b/dlep_radio_ipv6/sim_dlep_radio.c @@ -0,0 +1,511 @@ +/*---------------------------------------------------------------------- + * sim_dlep_radio.c -- Radio simulator + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *--------------------------------------------------------------------- + */ + +static char FileID[] = "@(#)dlep_radio "__DATE__" "__TIME__" "; + +#include +#include +#include +//#include +#include +#include + +#include "safe_types.h" +#include "cli.h" +#include "time_units.h" +#include "stw_system_timer.h" +#include "packet_dump.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" +#include "rfc5444_encoder_tlv.h" +#include "rfc5444_encoder.h" +#include "rfc5444_decoder.h" +#include "rfc5444_decoder_tlv.h" +#include "rfc5444_experimental_tlv.h" + + +#include "dlep_debug.h" +//#include "dlep_porter.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" +#include "dlep_client_timer.h" +#include "dlep_client_peer_fsm.h" +#include "sim_dlep_radio_cli.h" + +#include "dlep_porter.h" + +#include "dlep_client_message_parser.h" + + +#define MAXMESG ( 1500 ) + + +static char *instructions[] = { + " dlep_radio ", + " options: ", + " -d Debug peer flags, hex ", + " -f Configuration filename ", + " -h This help file ", + " -v Display version ", + " ", + }; + + +int TCP_READY = 0; +int TCP_CLIENT_READY = 0; + +/** + * NAME + * show_instructions + * + * DESCRIPTION + * Displays the help info to stdout. + * + * INPUT PARAMETERS + * None. + * + * RETURN VALUE + * None. + * + */ +static void +show_instructions( ) +{ + int i; + + for (i=0; ifilename, args); + break; + + case 'h': + show_instructions(); + exit (EXIT_SUCCESS); + break; + + case 'v': + printf("\n%s \n\n", &FileID[4]); + exit (EXIT_SUCCESS); + break; + + default: + fprintf(stderr, "\nUnknown option: %s\n", args); + exit (EXIT_SUCCESS); + break; + } + + } else { + return (i); + } + } + + return (argc); +} + + +/* + * This function is envoked as result of the interval timer expiration + */ +static void timer_handler (int signum) +{ + stw_system_timer_tick(); +} + + +int main (int argc, char **argv) +{ + dlep_config_t *p2config; + rfc5444_rc_t rc; + + uint8_t *tmp; + uint8_t udp_msg[2000]; + int32_t udp_msg_len; + uint8_t tcp_msg[2000]; + int32_t tcp_msg_len; + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + +#define SCENARIO_INDICATOR ( 0xFFFF ) + uint16_t scenario_key; + + /* + * interval timer variables + */ + struct sigaction sa; + struct itimerval timer; + uint32_t microseconds; + //uint32_t milliseconds; + dlep_context_peer_t *p2peer; + + struct sockaddr_in6 rcvd_msg_addr; +// struct sockaddr_in6 rcvd_msg_addr6; + + socklen_t rcvd_msg_socket_length; + ipv6_address_t rcvd_msg_socket_length6; + + int highsock=0; + fd_set readfds={0}; + boolean_t verbose; + rfc5444_decoder_init(&dlep_client_message_parser); + rfc5444_decoder_tlv_init(); + rfc5444_experimental_tlv_init(); + + dlep_cli_init(); + dlep_debug_init(&dlep_debug_flags, 0); + + dlep_default_config(); + p2config = dlep_get_config_ptr(); + + dlep_parse_user_options(p2config, argc, argv); + + dlep_read_config_file(p2config); + dlep_display_config(p2config); + + dlep_porter_init(p2config); + dlep_porter_open(p2config); + dlep_tcp_porter_open(p2config); + + /* + * create and configure the timer + */ +#define DLEP_STW_NUMBER_BUCKETS ( 512 ) +#define DLEP_STW_RESOLUTION ( 100 ) + + stw_system_timer_create(DLEP_STW_NUMBER_BUCKETS, + DLEP_STW_RESOLUTION, + "DLEP Timer"); + + /* + * Install the interval timer_handler as the signal handler + * for SIGALRM. + */ + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = &timer_handler; + sigaction (SIGALRM, &sa, NULL); + + /* + * Configure the initial and post delay + */ + microseconds = milli_to_microseconds(DLEP_STW_RESOLUTION); + timer.it_value.tv_sec = 0; + timer.it_value.tv_usec = microseconds; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = microseconds; + + /* + * Now start the interval timer. + */ + setitimer (ITIMER_REAL, &timer, NULL); + + + /* + * allocate and instantiate a peer for simulation + */ + p2peer = dlep_peer_allocate(&p2config->local_ipv6, + &p2config->local_ipv4, + p2config->local_udp_port, + p2config->local_tcp_port); + + if (!p2peer) { + printf("%s-%u ERROR: did not allocate peer block \n", + DEBUG_FUNCTION, + DEBUG_LINE); + exit (0); + } + dlep_peer_init(p2config, p2peer); + + /* set the peer udp/tcp port to router udp/tcp port and + * peer address to the router address */ + + p2peer->peer_udp_port = p2config->router_udp_port; + p2peer->peer_tcp_port = p2config->router_tcp_port; + + + p2peer->peer_ipv4.v4_addr.v4_addr32 = + p2config->router_ipv4.v4_addr.v4_addr32; +// memcpy(p2peer->peer_ipv6.v6_addr.v6_addr32,&p2config->router_ipv6.v6_addr.v6_addr32,sizeof(ipv6_address_t)); + +#if 0 + p2peer->peer_ipv6.v6_addr.v6_addr32[0] = + p2config->router_ipv6.v6_addr.v6_addr32[0]; + p2peer->peer_ipv6.v6_addr.v6_addr32[1] = + p2config->router_ipv6.v6_addr.v6_addr32[1]; + p2peer->peer_ipv6.v6_addr.v6_addr32[2] = + p2config->router_ipv6.v6_addr.v6_addr32[2]; + p2peer->peer_ipv6.v6_addr.v6_addr32[3] = + p2config->router_ipv6.v6_addr.v6_addr32[3]; +#endif + p2peer->peer_ipv6.v6_addr.v6_addr16[0] = + p2config->router_ipv6.v6_addr.v6_addr16[0]; + p2peer->peer_ipv6.v6_addr.v6_addr16[1] = + p2config->router_ipv6.v6_addr.v6_addr16[1]; + p2peer->peer_ipv6.v6_addr.v6_addr16[2] = + p2config->router_ipv6.v6_addr.v6_addr16[2]; + p2peer->peer_ipv6.v6_addr.v6_addr16[3] = + p2config->router_ipv6.v6_addr.v6_addr16[3]; + p2peer->peer_ipv6.v6_addr.v6_addr16[4] = + p2config->router_ipv6.v6_addr.v6_addr16[4]; + p2peer->peer_ipv6.v6_addr.v6_addr16[5] = + p2config->router_ipv6.v6_addr.v6_addr16[5]; + p2peer->peer_ipv6.v6_addr.v6_addr16[6] = + p2config->router_ipv6.v6_addr.v6_addr16[6]; + p2peer->peer_ipv6.v6_addr.v6_addr16[7] = + p2config->router_ipv6.v6_addr.v6_addr16[7]; + + +#if 0 + ipv4_print_address("router IPv4", &p2peer->peer_ipv4); + ipv6_print_address("router IPv6", &p2peer->peer_ipv6); +#endif + + /* position the DLEP IDs */ + p2peer->client_id = p2config->local_id; + p2peer->router_id = 0; + + p2config->client_lenght = sizeof(p2config->client); + printf("start on launch\n"); + +#if 0 + if (p2config->start_on_launch) { + ** start the state machine ** + if (p2config->start_on_discovery) { + dlep_client_fsm_engine(start_init_e, p2peer, NULL); + } else { + dlep_client_fsm_engine(peer_init_request_e, p2peer, NULL); + } + } +#endif + + cli_set_prompt(p2config->sim_name); + highsock = p2config->dlep_tcp_sockfd +1 ; + +#if 0 + FD_ZERO(&readfds); + FD_SET(0, &readfds); + FD_SET(p2config->dlep_udp_sockfd, &readfds); + FD_SET(p2config->dlep_tcp_sockfd, &readfds); +#endif + while (1) { + // printf("inside while loop of udp\n"); + + /* zero out the control header and initial payload data */ + memset(udp_msg, 0, 20); + + FD_ZERO(&readfds); + FD_SET(0, &readfds); + FD_SET(p2config->dlep_udp_sockfd, &readfds); + FD_SET(p2config->dlep_tcp_sockfd, &readfds); + + if (TCP_CLIENT_READY == 1) { + FD_SET(p2config->dlep_tcp_client_sockfd, &readfds); + //printf("tcp client is ready\n"); + } + + /* Since tcp socket is created after udp socket, it will have + * the highest-numbered file descriptor. + */ + // printf("before select\n"); + + if (select(highsock, &readfds, NULL, NULL, NULL) < 0 ) { + continue; + } + printf("after select call \n"); + + /* check is udp socket ready for read operation */ + if (FD_ISSET(p2config->dlep_udp_sockfd, &readfds)) { + //printf("ready udp\n"); + /* blocking call */ + udp_msg_len = dlep_udp_receive(p2config, + &rcvd_msg_addr, + &rcvd_msg_socket_length, + udp_msg, + 1400); + if (udp_msg_len < 1 ) { + continue; + } + printf("udp is failed to receive due to socket issue\n"); + + tmp = udp_msg; + NETWORK_ORDER_GETSHORT(udp_msg, scenario_key); + tmp += sizeof(uint16_t); + if (scenario_key == SCENARIO_INDICATOR) { + printf(" %s \n", tmp); + dlep_cli_engine((char *)tmp); + } else { + + rfc5444_scrub_packet_scratch_pad( + &p2peer->packet_scratch_pad); + rfc5444_scrub_message_scratch_pad( + &p2peer->message_scratch_pad); + + if (dlep_debug_flags & DLEP_INCOMING_TRACE_FLAG) { + packet_dump("INCOMING-", udp_msg, udp_msg_len); + } + + verbose = + ((dlep_debug_flags & DLEP_DECODER_TRACE_FLAG) ? TRUE : FALSE); + //printf("reaching decoder packet\n"); + rc = rfc5444_decoder_packet(udp_msg, + udp_msg_len, + p2peer, + verbose); + if (verbose) { + DLEP_DEBUG("%s-%u Packet decode rc=%u %s \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rc, + rfc5444_rc2string(rc) ); + } + } + } + + /* check is tcp socket ready for read operation */ + if (FD_ISSET(p2config->dlep_tcp_sockfd, &readfds)) { + p2config->dlep_tcp_client_sockfd = accept(p2config->dlep_tcp_sockfd, + (struct sockaddr *)&p2config->client, &p2config->client_lenght); + + if (p2config->dlep_tcp_client_sockfd < 0) { + perror("ERROR on accept"); + } + + FD_SET(p2config->dlep_tcp_client_sockfd, &readfds); + highsock = (p2config->dlep_tcp_client_sockfd + 1); + TCP_CLIENT_READY = 1; + } + + if (FD_ISSET(p2config->dlep_tcp_client_sockfd, &readfds) && TCP_CLIENT_READY) { + /* blocking call */ + tcp_msg_len = dlep_tcp_receive(p2config, + &rcvd_msg_addr, + &rcvd_msg_socket_length, + tcp_msg, + 1400); + printf("read bytes are %d\n",tcp_msg_len); + if (tcp_msg_len < 1 ) { + if (TCP_CLIENT_READY == 0) { + printf("\n TCP Connection closed"); + close(p2config->dlep_tcp_client_sockfd); + } + continue; + } + + tmp = tcp_msg; + NETWORK_ORDER_GETSHORT(tcp_msg, scenario_key); + tmp += sizeof(uint16_t); + if (scenario_key == SCENARIO_INDICATOR) { + printf(" %s \n", tmp); + dlep_cli_engine((char *)tmp); + } else { + + rfc5444_scrub_packet_scratch_pad( + &p2peer->packet_scratch_pad); + rfc5444_scrub_message_scratch_pad( + &p2peer->message_scratch_pad); + + if (dlep_debug_flags & DLEP_INCOMING_TRACE_FLAG) { + packet_dump("INCOMING-", tcp_msg, tcp_msg_len); + } + + verbose = + ((dlep_debug_flags & DLEP_DECODER_TRACE_FLAG) ? TRUE : FALSE); + rc = rfc5444_decoder_packet(tcp_msg, + tcp_msg_len, + p2peer, + verbose); + if (verbose) { + DLEP_DEBUG("%s-%u Packet decode rc=%u %s \n", + DEBUG_FUNCTION, + DEBUG_LINE, + rc, + rfc5444_rc2string(rc) ); + } + } + } + + + /* console */ + if (FD_ISSET(0, &readfds)) { + fgets((char *)udp_msg, MAXMESG, stdin); + dlep_cli_engine((char *)udp_msg); + } + + } + + exit (0); +} + + diff --git a/dlep_radio_ipv6/sim_dlep_radio_cli.c b/dlep_radio_ipv6/sim_dlep_radio_cli.c new file mode 100644 index 0000000..6ea6efc --- /dev/null +++ b/dlep_radio_ipv6/sim_dlep_radio_cli.c @@ -0,0 +1,2062 @@ +/*------------------------------------------------------------------ + * sim_dlep_radio_cli.c -- Radio simulator CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reerved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include +#include + +#include "safe_types.h" +#include "cli.h" +#include "mac_address.h" +#include "ipv4_address.h" +#include "ipv6_address.h" +#include "stw_system_timer.h" + +#include "rfc5444_types.h" +#include "rfc5444_utils.h" + +#include "dlep_debug.h" +#include "dlep_debug_cli.h" +#include "dlep_client_neighbor_fsm.h" +#include "dlep_client_peer_fsm.h" +#include "dlep_message_builder.h" + +#include "dlep_context_neighbor.h" +#include "dlep_context_neighbor_management.h" +#include "dlep_context_peer.h" +#include "dlep_context_peer_management.h" +#include "dlep_client_timer.h" + +#include "dlep_source_cli.h" +#include "fuzz_dlep_cli.h" + +#include "sim_dlep_radio_cli.h" +#include "dlep_porter.h" + +static boolean_t started = FALSE; +//static boolean_t CREDIT_NOT_SUPPORTED = FALSE; +//static boolean_t CREDIT_ENABLED = FALSE; + + +/* + * directory record + */ +static cli_record_t show_system_dir; +static cli_record_t show_peer_dir; +static cli_record_t show_neighbor_dir; + +//static cli_record_t clear_peer_dir; +//static cli_record_t clear_neighbor_dir; + +static cli_record_t test_peer_dir; +static cli_record_t test_neighbor_dir; + + +/* + * allocate command records + */ +static cli_record_t system_start_cmd; +static cli_record_t system_stop_cmd; + +static cli_record_t show_timer_stats_cmd; + +static cli_record_t show_peer_all_cmd; +static cli_record_t show_peer_fsm_history_cmd; +static cli_record_t show_peer_fsm_table_cmd; + +//static cli_record_t show_neighbor_id_cmd; +static cli_record_t show_neighbor_mac_cmd; +static cli_record_t show_neighbors_on_peer_cmd; +static cli_record_t show_neighbor_fsm_history_cmd; +static cli_record_t show_neighbor_fsm_table_cmd; + + +/* + * test command records + */ +static cli_record_t test_session_init_cmd; +static cli_record_t test_peer_term_cmd; +static cli_record_t test_peer_update_cmd; +static cli_record_t test_peer_offer_cmd; +static cli_record_t test_peer_update_res_cmd; +static cli_record_t test_peer_term_res_cmd; +static cli_record_t test_peer_init_ack_cmd; +static cli_record_t test_peer_heartbeat_cmd; +static cli_record_t test_neighbor_up_cmd; +static cli_record_t test_neighbor_update_cmd; +//static cli_record_t test_neighbor_l3_up_cmd; +static cli_record_t test_neighbor_credit_up_cmd; +static cli_record_t test_neighbor_metric_up_cmd; + +static cli_record_t test_neighbor_ipv4_req_cmd; +static cli_record_t test_neighbor_ipv6_req_cmd; + +static cli_record_t test_neighbor_down_cmd; + +static cli_record_t test_neighbor_metrics_cmd; +static cli_record_t test_neighbor_rlq_cmd; +static cli_record_t test_neighbor_resources_cmd; +static cli_record_t test_neighbor_latency_cmd; +static cli_record_t test_neighbor_cdr_cmd; +static cli_record_t test_neighbor_mdr_cmd; +static cli_record_t test_neighbor_mtu_cmd; +int init = 0; + + + +static void +system_start (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + dlep_config_t *p2config; + + if (argv[1] && *argv[1] == '?') { + printf("start - starts the discovery process when MANUAL " + "is defined in the config file. \n"); + return; + } + + if (started) { + printf("\n"); + printf("Hey, the radio sim is already running!! \n"); + printf("\n"); + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + p2config = dlep_get_config_ptr(); + if (p2peer) { + /*** start the state machine ***/ +/* if (p2config->start_on_discovery) { + dlep_client_fsm_engine(start_init_e, p2peer, NULL); + } else { + dlep_client_fsm_engine(peer_init_request_e, p2peer, NULL); + } + started = TRUE; +*/ + + } else { + printf("ERROR: hum, could not find peer to start \n"); + } + return; +} + + +static void +system_stop (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("stop - immediately exits the simulation \n"); + return; + } + + exit (0); + return; +} + + + +/** + ** show system commands + **/ +static void +system_show_timer (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("system_show_timer - lists timer stats \n"); + return; + } + + stw_system_timer_stats(); + return; +} + + +/** + ** show peer commands + **/ +static void +peer_show_peer_all (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("peer_show_all - lists all peers \n"); + printf("\n"); + return; + } + + dlep_peer_list_all(); + return; +} + + +static void +peer_show_fsm_history (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_show_fsm_history - display peer state history \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + dlep_client_fsm_show_history(p2peer); + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + + +static void +peer_show_fsm_table (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_show_fsm_table - displays peer state machine \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + dlep_client_fsm_show_state_table(p2peer); + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + + +static void +neighbor_show_neighbor_mac (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + uint16_t nid; + + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_show_mac - " + "display neighbor info for MAC address \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + p2config = dlep_get_config_ptr(); + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (!p2peer) { + printf("Input error: local peer id %u not known \n", nid); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac address missing \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (p2neighbor) { + dlep_neighbor_display(p2neighbor); + } else { + printf("Input error: mac address %s not known \n", argv[1]); + } + return; +} + + +static void +neighbor_show_all_neighbors (uint32_t argc, char *argv[]) +{ + if (argv[1] && *argv[1] == '?') { + printf("neighbor_show_all - lists all client neighbors \n"); + printf("\n"); + return; + } + + dlep_peer_neighbor_list_all(); + return; +} + + +static void +neighbor_show_fsm_history (uint32_t argc, char *argv[]) +{ + uint32_t nid; + uint8_t mac_address[8]; + dlep_context_neighbor_t *p2neighbor; + dlep_context_peer_t *p2peer; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_show_fsm_history - displays " + "neighbor state history\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (!p2peer) { + printf("Input error: local peer id %u not known \n", nid); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac address missing \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (p2neighbor) { + dlep_client_neighbor_fsm_show_history(p2neighbor); + } else { + printf("Input error: mac address %s not known \n", argv[1]); + } + return; +} + + +static void +neighbor_show_fsm_table (uint32_t argc, char *argv[]) +{ + uint32_t nid; + uint8_t mac_address[8]; + dlep_context_neighbor_t *p2neighbor; + dlep_context_peer_t *p2peer; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_show_fsm_table - displays neighbor " + "state machine\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (!p2peer) { + printf("Input error: local peer id %u not known \n", nid); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac address missing \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (p2neighbor) { + dlep_client_neighbor_fsm_show_state_table(p2neighbor); + } else { + printf("Input error: mac address %s not known \n", argv[1]); + } + return; +} + + +/** + ** test peer commands + **/ +static void +peer_test_peer_term (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + if (argv[1] && *argv[1] == '?') { + printf("peer_test_terminate - sends a peer terminate \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + p2peer->status_code = RFC5444_MSG_TIMEOUT; /* suriya just added for now */ + dlep_client_fsm_engine(user_peer_term_request_e, p2peer, NULL); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; + +} + +static void +peer_test_peer_update (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + uint8_t rlq_tx,rlq_rx; + uint8_t resources; + uint64_t latency; + uint64_t cdr_tx,cdr_rx; + uint64_t mdr_tx,mdr_rx; + uint16_t mtu; + uint64_t temp; + uint32_t ttl ; + + + if (argv[1] && *argv[1] == '?') { + printf("peer_test_update - sends a peer update \n"); + printf("\n"); + return; + } + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + if (argv[1]) { + temp = strtoul(argv[1], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_tx = RFC5444_100_PERCENT; + } else { + rlq_tx = temp; + } + } else { + printf("Input error: rlq tx missing \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_rx = RFC5444_100_PERCENT; + } else { + rlq_rx = temp; + } + } else { + printf("Input error: rlq rx missing \n"); + return; + } + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + resources = RFC5444_100_PERCENT; + } else { + resources = temp; + } + } else { + printf("Input error: resources missing \n"); + return; + } + + latency=0; + + if (argv[4]) { + latency = strtoull(argv[4], NULL, 10); + } else { + printf("Input error: latency missing \n"); + return; + } + cdr_tx = 0; + if (argv[5]) { + cdr_tx = strtoull(argv[5], NULL, 10); + } else { + printf("Input error: cdr tx missing \n"); + return; + } + + cdr_rx = 0; + if (argv[6]) { + cdr_rx = strtoull(argv[6], NULL, 10); + } else { + printf("Input error: cdr rx missing \n"); + return; + } + + + mdr_tx = 0; + if (argv[7]) { + mdr_tx = strtoull(argv[7], NULL, 10); + } else { + printf("Input error: mdr tx missing \n"); + return; + } + + mdr_rx = 0; + if (argv[8]) { + mdr_rx = strtoull(argv[8], NULL, 10); + } else { + printf("Input error: mdr rx missing \n"); + return; + } + + mtu = 0; + if (argv[9]) { + mtu = strtoull(argv[9], NULL, 10); + } else { + printf("Input error: mtu missing \n"); + return; + } + + ttl = 0; + if (argv[10]) { + ttl = strtoull(argv[10], NULL, 10); + } + +#if 0 + if (argv[11]) { + printf(" Input error: extra argument is passed \n"); + return; + } +#endif + + /* set the neighbor data to be picked up at the next interval */ + p2peer->rlq_tx = rlq_tx; + p2peer->rlq_rx = rlq_rx; + p2peer->resources = resources; + p2peer->latency = latency; + p2peer->cdr_tx = cdr_tx; + p2peer->cdr_rx = cdr_rx; + p2peer->mdr_tx = mdr_tx; + p2peer->mdr_rx = mdr_rx; + p2peer->mtu = mtu; + p2peer->ttl = ttl; + + send_dlep_peer_update_request(p2peer); + + printf(" metrics updated: RLQ TX=%u RLQ RX=%u \n" + + "Resources =%u \n" + "Latency=%llu \n" + "CDR TX=%llu CDR RX=%llu \n" + "MDR TX=%llu MDR RX=%llu \n" + "MTU =%u ", + rlq_tx, + rlq_rx, + resources, + latency, + cdr_tx, + cdr_rx, + mdr_tx, + mdr_rx, + mtu); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} + + +/** + ** test neighbor commands + **/ +static void +cli_test_neighbor_update_msg (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_update_msg - generate a neighbor up \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + /* don't send the layer 3 addresses, force router to ARP/ND */ + ipv4_zero_address(&p2neighbor->ipv4_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + + /* set the neighbor metrics */ + p2neighbor->rlq_rx = 100; + p2neighbor->rlq_tx = 100; + p2neighbor->resources = 100; + p2neighbor->latency = 250; + p2neighbor->cdr_rx = 100000000; + p2neighbor->cdr_tx = 100000000; + p2neighbor->mdr_rx = 100000000; + p2neighbor->mdr_tx = 100000000; + p2neighbor->mtu = 1500; + send_dlep_neighbor_address_request(p2peer, p2neighbor); + /* + * start the ack timer + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_init_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_init_ack_tmr, + (void *)p2neighbor); + + return; +} + + + +static void +cli_test_neighbor_up (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + ipv4_address_t ipv4_address; + ipv6_address_t ipv6_address; + char ipv6_addr[130]; + + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_up - generate " + " a neighbor up with Layer 3 addresse\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 210.123.234.102 \n"); + printf(" - 2001:0db8:85a3:0000:0000:8a2e:0370:7334 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + +#if 0 + if (argv[2]) { + ipv4_dot_decimal2digits(&ipv4_address, argv[2]); + ipv4_print_address(NULL, &ipv4_address); + } else { + printf("Input error: IPv4 is missing \n"); + return; + } +#endif + + if (argv[2]) { + inet_pton(AF_INET6,argv[2],&ipv6_address.v6_addr.v6_addr16); + expand_ipv6_addr(ipv6_addr,&ipv6_address); + ipv6_ascii2digits(&ipv6_address, ipv6_addr); + // ipv6_ascii2digits(&ipv6_address, argv[2]); + ipv6_print_address(NULL, &ipv6_address); + printf("v6 is %p\n",&ipv6_address); + } else { + printf("Input error: IPv6 is missing \n"); + return; + } + + if (argv[3]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + //ipv4_copy_address(&p2neighbor->ipv4_address, &ipv4_address); + ipv6_copy_address(&p2neighbor->ipv6_address, &ipv6_address); + + //memcpy(&p2neighbor->ipv6_address,&ipv6_address.v6_addr,sizeof(ipv6_address_t)); + + /* set the neighbor metrics */ + p2neighbor->rlq_tx = 100; + p2neighbor->rlq_rx = 100; + p2neighbor->resources = 100; + p2neighbor->latency = 250; + p2neighbor->cdr_tx = 100000000; + p2neighbor->cdr_rx = 100000000; + p2neighbor->mdr_tx = 100000000; + p2neighbor->mdr_rx = 100000000; + p2neighbor->mtu = 1500; + + send_dlep_neighbor_up(p2peer, p2neighbor); + + /* + * start the ack timer + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_init_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_init_ack_tmr, + (void *)p2neighbor); + + return; +} + + +static void +cli_test_neighbor_credit_up (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_up - generate a neighbor up \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + /* don't send the layer 3 addresses, force router to ARP/ND */ + ipv4_zero_address(&p2neighbor->ipv4_address); + ipv6_zero_address(&p2neighbor->ipv6_address); + + /* set the neighbor metrics */ + p2neighbor->rlq_rx = 100; + p2neighbor->rlq_tx = 100; + p2neighbor->resources = 100; + p2neighbor->latency = 250; + p2neighbor->cdr_rx = 100000000; + p2neighbor->cdr_tx = 100000000; + p2neighbor->mdr_rx = 100000000; + p2neighbor->mdr_tx = 100000000; + p2neighbor->mtu = 1500; + + if (p2neighbor->CREDIT_NOT_SUPPORTED) { + p2neighbor->mrw = 0; + } else { + p2neighbor->mrw = 65534; + } + p2neighbor->rrw = 0; + + + send_dlep_neighbor_up(p2peer, p2neighbor); + + /* + * start the ack timer + */ + (void)stw_system_timer_start(&p2neighbor->neighbor_init_ack_tmr, + p2peer->neighbor_up_ack_tmo, + p2peer->neighbor_up_ack_tmo, + &dlep_neighbor_init_ack_tmr, + (void *)p2neighbor); + + return; +} + + +static void +cli_test_neighbor_metric_up (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + ipv6_address_t ipv6_address; + dlep_config_t *p2config; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + uint8_t rlq_tx; + uint8_t rlq_rx; + uint8_t resources; + uint64_t latency; + uint64_t cdr_tx; + uint64_t cdr_rx; + uint64_t mdr_tx; + uint64_t mdr_rx; + uint16_t mtu; + uint32_t temp; + + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_metric_up " + " - generate a " + "neighbor up w/ metrics \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" ipv6_address \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf(" - 64-bit millisecond value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 16-bit \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + if (argv[2]) { + ipv6_ascii2digits(&ipv6_address, argv[2]); + ipv6_print_address(NULL, &ipv6_address); + } else { + printf("Input error: IPv6 is missing \n"); + return; + } + p2config = dlep_get_config_ptr(); + p2peer = dlep_get_peer_by_peer_id(1); + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + p2neighbor = dlep_neighbor_allocate(p2peer, mac_address); + } + + if (!p2neighbor) { + printf("Error: new neighbor instaniation failed \n"); + return; + } + + ipv6_copy_address(&p2neighbor->ipv6_address, &ipv6_address); + + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_tx = RFC5444_100_PERCENT; + rlq_rx = RFC5444_100_PERCENT; + } else { + rlq_tx = temp; + rlq_rx = temp; + } + } else { + printf("Input error: rlq missing \n"); + return; + } + + if (argv[4]) { + temp = strtoul(argv[4], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + resources = RFC5444_100_PERCENT; + } else { + resources = temp; + } + } else { + printf("Input error: resources tx missing \n"); + return; + } + + latency =0; + if (argv[5]) { + latency = strtoull(argv[5], NULL, 10); + } else { + printf("Input error: latency missing \n"); + return; + } + + cdr_tx = 0; + cdr_rx = 0; + if (argv[6]) { + cdr_tx = strtoull(argv[6], NULL, 10); + cdr_rx = strtoull(argv[6], NULL, 10); + } else { + printf("Input error: cdr missing \n"); + return; + } + + + mdr_tx = 0; + mdr_rx = 0; + if (argv[7]) { + mdr_tx = strtoull(argv[7], NULL, 10); + mdr_rx = strtoull(argv[7], NULL, 10); + } else { + printf("Input error: mdr_tx missing \n"); + return; + } + + mtu = 0; + if (argv[8]) { + mtu = strtoul(argv[8], NULL, 10); + } else { + printf("Input error: mtu missing \n"); + return; + } + + if (argv[9]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor metrics for the neighbor up */ + p2neighbor->rlq_tx = rlq_tx; + p2neighbor->rlq_rx = rlq_rx; + p2neighbor->resources = resources; + p2neighbor->latency = latency; + p2neighbor->cdr_tx = cdr_tx; + p2neighbor->cdr_rx = cdr_rx; + p2neighbor->mdr_tx = mdr_tx; + p2neighbor->mdr_rx = mdr_rx; + p2neighbor->mtu = mtu; + + printf(" sending reaching here\n"); + send_dlep_neighbor_up(p2peer, p2neighbor); + return; +} + + +static void +cli_test_neighbor_ipv4_req (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + ipv4_address_t ipv4_address; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_ipv4 " + " - generate " + " a neighbor address IPv4 update \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - add | drop \n"); + printf(" - 210.123.234.102 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + if (argv[3]) { + ipv4_dot_decimal2digits(&ipv4_address, argv[3]); + printf("\n Going to print entered ip add"); + ipv4_print_address(NULL, &ipv4_address); + } else { + printf("Input error: IPv4 is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Input error: local peer not present \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Input error: neighbor mac not known \n"); + return; + } + + if (strcmp("add", argv[2]) == 0) { + p2neighbor->update_ipv4_operation = RFC5444_EXISTING_ADD_ADDRESS; + ipv4_copy_address(&p2neighbor->update_ipv4_address, &ipv4_address); +// send_dlep_neighbor_address_request(p2peer, p2neighbor); + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + } else if (strcmp("drop", argv[2]) == 0) { + p2neighbor->update_ipv4_operation = RFC5444_DROP_ADDRESS; + ipv4_copy_address(&p2neighbor->update_ipv4_address, &ipv4_address); + // send_dlep_neighbor_address_request(p2peer, p2neighbor); + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + } else { + printf("Input error: invalid add-drop operation \n"); + return; + } + return; +} + + +static void +cli_test_neighbor_ipv6_req (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8] , subnet; + ipv6_address_t ipv6_address; + ipv6_address_t ipv6_subnet_address; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_ipv6 " + " - generate " + " a neighbor address IPv6 update \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - add | drop \n"); + printf(" - 11223344:22334455:33445566:44556677 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + if (argv[3]) { + ipv6_ascii2digits(&ipv6_address, argv[3]); + ipv6_print_address(NULL, &ipv6_address); + } else { + printf("Input error: IPv6 is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Input error: local peer not present \n"); + return; + } + + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Input error: neighbor mac not known \n"); + return; + } + + if (argv[4]) { + ipv6_ascii2digits(&ipv6_subnet_address, argv[4]); + ipv6_print_address(NULL, &ipv6_subnet_address); + } else { + printf("Input error: IPv6 subnet is missing \n"); + return; + } + + + if(argv[5]) { + subnet = strtoul(argv[5], NULL, 10); + } else { + printf("Input error: subnet prefix is missing \n"); + return; + } + + if (strcmp("add", argv[2]) == 0) { + p2neighbor->update_ipv6_operation = RFC5444_EXISTING_ADD_ADDRESS; + ipv6_copy_address(&p2neighbor->update_ipv6_address, &ipv6_address); + ipv6_copy_address(&p2neighbor->update_ipv6_subnet_address, &ipv6_subnet_address); + p2neighbor->ipv6_subnet_prefix = subnet; + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + } else if (strcmp("drop", argv[2]) == 0) { + p2neighbor->update_ipv6_operation = RFC5444_DROP_ADDRESS; + ipv6_copy_address(&p2neighbor->update_ipv6_address, &ipv6_address); + ipv6_copy_address(&p2neighbor->update_ipv6_subnet_address, &ipv6_subnet_address); + p2neighbor->ipv6_subnet_prefix = subnet; + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + } else { + printf("Input error: invalid add-drop operation \n"); + return; + } + return; +} + + +static void +cli_test_neighbor_metrics (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + uint8_t rlq_tx,rlq_rx; + uint8_t resources_tx,resources_rx,resources; + uint64_t latency; + uint64_t cdr_tx,cdr_rx; + uint64_t mdr_tx,mdr_rx; + uint16_t mtu; + uint32_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_metrics " + " " + " - " + "generate a neighbor metrics update \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf(" - 16-bit millisecond value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 64-bit bps value \n"); + printf(" - 16-bit \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_tx = RFC5444_100_PERCENT; + } else { + rlq_tx = temp; + } + } else { + printf("Input error: rlq tx missing \n"); + return; + } + + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + rlq_rx = RFC5444_100_PERCENT; + } else { + rlq_rx = temp; + } + } else { + printf("Input error: rlq rx missing \n"); + return; + } + + if (argv[4]) { + temp = strtoul(argv[4], NULL, 10); + if (temp > RFC5444_100_PERCENT) { + resources = RFC5444_100_PERCENT; + } else { + resources = temp; + } + } else { + printf("Input error: resources tx missing \n"); + return; + } + + latency = 0; + + if (argv[5]) { + latency = strtoull(argv[5], NULL, 10); + } else { + printf("Input error: latency missing \n"); + return; + } + + cdr_tx = 0; + if (argv[6]) { + cdr_tx = strtoull(argv[6], NULL, 10); + } else { + printf("Input error: cdr tx missing \n"); + return; + } + + cdr_rx = 0; + if (argv[7]) { + cdr_rx = strtoull(argv[7], NULL, 10); + } else { + printf("Input error: cdr rx missing \n"); + return; + } + + + mdr_tx = 0; + if (argv[8]) { + mdr_tx = strtoull(argv[8], NULL, 10); + } else { + printf("Input error: mdr tx missing \n"); + return; + } + + mdr_rx = 0; + if (argv[9]) { + mdr_rx = strtoull(argv[9], NULL, 10); + } else { + printf("Input error: mdr rx missing \n"); + return; + } + + mtu = 0; + if (argv[10]) { + mtu = strtoull(argv[10], NULL, 10); + } else { + printf("Input error: mtu missing \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->rlq_tx = rlq_tx; + p2neighbor->rlq_rx = rlq_rx; + p2neighbor->resources = resources; + p2neighbor->latency = latency; + p2neighbor->cdr_tx = cdr_tx; + p2neighbor->cdr_rx = cdr_rx; + p2neighbor->mdr_tx = mdr_tx; + p2neighbor->mdr_rx = mdr_rx; + p2neighbor->mtu = mtu; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: RLQ TX=%u RLQ RX=%u \n" + "Resources =%u \n" + "Latency=%llu \n" + "CDR TX=%llu CDR RX=%llu \n" + "MDR TX=%llu MDR RX=%llu \n" + "MTU =%u", + rlq_tx, + rlq_rx, + resources, + latency, + cdr_tx, + cdr_rx, + mdr_tx, + mdr_rx, + mtu); + return; +} + + +static void +cli_test_neighbor_rlq (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint8_t rlq_tx, rlq_rx; + uint32_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_rlq - " + "generate a neighbor metrics update with a new RLQ \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > 100) { + rlq_tx =100; + } else { + rlq_tx = temp; + } + } else { + printf("Input error: rlq tx missing \n"); + return; + } + + if (argv[3]) { + temp = strtoul(argv[3], NULL, 10); + if (temp > 100) { + rlq_rx =100; + } else { + rlq_rx = temp; + } + } else { + printf("Input error: rlq rx missing \n"); + return; + } + + if (argv[4]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->rlq_tx = rlq_tx; + p2neighbor->rlq_rx = rlq_rx; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: RLQ TX=%u \n", + rlq_tx); + printf(" metrics updated: RLQ RX=%u \n", + rlq_rx); + return; +} + + +static void +cli_test_neighbor_resources (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint8_t resources; + uint8_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_resources - " + "" + "generate a neighbor metrics update with a new resource \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" - 0 - 100 \n"); + printf(" - 0 - 100 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoul(argv[2], NULL, 10); + if (temp > 100) { + resources = 100; + } else { + resources = temp; + } + } else { + printf("Input error: resources missing \n"); + return; + } + + if (argv[3]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->resources = resources; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: Resources=%u \n", + resources); + return; +} + + +static void +cli_test_neighbor_latency (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint64_t latency; + uint64_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_latency -" + "generate a neighbor metrics update with a new latency \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" 64-bit millisecond value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + latency = 0 ; + if (argv[2]) { + latency = strtoull(argv[2], NULL, 10); + } else { + printf("Input error: latency missing \n"); + return; + } + + if (argv[3]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->latency = latency; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: Latency=%u \n", + latency); + return; +} + + +static void +cli_test_neighbor_cdr (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint64_t cdr_tx, cdr_rx; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_cdr - " + "generate a neighbor metrics update with a new CDR\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" 64-bit bps value \n"); + printf(" 64-bit bps value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + cdr_tx = 0; + if (argv[2]) { + cdr_tx = strtoull(argv[2], NULL, 10); + } else { + printf("Input error: cdr_tx missing \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->cdr_tx = cdr_tx; + + cdr_rx = 0; + if (argv[3]) { + cdr_rx = strtoull(argv[3], NULL, 10); + } else { + printf("Input error: cdr_rx missing \n"); + return; + } + + if (argv[4]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->cdr_rx = cdr_rx; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: CDR TX=%llu \n", + cdr_tx); + printf(" metrics updated: CDR RX=%llu \n", + cdr_rx); + return; +} + + +static void +cli_test_neighbor_mdr (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint64_t mdr_tx, mdr_rx; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_mdr - " + "generate a neighbor metrics update with a new MDR\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" 64-bit bps value \n"); + printf(" 64-bit bps value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + mdr_tx = 0; + if (argv[2]) { + mdr_tx = strtoull(argv[2], NULL, 10); + } else { + printf("Input error: mdr_tx missing \n"); + return; + } + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->mdr_tx = mdr_tx; + + mdr_rx = 0; + if (argv[3]) { + mdr_rx = strtoull(argv[3], NULL, 10); + } else { + printf("Input error: mdr_rx missing \n"); + return; + } + + if (argv[4]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->mdr_rx = mdr_rx; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: MDR TX=%llu \n", + mdr_tx); + printf(" metrics updated: MDR RX=%llu \n", + mdr_rx); + return; +} + +static void +cli_test_neighbor_mtu (uint16_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + uint16_t mtu; + uint16_t temp; + + if (argv[1] && *argv[1] == '?') { + printf("neighbor_test_mdr - " + "generate a neighbor metrics update with a new MDR\n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf(" 64-bit bps value \n"); + printf(" 64-bit bps value \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + return; + } + + if (argv[2]) { + temp = strtoull(argv[2], NULL, 10); + if ((temp >= 64) && (temp <= 1500)) { + mtu = temp; + } else { + mtu = 1500; + } + } else { + printf("Input error: mtu missing \n"); + return; + } + + if (argv[3]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + + /* set the neighbor data to be picked up at the next interval */ + p2neighbor->mtu = mtu; + + send_dlep_neighbor_metrics(p2peer, p2neighbor); + + printf(" metrics updated: MTU=%u \n", + mtu); + return; +} + + +static void +cli_test_neighbor_down (uint32_t argc, char *argv[]) +{ + uint8_t mac_address[8]; + dlep_context_peer_t *p2peer; + dlep_context_neighbor_t *p2neighbor; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("neighbor_test_down - generate a " + "neighbor down \n"); + printf("where \n"); + printf(" - 11:22:33:44:55:66 \n"); + printf("\n"); + return; + } + + if (argv[1]) { + mac_ascii2digits(mac_address, argv[1]); + //mac_print_address(NULL, mac_address); + } else { + printf("Input error: mac is missing \n"); + return; + } + + if (argv[2]) { + printf(" Input error: extra argument is passed \n"); + return; + } + + p2peer = dlep_get_peer_by_peer_id(1); + if (!p2peer) { + printf("Error: peer not known \n"); + } + p2neighbor = dlep_get_neighbor_by_mac_address(p2peer, mac_address); + if (!p2neighbor) { + printf("Error: neighbor not known \n"); + //return; + } + + dlep_client_neighbor_fsm_engine(neighbor_term_user_req_e, + p2peer, p2neighbor); + return; +} + +static void +peer_test_peer_offer (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + if (p2peer) { + dlep_client_fsm_engine(peer_offer_e, p2peer, NULL); + + } else { + printf("Input error: local peer id %u not known \n", nid); + } + return; +} +static void +peer_test_init_ack (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + printf("reaching here\n"); + send_dlep_peer_init_ack(p2peer); + return; +} +static void +peer_test_update_res (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + send_dlep_peer_update_response(p2peer); + return; +} +static void +peer_test_term_res (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + + send_dlep_peer_termination_ack(p2peer); + return; +} +static void +peer_test_heartbeat (uint32_t argc, char *argv[]) +{ + uint32_t nid; + dlep_context_peer_t *p2peer; + + nid = 1; + p2peer = dlep_get_peer_by_peer_id(nid); + + send_dlep_peer_heartbeat(p2peer); + return; +} +static void +test_session_init (uint32_t argc, char *argv[]) +{ + int temp; + + if (!argv[1] || (argv[1] && *argv[1] == '?')) { + printf("session init enter 0 or 1 \n"); + printf("\n"); + return; + } + + temp = strtoul(argv[1], NULL, 10); + if(temp ==0 || temp ==1) { + init = strtoul(argv[1], NULL, 10); + } + else { + printf("Input error : Invalid option should be 0 or 1 \n"); + } + + return; +} + +/** + * NAME + * dlep_cli_engine + * + * SYNOPSIS + * void + * dlep_cli_engine() + * + * DESCRIPTION + * Drives the Radio Test Tool CLI. + * + * INPUT PARAMETERS + * input_string This is a string containing user input. + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_cli_engine (char *input_string) +{ + cli_engine(input_string); + return; +} + + +/** + * NAME + * dlep_cli_init + * + * SYNOPSIS + * void + * dlep_cli_init() + * + * DESCRIPTION + * Registers the dlep test tool commands with the cli + * facility. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +dlep_cli_init (void) +{ + cli_init_data_t init_data; + RC_CLI_t rc; + + strcpy(init_data.prefix, "Radio Test Tool"); + cli_init(&init_data); + + dlep_debug_cli_init(); + //dlep_source_cli_init(); + fuzz_dlep_cli_init(); + + + /* + * Create directory and commands + */ + + rc = cli_mkdir("system", &cli_show_dir, &show_system_dir); + rc = cli_mkdir("peer", &cli_show_dir, &show_peer_dir); + rc = cli_mkdir("neighbor", &cli_show_dir, &show_neighbor_dir); + +// rc = cli_mkdir("peer", &cli_clear_dir, &clear_peer_dir); +// rc = cli_mkdir("neighbor", &cli_clear_dir, &clear_neighbor_dir); + + rc = cli_mkdir("peer", &cli_test_dir, &test_peer_dir); + rc = cli_mkdir("neighbor", &cli_test_dir, &test_neighbor_dir); + + + /* + * root commands + */ + rc = cli_mkcmd("start", system_start, + NULL, &system_start_cmd); + rc = cli_mkcmd("stop", system_stop, + NULL, &system_stop_cmd); + + /* + * show system + */ + rc = cli_mkcmd("system_show_timer", system_show_timer, + &show_system_dir, &show_timer_stats_cmd); + + /* + * show peer + */ + rc = cli_mkcmd("peer_show_all", peer_show_peer_all, + &show_peer_dir, &show_peer_all_cmd); + rc = cli_mkcmd("peer_show_fsm_history", peer_show_fsm_history, + &show_peer_dir, &show_peer_fsm_history_cmd); + rc = cli_mkcmd("peer_show_fsm_table", peer_show_fsm_table, + &show_peer_dir, &show_peer_fsm_table_cmd); + + /* + * show neighbor + */ + rc = cli_mkcmd("neighbor_show_mac", neighbor_show_neighbor_mac, + &show_neighbor_dir, &show_neighbor_mac_cmd); + rc = cli_mkcmd("neighbor_show_all", neighbor_show_all_neighbors, + &show_neighbor_dir, &show_neighbors_on_peer_cmd); + rc = cli_mkcmd("neighbor_show_fsm_history", neighbor_show_fsm_history, + &show_neighbor_dir, &show_neighbor_fsm_history_cmd); + rc = cli_mkcmd("neighbor_show_fsm_table", neighbor_show_fsm_table, + &show_neighbor_dir, &show_neighbor_fsm_table_cmd); + + /* + * test peer + */ + + rc = cli_mkcmd("test_session_init", test_session_init, + &test_peer_dir, &test_session_init_cmd); + + rc = cli_mkcmd("peer_test_terminate", peer_test_peer_term, + &test_peer_dir, &test_peer_term_cmd); + + rc = cli_mkcmd("peer_test_update", peer_test_peer_update, + &test_peer_dir, &test_peer_update_cmd); + + /* added for testing purpose */ + rc= cli_mkcmd("peer_test_offer", peer_test_peer_offer, + &test_peer_dir, &test_peer_offer_cmd); + + rc=cli_mkcmd("peer_test_init_ack", peer_test_init_ack, + &test_peer_dir, &test_peer_init_ack_cmd); + rc=cli_mkcmd("peer_test_update_res", peer_test_update_res, + &test_peer_dir, &test_peer_update_res_cmd); + rc=cli_mkcmd("peer_test_term_res", peer_test_term_res, + &test_peer_dir, &test_peer_term_res_cmd); + rc=cli_mkcmd("peer_test_heartbeat", peer_test_heartbeat, + &test_peer_dir, &test_peer_heartbeat_cmd); + + /* + * test neighbor + */ + rc = cli_mkcmd("neighbor_test_up", cli_test_neighbor_up, + &test_neighbor_dir, &test_neighbor_up_cmd); + /* rc = cli_mkcmd("neighbor_test_l3_up", cli_test_neighbor_l3_up, + &test_neighbor_dir, &test_neighbor_l3_up_cmd); */ + rc = cli_mkcmd("neighbor_test_credit_up", cli_test_neighbor_credit_up, + &test_neighbor_dir, &test_neighbor_credit_up_cmd); + rc = cli_mkcmd("neighbor_test_metric_up", cli_test_neighbor_metric_up, + &test_neighbor_dir, &test_neighbor_metric_up_cmd); + + rc = cli_mkcmd("neighbor_test_ipv4", cli_test_neighbor_ipv4_req, + &test_neighbor_dir, &test_neighbor_ipv4_req_cmd); + rc = cli_mkcmd("neighbor_test_ipv6", cli_test_neighbor_ipv6_req, + &test_neighbor_dir, &test_neighbor_ipv6_req_cmd); + + rc = cli_mkcmd("neighbor_test_down", cli_test_neighbor_down, + &test_neighbor_dir, &test_neighbor_down_cmd); + rc = cli_mkcmd("neighbor_test_metrics", cli_test_neighbor_metrics, + &test_neighbor_dir, &test_neighbor_metrics_cmd); + + rc = cli_mkcmd("neighbor_test_rlq", cli_test_neighbor_rlq, + &test_neighbor_dir, &test_neighbor_rlq_cmd); + rc = cli_mkcmd("neighbor_test_resources", cli_test_neighbor_resources, + &test_neighbor_dir, &test_neighbor_resources_cmd); + rc = cli_mkcmd("neighbor_test_latency", cli_test_neighbor_latency, + &test_neighbor_dir, &test_neighbor_latency_cmd); + rc = cli_mkcmd("neighbor_test_cdr", cli_test_neighbor_cdr, + &test_neighbor_dir, &test_neighbor_cdr_cmd); + rc = cli_mkcmd("neighbor_test_mdr", cli_test_neighbor_mdr, + &test_neighbor_dir, &test_neighbor_mdr_cmd); + rc = cli_mkcmd("neighbor_test_mtu", cli_test_neighbor_mtu, + &test_neighbor_dir, &test_neighbor_mtu_cmd); + rc = cli_mkcmd("neighbor_test_update_msg", cli_test_neighbor_update_msg, + &test_neighbor_dir, &test_neighbor_update_cmd); + + return; +} + diff --git a/dlep_radio_ipv6/sim_dlep_radio_cli.h b/dlep_radio_ipv6/sim_dlep_radio_cli.h new file mode 100644 index 0000000..c8f08b4 --- /dev/null +++ b/dlep_radio_ipv6/sim_dlep_radio_cli.h @@ -0,0 +1,43 @@ +/*------------------------------------------------------------------ + * sim_radio_cli.h -- Radio simulator CLI support + * + * August 2010, Bo Berry + * + * Copyright (c) 2010 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __SIM_RADIO_CLI_H__ +#define __SIM_RADIO_CLI_H__ + + +extern +void dlep_cli_engine(char *input_string); + +extern +void dlep_cli_init(void); + +#endif + diff --git a/dlep_radio_ipv6/stw_system_timer.c b/dlep_radio_ipv6/stw_system_timer.c new file mode 100644 index 0000000..56f74e6 --- /dev/null +++ b/dlep_radio_ipv6/stw_system_timer.c @@ -0,0 +1,339 @@ +/*----------------------------------------------------------------- + * stw_system_timer.c -- System Timer Wheel APIs + * + * February 2005, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include "stw_system_timer.h" + + +static stw_t *stw_system_handle = 0; + + +/** + * NAME + * stw_system_timer_prepare + * + * SYNOPSIS + * #include "stw_system_timer.h" + * void + * stw_system_timer_prepare(stw_tmr_t *tmr) + * + * DESCRIPTION + * Utility routine to initialize the links of timer elements. + * + * INPUT PARAMETERS + * tmr - pointer to the timer + * + * OUTPUT PARAMETERS + * tmr - updated + * + * RETURN VALUE + * none + * + */ +void +stw_system_timer_prepare (stw_tmr_t *tmr) +{ + stw_timer_prepare(tmr); + return; +} + + +/** + * NAME + * stw_system_timer_stats + * + * SYNOPSIS + * #include "stw_system_timer.h" + * void + * stw_system_timer_stats(void) + * + * DESCRIPTION + * Displays the stats for the system timer wheel. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +stw_system_timer_stats (void) +{ + stw_timer_stats(stw_system_handle); + return; +} + + +/** + * NAME + * stw_system_timer_running + * + * SYNOPSIS + * #include "stw_system_timer.h" + * boolean_t + * stw_system_timer_running(stw_tmr_t *tmr) + * + * DESCRIPTION + * Returns TRUE if the timer is active + * + * INPUT PARAMETERS + * tmr - pointer to the timer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE==tmer is active + * False==timer is not active + * + */ +boolean_t +stw_system_timer_running (stw_tmr_t *tmr) +{ + return (stw_timer_running(tmr)); +} + + +/** + * NAME + * stw_system_timer_start + * + * SYNOPSIS + * #include "stw_system_timer.h" + * RC_STW_t + * stw_system_timer_start(stw_tmr_t *tmr, + * uint32_t delay, + * uint32_t periodic_delay, + * stw_call_back user_cb, + * void *parm) + * + * DESCRIPTION + * Start (or restart) a system timer to expire + * in the future. If the timer is currently active, + * it will be stopped first then restarted with + * time delay requested. + * + * INPUT PARAMETERS + * tmr - pointer to the timer element + * + * delay - specified delay in milliseconds + * + * periodic_delay - periodic delay in milliseconds + * + * user_cb - application function call-back to be + * invoked when the timer expires. This + * call-back must not block. + * + * parm - persistent parameter passed to the application + * call-back upon expiration + * + * OUTPUT PARAMETERS + * tmr - updated with the user_cb and the parm, and + * put on the tiemr wheel of fortune. + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_system_timer_start (stw_tmr_t *tmr, + uint32_t delay, + uint32_t periodic_delay, + stw_call_back user_cb, + void *parm) +{ + return (stw_timer_start(stw_system_handle, + tmr, + delay, + periodic_delay, + user_cb, + parm)); +} + + +/** + * NAME + * stw_system_timer_stop + * + * SYNOPSIS + * #include "stw_system_timer.h" + * RC_STW_t + * stw_system_timer_stop(stw_tmr_t *tmr) + * + * DESCRIPTION + * Stop the timer by removing it from the timer wheel. + * Note that it is safe to call this function with a + * timer that has already been stopped in order to + * avoid making all callers check for an active timer + * first. + * + * INPUT PARAMETERS + * tmr - pointer to the timer element + * + * OUTPUT PARAMETERS + * tmr - updated, taken off the wheel + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_system_timer_stop (stw_tmr_t *tmr) +{ + return (stw_timer_stop(stw_system_handle, tmr)); +} + + +/** + * NAME + * stw_system_timer_tick + * + * SYNOPSIS + * #include "stw_system_timer.h" + * void + * stw_system_timer_tick(void) + * + * DESCRIPTION + * Expire timers on the current spoke and move + * the wheel cursor forward to the next spoke. + * + * Application call-backs must be non-blocking + * + * INPUT PARAMETERS + * stw - pointer to the timer wheel + * + * OUTPUT PARAMETERS + * stw is updated, timers at the current tick are + * expired. + * + * RETURN VALUE + * none + * + */ +void +stw_system_timer_tick (void) +{ + /* + * protect from the possibility of not having initialized the stw yet + */ + if (stw_system_handle) { + stw_timer_tick(stw_system_handle); + } + return; +} + + +/** + * NAME + * stw_system_timer_destroy + * + * SYNOPSIS + * #include "stw_system_timer.h" + * RC_STW_t + * stw_system_timer_destroy(void) + * + * DESCRIPTION + * Destroys the timer wheel. All timers are stopped + * and resources released. + * + * INPUT PARAMETERS + * none + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_system_timer_destroy (void) +{ + return (stw_timer_destroy(stw_system_handle)); +} + + +/** + * NAME + * stw_system_timer_create + * + * SYNOPSIS + * #include "stw_system_timer.h" + * RC_STW_t + * stw_system_timer_create(uint32_t wheel_size, + * uint32_t granularity, + * const char *p2name ) + * + * DESCRIPTION + * This function is used to create and initialize the system timer + * wheel. Timers must not be started before this routine is called. + * + * INPUT PARAMETERS + * wheel_size - number of spokes in the wheel. The number + * of spoks should be engineered such that + * wheel_size >= (longest duration / granularity ) + * Depending upon the number of concurrent timers, the + * distribution of those timers, it may be beneficial to + * further increase the wheel size. Objective is to + * minimize frequency of 'long' timers requiring wheel + * revolutions. + * + * granularity - milliseconds between ticks + * + * *p2name - pointer to the name of identify wheel. + * Limited to STW_NAME_LENGTH + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_system_timer_create (uint32_t wheel_size, + uint32_t granularity, + const char *p2name) +{ + return (stw_timer_create(wheel_size, + granularity, + p2name, + &stw_system_handle)); +} + + diff --git a/dlep_radio_ipv6/stw_system_timer.h b/dlep_radio_ipv6/stw_system_timer.h new file mode 100644 index 0000000..ed6019e --- /dev/null +++ b/dlep_radio_ipv6/stw_system_timer.h @@ -0,0 +1,102 @@ +/*------------------------------------------------------------------ + * stw_system_timer.h -- System Timer Wheel Definitions + * + * July 2009 - Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __STW_SYSTEM_TIMER_H__ +#define __STW_SYSTEM_TIMER_H__ + +#include "safe_types.h" +#include "stw_timer.h" + + +/* + * Utility routine to initialize the links of timer elements. + */ +extern void +stw_system_timer_prepare(stw_tmr_t *tmr); + + +/* + * Displays timer wheel stats and counters to stdout. + */ +extern void +stw_system_timer_stats(void); + + +/* + * Returns the active status of a timer. + */ +extern boolean_t +stw_system_timer_running(stw_tmr_t *tmr); + + +/* + * Starts a new timer. If the timer is currently + * running, it is stopped and restarted anew. + */ +extern RC_STW_t +stw_system_timer_start(stw_tmr_t *tmr, + uint32_t delay, + uint32_t periodic_delay, + stw_call_back user_cb, + void *parm); + +/* + * Stops a currently running timer + */ +extern RC_STW_t +stw_system_timer_stop(stw_tmr_t *); + + +/* + * System Timer Wheel tick handler + */ +extern void +stw_system_timer_tick(void); + + +/* + * destroy the R2CP timer wheel + */ +extern RC_STW_t +stw_system_timer_destroy(void); + + +/* + * Creates and initializes the R2CP timer wheel + */ +extern RC_STW_t +stw_system_timer_create(uint32_t wheel_size, + uint32_t granularity, + const char *name); + + +#endif /* __STW_SYSTEM_TIMER_H__ */ + diff --git a/dlep_radio_ipv6/stw_timer.c b/dlep_radio_ipv6/stw_timer.c new file mode 100644 index 0000000..c175245 --- /dev/null +++ b/dlep_radio_ipv6/stw_timer.c @@ -0,0 +1,762 @@ +/*------------------------------------------------------------------ + * stw_timer.c -- Single Timer Wheel Timer + * + * February 2005, Bo Berry + * + * Copyright (c) 2002-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#include +#include +#include + +#include "runtime_environment.h" +#include "safe_types.h" + +#include "stw_timer.h" + + +/* + * used to verify wheel pointers. Nothing special about + * the value, other than to help identify a valid stw pointer + */ +#define MAGIC_TAG ( 0x0FEDCA3BA ) + + +/* + * NAME + * tmr_enqueue + * + * SYNOPSIS + * #include "stw_timer.h" + * static void + * tmr_enqueue(stw_t *stw, stw_tmr_t *tmr, uint32_t delay) + * + * DESCRIPTION + * Enqueues the timer to the proper spoke per delay. + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel that the timer + * will run on + * + * *tmr - pointer to the timer element + * + * delay - delay in milliseconds + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + */ +static void +tmr_enqueue (stw_t *stw, stw_tmr_t *tmr, uint32_t delay) +{ +printf("tmr_enqueue\n"); + stw_links_t *prev, *spoke; + + uint32_t cursor; + uint32_t ticks; + uint32_t td; + + /* + * BEGIN CRITICAL REGION + */ + LOCK_INTERRUPTS(); + + if (delay < stw->granularity) { + /* + * must delay at least one tick, can not delay in past... + */ + ticks = 1; + + } else { + /* + * compute number ticks reqquired to expire the duration + */ + ticks = (delay / stw->granularity); + } + + /* + * tick displacement from current cursor + */ + td = (ticks % stw->wheel_size); + + /* + * times around the wheel required to expire duration + */ + tmr->rotation_count = (ticks / stw->wheel_size); + + /* + * calculate cursor to place the timer + */ + cursor = ((stw->spoke_index + td) % stw->wheel_size); + + spoke = &stw->spokes[cursor]; + /* + * We have a timer and now we have a spoke. All that is left is to + * link the timer to the spoke's list of timers. With a doubly linked + * list, there is no need to check for an empty list. We simply link + * it to the end of the list. This is the same price as putting it + * on the front of the list but feels more 'right'. + */ + prev = spoke->stw_prev; + tmr->links.stw_next = spoke; /* append to end of spoke */ + tmr->links.stw_prev = prev; + + prev->stw_next = (stw_links_t *)tmr; + spoke->stw_prev = (stw_links_t *)tmr; + + UNLOCK_INTERRUPTS(); + /* + * END CRITICAL REGION + */ + + return; +} + + + +/** + * NAME + * stw_timer_stats + * + * SYNOPSIS + * #include "stw_timer.h" + * void + * stw_timer_stats(const stw_t *stw) + * + * DESCRIPTION + * Displays the stats for the specified timer wheel. + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +stw_timer_stats (const stw_t *stw) +{ + /* + * protect against a bad wheel + */ + if ((stw == NULL) || (stw->magic_tag != MAGIC_TAG)) { + return; + } + + printf("\n%s \n", stw->wheel_name ); + printf(" Granularity=%u\n", stw->granularity); + printf(" Wheel Size=%u\n", stw->wheel_size); + printf(" Tick Count=%u\n", stw->ticks); + printf(" Spoke Index=%u\n", stw->spoke_index); + + printf(" Active timers=%u\n", stw->timer_active); + printf(" Expired timers=%u\n", stw->timer_expired); + printf(" Hiwater mark=%u\n", stw->timer_hiwater_mark); + printf(" Started timers=%u\n", stw->timer_starts); + printf(" Cancelled timers=%u\n", stw->timer_cancelled); + return; +} + + +/** + * NAME + * stw_timer_running + * + * SYNOPSIS + * #include "stw_timer.h" + * boolean_t + * stw_timer_running(stw_tmr_t *tmr) + * + * DESCRIPTION + * RETURN VALUE TRUE if the timer structure is active + * + * INPUT PARAMETERS + * *tmr - pointer to the timer + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * TRUE==timer is active + * FALSE==timer is not active + * + */ +boolean_t +stw_timer_running (stw_tmr_t *tmr) +{ + if (tmr == NULL) { + return (FALSE); + } + + /* + * if the timer is linked, its active + */ + if (tmr->links.stw_next != NULL) { + return (TRUE); + } + + return (FALSE); +} + + +/** + * NAME + * stw_timer_prepare + * + * SYNOPSIS + * #include "stw_timer.h" + * void + * stw_timer_prepare(stw_tmr_t *tmr) + * + * Descriiption + * Utility routine to initialize the links of timer elements. + * + * INPUT PARAMETERS + * *tmr - pointer to the timer + * + * OUTPUT PARAMETERS + * *tmr - The timer links are initialized. + * + * RETURN VALUE + * none + * + */ +void +stw_timer_prepare (stw_tmr_t *tmr) +{ + if (tmr) { + tmr->links.stw_next = NULL; + tmr->links.stw_prev = NULL; + } +} + + +/** + * NAME + * stw_timer_start + * + * SYNOPSIS + * #include "stw_timer.h" + * RC_STW_t + * stw_timer_start(stw_t *stw, + * stw_tmr_t *tmr, + * uint32_t delay, + * uint32_t periodic_delay, + * stw_call_back user_cb, + * void *parm) + * + * DESCRIPTION + * Start (or restart) a timer to expire in the future. If the timer is + * currently linked to a timer wheel spoke, it will be removed + * first. A new timer spoke will be determined based on the millisecond + * time delay requested and linked into the appropriate + * timer wheel spoke. + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel + * + * *tmr - pointer to the timer element + * + * delay - initial delay in milliseconds + * + * periodic_delay - periodic delay in milliseconds + * + * user_cb - application function call-back to be + * invoked when the timer expires. This call-back + * must run-to-completion and not block. + * + * parm - persistent parameter passed to the application + * call-back upon expiration + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_timer_start (stw_t *stw, + stw_tmr_t *tmr, + uint32_t delay, + uint32_t periodic_delay, + stw_call_back user_cb, + void *parm) +{ + stw_links_t *next, *prev; + + + if (stw == NULL) { + return (RC_STW_NULL_WHEEL); + } + + if (tmr == NULL) { + return (RC_STW_NULL_TMR); + } + + if (stw->magic_tag != MAGIC_TAG) { + return (RC_STW_INVALID_WHEEL); + } + + + /* + * BEGIN CRITICAL REGION + */ + LOCK_INTERRUPTS(); + + /* + * First check to see if it is already running. If so, remove + * it from the wheel. We don't bother cleaning up the fields + * because we will be setting them below. + */ + next = tmr->links.stw_next; + if (next) { + prev = tmr->links.stw_prev; + next->stw_prev = prev; + prev->stw_next = next; + + /* + * stats book keeping + */ + stw->timer_active--; + } + + UNLOCK_INTERRUPTS(); + /* + * END CRITICAL REGION + */ + + + /* + * set user call_back and parameter + */ + tmr->func_ptr = user_cb; + tmr->parm = parm; + tmr->delay = delay; + tmr->periodic_delay = periodic_delay; + + tmr_enqueue(stw, tmr, delay); + + + stw->timer_starts++; + stw->timer_active++; + if (stw->timer_active > stw->timer_hiwater_mark) { + stw->timer_hiwater_mark = stw->timer_active; + } + + return (RC_STW_OK); +} + + +/** + * NAME + * stw_timer_stop + * + * SYNOPSIS + * #include "stw_timer.h" + * RC_STW_t + * stw_timer_stop(stw_t *stw, stw_tmr_t *tmr) + * + * DESCRIPTION + * Stop the timer by removing it from whatever timer wheel spoke list + * it is currently attached to (if any). Note that it is safe to call + * this function with a timer that has already been stopped in order to + * avoid making all callers check for a running timer first. + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel + * + * *tmr - pointer to the timer element + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_timer_stop (stw_t *stw, stw_tmr_t *tmr) +{ + stw_links_t *next, *prev; + + if (stw == NULL) { + return (RC_STW_NULL_WHEEL); + } + + if (tmr == NULL) { + return (RC_STW_NULL_TMR); + } + + if (stw->magic_tag != MAGIC_TAG ) { + return (RC_STW_INVALID_WHEEL); + } + + /* + * BEGIN CRITICAL REGION + */ + LOCK_INTERRUPTS(); + + next = tmr->links.stw_next; + if (next) { + prev = tmr->links.stw_prev; + next->stw_prev = prev; + prev->stw_next = next; + tmr->links.stw_next = NULL; /* NULL == tmr is free */ + tmr->links.stw_prev = NULL; + + /* + * stats bookkeeping + */ + stw->timer_active--; + stw->timer_cancelled++; + } + + UNLOCK_INTERRUPTS(); + /* + * END CRITICAL REGION + */ + + return (RC_STW_OK); +} + + +/** + * NAME + * stw_timer_tick + * + * SYNOPSIS + * #include "stw_timer.h" + * void + * stw_timer_tick(stw_t *stw) + * + * DESCRIPTION + * This function moves the wheel cursor forward to the + * next spoke and expire the timers. + * + * Application call-backs must be non-blocking + * + * INPUT PARAMETERS + * *stw - pointer to the timer wheel + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * none + * + */ +void +stw_timer_tick (stw_t *stw) +{ + stw_links_t *spoke, *next, *prev; + stw_tmr_t *tmr; + + stw_call_back user_call_back; + + if ((stw == NULL) || (stw->magic_tag != MAGIC_TAG)) { + return; + } + + /* + * keep track of rolling the wheel + */ + stw->ticks++; + + /* + * advance the index to the next spoke + */ + stw->spoke_index = ( stw->spoke_index + 1 ) % + stw->wheel_size; + + /* + * Process the spoke, removing timers that have expired. + * If the timer rotation count is positive + * decrement and catch the timer on the next wheel revolution. + */ + spoke = &stw->spokes[stw->spoke_index]; + tmr = (stw_tmr_t *)spoke->stw_next; + + while( (stw_links_t *)tmr != spoke) { + + next = (stw_links_t *)tmr->links.stw_next; + prev = (stw_links_t *)tmr->links.stw_prev; + + /* + * if the timer is a long one and requires one or more rotations + * decrement rotation count and leave for next turn. + */ + if (tmr->rotation_count != 0) { + tmr->rotation_count--; + } else { + + /* + ** BEGIN CRITICAL REGION + */ + LOCK_INTERRUPTS(); + + prev->stw_next = next; + next->stw_prev = prev; + + tmr->links.stw_next = NULL; + tmr->links.stw_prev = NULL; + + /* book keeping */ + stw->timer_active--; + stw->timer_expired++; + + UNLOCK_INTERRUPTS(); + /* + ** END CRITICAL REGION + */ + + /* + * automatically restart the timer if periodic_delay > 0 + */ + if (tmr->periodic_delay > 0) { + tmr_enqueue(stw, tmr, tmr->periodic_delay); + stw->timer_active++; + } + + /* + * Invoke the user expiration handler to do the actual work. + */ + user_call_back = tmr->func_ptr; + (*user_call_back)(tmr, tmr->parm); + + } + + tmr = (stw_tmr_t *)next; + } + return; +} + + +/** + * NAME + * stw_timer_destroy + * + * SYNOPSIS + * #include "stw_timer.h" + * + * DESCRIPTION + * Destroys the specified timer wheel. All + * timers are stopped and resources released. + * + * INPUT PARAMETERS + * stw - pointer to the timer wheel + * + * OUTPUT PARAMETERS + * none + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_timer_destroy (stw_t *stw) +{ + uint32_t j; + stw_links_t *spoke; + + stw_tmr_t *tmr; + + + if (stw == NULL) { + return (RC_STW_NULL_WHEEL); + } + + if (stw->magic_tag != MAGIC_TAG ) { + return (RC_STW_INVALID_WHEEL); + } + + + /* + * Drive around the wheel and stop all timers + */ + + for (j = 0; j < stw->wheel_size; j++) { + spoke = &stw->spokes[j]; + + tmr = (stw_tmr_t *)spoke->stw_next; + + while ( (stw_links_t *)tmr != spoke) { + stw_timer_stop(stw, tmr); + + tmr = (stw_tmr_t *)spoke->stw_next; + } /* end while */ + + } /* end for */ + + /* + * clear the magic so we do not mistakenly access this wheel + */ + stw->magic_tag = 0; + + /* + * now free the wheel structures + */ + free(stw->spokes); + free(stw); + + return (RC_STW_OK); +} + + +/** + * NAME + * stw_timer_create + * + * SYNOPSIS + * #include "stw_timer.h" + * RC_STW_t + * stw_timer_create(uint32_t wheel_size, + * uint32_t granularity, + * const char *p2name, + * stw_t **stw) + * + * DESCRIPTION + * This function creates and initializes the timer wheel. Timers + * must not be started before this routine is called. + * + * Parmeters + * wheel_size - number of spokes in the wheel. The number + * of spokes should be engineered such that + * wheel_size >= (longest duration / granularity) + * Depending upon the number of concurrent timers, the + * distribution of those timers, it may be beneficial to + * further increase the wheel size. Objective is to + * minimize frequency of 'long' timers requiring wheel + * revolutions. + * + * granularity - milliseconds between ticks + * + * *p2name - pointer to the name of identify wheel. Limited + * to STW_NAME_LENGTH + * + * **stw - returned pointer to the created timer wheel + * + * RETURN VALUE + * RC_STW_OK + * error otherwise + * + */ +RC_STW_t +stw_timer_create (uint32_t wheel_size, + uint32_t granularity, + const char *p2name, + stw_t **stw) +{ + uint32_t j; + stw_links_t *spoke; + + stw_t *p2stw; + + + if (stw == NULL) { + return (RC_STW_NULL_WHEEL); + } + *stw = NULL; + + /* + * we need to put some bounds to protect against extremely + * large numbers + */ + if (wheel_size < STW_MIN_WHEEL_SIZE || wheel_size > STW_MAX_WHEEL_SIZE) { + return (RC_STW_INVALID_WHEEL_SIZE); + } + + if (granularity < STW_MIN_GRANULARITY || + granularity > STW_MAX_GRANULARITY) { + return (RC_STW_INVALID_GRANULARITY); + } + + /* + * allocate memory for wheel control structure + */ + p2stw = (stw_t *)malloc( sizeof(stw_t)); + if (p2stw == NULL) { + return (RC_STW_NO_RESOURCES); + } + + /* + * allocate memory for wheel spokes + */ + p2stw->spokes = (stw_links_t *)malloc(wheel_size * sizeof(stw_links_t)); + if (p2stw->spokes == NULL) { + free(p2stw); + return (RC_STW_NO_RESOURCES); + } + + + /* + * Initialize the internal tick count at zero, should use + * safe string lib! + */ + strncpy(p2stw->wheel_name, p2name, STW_NAME_LENGTH-1); + p2stw->wheel_name[STW_NAME_LENGTH-1] = '\0'; + + p2stw->magic_tag = MAGIC_TAG; + + p2stw->ticks = 0; + + p2stw->spoke_index = 0; + p2stw->granularity = granularity; + p2stw->wheel_size = wheel_size; + + /* + * timer stats to tune wheel + */ + p2stw->timer_hiwater_mark = 0; + p2stw->timer_active = 0; + p2stw->timer_cancelled=0; + p2stw->timer_expired=0; + p2stw->timer_starts=0; + + /* + * Set all spokes to empty + */ + spoke = &p2stw->spokes[0]; + for (j = 0; j < wheel_size; j++) { + spoke->stw_next = spoke; /* empty spoke points to itself */ + spoke->stw_prev = spoke; + spoke++; + } + + *stw = p2stw; + return (RC_STW_OK); +} + + diff --git a/dlep_radio_ipv6/stw_timer.h b/dlep_radio_ipv6/stw_timer.h new file mode 100644 index 0000000..60219c6 --- /dev/null +++ b/dlep_radio_ipv6/stw_timer.h @@ -0,0 +1,234 @@ +/*------------------------------------------------------------------ + * stw_timer.h -- Definitions for Single Timer Wheel + * + * Februrary 2002, Bo Berry + * + * Copyright (c) 2005-2009 by Cisco Systems, Inc. + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + *------------------------------------------------------------------ + */ + +#ifndef __STW_TIMER_H__ +#define __STW_TIMER_H__ + +#include "safe_types.h" + + +/* + * This file provides the public definitions for external users of the + * Timer Wheel Timer facility. + * + * The Single Timer Wheel Timer facility is optimized to support embedded + * timer structures, ie where the timer structure is integrated into the + * structure it is associated with. + * + * Definitions + * + * Spoke - A queue of timers set to expire. A timer wheel consists of + * multiple spokes. + * + * Granularity - The amount of time between the processing of each + * spoke. Granularity is measured in time units between ticks. + * + * Rotation - one complete turn around the wheel + * + * Timer Duration given 32 bits + * Time per Tick Duration + * ------------------------------------ + * 10ms 497.1 days + * 20ms 994.2 + * 50ms 2485.5 + * + * milliseconds per day [1000 * 60 * 60 * 24] + * + */ + + +typedef enum { + RC_STW_OK = 0, + RC_STW_NULL_NAME, + RC_STW_NULL_FV, + RC_STW_NULL_WHEEL, + RC_STW_NULL_TMR, + RC_STW_INVALID_WHEEL, + RC_STW_INVALID_WHEEL_SIZE, + RC_STW_INVALID_GRANULARITY, + RC_STW_NO_RESOURCES, +} RC_STW_t; + + + +/* + * we need to put some bounds to protect against extremely + * large numbers. Ranges selected from pratical experience. + */ + +/* + * range of valid wheel sizes + */ +#define STW_MIN_WHEEL_SIZE ( 32 ) +#define STW_MAX_WHEEL_SIZE ( 4096 ) + +/* + * Granularity of a timer tick in milliseconds + */ +#define STW_MIN_GRANULARITY ( 1 ) +#define STW_MAX_GRANULARITY ( 100 ) + + +/* + * stw_links + * Definition of the pointers used to link a timer into + * a spoke. Double-linked list for efficiency. + */ +typedef struct stw_links_t_ { + struct stw_links_t_ *stw_next; + struct stw_links_t_ *stw_prev; +} stw_links_t; + + + +/* + * Timer Wheel Structure used to manage the timer wheel + * and keep stats to help understand performance + */ +#define STW_NAME_LENGTH ( 32 ) + +typedef struct { + char wheel_name[ STW_NAME_LENGTH ]; + uint32_t magic_tag; /* for sanity check */ + uint32_t wheel_size; + uint32_t spoke_index; /* mod index around wheel */ + uint32_t ticks; /* absolute ticks */ + uint32_t granularity; /* millisecond per tick */ + + /* + * few book keeping parameters to help engineer the wheel + */ + uint32_t timer_hiwater_mark; + uint32_t timer_active; + uint32_t timer_cancelled; + uint32_t timer_expired; + uint32_t timer_starts; + + stw_links_t *spokes; +} stw_t; + + +/* + * stw_tmr_t + * Definition of a timer element. + * This can be malloc'ed or embedded into an existing + * application structure. + */ +typedef struct { + stw_links_t links; + uint32_t rotation_count; + uint32_t delay; /* initial delay */ + uint32_t periodic_delay; /* auto-restart if > 0 */ + void *func_ptr; + void *parm; +} stw_tmr_t; + + +/* + * Application call-back type to be invoked at timer + * expiration. The call-back must be short-n-sweet, + * non-blocking. + */ +typedef void (*stw_call_back)(stw_tmr_t *tmr, void *parm); + + + +/* + * stw_timer_running + * RETURN VALUEs TRUE if the timer is active + */ +extern boolean_t +stw_timer_running(stw_tmr_t *tmr); + + +/* + * stw_timer_prepare + * Utility routine to initialize the links of timer elements. + */ +extern void +stw_timer_prepare(stw_tmr_t *tmr); + + +/* + * Displays timer wheel stats and counters to stdout. + */ +extern void +stw_timer_stats(const stw_t *stw); + + +/* + * Starts a new timer. If the timer is currently running, + * it is stopped and restarted anew + */ +extern RC_STW_t +stw_timer_start(stw_t *stw, + stw_tmr_t *tmr, + uint32_t delay, + uint32_t periodic_delay, + stw_call_back user_cb, + void *parm); + + +/* + * stops a currently running timer + */ +extern RC_STW_t +stw_timer_stop(stw_t *stw, stw_tmr_t *tmr); + + +/* + * Timer Wheel tick handler which drives time for the + * specified wheel + */ +extern void +stw_timer_tick(stw_t *stw); + + +/* + * Destroys a timer wheel + */ +extern RC_STW_t +stw_timer_destroy(stw_t *stw); + + +/* + * creates and initializes a single timer wheel + */ +extern RC_STW_t +stw_timer_create(uint32_t wheel_size, + uint32_t granularity, + const char *name, + stw_t **stw); + + +#endif /* __STW_TIMER_H__ */ + + diff --git a/dlep_radio_ipv6/tags b/dlep_radio_ipv6/tags new file mode 100644 index 0000000..ec9404f --- /dev/null +++ b/dlep_radio_ipv6/tags @@ -0,0 +1,450 @@ +DEBUG_PRINTF cli.c /^#define DEBUG_PRINTF(myargs...) printf(myargs) $/ +DEBUG_PRINTF cli.c /^#define DEBUG_PRINTF(myargs...) ((void)0)$/ +GETSHORT dlep_porter.c /^#define GETSHORT(ptr) ((unsigned char *)ptr)[0] < (UINT32_MAX / 1000 / 1000)) { + nanoseconds = 0; + } else { + nanoseconds = (milliseconds * 1000 * 1000); + } + + return (nanoseconds); +} + + +/* + * Converts milliseconds to microseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t milli_to_microseconds (uint32_t milliseconds) +{ + uint32_t microseconds; + + if (milliseconds > (UINT32_MAX / 1000)) { + microseconds = 0; + } else { + microseconds = (milliseconds * 1000); + } + return (microseconds); +} + + +/* + * Converts milliseconds to seconds. + * Can return 0. + */ +static inline uint32_t milli_to_seconds (uint32_t milliseconds) +{ + return (milliseconds / 1000); +} + + +/* + * Converts seconds to nanoseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t secs_to_nanoseconds (uint32_t seconds) +{ + uint32_t nanoseconds; + + if (seconds > (UINT32_MAX / 1000 / 1000 / 1000)) { + nanoseconds = 0; + } else { + nanoseconds = (seconds * 1000 * 1000 * 1000); + } + return (nanoseconds); +} + + +/* + * Converts seconds to microseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t secs_to_microseconds (uint32_t seconds) +{ + uint32_t microseconds; + + if (seconds > (UINT32_MAX / 1000 / 1000)) { + microseconds = 0; + } else { + microseconds = (seconds * 1000 * 1000); + } + return (microseconds); +} + + +/* + * Converts seconds to milliseconds. + * RETURN VALUEs 0 if there is an overflow. + */ +static inline uint32_t secs_to_milliseconds (uint32_t seconds) +{ + uint32_t milliseconds; + + if (seconds > (UINT32_MAX / 1000)) { + milliseconds = 0; + } else { + milliseconds = (seconds * 1000); + } + return (milliseconds); +} + + +#endif +