diff options
370 files changed, 24746 insertions, 19851 deletions
@@ -1,5 +1,5 @@ [tool] [tool.commitizen] name = "cz_conventional_commits" -version = "22.02" +version = "3.14.0" tag_format = "v$version" diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..620933eb0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,1030 @@ +## v3.14.0 (2022-07-18) + +### Feat + +- release 3.14 of hicn +- move interest manifest inside libhicn to be reused by hicn-plugin +- include wrapper asio files +- include wrapper asio files +- rewrite new PCS, backed by clib_bihash + +### Fix + +- **lib**: install interest manifest header +- **hicn-light**: code style +- **hicn-light**: fix connection table issue +- **hicn-light**: fix connection table issue +- **hicn-light**: fix crash on connection close +- **hicn-light**: fix interest send on mac os +- **transport**: fix udp connector for mac os +- do not reuse vpp struct/macros in libhicn +- **ci/docker-build-ios.sh**: accept ios dockerfile eula +- **core**: add ifndef to compile on macos +- **pcs.h**: align PCS entry to 64 bytes in place of CLIB_CACHELINE + +## v3.13.0 (2022-06-17) + +## v3.13.0b0 (2022-06-16) + +### Feat + +- release 3.13 of hicn +- **transport**: codel style +- **transport**: imporve switch between RTX and FEC with variable RTT +- **transport**: improve fec for low rtt +- **aggregated-interests**: fix multipath with aggregated interests +- packet generator to assess performance +- **hicn-light-collectd**: add per-face stats in collectd plugin +- **hicn-light-collectd**: add per-face stats in forwarder +- **hicn-light-collectd**: update cmake for vpp collectd plugins +- **hicn-light-collectd**: modify kafka output collectd plugin to use influxdb format and do dispatching +- **hicn-light-collectd**: use input collectd plugin to retrieve stats from forwarder +- **hicn-light-collectd**: expose libhicnctrl api to retrieve hicn-light stats +- **hicn-light-collectd**: setup cmake for hicn-light and kafka plugins +- **transport**: set the expirtation time of the data packets using socket options +- **libtransport**: use microseconds to improve RTT precision +- **aggregated-interests**: enable aggregated interests at runtime +- **aggregated-interests**: add aggregated interest support in transport +- **hicn-plugin**: parse hicn packet only one time, as soon as it is received +- **transport**: modify delay in delay strategy +- **manifest**: improve encoding and decoding +- **aggregated-interests**: add signature to interest manifest +- **aggregated-interests**: add disaggregation and bitmap in interest manifest +- **libhicn**: move common data structures in lib +- **vector**: add missing api functions to vector data structure +- **libhicn**: use same map data structure between hicn-light and hicn-ctrl +- **libtransport**: remove all references to ntoh and hton +- **packet-cache**: add CS clear in hicn-light +- **portal.h**: modify PIT to register penging interests in both sides +- **libtransport**: add global module manager and library constructor +- multistream hiperf +- **libtransport**: add cache prefetch support and test to assess performance +- Add API to get/set ports in libhicn +- add enumeration for packet type in libhicn +- **pool**: remove unnecessary memset in pool and add script to test hiperf locally +- **packet-cache**: avoid double lookups when possible +- **packet-cache**: add two-level packet cache +- **hicn-ping**: add interest manifest support in hicn-ping +- sync build scripts with master-fdio +- **auth**: use membuf + +### Fix + +- **hiperf**: fix buffer contention when using multiple producers +- **manifest**: remove unnecessary debug assert +- better organize flags in hicn-plugin +- replace deprecated std::random_shuffle function +- **transport**: use constant var in recovery strategy baeds on delay +- **hiperf**: fix bandwidth computaton in hiperf +- **manifest**: compilation error +- **libhicnctrl**: fix name generation for new faces +- **libhicnctrl**: fix name generation for new faces +- fix memory corruption in msgbuf ids vector +- **hicn-light**: fix hardcoded limit on number of pending connections +- **hicn-light**: return error when not able to generate new connection name +- **transport**: fix forwarder io module in transport +- **auth**: invalid memory read in signer +- **libtransport**: pass all required callbacks when creating connectors +- fix htonll and ntohll in libhicn +- **packet-cache**: add missing data prefix caching on content packet received +- **production_protocol.h**: do not accept unvalid values of TRANSPORT_FEC_TYPE if environment variable is set +- use proper function to compare elements in listener and conenction table +- **docker**: do no use internal image in public dockerfile and remove old functional tests +- **fec**: correctly compute the transport header size of each packet +- **transport**: add rs fec header size also in the decoder +- **transport**: fix max packet size in producer socket +- **prod_protocol_rtc.cc**: check if fec_type is valid before using it +- **hicnctrl**: fix route command validation + +### Perf + +- **transport**: reduce cpu usage at RTC consumer socket for loss detection + +### Refactor + +- **tls**: remove support for TLS +- **manifest**: move decoding of manifest out of decoder constructor +- move interest manifest header to libhicn and update log +- refactor listener and connection table +- **manifest**: improve manifest verification and performance + +## v3.12.2 (2022-06-01) + +### Fix + +- **lib/includes/hicn/util/bitmap.h**: correct include header + +## v3.12.1 (2022-06-01) + +### Fix + +- **cmake**: wrong version number in hicn + +## v3.12.0 (2022-05-31) + +### Feat + +- release 3.12 of hicn +- **aggregated-interests**: add signature to interest manifest +- **aggregated-interests**: add disaggregation and bitmap in interest manifest +- **libhicn**: move common data structures in lib +- **vector**: add missing api functions to vector data structure +- **libhicn**: use same map data structure between hicn-light and hicn-ctrl +- **libtransport**: remove all references to ntoh and hton +- **packet-cache**: add CS clear in hicn-light +- **portal.h**: modify PIT to register penging interests in both sides +- **libtransport**: add global module manager and library constructor +- multistream hiperf +- **libtransport**: add cache prefetch support and test to assess performance +- Add API to get/set ports in libhicn +- add enumeration for packet type in libhicn +- **pool**: remove unnecessary memset in pool and add script to test hiperf locally +- **packet-cache**: avoid double lookups when possible +- **packet-cache**: add two-level packet cache +- **hicn-ping**: add interest manifest support in hicn-ping +- sync build scripts with master-fdio +- **auth**: use membuf + +### Fix + +- **libhicnctrl**: fix name generation for new faces +- **libhicnctrl**: fix name generation for new faces +- fix memory corruption in msgbuf ids vector +- **hicn-light**: fix hardcoded limit on number of pending connections +- **hicn-light**: return error when not able to generate new connection name +- **transport**: fix forwarder io module in transport +- **auth**: invalid memory read in signer +- **libtransport**: pass all required callbacks when creating connectors +- fix htonll and ntohll in libhicn +- **packet-cache**: add missing data prefix caching on content packet received +- **production_protocol.h**: do not accept unvalid values of TRANSPORT_FEC_TYPE if environment variable is set +- use proper function to compare elements in listener and conenction table +- **docker**: do no use internal image in public dockerfile and remove old functional tests +- **fec**: correctly compute the transport header size of each packet +- **transport**: add rs fec header size also in the decoder +- **transport**: fix max packet size in producer socket +- **prod_protocol_rtc.cc**: check if fec_type is valid before using it +- **hicnctrl**: fix route command validation + +### Refactor + +- **manifest**: move decoding of manifest out of decoder constructor +- move interest manifest header to libhicn and update log +- refactor listener and connection table +- **manifest**: improve manifest verification and performance + +## v3.11.3 (2022-04-18) + +### Feat + +- **manifest**: optimize manifest processing + +## v3.11.2 (2022-04-13) + +### Fix + +- **manifest**: do not iterate on full data buffer to compute ratio + +## v3.11.1 (2022-04-13) + +### Fix + +- **manifest**: ignore manifest entries of discarded unverified packets + +## v3.11.0 (2022-04-11) + +## v3.11.0b0 (2022-04-08) + +### Feat + +- release 3.11 of hicn +- **manifest**: add FEC parameters to manifests +- **manifest**: refactor verification process +- **manifest**: report auth alerts in hiperf instead of aborting +- **manifest**: remove FEC buffer callback in consumer +- **manifest**: refactor and enable manifests by default +- **manifest**: update manifest header with transport parameters +- **manifest**: batch interests for first manifest from RTC producer +- **manifest**: refactor processing of RTC manifests +- **manifest**: update manifest-related socket options of consumers +- **manifest**: update unit tests for manifests +- **manifest**: pack manifest headers +- **manifest**: verify FEC packets +- **auth**: add consumer socket option to set max unverified delay +- **manifest**: process manifests after full FEC decoding +- **manifest**: manage forward jumps in RTC verifier +- **fec**: remove useless fec codes +- **rs**: add new code rate +- **rs**: add new code rate +- **rs**: add new code rate +- **rs**: add new code rate +- **libtransport**: increase internal packet cache size +- remove internal cisco info in cmake +- **manifest**: add option to set manifest capacity +- **data_input_node.c**: add information about adj_index[VLIB_RX] on received data packets +- **hicn-plugin**: upgrade to VPP 22.02 + +### Refactor + +- **manifest**: change default manifest options to support low-rate +- remove remaining traces of fec type option +- **hiperf**: cosmetic update +- **manifest**: apply code reviews +- **auth**: change auth failed callback signature + +### Fix + +- **strategy-callbacks**: fix callback calls when transport is out of scope +- **bitmap**: fix bitmap set operation +- **transport**: avoid to add fec at start up if no loss is detected +- **notifications**: add callbacks for forwarding/recovery strategy changes +- **face_node.c**: ensure IPv6 loopback is not interpreted as IPv4 address +- **manifest**: fix segfault with RS + manifests +- **manifest**: support RS +- **auth**: verify previously unverified packet signatures +- **bytestream**: make manifest branch work with RAAQM +- **pathlabel**: fix data path label in the hicn-light forwarder +- **deps**: fix cisco openssl and safec dependencies inclusion +- **udp_connector.cc**: call receive callback with correct parameters +- cannot retrieve integer producer socket option +- **fec.cc**: correct fec after wrong merge +- **liiib/CMakeLists.txt**: correct typo + +## v3.10.0 (2022-04-02) + +### Feat + +- release 3.10 of hicn +- **manifest**: refactor verification process +- **manifest**: report auth alerts in hiperf instead of aborting +- **manifest**: remove FEC buffer callback in consumer +- **manifest**: refactor and enable manifests by default +- **manifest**: update manifest header with transport parameters +- **manifest**: batch interests for first manifest from RTC producer +- **manifest**: refactor processing of RTC manifests +- **manifest**: update manifest-related socket options of consumers +- **manifest**: update unit tests for manifests +- **manifest**: pack manifest headers +- **manifest**: verify FEC packets +- **auth**: add consumer socket option to set max unverified delay +- **manifest**: process manifests after full FEC decoding +- **manifest**: manage forward jumps in RTC verifier +- **fec**: remove useless fec codes +- **rs**: add new code rate +- **rs**: add new code rate +- **rs**: add new code rate +- **rs**: add new code rate +- **libtransport**: increase internal packet cache size +- remove internal cisco info in cmake +- **manifest**: add option to set manifest capacity +- **hicn-plugin**: upgrade to VPP 22.02 + +### Fix + +- **transport**: avoid to add fec at start up if no loss is detected +- **notifications**: add callbacks for forwarding/recovery strategy changes +- **face_node.c**: ensure IPv6 loopback is not interpreted as IPv4 address +- **manifest**: fix segfault with RS + manifests +- **manifest**: support RS +- **auth**: verify previously unverified packet signatures +- **bytestream**: make manifest branch work with RAAQM +- **pathlabel**: fix data path label in the hicn-light forwarder +- **deps**: fix cisco openssl and safec dependencies inclusion +- **udp_connector.cc**: call receive callback with correct parameters +- cannot retrieve integer producer socket option + +### Refactor + +- **hiperf**: cosmetic update +- **manifest**: apply code reviews +- **auth**: change auth failed callback signature + +## v3.9.1 (2022-03-21) + +### Fix + +- **route**: fix route creation failure when id instead of symbolic + +## v3.9.0 (2022-03-21) + +### Feat + +- release 3.9 +- **data_input_node.c**: add information about adj_index[VLIB_RX] on received data packets +- **hicn-plugin**: upgrade to VPP 22.02 + +### Fix + +- **liiib/CMakeLists.txt**: correct typo + +## v3.8.1 (2022-03-15) + +### Fix + +- **android-sdk**: upgrade android-sdk version + +## v3.8.0 (2022-03-14) + +## v3.8.0b0 (2022-03-12) + +### Feat + +- release 3.8 of hicn +- **ci**: install correct VPP version in local ci scripts +- **Makefile**: add conveniente targets to build/use docker container +- **security**: define custom secure functions if not available +- **security**: improve input validation +- insert CPU info as compilation options + +### Refactor + +- **fec**: do not include FEC header when copying FEC payload +- **auth**: clean up +- **CMakeLists.txt**: global cleanup of CMakeLists files + +### Fix + +- **probe-generator**: return probe register time (fix probe generator test) +- fix pool index validation and removal of current listener/connection +- **strcpy_s**: fix warnings appearing after strcpy_s introduction +- **security**: use secure version of strlen +- **security**: use secure version of strcpy +- **test-rs**: typo +- **rs-test**: fix packet index size +- **cmake**: add ciscossl path +- **fec-rate**: set max loss rate to 0.95 +- **loss-rate**: init loss rate using the rtt probes + +## v3.7.2 (2022-02-25) + +### Feat + +- update android-sdk version to 2.0.6 + +## v3.7.1 (2022-02-17) + +### Feat + +- use android-sdk image with librdkafka 1.8.2 + +## v3.7.0 (2022-02-17) + +### Fix + +- **CS**: correctly forward packets coming from the CS + +## v3.7.0b0 (2022-02-14) + +### Feat + +- release 3.7 of hicn +- **hicn-light-control**: distinguish between command and serialization errors +- **pit**: code style +- **pit**: code style +- **pit**: do not send aggregated interests +- **pit**: do not store state in the pit for interests with no nexthop +- add arm and x86 support to hicn +- **hicn-light-control**: add input validation in hicn-light-control parser +- **hicn-ctrl**: add command for notification subscription in hicn-light-control +- add vpp logs +- **hicn-plugin**: return the list of created faces after running hicn_route_enable. +- add constants for invalid face and invalid netdevice +- **packet-cache**: use Name instead of name_key_t as hashtable key +- **forwarder**: code style +- **hicn-light**: fix mapme packet processing +- **hicn-light**: remove commented code and missing initiliazations +- **forwarder**: fix tests +- **hicn-plugin**: add log +- create prod image of hicn +- **hicn-plugin**: allow UDP tunnels to be dynamically created upon interest reception. +- **hicn-plugin**: add support for UDP tunnels in mapme +- **strategy**: fix crash and nexthops compare +- **strategy**: fix add local prefixes +- **strategy**: add local prefixes and mapme updates to replication +- **strategy**: code style +- **strategy**: improve path switch +- **transport**: improve path switch +- **strategy**: set bestpath before send mapme message +- **strategy**: send mapme update at the end of each probing phase +- **hicn-light**: add support for strategy_add_local_prefix command from config file +- **facemgr**: use separate sockets for control and polling hicn-light +- **hicn-light**: close listener and connection file descriptors on forwarder stop +- **hicnctrl**: add timeout for recv operations +- **hicn-light**: remove hicnctrl connection from 'list connection' command output +- **listeners**: set local listeners without using resolver +- **doc**: update readme file +- **doc**: update readme file and authors' list + +### Fix + +- **parser**: add cast to compile in android +- **hicn-light-control**: fix missing error code in case of nack +- **hicn-light-control**: remove sopport for old forwarder +- **facemgr/libhicn**: Assigned value is garbage or undefined +- **facemgr**: Remove the commented out code +- **facemgr**: code/return will never be executed +- check that face_output sends interest to a complete face +- try not to keep a lock to dpo_ctx in each PIT entry. +- log route creation/deletion failures in linhicnctrl +- **memif_vapi.c**: initialize memif id before retrieving the next id to use. +- **libvapi_safe**: implement vapi_disconnect API +- **libhinctrl**: fix ring buffer management + refactor code +- **facemgr/netlink**: leaked facelets for interfaces not up and running +- **facemgr/hicn-light**: timerfd leak +- **hicnctrl**: fix notification processing +- **core::Portal**: ensure interest timeout handler refers to a valid Portal. +- **rtc-transport**: ensure RTC is running and valid before executing timer handlers +- **libhinctrl**: fix ring buffer management + refactor code +- **listener-table**: forbid creation of listener for already-existing address +- **connection-table**: fix multiple connections with same name +- **hicn-light**: fixed uninitialized memory in parser code +- **Jenkinsfile**: prod image is not created +- initialize listener memory +- **libhicnctrl**: remove useless size_in field in hicn_sock_request_t +- propagate listener hashtable fix in connection table and packet cache +- **listener-table**: fix listener removal from hashtable +- **dockerfile**: tests failed due the wrong docker image +- **rtc_state.h**: initialize rtc_state out of constructor +- **rtc_state.h**: check if RTCState is valid before dereferencing it. +- **hicn-light**: missing command_id in LIST command replies + cleanup +- producer face deletion does not delete the route from fib 0 +- **hicn-plugin**: insert drop node in the next nodes of face-node +- delete faces when lock count reaches 0 +- **libhicnctrl**: fix hardcoded AF_INET in hc_face_to_connection +- **facemgr/android**: handle missing android information on down interfaces +- **hicn-light**: fix memory leaks when forwarder is closed +- **hicn-light**: fix forwarder receive +- fix MacOS build errors + +### Perf + +- **hicn-light**: remove memory allocation inside name + +### Refactor + +- **packet-cache**: remove macro used in packet cache entry allocation +- **facemgr/hicn-light**: refactor poll timer code + +## v3.6.8 (2022-02-10) + +### Fix + +- **mapme**: Ignore updates from current nexthop with lower sequence number + +## v3.6.7 (2022-02-09) + +### Fix + +- **hicn-plugin**: get input face using source address lookup in place of using a list of possible incoming faces + +## v3.6.6 (2022-02-08) + +### Fix + +- **hicn-plugin**: remove unused in_face_id from PCS +- **hicn-plugin**: remove vector of in_face_id + +## v3.6.5 (2022-02-07) + +### Fix + +- **memif-connector**: signal send error up to application + +## v3.6.4 (2022-02-05) + +### Fix + +- add NH before deleting tfib entr + +## v3.6.3 (2022-02-05) + +### Fix + +- disable prints when hicn is compiled in release mode + +## v3.6.2 (2022-02-04) + +### Fix + +- **facemgr**: prevent incorrect free of facelet added to cache + +## v3.6.1 (2022-02-02) + +### Fix + +- use correct fib source when updating next hops with mapme + +## v3.6.0 (2022-02-01) + +### Fix + +- update cmake version +- check that face_output sends interest to a complete face +- try not to keep a lock to dpo_ctx in each PIT entry. +- log route creation/deletion failures in linhicnctrl +- **memif_vapi.c**: initialize memif id before retrieving the next id to use. +- **libvapi_safe**: implement vapi_disconnect API +- **libhinctrl**: fix ring buffer management + refactor code +- **facemgr/netlink**: leaked facelets for interfaces not up and running +- **facemgr/hicn-light**: timerfd leak +- **hicnctrl**: fix notification processing +- **core::Portal**: ensure interest timeout handler refers to a valid Portal. +- **rtc-transport**: ensure RTC is running and valid before executing timer handlers +- **libhinctrl**: fix ring buffer management + refactor code +- **listener-table**: forbid creation of listener for already-existing address +- **connection-table**: fix multiple connections with same name +- **hicn-light**: fixed uninitialized memory in parser code +- **Jenkinsfile**: prod image is not created +- initialize listener memory +- **libhicnctrl**: remove useless size_in field in hicn_sock_request_t +- propagate listener hashtable fix in connection table and packet cache +- **listener-table**: fix listener removal from hashtable +- **dockerfile**: tests failed due the wrong docker image +- **rtc_state.h**: initialize rtc_state out of constructor +- **rtc_state.h**: check if RTCState is valid before dereferencing it. +- **hicn-light**: missing command_id in LIST command replies + cleanup +- producer face deletion does not delete the route from fib 0 +- **hicn-plugin**: insert drop node in the next nodes of face-node +- delete faces when lock count reaches 0 +- **libhicnctrl**: fix hardcoded AF_INET in hc_face_to_connection +- **facemgr/android**: handle missing android information on down interfaces +- **hicn-light**: fix memory leaks when forwarder is closed +- **hicn-light**: fix forwarder receive +- fix MacOS build errors + +### Feat + +- release 3.6 of hicn +- add vpp logs +- **hicn-plugin**: return the list of created faces after running hicn_route_enable. +- add constants for invalid face and invalid netdevice +- **packet-cache**: use Name instead of name_key_t as hashtable key +- **forwarder**: code style +- **hicn-light**: fix mapme packet processing +- **hicn-light**: remove commented code and missing initiliazations +- **forwarder**: fix tests +- **hicn-plugin**: add log +- create prod image of hicn +- **hicn-plugin**: allow UDP tunnels to be dynamically created upon interest reception. +- **hicn-plugin**: add support for UDP tunnels in mapme +- **strategy**: fix crash and nexthops compare +- **strategy**: fix add local prefixes +- **strategy**: add local prefixes and mapme updates to replication +- **strategy**: code style +- **strategy**: improve path switch +- **transport**: improve path switch +- **strategy**: set bestpath before send mapme message +- **strategy**: send mapme update at the end of each probing phase +- **hicn-light**: add support for strategy_add_local_prefix command from config file +- **facemgr**: use separate sockets for control and polling hicn-light +- **hicn-light**: close listener and connection file descriptors on forwarder stop +- **hicnctrl**: add timeout for recv operations +- **hicn-light**: remove hicnctrl connection from 'list connection' command output +- **listeners**: set local listeners without using resolver +- **doc**: update readme file +- **doc**: update readme file and authors' list + +### Perf + +- **hicn-light**: remove memory allocation inside name + +### Refactor + +- **packet-cache**: remove macro used in packet cache entry allocation +- **facemgr/hicn-light**: refactor poll timer code + +## v3.5.0 (2022-01-15) + +## v3.5.0b0 (2022-01-14) + +### Feat + +- release 3.5 of hicn +- **quality-score**: expose quality score header file +- **bytestream**: add segment size option for bytestream production +- **strategy-map**: duplicate string before adding to strategy hashmap +- **hicn-light-control**: add help command +- **.cz.toml**: release 3.4 + +### Fix + +- **msgbuf-pool**: fix crash in msgbuf release when debug log is set to trace +- **hicn-light-control**: fix build error on android and clean hicn-light-control output + +## v3.4.3 (2021-12-20) + +### Fix + +- **facemgr/android**: adding mutex to protect facelet array across threads + +## v3.4.2 (2021-12-17) + +### Fix + +- **facemgr**: workaround for blocking operation preventing loop break + +## v3.4.1 (2021-12-16) + +### Fix + +- **transport**: do not generate NaN values for loss rate + +## v3.4.0 (2021-12-15) + +## v3.4.0b0 (2021-12-14) + +### Feat + +- **.cz.toml**: release 3.4 +- **libhicntransport**: split producer socket connect and start into 2 different APIs +- facemgr: android interface as an alternative to netlink (targetSdk >= 30) +- **functional-tests**: report output of test commands into robot report +- **content-store**: report number of stale entries +- **content-store**: add 'list cache' control command +- **transport**: select forwarding strategy from transport +- libtransport threading rework +- hicn-light: add ring buffer for connection egress +- **listener**: create local listeners using the "localhost" name +- **hicn-light**: add default ipv6 listener +- **test**: functional testing link model Signed-off-by: Luca Muscariello lumuscar@cisco.com +- **test**: functional testing link model +Signed-off-by: Luca Muscariello lumuscar@cisco.com +- **content-store**: disable content store when capacity is set to 0 +- separate packet cache logic from debug prints and incorporate bugfix ICN-1127 + +### Fix + +- **listener**: fix listener removal +- misc android fixes +- **production_protocol**: fix bugs in production protocols +- ensure sendContentObject is called from portal thread +- hicn-light/mapme: don't send adjacency updates to local faces +- **loop**: stop loop in signal handler +- fix access to uninitialized memory +- facemgr/android: release all resources +- **memif_connector.cc**: call reconnect_callback_ also from memif connector +- **build-system**: generate correct cmake config files +- **strategy**: avoid crash on new forwarding strategy selection + +### BREAKING CHANGE + +- this commit breaks the interface between transport and +application. Calls to socket operations are not blocking anymore, so applications +expecting a blocking behavior will need to be modified. + +## v3.3.2 (2021-12-10) + +### Fix + +- **transport**: init forwarding strategy selection + +## v3.3.1 (2021-12-10) + +### Feat + +- **libtransport**: make API of consumer and producer socket similar + +## v3.3.0 (2021-12-10) + +### Fix + +- specify componenet when installing cmake config files +- **build-system**: generate correct cmake config files + +### Feat + +- release 3.3 of hicn +- facemgr: android interface as an alternative to netlink (targetSdk >= 30) +- **functional-tests**: report output of test commands into robot report +- **content-store**: report number of stale entries +- **content-store**: add 'list cache' control command +- **transport**: select forwarding strategy from transport +- libtransport threading rework +- hicn-light: add ring buffer for connection egress +- **listener**: create local listeners using the "localhost" name +- **hicn-light**: add default ipv6 listener +- **test**: functional testing link model Signed-off-by: Luca Muscariello lumuscar@cisco.com +- **test**: functional testing link model +Signed-off-by: Luca Muscariello lumuscar@cisco.com +- **content-store**: disable content store when capacity is set to 0 +- separate packet cache logic from debug prints and incorporate bugfix ICN-1127 + +### BREAKING CHANGE + +- this commit breaks the interface between transport and +application. Calls to socket operations are not blocking anymore, so applications +expecting a blocking behavior will need to be modified. + +## v3.2.3 (2021-12-06) + +### Feat + +- **Dockerfile.android**: add android verify job + +## v3.2.2 (2021-12-03) + +### Fix + +- revert removal for now to remain compatible with hicn_plugin_api #promote PATCH +- fixed hc_route_t face_id / name attributes overlap +- work around to create the right route +- **strategy**: avoid crash on new forwarding strategy selection +- **Dockerfile**: update base docker image of hicn + +## v3.2.1 (2021-12-02) + +### Fix + +- remove libparc dependency + +## v3.2.0 (2021-12-01) + +## v3.2.0b0 (2021-11-30) + +### Feat + +- **.cz.toml**: release 3.2 of hicn +- trigger mapme updates from producer sockets to traverse nats + +### Fix + +- added check on listener and connection add +- **listener**: handle listener creation failure +- **packet-cache**: fix msgbuf acquire and release in cs update operations +- libhicntrl: default to hicn-light-ng +- hicn-light: don't disable MAP-Me messages +- libhicn: always_inline macro compilation issues +- libtransport : default to hicn-light-ng +- hicn-light : consistent listener and connection types +- **packet-cache**: fix collisions for names in packet cache +- go back to the use of system clock for delay measurements instead of steady clock +- **hash**: fix hash function usage +- **hash**: replace hash function +- **packet-cache**: fix wrong CS hit due to data name collision in pkt cache +- consistently use std::chrono to enforce timestamp types +- **Jenkinsfile**: re-enable publishing of robot tests on hicn +- set default log level to info + +## v3.1.3 (2021-11-25) + +### Fix + +- **Jenkinsfile**: re-enable publishing of robot tests on hicn + +## v3.1.2 (2021-11-24) + +### Fix + +- **ctrl/CMakeLists.txt**: libfacemgr does not compile on android + +## v3.1.1 (2021-11-24) + +### Fix + +- **transport**: do not count the same packet multiple times as definitely lost + +## v3.1.0 (2021-11-24) + +### Fix + +- **strategy**: do not switch back to old path at the end of a probing pahse + +## v3.1.0b0 (2021-11-23) + +### Feat + +- release 3.1 +- **.cz.toml**: create relesa 3.0 hicn +- **hiperf**: code style +- **hiperf**: remove commented queue check +- **hiperf**: fix compiling error +- **hiperf**: do not start forwarder interfaces if not needed +- **hiperf**: fix check to call best path +- **hiperf**: new check to trigger best path +- **hiperf**: add set strategy command +- **hiperf**: add set strategy command +- add cmake config for dependencies +- add cmake config for dependencies +- add cmake config for dependencies + +### Fix + +- **pipeline**: update pipeline version +- fix bugs in sonar +- **forwarder**: fix cmake +- fix command linkage for forwarder and remove unnecessary debug prints +- fix command registration for static lib +- fix missing libevent dependency on macos + +## v3.0.0 (2021-11-23) + +### Fix + +- **pipeline**: update pipeline version + +## v3.0.0b0 (2021-11-19) + +### Feat + +- **.cz.toml**: create relesa 3.0 hicn +- **transport**: fix error in setting fec to ask param +- **transport**: add second threshold for loss rate +- **transport**: add low rate transport strategy +- **transport**: compute (network) loss rate per second +- **libhicnctrl**: remove connection used to send commands +- **libhicnctrl**: Add support for serialization of connection and subscription removal commands +- **notification**: add notification processing +- **notification**: update libhicnctrl to support notifications +- **notification**: add retrieval of connections for a subscription +- **strategy**: code style +- **strategy**: add comment to log the issue with sendto +- **strategy**: add test for probe generator +- **strategy**: send probes at each interest +- **strategy**: use batching mode to send probes +- **strategy**: improve probing phase +- **stategy**: improve probing in best path strategy +- **stats**: Put additional stats and improve debug prints +- **subscription**: Add support for subscribe/unsubscribe +- **vector**: Add remove operation in vector +- **forwarder**: Enable daemon mode in forwarder +- **fec**: add metadata support to reedsolomon. + +### Fix + +- **Jenkinsfile**: change arch from x86_64 to amd64 +- fix build errors +- GCC11 fixes and workarounds +- **transport**: keep track of skipped interests +- **transport**: count as lost the fec packets that are not recevied +- **transport**: fix check to increase highest seq in order +- **transport**: fix loss rate counters +- select latest version of pipelines library +- **addresses**: fix ipv6 addresses creation for listeners and connections +- restore previous cmake submodule reference +- fix circular dependency +- **connection**: fix bug in connection name generation +- set version of jenkins shared library to stable version #promote PATCH +- use hicn as image name in all scripts #promote 2.9 +- **docker-gcc**: docker build script fails if env variables don't exist +- use hicn as image name in all scripts #promote 2.9 +- Fix memory leakages and unreleased msgbufs in batch read +- **vector**: fix bug on vector reallocation and add related test +- **portal.h**: improve handling of unknown packet formats in libtransport. +- **packet-cache**: Check if data received from the expected interface +- **msgbuf-pool**: Fix release of msgbufs (after queue is emptied) +- **pit-entry**: Reset nexthops during pit entry creation +- Fix socket cleanup when receiving ack/nack +- **strategy**: Fix symbol not found in libhicn +- **forwarder**: Remove unused buffer allocations in release mode +- **command**: Fix connection parsing in connection list command +- **functional-tests**: Fix functional tests for hicn-light +- **mapme**: fix nexthop slection on mapme update +- **bitmap**: Fix bitmap set operation +- **fib_entry**: code style +- **fib_entry**: reset nexthop len if no local face is found +- Use msgbuf ids instead of msgbuf pointers +- start jenkins job + +### Perf + +- **RTX**: reduce wainting time for RTX in low rate flows + +## v2.9.6 (2021-11-18) + +### Fix + +- **Jenkinsfile**: change threshold test limits +- **Packaging.cmake**: vpp deb dependency version is wrong + +## v2.9.5 (2021-11-17) + +### Fix + +- **Jenkinsfile**: change arch from x86_64 to amd64 + +## v2.9.4 (2021-11-11) + +### Feat + +- **cmake**: update version of cmake +- **cmake**: update version of cmake + +## v2.9.3 (2021-11-11) + +### Feat + +- add dockerfile for development + +## v2.9.2 (2021-11-10) + +### Fix + +- fix circular dependency #promote PATCH + +## v2.9.1 (2021-11-09) + +### Fix + +- set version of jenkins shared library to stable version #promote PATCH + +## v2.9.0 (2021-11-09) + +### Fix + +- use hicn as image name in all scripts #promote 2.9 +- **docker-gcc**: docker build script fails if env variables don't exist +- use hicn as image name in all scripts #promote 2.9 +- start jenkins job +- **README**: remove white spaces #promote 2.9 Signed-off-by: Angelo Mantellini <manangel@cisco.com> +- **transport**: comment +- **transport**: remove fec packets from pending interests +- **transport**: do not use nacks to compute the avg RTT +- **promote-2.9**: promote 2.9 +- **versions.cmake**: wrong dep versions +- **Dockerfile-gcc**: pass branch name env variable to dockerfile +- **cmake**: create packages with right version name and repo name corrected +- **libconfig**: correct libconfig version +- ICN-1047, adding Android support for hc_sock_create_forwarder +- **libhicnctrl**: unused file descriptor was closed when freeing the libhicnctrl socket. +- **vapi_safe**: groupp all vapi msg ids definitions under vapi_safe.c +- **libhicnctrl**: initialize all the fields of the struct hc_data_t during instantiation. +- **libhicnctrl**: fix initialization of vpp_vapi. +- **libhicnctrl**: Update libhicnctrl from new forwarder +- **portal.h**: improve handling of unknown packet formats in libtransport. +- **rc.cc**: fix error in reed solomon fec when passing packets back to caller. +- publish unit test reports for all tests executables +- cleanup redundant file +- **libhicnctrl**: add missing face.c to libhicnctrl source files +- **Jenkinsfile**: fix version of jenkins shared library +- **auth**: include fec header in packet signature +- **CmakeLists.txt**: fix install path of projects. +- **vpp-memif.yaml**: fix IPv6 memif connection between 2 VPPs involved in test. +- **hicn-plugin**: include vapi source code in src and includes folders. +- **cmake**: Fetch submodule containing modules as first action in root CMakeLists.txt + +### Feat + +- **add-build-number-to-deb-package-name**: Ref: SPT-759 Add build number to deb package name, if defined #promote 2.9 +- **versions.cmake**: correct versions of deps +- **trasnport**: comment on RTT update +- **trasnport**: keep prev rtt in case of no available samples +- **trasnport**: remove moving avg from residual loss rate +- **transport**: add avg rtt +- create deb packages +- upgrade to new pipelines library version +- upgrade to new pipelines library version +- **fec**: add metadata support to reedsolomon. +- **Jenkinsfile**: Add robot threshold configuration. + +## v1.0.0 (2021-11-05) + +### Feat + +- **versions.cmake**: correct versions of deps +- **trasnport**: comment on RTT update +- **trasnport**: keep prev rtt in case of no available samples +- **trasnport**: remove moving avg from residual loss rate +- **transport**: add avg rtt +- create deb packages +- upgrade to new pipelines library version +- upgrade to new pipelines library version +- **fec**: add metadata support to reedsolomon. +- **Jenkinsfile**: Add robot threshold configuration. + +### Fix + +- **versions.cmake**: wrong dep versions +- **Dockerfile-gcc**: pass branch name env variable to dockerfile +- **cmake**: create packages with right version name and repo name corrected +- **libconfig**: correct libconfig version +- ICN-1047, adding Android support for hc_sock_create_forwarder +- **libhicnctrl**: unused file descriptor was closed when freeing the libhicnctrl socket. +- **vapi_safe**: groupp all vapi msg ids definitions under vapi_safe.c +- **libhicnctrl**: initialize all the fields of the struct hc_data_t during instantiation. +- **libhicnctrl**: fix initialization of vpp_vapi. +- **libhicnctrl**: Update libhicnctrl from new forwarder +- **portal.h**: improve handling of unknown packet formats in libtransport. +- **rc.cc**: fix error in reed solomon fec when passing packets back to caller. +- publish unit test reports for all tests executables +- cleanup redundant file +- **libhicnctrl**: add missing face.c to libhicnctrl source files +- **Jenkinsfile**: fix version of jenkins shared library +- **auth**: include fec header in packet signature +- **CmakeLists.txt**: fix install path of projects. +- **vpp-memif.yaml**: fix IPv6 memif connection between 2 VPPs involved in test. +- **hicn-plugin**: include vapi source code in src and includes folders. +- **cmake**: Fetch submodule containing modules as first action in root CMakeLists.txt + +## v21.06-rc0 (2021-07-20) + +## v21.01-rc0 (2021-02-10) + +## v20.05-release (2020-11-11) + +## v20.01 (2020-01-30) + +## v19.08 (2019-08-14) + +## v19.04 (2019-04-29) + +## v19.01 (2019-01-25) diff --git a/Dockerfile b/Dockerfile new file mode 120000 index 000000000..91fb519b8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1 @@ +Dockerfile.dev
\ No newline at end of file diff --git a/Dockerfile.dev b/Dockerfile.dev index 9c96193a9..326f4676c 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -5,12 +5,26 @@ WORKDIR /hicn-build COPY Makefile versions.cmake ./ COPY scripts scripts/ +ARG USERNAME=ubuntu +ARG USER_UID=1000 +ARG USER_GID=${USER_UID} + RUN apt update && apt-get install -y \ make \ sudo \ curl \ + valgrind \ git RUN make deps debug-tools +# Add non-root user +RUN groupadd --gid ${USER_GID} ${USERNAME} && \ + useradd -s /bin/bash --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} && \ + echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL >/etc/sudoers.d/${USERNAME} && \ + chmod 0440 /etc/sudoers.d/${USERNAME} + +USER ${USERNAME} +WORKDIR /home/${USERNAME} + ENV DEBIAN_FRONTEND= diff --git a/apps/hiperf/src/common.h b/apps/hiperf/src/common.h index 5143afe31..29cc05c71 100644 --- a/apps/hiperf/src/common.h +++ b/apps/hiperf/src/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -178,11 +178,13 @@ class PayloadSize { bool ah = false) { switch (prefix.getAddressFamily()) { case AF_INET: - return ah ? HF_INET_TCP_AH : HF_INET_TCP; + return ah ? HICN_PACKET_FORMAT_IPV4_TCP_AH + : HICN_PACKET_FORMAT_IPV4_TCP; case AF_INET6: - return ah ? HF_INET6_TCP_AH : HF_INET6_TCP; + return ah ? HICN_PACKET_FORMAT_IPV6_TCP_AH + : HICN_PACKET_FORMAT_IPV6_TCP; default: - return HF_UNSPEC; + return HICN_PACKET_FORMAT_NONE; } } diff --git a/apps/hiperf/src/main.cc b/apps/hiperf/src/main.cc index 85cadd677..74724209b 100644 --- a/apps/hiperf/src/main.cc +++ b/apps/hiperf/src/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -33,7 +33,7 @@ void usage() { std::cerr << "-f\t<filename>\t\t\t" << "Log file" << std::endl; std::cerr << "-z\t<io_module>\t\t\t" - << "IO module to use. Default: hicnlightng_module" << std::endl; + << "IO module to use. Default: hicnlight_module" << std::endl; std::cerr << "-F\t<conf_file>\t\t\t" << "Path to optional configuration file for libtransport" << std::endl; @@ -214,7 +214,7 @@ int main(int argc, char *argv[]) { char *log_file = nullptr; transport::interface::global_config::IoModuleConfiguration config; std::string conf_file; - config.name = "hicnlightng_module"; + config.name = "hicnlight_module"; // Consumer ClientConfiguration client_configuration; @@ -290,8 +290,8 @@ int main(int argc, char *argv[]) { break; } case 'w': { - client_configuration.packet_format_ = Packet::Format::HF_INET6_UDP; - server_configuration.packet_format_ = Packet::Format::HF_INET6_UDP; + client_configuration.packet_format_ = HICN_PACKET_FORMAT_IPV6_UDP; + server_configuration.packet_format_ = HICN_PACKET_FORMAT_IPV6_UDP; break; } case 'k': { diff --git a/apps/http-proxy/CMakeLists.txt b/apps/http-proxy/CMakeLists.txt index dbe9bc51c..5acf09c19 100644 --- a/apps/http-proxy/CMakeLists.txt +++ b/apps/http-proxy/CMakeLists.txt @@ -15,7 +15,7 @@ # Compiler options ############################################################## set(COMPILER_OPTIONS - ${DEFAULT_COMPILER_OPTIONS} + PRIVATE ${DEFAULT_COMPILER_OPTIONS} ) # -Wno-c99-designator issue @@ -94,5 +94,6 @@ if (NOT DISABLE_EXECUTABLES) DEPENDS ${LIBHTTP_PROXY_STATIC} COMPONENT ${HICN_APPS} LINK_FLAGS ${LINK_FLAGS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) endif () diff --git a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h index 0741099df..c60e26c63 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h +++ b/apps/http-proxy/includes/hicn/http-proxy/forwarder_interface.h @@ -28,8 +28,7 @@ extern "C" { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wshorten-64-to-32" #endif -#include <asio.hpp> -#include <asio/steady_timer.hpp> +#include <hicn/transport/core/asio_wrapper.h> #ifdef __APPLE__ #pragma clang diagnostic pop #endif diff --git a/apps/http-proxy/includes/hicn/http-proxy/http_session.h b/apps/http-proxy/includes/hicn/http-proxy/http_session.h index 43d10e156..1563431dc 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/http_session.h +++ b/apps/http-proxy/includes/hicn/http-proxy/http_session.h @@ -21,7 +21,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wshorten-64-to-32" #endif -#include <asio.hpp> +#include <hicn/transport/core/asio_wrapper.h> #ifdef __APPLE__ #pragma clang diagnostic pop #endif diff --git a/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h index ab90fab07..a402d44cf 100644 --- a/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h +++ b/apps/http-proxy/includes/hicn/http-proxy/icn_receiver.h @@ -14,12 +14,12 @@ */ #include <hicn/http-proxy/http_session.h> +#include <hicn/transport/core/asio_wrapper.h> #include <hicn/transport/core/prefix.h> #include <hicn/transport/interfaces/publication_options.h> #include <hicn/transport/interfaces/socket_producer.h> #include <hicn/transport/utils/spinlock.h> -#include <asio.hpp> #include <cassert> #include <cstring> #include <queue> diff --git a/apps/http-proxy/src/forwarder_interface.cc b/apps/http-proxy/src/forwarder_interface.cc index 1c034f60f..5566eb6ff 100644 --- a/apps/http-proxy/src/forwarder_interface.cc +++ b/apps/http-proxy/src/forwarder_interface.cc @@ -27,7 +27,7 @@ namespace transport { ForwarderInterface::~ForwarderInterface() {} int ForwarderInterface::connectToForwarder() { - sock_ = hc_sock_create(); + sock_ = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); if (!sock_) return -1; if (hc_sock_connect(sock_) < 0) { @@ -96,7 +96,8 @@ void ForwarderInterface::internalRemoveConnectedUser(uint32_t route_id) { std::vector<hc_route_t *> routes_to_remove; foreach_route(r, data) { char remote_addr[INET6_ADDRSTRLEN]; - int ret = ip_address_ntop(&r->remote_addr, remote_addr, r->len, r->family); + int ret = + hicn_ip_address_ntop(&r->remote_addr, remote_addr, r->len, r->family); if (ret < 0) continue; std::string route_addr(remote_addr); @@ -201,8 +202,9 @@ int ForwarderInterface::tryToCreateFaceAndRoute(route_info_t *route_info) { if (interface.compare("lo") != 0) { found = true; - ip_address_t remote_ip; - if (ip_address_pton(route_info->remote_addr.c_str(), &remote_ip) < 0) { + hicn_ip_address_t remote_ip; + if (hicn_ip_address_pton(route_info->remote_addr.c_str(), &remote_ip) < + 0) { hc_data_free(data); return -1; } @@ -210,14 +212,14 @@ int ForwarderInterface::tryToCreateFaceAndRoute(route_info_t *route_info) { hc_face_t face; memset(&face, 0, sizeof(hc_face_t)); - face.face.type = FACE_TYPE_UDP; - face.face.family = route_info->family; - face.face.local_addr = l->local_addr; - face.face.remote_addr = remote_ip; - face.face.local_port = l->local_port; - face.face.remote_port = route_info->remote_port; + face.type = FACE_TYPE_UDP; + face.family = route_info->family; + face.local_addr = l->local_addr; + face.remote_addr = remote_ip; + face.local_port = l->local_port; + face.remote_port = route_info->remote_port; - if (netdevice_set_name(&face.face.netdevice, l->interface_name) < 0) { + if (netdevice_set_name(&face.netdevice, l->interface_name) < 0) { hc_data_free(data); return -1; } @@ -237,10 +239,10 @@ int ForwarderInterface::tryToCreateFaceAndRoute(route_info_t *route_info) { return -1; } - ip_address_t route_ip; + hicn_ip_address_t route_ip; hc_route_t route; - if (ip_address_pton(route_info->route_addr.c_str(), &route_ip) < 0) { + if (hicn_ip_address_pton(route_info->route_addr.c_str(), &route_ip) < 0) { hc_data_free(data); return -1; } diff --git a/apps/ping/src/ping_client.cc b/apps/ping/src/ping_client.cc index 2371e4453..6cc6de548 100644 --- a/apps/ping/src/ping_client.cc +++ b/apps/ping/src/ping_client.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -53,9 +53,6 @@ class Configuration { bool verbose_; bool dump_; bool jump_; - bool open_; - bool always_syn_; - bool always_ack_; bool quiet_; uint32_t jump_freq_; uint32_t jump_size_; @@ -73,9 +70,6 @@ class Configuration { verbose_ = false; dump_ = false; jump_ = false; - open_ = false; - always_syn_ = false; - always_ack_ = false; quiet_ = false; jump_freq_ = 0; jump_size_ = 0; @@ -155,12 +149,10 @@ class Client : interface::Portal::TransportCallback { std::cout << "<<< interest name: " << interest.getName() << " (n_suffixes=" << interest.numberOfSuffixes() << ")" << " src port: " << interest.getSrcPort() - << " dst port: " << interest.getDstPort() - << " flags: " << interest.printFlags() << std::endl; + << " dst port: " << interest.getDstPort() << std::endl; std::cout << "<<< object name: " << object.getName() << " src port: " << object.getSrcPort() - << " dst port: " << object.getDstPort() - << " flags: " << object.printFlags() << " path label " + << " dst port: " << object.getDstPort() << " path label " << object.getPathLabel() << " (" << (object.getPathLabel() >> 24) << ")" << " TTL: " << (int)object.getTTL() << std::endl; @@ -185,12 +177,6 @@ class Client : interface::Portal::TransportCallback { if (!config_->quiet_) std::cout << std::endl; - if (!config_->always_syn_) { - if (object.testSyn() && object.testAck() && state_ == SYN_STATE) { - state_ = ACK_STATE; - } - } - received_++; processed_++; if (processed_ >= config_->maxPing_) { @@ -202,8 +188,7 @@ class Client : interface::Portal::TransportCallback { if (config_->verbose_) { std::cout << "### timeout for " << name << " src port: " << interest->getSrcPort() - << " dst port: " << interest->getDstPort() - << " flags: " << interest->printFlags() << std::endl; + << " dst port: " << interest->getDstPort() << std::endl; } else if (!config_->quiet_) { std::cout << "### timeout for " << name << std::endl; } @@ -231,11 +216,11 @@ class Client : interface::Portal::TransportCallback { void doPing() { const Name interest_name(config_->name_, (uint32_t)sequence_number_); - hicn_format_t format; + hicn_packet_format_t format; if (interest_name.getAddressFamily() == AF_INET) { - format = signer_ ? HF_INET_TCP_AH : HF_INET_TCP; + format = HICN_PACKET_FORMAT_IPV4_TCP; } else { - format = signer_ ? HF_INET6_TCP_AH : HF_INET6_TCP; + format = HICN_PACKET_FORMAT_IPV6_TCP; } size_t additional_header_size = 0; @@ -244,17 +229,6 @@ class Client : interface::Portal::TransportCallback { additional_header_size); interest->setLifetime(uint32_t(config_->interestLifetime_)); - if (!signer_) interest->resetFlags(); - - if (config_->open_ || config_->always_syn_) { - if (state_ == SYN_STATE) { - interest->setSyn(); - } else if (state_ == ACK_STATE) { - interest->setAck(); - } - } else if (config_->always_ack_) { - interest->setAck(); - } interest->setSrcPort(config_->srcPort_); interest->setDstPort(config_->dstPort_); @@ -270,7 +244,6 @@ class Client : interface::Portal::TransportCallback { std::cout << ">>> send interest " << interest->getName() << " src port: " << interest->getSrcPort() << " dst port: " << interest->getDstPort() - << " flags: " << interest->printFlags() << " TTL: " << (int)interest->getTTL() << " suffixes in manifest: " << config_->num_int_manifest_suffixes_ << std::endl; @@ -362,13 +335,6 @@ void help() { std::cout << " e.g. '-m 6 -a -2' sends two interest (0 and " "3) with 2 suffixes each (1,2 and 4,5 respectively)" << std::endl; - std::cout << "-O open tcp connection (three way handshake) " - "(default false)" - << std::endl; - std::cout << "-S send always syn messages (default false)" - << std::endl; - std::cout << "-A send always ack messages (default false)" - << std::endl; std::cout << "HICN options" << std::endl; std::cout << "-n <val> hicn name (default b001::1)" << std::endl; std::cout @@ -383,7 +349,7 @@ void help() { << std::endl; std::cout << "-q quiet, not prints (default false)" << std::endl; - std::cerr << "-z <io_module> IO module to use. Default: hicnlightng_module" + std::cerr << "-z <io_module> IO module to use. Default: hicnlight_module" << std::endl; std::cerr << "-F <conf_file> Path to optional configuration file for " "libtransport" @@ -405,7 +371,7 @@ int main(int argc, char *argv[]) { std::string conf_file; transport::interface::global_config::IoModuleConfiguration io_config; - io_config.name = "hicnlightng_module"; + io_config.name = "hicnlight_module"; while ((opt = getopt(argc, argv, "a:j::t:i:m:s:d:n:l:f:c:SAOqVDHz:F:")) != -1) { @@ -445,21 +411,6 @@ int main(int argc, char *argv[]) { case 'D': c->dump_ = true; break; - case 'O': - c->always_syn_ = false; - c->always_ack_ = false; - c->open_ = true; - break; - case 'S': - c->always_syn_ = true; - c->always_ack_ = false; - c->open_ = false; - break; - case 'A': - c->always_syn_ = false; - c->always_ack_ = true; - c->open_ = false; - break; case 'q': c->quiet_ = true; c->verbose_ = false; diff --git a/apps/ping/src/ping_server.cc b/apps/ping/src/ping_server.cc index dd7d23b5e..876efd133 100644 --- a/apps/ping/src/ping_server.cc +++ b/apps/ping/src/ping_server.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -42,18 +42,15 @@ class CallbackContainer { public: CallbackContainer(const Name &prefix, uint32_t object_size, bool verbose, - bool dump, bool quite, bool flags, bool reset, uint8_t ttl, - auth::Signer *signer, bool sign, std::string passphrase, - uint32_t lifetime) + bool dump, bool quiet, uint8_t ttl, auth::Signer *signer, + bool sign, std::string passphrase, uint32_t lifetime) : buffer_(object_size, 'X'), content_objects_((std::uint32_t)(1 << log2_content_object_buffer_size)), mask_((std::uint16_t)(1 << log2_content_object_buffer_size) - 1), content_objects_index_(0), verbose_(verbose), dump_(dump), - quite_(quite), - flags_(flags), - reset_(reset), + quiet_(quiet), ttl_(ttl), signer_(signer), sign_(sign) { @@ -63,14 +60,14 @@ class CallbackContainer { core::Packet::Format format; if (prefix.getAddressFamily() == AF_INET) { - format = core::Packet::Format::HF_INET_TCP; + format = HICN_PACKET_FORMAT_IPV4_TCP; if (sign_) { - format = core::Packet::Format::HF_INET_TCP_AH; + format = HICN_PACKET_FORMAT_IPV4_TCP_AH; } } else { - format = core::Packet::Format::HF_INET6_TCP; + format = HICN_PACKET_FORMAT_IPV6_TCP; if (sign_) { - format = core::Packet::Format::HF_INET6_TCP_AH; + format = HICN_PACKET_FORMAT_IPV6_TCP_AH; } } @@ -99,11 +96,10 @@ class CallbackContainer { std::cout << "<<< received interest " << interest.getName() << " src port: " << interest.getSrcPort() << " dst port: " << interest.getDstPort() - << " flags: " << interest.printFlags() << "TTL: " << (int)interest.getTTL() << " suffixes in manifest: " << interest.numberOfSuffixes() << std::endl; - } else if (!quite_) { + } else if (!quiet_) { std::cout << "<<< received interest " << interest.getName() << std::endl; } @@ -113,78 +109,60 @@ class CallbackContainer { std::cout << "-------------------------" << std::endl; } - if (interest.testRst()) { - std::cout << "!!!got a reset, I don't reply" << std::endl; - } else { - uint32_t *suffix = interest.firstSuffix(); - uint32_t n_suffixes_in_manifest = interest.numberOfSuffixes(); - uint32_t *request_bitmap = interest.getRequestBitmap(); - if (!interest.isValid()) throw std::runtime_error("Bad interest format"); - - Name name = interest.getName(); - uint32_t pos = 0; // Position of current suffix in manifest - do { - // If suffix can be processed, i.e. no manifest with bitmap excluding it - if (!interest.hasManifest() || is_bit_set(request_bitmap, pos)) { - auto &content_object = - content_objects_[content_objects_index_++ & mask_]; - - content_object->setName(interest.getName()); - content_object->setLifetime(lifetime); - content_object->setLocator(interest.getLocator()); - content_object->setSrcPort(interest.getDstPort()); - content_object->setDstPort(interest.getSrcPort()); - content_object->setTTL(ttl_); - - if (!sign_) { - content_object->resetFlags(); - } - - if (flags_) { - if (interest.testSyn()) { - content_object->setSyn(); - content_object->setAck(); - } else if (interest.testAck()) { - content_object->setAck(); - } // here I may need to handle the FIN flag; - } else if (reset_) { - content_object->setRst(); - } - - if (verbose_) { - std::cout << ">>> send object " << content_object->getName() - << " src port: " << content_object->getSrcPort() - << " dst port: " << content_object->getDstPort() - << " flags: " << content_object->printFlags() - << " TTL: " << (int)content_object->getTTL() << std::endl; - } else if (!quite_) { - std::cout << ">>> send object " << content_object->getName() - << std::endl; - } - - if (dump_) { - std::cout << "----- object dump -----" << std::endl; - content_object->dump(); - std::cout << "-----------------------" << std::endl; - } - - if (sign_ && signer_) { - signer_->signPacket(content_object.get()); - } - - p.produce(*content_object); + uint32_t *suffix = interest.firstSuffix(); + uint32_t n_suffixes_in_manifest = interest.numberOfSuffixes(); + hicn_uword *request_bitmap = interest.getRequestBitmap(); + if (!interest.isValid()) throw std::runtime_error("Bad interest format"); + + Name name = interest.getName(); + uint32_t pos = 0; // Position of current suffix in manifest + do { + // If suffix can be processed, i.e. no manifest with bitmap excluding it + if (!interest.hasManifest() || + bitmap_is_set_no_check(request_bitmap, pos)) { + auto &content_object = + content_objects_[content_objects_index_++ & mask_]; + + content_object->setName(interest.getName()); + content_object->setLifetime(lifetime); + content_object->setLocator(interest.getLocator()); + content_object->setSrcPort(interest.getDstPort()); + content_object->setDstPort(interest.getSrcPort()); + content_object->setTTL(ttl_); + + if (verbose_) { + std::cout << ">>> send object " << content_object->getName() + << " src port: " << content_object->getSrcPort() + << " dst port: " << content_object->getDstPort() + << " TTL: " << (int)content_object->getTTL() << std::endl; + } else if (!quiet_) { + std::cout << ">>> send object " << content_object->getName() + << std::endl; } - if (interest.hasManifest()) { - uint32_t seq = *suffix; - suffix++; + if (dump_) { + std::cout << "----- object dump -----" << std::endl; + content_object->dump(); + std::cout << "-----------------------" << std::endl; + } - interest.setName(name.setSuffix(seq)); + if (sign_ && signer_) { + signer_->signPacket(content_object.get()); } - } while (pos++ < n_suffixes_in_manifest); - if (!quite_) std::cout << std::endl; - } + p.produce(*content_object); + } + + if (interest.hasManifest()) { + uint32_t seq = *suffix; + suffix++; + + Name name = interest.getName(); + interest.setName(name.setSuffix(seq)); + } + } while (pos++ < n_suffixes_in_manifest); + + if (!quiet_) std::cout << std::endl; } private: @@ -194,9 +172,7 @@ class CallbackContainer { std::uint16_t content_objects_index_; bool verbose_; bool dump_; - bool quite_; - bool flags_; - bool reset_; + bool quiet_; uint8_t ttl_; auth::Signer *signer_; bool sign_; @@ -209,13 +185,7 @@ void help() { std::cout << "-s <val> object content size (default 1350B)" << std::endl; std::cout << "-n <val> hicn name (default b001::/64)" << std::endl; - std::cout << "-f set tcp flags according to the flag received " - " (default false)" - << std::endl; std::cout << "-l data lifetime" << std::endl; - std::cout - << "-r always reply with a reset flag (default false)" - << std::endl; std::cout << "-t set ttl (default 64)" << std::endl; std::cout << "OUTPUT options" << std::endl; std::cout << "-V verbose, prints statistics about the " @@ -225,9 +195,9 @@ void help() { std::cout << "-D dump, dumps sent and received packets " "(default false)" << std::endl; - std::cout << "-q quite, not prints (default false)" + std::cout << "-q quiet, not prints (default false)" << std::endl; - std::cerr << "-z <io_module> IO module to use. Default: hicnlightng_module" + std::cerr << "-z <io_module> IO module to use. Default: hicnlight_module" << std::endl; std::cerr << "-F <conf_file> Path to optional configuration file for " "libtransport" @@ -250,9 +220,7 @@ int main(int argc, char **argv) { std::string delimiter = "/"; bool verbose = false; bool dump = false; - bool quite = false; - bool flags = false; - bool reset = false; + bool quiet = false; uint32_t object_size = 1250; uint8_t ttl = 64; std::string keystore_path = "./rsa_crypto_material.p12"; @@ -263,7 +231,7 @@ int main(int argc, char **argv) { std::string conf_file; transport::interface::global_config::IoModuleConfiguration io_config; - io_config.name = "hicnlightng_module"; + io_config.name = "hicnlight_module"; int opt; #ifndef _WIN32 @@ -296,19 +264,13 @@ int main(int argc, char **argv) { case 'q': verbose = false; dump = false; - quite = true; + quiet = true; break; #ifndef _WIN32 case 'd': daemon = true; break; #endif - case 'f': - flags = true; - break; - case 'r': - reset = true; - break; case 'k': keystore_path = optarg; sign = true; @@ -359,14 +321,13 @@ int main(int argc, char **argv) { if (sign) { signer = std::make_unique<auth::AsymmetricSigner>(keystore_path, keystore_password); - stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags, - reset, ttl, signer.get(), sign, passphrase, - data_lifetime); + stubs = + new CallbackContainer(n, object_size, verbose, dump, quiet, ttl, + signer.get(), sign, passphrase, data_lifetime); } else { auth::Signer *signer = nullptr; - stubs = new CallbackContainer(n, object_size, verbose, dump, quite, flags, - reset, ttl, signer, sign, passphrase, - data_lifetime); + stubs = new CallbackContainer(n, object_size, verbose, dump, quiet, ttl, + signer, sign, passphrase, data_lifetime); } ProducerSocket p; diff --git a/ctrl/CMakeLists.txt b/ctrl/CMakeLists.txt index 221121818..e601d9509 100644 --- a/ctrl/CMakeLists.txt +++ b/ctrl/CMakeLists.txt @@ -23,4 +23,4 @@ project(ctrl) add_subdirectory(libhicnctrl) if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Android" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "iOS") add_subdirectory(facemgr) -endif ()
\ No newline at end of file +endif () diff --git a/ctrl/facemgr/includes/hicn/facemgr/api.h b/ctrl/facemgr/includes/hicn/facemgr/api.h index 3fe049c06..582be0e78 100644 --- a/ctrl/facemgr/includes/hicn/facemgr/api.h +++ b/ctrl/facemgr/includes/hicn/facemgr/api.h @@ -44,7 +44,7 @@ typedef int (*facemgr_cb_t)(void *loop, facemgr_cb_type_t type, void *data); typedef struct { uint16_t local_port; - ip_address_t remote_addr; + hicn_ip_address_t remote_addr; uint16_t remote_port; } facemgr_overlay_setting_t; diff --git a/ctrl/facemgr/includes/hicn/facemgr/cfg.h b/ctrl/facemgr/includes/hicn/facemgr/cfg.h index bbbe81825..57d8f35bc 100644 --- a/ctrl/facemgr/includes/hicn/facemgr/cfg.h +++ b/ctrl/facemgr/includes/hicn/facemgr/cfg.h @@ -76,8 +76,9 @@ int facemgr_cfg_rule_set_ipv6(facemgr_cfg_rule_t* cfg_rule, bool status); int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t* cfg_rule); int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t* rule, int family, - ip_address_t* local_addr, uint16_t local_port, - ip_address_t* remote_addr, + hicn_ip_address_t* local_addr, + uint16_t local_port, + hicn_ip_address_t* remote_addr, uint16_t remote_port); int facemgr_rule_unset_overlay(facemgr_cfg_rule_t* rule, int family); @@ -93,8 +94,9 @@ int facemgr_cfg_set_ipv6(facemgr_cfg_t* cfg, bool status); int facemgr_cfg_unset_ipv6(facemgr_cfg_t* cfg); int facemgr_cfg_set_overlay(facemgr_cfg_t* cfg, int family, - ip_address_t* local_addr, uint16_t local_port, - ip_address_t* remote_addr, uint16_t remote_port); + hicn_ip_address_t* local_addr, uint16_t local_port, + hicn_ip_address_t* remote_addr, + uint16_t remote_port); int facemgr_cfg_unset_overlay(facemgr_cfg_t* cfg, int family); int facemgr_cfg_add_rule(facemgr_cfg_t* cfg, facemgr_cfg_rule_t* rule); @@ -128,7 +130,7 @@ int facemgr_cfg_get_ipv6(const facemgr_cfg_t* cfg, const netdevice_t* netdevice, int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t* cfg, const netdevice_t* netdevice, netdevice_type_t netdevice_type, - int family, ip_address_t* addr); + int family, hicn_ip_address_t* addr); int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t* cfg, const netdevice_t* netdevice, netdevice_type_t netdevice_type, @@ -136,7 +138,7 @@ int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t* cfg, int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t* cfg, const netdevice_t* netdevice, netdevice_type_t netdevice_type, - int family, ip_address_t* addr); + int family, hicn_ip_address_t* addr); int facemgr_cfg_get_overlay_remote_port(const facemgr_cfg_t* cfg, const netdevice_t* netdevice, netdevice_type_t netdevice_type, @@ -154,11 +156,13 @@ int facemgr_cfg_rule_get_ignore(const facemgr_cfg_rule_t* cfg_rule, int facemgr_cfg_rule_get_ipv4(const facemgr_cfg_rule_t* cfg_rule, bool* status); int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t* cfg_rule, bool* status); int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t* rule, - int family, ip_address_t* addr); + int family, + hicn_ip_address_t* addr); int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t* rule, int family, uint16_t* port); int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t* rule, - int family, ip_address_t* addr); + int family, + hicn_ip_address_t* addr); int facemgr_cfg_rule_get_overlay_remote_port(const facemgr_cfg_rule_t* rule, int family, uint16_t* port); diff --git a/ctrl/facemgr/includes/hicn/facemgr/facelet.h b/ctrl/facemgr/includes/hicn/facemgr/facelet.h index d9c986731..9b04832b3 100644 --- a/ctrl/facemgr/includes/hicn/facemgr/facelet.h +++ b/ctrl/facemgr/includes/hicn/facemgr/facelet.h @@ -168,32 +168,18 @@ extern const char* facelet_attr_status_str_short[]; /* Facelet attribute */ -#ifdef WITH_POLICY #define foreach_facelet_attr \ _(netdevice_type_t, netdevice_type) \ _(netdevice_t, netdevice) \ _(int, family) \ - _(ip_address_t, local_addr) \ + _(hicn_ip_address_t, local_addr) \ _(u16, local_port) \ - _(ip_address_t, remote_addr) \ + _(hicn_ip_address_t, remote_addr) \ _(u16, remote_port) \ _(face_state_t, admin_state) \ _(face_state_t, state) \ _(u32, priority) \ _(facemgr_face_type_t, face_type) -#else -#define foreach_facelet_attr \ - _(netdevice_type_t, netdevice_type) \ - _(netdevice_t, netdevice) \ - _(int, family) \ - _(ip_address_t, local_addr) \ - _(u16, local_port) \ - _(ip_address_t, remote_addr) \ - _(u16, remote_port) \ - _(face_state_t, admin_state) \ - _(face_state_t, state) \ - _(facemgr_face_type_t, face_type) -#endif /* WITH_POLICY */ #define foreach_facelet_event \ _(UNDEFINED) \ diff --git a/ctrl/facemgr/src/api.c b/ctrl/facemgr/src/api.c index d030abd1f..f271b24c7 100644 --- a/ctrl/facemgr/src/api.c +++ b/ctrl/facemgr/src/api.c @@ -28,7 +28,7 @@ /* * Dump facelets (debug) */ -//#define WITH_DUMP +#define WITH_DUMP 1 /* * Allow priority setting before interface is actually created @@ -291,7 +291,10 @@ int facemgr_finalize(facemgr_t *facemgr) { facelet_set_free(facemgr->facelet_cache); /* Free all facelets from static array */ - for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) { + n = (int)facelet_array_len(facemgr->static_facelets); + + INFO("Removing %d facelets from static array", n); + for (unsigned i = 0; i < n; i++) { facelet_t *facelet; if (facelet_array_get_index(facemgr->static_facelets, i, &facelet) < 0) { ERROR("[facemgr_cfg_finalize] Error getting facelet in array"); @@ -817,7 +820,7 @@ int facemgr_complement_facelet_manual(facemgr_t *facemgr, facelet_t *facelet) { * We never override a result we have obtained through bonjour */ if (!facelet_has_remote_addr(facelet)) { - ip_address_t remote_addr; + hicn_ip_address_t remote_addr; if (facemgr_cfg_get_overlay_remote_addr(facemgr->cfg, &netdevice, netdevice_type, family, &remote_addr) < 0) { @@ -826,7 +829,7 @@ int facemgr_complement_facelet_manual(facemgr_t *facemgr, facelet_t *facelet) { "information from cfg"); return -1; } - if (ip_address_empty(&remote_addr)) { + if (hicn_ip_address_empty(&remote_addr)) { ERROR( "[facemgr_complement_facelet_manual] Got empty remote addr " "information from cfg"); @@ -859,7 +862,7 @@ int facemgr_complement_facelet_manual(facemgr_t *facemgr, facelet_t *facelet) { * whether this is an address that belong to us... it might be used * to arbitrate amongst several IP addresses instead... */ - ip_address_t local_addr; + hicn_ip_address_t local_addr; if (facemgr_cfg_get_overlay_local_addr( facemgr->cfg, &netdevice, netdevice_type, family, &local_addr) < 0) { ERROR( @@ -867,7 +870,7 @@ int facemgr_complement_facelet_manual(facemgr_t *facemgr, facelet_t *facelet) { "information from cfg"); return -1; } - if (ip_address_empty(&local_addr)) { + if (hicn_ip_address_empty(&local_addr)) { ERROR( "[facemgr_complement_facelet_manual] Got empty local addr information " "from cfg"); @@ -1435,7 +1438,7 @@ int facemgr_process_facelet_get(facemgr_t *facemgr, facelet_t *facelet) { if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { /* Inspect local address */ int family; - ip_address_t local; + hicn_ip_address_t local; if (facelet_get_family(facelet, &family) < 0) { ERROR("[facemgr_process_facelet_get] Error getting facelet family"); return -1; @@ -1448,14 +1451,14 @@ int facemgr_process_facelet_get(facemgr_t *facemgr, facelet_t *facelet) { } switch (family) { case AF_INET: - if (ip_address_cmp(&local, &IPV4_LOOPBACK, family) == 0) { + if (hicn_ip_address_cmp(&local, &IPV4_LOOPBACK) == 0) { facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK); } else { return -2; } break; case AF_INET6: - if (ip_address_cmp(&local, &IPV6_LOOPBACK, family) == 0) { + if (hicn_ip_address_cmp(&local, &IPV6_LOOPBACK) == 0) { facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_LOOPBACK); } else { return -2; @@ -1673,7 +1676,8 @@ ERR_PRIORITY: * routes managed by the face manager. */ DEBUG("[facemgr_process_facelet_create_no_family] Loop static"); - for (unsigned i = 0; i < facelet_array_len(facemgr->static_facelets); i++) { + int n = (int)facelet_array_len(facemgr->static_facelets); + for (unsigned i = 0; i < n; i++) { facelet_t *static_facelet; if (facelet_array_get_index(facemgr->static_facelets, i, &static_facelet) < 0) { @@ -1733,7 +1737,7 @@ ERR_PRIORITY: */ int facemgr_on_event(facemgr_t *facemgr, facelet_t *facelet_in) { bool remove_facelet = true; -#if WITH_DUMP +#ifdef WITH_DUMP bool dump = true; #endif /* WITH_DUMP */ int ret = 0; @@ -1826,7 +1830,7 @@ int facemgr_on_event(facemgr_t *facemgr, facelet_t *facelet_in) { // DEBUG("[facemgr_on_event] GET NEW %s", facelet_s); rc = facemgr_process_facelet_get(facemgr, facelet_in); if (rc == 0) remove_facelet = false; -#if WITH_DUMP +#ifdef WITH_DUMP dump = false; #endif if (rc == -1) { @@ -1943,7 +1947,7 @@ int facemgr_on_event(facemgr_t *facemgr, facelet_t *facelet_in) { // ERROR("[facemgr_on_event] GET event for a face that already // exists..."); #ifdef WITH_DUMP - dump = false; + // dump = false; #endif /* WITH_DUMP */ continue; @@ -2025,7 +2029,7 @@ ERR: ret = -1; DUMP_CACHE: -#if WITH_DUMP +#ifdef WITH_DUMP if (dump) { DEBUG(" <CACHE>"); facelet_set_dump(facemgr->facelet_cache); diff --git a/ctrl/facemgr/src/cfg.c b/ctrl/facemgr/src/cfg.c index 76e1f5e72..87a6279ca 100644 --- a/ctrl/facemgr/src/cfg.c +++ b/ctrl/facemgr/src/cfg.c @@ -17,11 +17,11 @@ typedef struct { bool is_local_port; uint16_t local_port; bool is_local_addr; - ip_address_t local_addr; + hicn_ip_address_t local_addr; bool is_remote_port; uint16_t remote_port; bool is_remote_addr; - ip_address_t remote_addr; + hicn_ip_address_t remote_addr; } facemgr_cfg_overlay_t; int facemgr_cfg_overlay_initialize(facemgr_cfg_overlay_t *overlay) { @@ -185,8 +185,8 @@ void facemgr_cfg_rule_dump(facemgr_cfg_rule_t *rule) { DEBUG(" <ipv4>"); if (rule->override.overlays.v4->is_local_addr) { char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &rule->override.overlays.v4->local_addr, AF_INET); + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, + &rule->override.overlays.v4->local_addr); DEBUG(" <local_addr>%s</local_addr>", buf); } if (rule->override.overlays.v4->is_local_port) { @@ -195,8 +195,8 @@ void facemgr_cfg_rule_dump(facemgr_cfg_rule_t *rule) { } if (rule->override.overlays.v4->is_remote_addr) { char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &rule->override.overlays.v4->remote_addr, AF_INET); + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, + &rule->override.overlays.v4->remote_addr); DEBUG(" <remote_addr>%s</remote_addr>", buf); } if (rule->override.overlays.v4->is_remote_port) { @@ -209,8 +209,8 @@ void facemgr_cfg_rule_dump(facemgr_cfg_rule_t *rule) { DEBUG(" <ipv6>"); if (rule->override.overlays.v6->is_local_addr) { char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &rule->override.overlays.v6->local_addr, AF_INET6); + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, + &rule->override.overlays.v6->local_addr); DEBUG(" <local_addr>%s</local_addr>", buf); } if (rule->override.overlays.v6->is_local_port) { @@ -219,8 +219,8 @@ void facemgr_cfg_rule_dump(facemgr_cfg_rule_t *rule) { } if (rule->override.overlays.v6->is_remote_addr) { char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, - &rule->override.overlays.v6->remote_addr, AF_INET6); + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, + &rule->override.overlays.v6->remote_addr); DEBUG(" <remote_addr>%s</remote_addr>", buf); } if (rule->override.overlays.v6->is_remote_port) { @@ -300,8 +300,9 @@ int facemgr_cfg_rule_unset_ipv6(facemgr_cfg_rule_t *rule) { } int facemgr_cfg_rule_set_overlay(facemgr_cfg_rule_t *rule, int family, - ip_address_t *local_addr, uint16_t local_port, - ip_address_t *remote_addr, + hicn_ip_address_t *local_addr, + uint16_t local_port, + hicn_ip_address_t *remote_addr, uint16_t remote_port) { if ((family != AF_INET) && (family != AF_INET6)) return -1; @@ -546,8 +547,9 @@ int facemgr_cfg_unset_ipv6(facemgr_cfg_t *cfg) { } int facemgr_cfg_set_overlay(facemgr_cfg_t *cfg, int family, - ip_address_t *local_addr, uint16_t local_port, - ip_address_t *remote_addr, uint16_t remote_port) { + hicn_ip_address_t *local_addr, uint16_t local_port, + hicn_ip_address_t *remote_addr, + uint16_t remote_port) { if ((family != AF_INET) && (family != AF_INET6)) return -1; facemgr_cfg_overlay_t *overlay = facemgr_cfg_overlay_create(); @@ -589,7 +591,7 @@ int facemgr_cfg_set_overlay(facemgr_cfg_t *cfg, int family, DEBUG(" <ipv4>"); if (overlay->is_local_addr) { char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, &overlay->local_addr, AF_INET); + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, &overlay->local_addr); DEBUG(" <local_addr>%s</local_addr>", buf); } if (overlay->is_local_port) { @@ -597,8 +599,7 @@ int facemgr_cfg_set_overlay(facemgr_cfg_t *cfg, int family, } if (overlay->is_remote_addr) { char buf[MAXSZ_IP_ADDRESS]; - ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, &overlay->remote_addr, - AF_INET); + hicn_ip_address_snprintf(buf, MAXSZ_IP_ADDRESS, &overlay->remote_addr); DEBUG(" <remote_addr>%s</remote_addr>", buf); } if (overlay->is_remote_port) { @@ -803,7 +804,7 @@ int facemgr_cfg_get_ignore(const facemgr_cfg_t *cfg, int facemgr_cfg_get_overlay_local_addr(const facemgr_cfg_t *cfg, const netdevice_t *netdevice, netdevice_type_t netdevice_type, - int family, ip_address_t *addr) { + int family, hicn_ip_address_t *addr) { facemgr_cfg_override_t *override; int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); if (rc < 0) return rc; @@ -889,7 +890,7 @@ int facemgr_cfg_get_overlay_local_port(const facemgr_cfg_t *cfg, int facemgr_cfg_get_overlay_remote_addr(const facemgr_cfg_t *cfg, const netdevice_t *netdevice, netdevice_type_t netdevice_type, - int family, ip_address_t *addr) { + int family, hicn_ip_address_t *addr) { facemgr_cfg_override_t *override; int rc = facemgr_cfg_get_override(cfg, netdevice, netdevice_type, &override); if (rc < 0) return rc; @@ -1042,7 +1043,8 @@ int facemgr_cfg_rule_get_ipv6(const facemgr_cfg_rule_t *rule, bool *ipv6) { } int facemgr_cfg_rule_get_overlay_local_addr(const facemgr_cfg_rule_t *rule, - int family, ip_address_t *addr) { + int family, + hicn_ip_address_t *addr) { facemgr_cfg_overlay_t *overlay = NULL; switch (family) { case AF_INET: @@ -1078,7 +1080,8 @@ int facemgr_cfg_rule_get_overlay_local_port(const facemgr_cfg_rule_t *rule, } int facemgr_cfg_rule_get_overlay_remote_addr(const facemgr_cfg_rule_t *rule, - int family, ip_address_t *addr) { + int family, + hicn_ip_address_t *addr) { facemgr_cfg_overlay_t *overlay = NULL; switch (family) { case AF_INET: diff --git a/ctrl/facemgr/src/cfg_file.c b/ctrl/facemgr/src/cfg_file.c index 966e35816..9b5f592dd 100644 --- a/ctrl/facemgr/src/cfg_file.c +++ b/ctrl/facemgr/src/cfg_file.c @@ -99,16 +99,16 @@ int parse_config_global(facemgr_cfg_t *cfg, config_setting_t *setting) { config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4"); if (overlay_v4) { const char *local_addr_str, *remote_addr_str; - ip_address_t local_addr = IP_ADDRESS_EMPTY; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - ip_address_t *local_addr_p = NULL; - ip_address_t *remote_addr_p = NULL; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t *local_addr_p = NULL; + hicn_ip_address_t *remote_addr_p = NULL; int local_port = 0; int remote_port = 0; if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) { - if (ip_address_pton(local_addr_str, &local_addr) < 0) { + if (hicn_ip_address_pton(local_addr_str, &local_addr) < 0) { ERROR("Error parsing v4 local addr"); goto ERR; } @@ -121,7 +121,7 @@ int parse_config_global(facemgr_cfg_t *cfg, config_setting_t *setting) { if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) { - if (ip_address_pton(remote_addr_str, &remote_addr) < 0) { + if (hicn_ip_address_pton(remote_addr_str, &remote_addr) < 0) { ERROR("Error parsing v4 remote addr"); goto ERR; } @@ -140,16 +140,16 @@ int parse_config_global(facemgr_cfg_t *cfg, config_setting_t *setting) { config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6"); if (overlay_v6) { const char *local_addr_str, *remote_addr_str; - ip_address_t local_addr = IP_ADDRESS_EMPTY; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - ip_address_t *local_addr_p = NULL; - ip_address_t *remote_addr_p = NULL; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t *local_addr_p = NULL; + hicn_ip_address_t *remote_addr_p = NULL; int local_port = 0; int remote_port = 0; if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) { - if (ip_address_pton(local_addr_str, &local_addr) < 0) { + if (hicn_ip_address_pton(local_addr_str, &local_addr) < 0) { ERROR("Error parsing v6 local addr"); goto ERR; } @@ -162,7 +162,7 @@ int parse_config_global(facemgr_cfg_t *cfg, config_setting_t *setting) { if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) { - if (ip_address_pton(remote_addr_str, &remote_addr) < 0) { + if (hicn_ip_address_pton(remote_addr_str, &remote_addr) < 0) { ERROR("Error parsing v6 remote addr"); goto ERR; } @@ -353,16 +353,16 @@ int parse_config_rules(facemgr_cfg_t *cfg, config_setting_t *setting) { config_setting_t *overlay_v4 = config_setting_get_member(overlay, "ipv4"); if (overlay_v4) { const char *local_addr_str, *remote_addr_str; - ip_address_t local_addr = IP_ADDRESS_EMPTY; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - ip_address_t *local_addr_p = NULL; - ip_address_t *remote_addr_p = NULL; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t *local_addr_p = NULL; + hicn_ip_address_t *remote_addr_p = NULL; int local_port = 0; int remote_port = 0; if (config_setting_lookup_string(overlay_v4, "local_addr", &local_addr_str)) { - ip_address_pton(local_addr_str, &local_addr); + hicn_ip_address_pton(local_addr_str, &local_addr); local_addr_p = &local_addr; } @@ -372,7 +372,7 @@ int parse_config_rules(facemgr_cfg_t *cfg, config_setting_t *setting) { if (config_setting_lookup_string(overlay_v4, "remote_addr", &remote_addr_str)) { - ip_address_pton(remote_addr_str, &remote_addr); + hicn_ip_address_pton(remote_addr_str, &remote_addr); remote_addr_p = &remote_addr; } @@ -390,16 +390,16 @@ int parse_config_rules(facemgr_cfg_t *cfg, config_setting_t *setting) { config_setting_t *overlay_v6 = config_setting_get_member(overlay, "ipv6"); if (overlay_v6) { const char *local_addr_str, *remote_addr_str; - ip_address_t local_addr = IP_ADDRESS_EMPTY; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; - ip_address_t *local_addr_p = NULL; - ip_address_t *remote_addr_p = NULL; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t *local_addr_p = NULL; + hicn_ip_address_t *remote_addr_p = NULL; int local_port = 0; int remote_port = 0; if (config_setting_lookup_string(overlay_v6, "local_addr", &local_addr_str)) { - ip_address_pton(local_addr_str, &local_addr); + hicn_ip_address_pton(local_addr_str, &local_addr); local_addr_p = &local_addr; } @@ -409,7 +409,7 @@ int parse_config_rules(facemgr_cfg_t *cfg, config_setting_t *setting) { if (config_setting_lookup_string(overlay_v6, "remote_addr", &remote_addr_str)) { - ip_address_pton(remote_addr_str, &remote_addr); + hicn_ip_address_pton(remote_addr_str, &remote_addr); remote_addr_p = &remote_addr; } @@ -450,7 +450,7 @@ int parse_config_static_facelets(facemgr_cfg_t *cfg, const char *family_str; int family; const char *remote_addr_str; - ip_address_t remote_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t remote_addr = IP_ADDRESS_EMPTY; int remote_port = 0; const char *interface_name; const char *interface_type_str; @@ -496,7 +496,7 @@ int parse_config_static_facelets(facemgr_cfg_t *cfg, /* Remote address */ if (config_setting_lookup_string(static_setting, "remote_addr", &remote_addr_str)) { - if (ip_address_pton(remote_addr_str, &remote_addr) < 0) { + if (hicn_ip_address_pton(remote_addr_str, &remote_addr) < 0) { ERROR("Error parsing v4 remote addr"); goto ERR_FACELET; } @@ -554,12 +554,12 @@ int parse_config_static_facelets(facemgr_cfg_t *cfg, config_setting_get_elem(routes_static_setting, j); const char *prefix_str; - ip_prefix_t prefix; + hicn_ip_prefix_t prefix; int cost = 0; /* default */ if (config_setting_lookup_string(route_static_setting, "prefix", &prefix_str)) { - if (ip_prefix_pton(prefix_str, &prefix) < 0) { + if (hicn_ip_prefix_pton(prefix_str, &prefix) < 0) { ERROR("Error parsing prefix in route #%d, rule #%d", j, i); goto ERR_FACELET; } diff --git a/ctrl/facemgr/src/common.h b/ctrl/facemgr/src/common.h index 2fda668c8..2adbc9a23 100644 --- a/ctrl/facemgr/src/common.h +++ b/ctrl/facemgr/src/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -34,8 +34,6 @@ #define INDENT(n, fmt) "%*s" fmt, n, "" #define printfi(n, fmt, ...) printf(INDENT(n * 4, fmt), ##__VA_ARGS__) -#define _unused(x) ((void)(x)) - /* Random strings */ static inline void rand_str(char *dest, size_t length) { diff --git a/ctrl/facemgr/src/facelet.c b/ctrl/facemgr/src/facelet.c index 609950f75..a299cc5ac 100644 --- a/ctrl/facemgr/src/facelet.c +++ b/ctrl/facemgr/src/facelet.c @@ -114,9 +114,7 @@ facelet_t *facelet_create() { facelet->remote_port_status = FACELET_ATTR_STATUS_UNSET; facelet->admin_state_status = FACELET_ATTR_STATUS_UNSET; facelet->state_status = FACELET_ATTR_STATUS_UNSET; -#ifdef WITH_POLICY facelet->priority_status = FACELET_ATTR_STATUS_UNSET; -#endif /* WITH_POLICY */ facelet->face_type_status = FACELET_ATTR_STATUS_UNSET; facelet->status = FACELET_STATUS_UNDEFINED; @@ -187,7 +185,6 @@ int facelet_validate_face(const facelet_t *facelet) { } netdevice_type_t netdevice_type_from_face_tags(const face_t *face) { -#ifdef WITH_POLICY policy_tags_t tags = face->tags; if (policy_tags_has(tags, POLICY_TAG_WIRED)) return NETDEVICE_TYPE_WIRED; @@ -195,7 +192,6 @@ netdevice_type_t netdevice_type_from_face_tags(const face_t *face) { return NETDEVICE_TYPE_WIFI; else if (policy_tags_has(tags, POLICY_TAG_CELLULAR)) return NETDEVICE_TYPE_CELLULAR; -#endif /* WITH_POLICY */ return NETDEVICE_TYPE_UNDEFINED; } @@ -232,8 +228,7 @@ facelet_t *facelet_create_from_face(face_t *face) { facelet->family_status = FACELET_ATTR_STATUS_CLEAN; /* Attribute : local_addr */ - if (ip_address_cmp(&face->local_addr, &IP_ADDRESS_EMPTY, face->family) != - 0) { + if (hicn_ip_address_cmp(&face->local_addr, &IP_ADDRESS_EMPTY) != 0) { facelet->local_addr = face->local_addr; facelet->local_addr_status = FACELET_ATTR_STATUS_CLEAN; } else { @@ -249,8 +244,7 @@ facelet_t *facelet_create_from_face(face_t *face) { } /* Attribute : remote_addr */ - if (ip_address_cmp(&face->remote_addr, &IP_ADDRESS_EMPTY, face->family) != - 0) { + if (hicn_ip_address_cmp(&face->remote_addr, &IP_ADDRESS_EMPTY) != 0) { facelet->remote_addr = face->remote_addr; facelet->remote_addr_status = FACELET_ATTR_STATUS_CLEAN; } else { @@ -290,7 +284,6 @@ facelet_t *facelet_create_from_face(face_t *face) { facelet->state_status = FACELET_ATTR_STATUS_UNSET; } -#ifdef WITH_POLICY /* Attribute : priority */ if (face->priority > 0) { facelet->priority = face->priority; @@ -298,7 +291,6 @@ facelet_t *facelet_create_from_face(face_t *face) { } else { facelet->priority_status = FACELET_ATTR_STATUS_UNSET; } -#endif /* WITH_POLICY */ /* Attribute : face_type */ if ((face->type != FACE_TYPE_UNDEFINED) && (face->type != FACE_TYPE_N)) { @@ -382,7 +374,8 @@ facelet_t *facelet_dup(const facelet_t *current_facelet) { hicn_route_t **route_array; int n = route_set_get_array(current_facelet->routes, &route_array); if (n < 0) { - ERROR("[facelet_free] Error getting route set associated to facelet"); + ERROR("[facelet_free] Error getting route set associated to facelet %p", + current_facelet); } else { for (unsigned i = 0; i < n; i++) { hicn_route_t *route = route_array[i]; @@ -775,7 +768,6 @@ int facelet_get_face(const facelet_t *facelet, face_t **pface) { face->state = FACE_STATE_UP; } -#ifdef WITH_POLICY /* Priority */ if (facelet_has_priority(facelet)) { if (facelet_get_priority(facelet, &face->priority) < 0) { @@ -815,7 +807,6 @@ int facelet_get_face(const facelet_t *facelet, face_t **pface) { } } face->tags = tags; -#endif /* WITH_POLICY */ *pface = face; @@ -956,8 +947,7 @@ int facelet_snprintf(char *s, size_t size, const facelet_t *facelet) { cur += rc; if (cur >= s + size) return (int)(cur - s); - rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr, - facelet->family); + rc = hicn_ip_address_snprintf(cur, s + size - cur, &facelet->local_addr); if (rc < 0) return rc; cur += rc; if (cur >= s + size) return (int)(cur - s); @@ -978,8 +968,7 @@ int facelet_snprintf(char *s, size_t size, const facelet_t *facelet) { cur += rc; if (cur >= s + size) return (int)(cur - s); - rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr, - facelet->family); + rc = hicn_ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr); if (rc < 0) return rc; cur += rc; if (cur >= s + size) return (int)(cur - s); @@ -1011,7 +1000,6 @@ int facelet_snprintf(char *s, size_t size, const facelet_t *facelet) { if (cur >= s + size) return (int)(cur - s); } -#ifdef WITH_POLICY /* Priority */ if (facelet_has_priority(facelet)) { rc = snprintf(cur, s + size - cur, " priority=%d", facelet->priority); @@ -1019,7 +1007,6 @@ int facelet_snprintf(char *s, size_t size, const facelet_t *facelet) { cur += rc; if (cur >= s + size) return (int)(cur - s); } -#endif /* WITH_POLICY */ /* Face type */ if (facelet_has_face_type(facelet)) { @@ -1138,8 +1125,7 @@ int facelet_snprintf_json(char *s, size_t size, const facelet_t *facelet, cur += rc; if (cur >= s + size) return (int)(cur - s); - rc = ip_address_snprintf(cur, s + size - cur, &facelet->local_addr, - facelet->family); + rc = hicn_ip_address_snprintf(cur, s + size - cur, &facelet->local_addr); if (rc < 0) return rc; cur += rc; if (cur >= s + size) return (int)(cur - s); @@ -1167,8 +1153,7 @@ int facelet_snprintf_json(char *s, size_t size, const facelet_t *facelet, cur += rc; if (cur >= s + size) return (int)(cur - s); - rc = ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr, - facelet->family); + rc = hicn_ip_address_snprintf(cur, s + size - cur, &facelet->remote_addr); if (rc < 0) return rc; cur += rc; if (cur >= s + size) return (int)(cur - s); @@ -1206,7 +1191,6 @@ int facelet_snprintf_json(char *s, size_t size, const facelet_t *facelet, if (cur >= s + size) return (int)(cur - s); } -#ifdef WITH_POLICY /* Priority */ if (facelet_has_priority(facelet)) { rc = snprintf(cur, s + size - cur, "%*s%s: %d,\n", 4 * (indent + 1), "", @@ -1215,7 +1199,6 @@ int facelet_snprintf_json(char *s, size_t size, const facelet_t *facelet, cur += rc; if (cur >= s + size) return (int)(cur - s); } -#endif /* WITH_POLICY */ if (facelet_has_face_type(facelet)) { rc = snprintf(cur, s + size - cur, "%*s%s: \"LAYER%s/%s\",\n", diff --git a/ctrl/facemgr/src/interfaces/android/android.c b/ctrl/facemgr/src/interfaces/android/android.c index 4e084d76d..578e7472a 100644 --- a/ctrl/facemgr/src/interfaces/android/android.c +++ b/ctrl/facemgr/src/interfaces/android/android.c @@ -74,9 +74,9 @@ int android_on_network_event(interface_t *interface, const char *interface_name, goto ERR_ND; } - ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; if (ip_address) { - if (ip_address_pton(ip_address, &local_addr) < 0) { + if (hicn_ip_address_pton(ip_address, &local_addr) < 0) { ERROR("[android_on_network_event] error processing IP address"); goto ERR_IP_ADDRESS; } diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c index 90f18c299..e7de5d648 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c +++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c @@ -211,8 +211,8 @@ static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity, return str; } -static mdns_string_t ip_address_to_string(char* buffer, size_t capacity, - const struct sockaddr* addr) { +static mdns_string_t hicn_ip_address_to_string(char* buffer, size_t capacity, + const struct sockaddr* addr) { if (addr->sa_family == AF_INET6) return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr); @@ -220,7 +220,8 @@ static mdns_string_t ip_address_to_string(char* buffer, size_t capacity, (const struct sockaddr_in*)addr); } -int ip_address_set_sockaddr(ip_address_t* ip_address, struct sockaddr* sa) { +int hicn_ip_address_set_sockaddr(hicn_ip_address_t* ip_address, + struct sockaddr* sa) { switch (sa->sa_family) { case AF_INET: ip_address->v4.as_inaddr = ((struct sockaddr_in*)sa)->sin_addr; @@ -245,7 +246,7 @@ static int callback(const struct sockaddr* from, mdns_entry_type_t entry, struct sockaddr_storage addr; mdns_string_t fromaddrstr = - ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); + hicn_ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" @@ -253,10 +254,10 @@ static int callback(const struct sockaddr* from, mdns_entry_type_t entry, switch (type) { case MDNS_RECORDTYPE_A: { - ip_address_t ip_address; + hicn_ip_address_t ip_address; mdns_record_parse_a(data, size, offset, length, (struct sockaddr_in*)&addr); - ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); + hicn_ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); mdns_string_t addrstr = ipv4_address_to_string( namebuffer, sizeof(namebuffer), (struct sockaddr_in*)&addr); @@ -276,10 +277,10 @@ static int callback(const struct sockaddr* from, mdns_entry_type_t entry, } case MDNS_RECORDTYPE_AAAA: { - ip_address_t ip_address; + hicn_ip_address_t ip_address; mdns_record_parse_aaaa(data, size, offset, length, (struct sockaddr_in6*)&addr); - ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); + hicn_ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); mdns_string_t addrstr = ipv6_address_to_string( namebuffer, sizeof(namebuffer), (struct sockaddr_in6*)&addr); diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c index b396782f5..2275d1cff 100644 --- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c +++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -23,6 +23,7 @@ #include <time.h> // time #include <hicn/ctrl.h> +#include <hicn/ctrl/socket.h> #include <hicn/facemgr.h> #include <hicn/util/ip_address.h> #include <hicn/util/log.h> @@ -110,7 +111,7 @@ int hl_process_state(interface_t *interface) assert(!data->polled_routes); stop_poll_timer(interface); - // DEBUG("[hl_process_state] Querying route list"); + DEBUG("[hl_process_state] Querying route list"); if (hc_route_list_async(data->sp) < 0) { DEBUG("[hl_process_state] Error querying route list"); return -1; @@ -119,7 +120,8 @@ int hl_process_state(interface_t *interface) break; case HL_STATE_ROUTES_RECEIVED: - // DEBUG("[hl_process_state] Querying face list"); + DEBUG("[hl_process_state] Got route list"); + DEBUG("[hl_process_state] Querying face list"); if (hc_face_list_async(data->sp) < 0) { DEBUG("[hl_process_state] Error querying face list"); return -1; @@ -128,6 +130,7 @@ int hl_process_state(interface_t *interface) break; case HL_STATE_FACES_RECEIVED: + DEBUG("[hl_process_state] Got face list"); data->state = HL_STATE_IDLE; start_poll_timer(interface); break; @@ -215,11 +218,12 @@ int hl_connect_timeout(interface_t *interface, int fd, void *unused) { * connected to succeed. */ int _hl_connect(interface_t *interface) { + ERROR("[MACCHA] CONNECT"); hl_data_t *data = interface->data; assert(!data->s); assert(!data->sp); - data->s = hc_sock_create(); + data->s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); if (data->s <= 0) { ERROR("[hc_connect] Could not create control socket"); goto ERR_SOCK; @@ -230,7 +234,7 @@ int _hl_connect(interface_t *interface) { goto ERR_CONNECT; } - data->sp = hc_sock_create(); + data->sp = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); if (data->sp <= 0) { ERROR("[hc_connect] Could not create polling socket"); goto ERR_SOCK_POLL; @@ -339,16 +343,12 @@ int hl_finalize(interface_t *interface) { } int hl_on_event(interface_t *interface, facelet_t *facelet) { - hc_face_t hc_face; hc_route_t route; int rc; int ret = 0; hl_data_t *data = (hl_data_t *)interface->data; face_t *face = NULL; - hc_face.id = 0; - memset(hc_face.name, 0, sizeof(hc_face.name)); - /* NOTE * - One example where this fails (and it is normal) is when we delete a * face that was not completely created, because for instance bonjour did @@ -373,14 +373,13 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { facelet_snprintf(buf, MAXSZ_FACELET, facelet); DEBUG("Create facelet %s", buf); - hc_face.face = *face; - rc = hc_face_create(data->s, &hc_face); + rc = hc_face_create(data->s, face); if (rc < 0) { ERROR("Failed to create face\n"); ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; goto ERR; } - INFO("Created face id=%d - %s", hc_face.id, buf); + INFO("Created face id=%d - %s", face->id, buf); } hicn_route_t **route_array; @@ -393,7 +392,7 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { if (n == 0) { /* Adding default routes */ route = (hc_route_t){ - .face_id = hc_face.id, + .face_id = face->id, .family = AF_INET, .remote_addr = IPV4_ANY, .len = 0, @@ -406,7 +405,7 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { } route = (hc_route_t){ - .face_id = hc_face.id, + .face_id = face->id, .family = AF_INET6, .remote_addr = IPV6_ANY, .len = 0, @@ -421,7 +420,7 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { } else { for (unsigned i = 0; i < n; i++) { hicn_route_t *hicn_route = route_array[i]; - ip_prefix_t prefix; + hicn_ip_prefix_t prefix; int cost; if (hicn_route_get_prefix(hicn_route, &prefix) < 0) { ERROR("Failed to get route prefix"); @@ -434,8 +433,8 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { continue; } route = (hc_route_t){ - .face_id = hc_face.id, - .name = "", /* take face_id into account */ + .face_id = face->id, + .face_name = "", /* take face_id into account */ .family = prefix.family, .remote_addr = prefix.address, .len = prefix.len, @@ -454,8 +453,7 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { case FACELET_EVENT_DELETE: /* Removing a face should also remove associated routes */ - hc_face.face = *face; - rc = hc_face_delete(data->s, &hc_face, 1); + rc = hc_face_delete(data->s, face); // delete_listener= */ 1); if (rc < 0) { ERROR("Failed to delete face\n"); ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; @@ -464,7 +462,7 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { char buf[MAXSZ_FACELET]; facelet_snprintf(buf, MAXSZ_FACELET, facelet); - INFO("Deleted face id=%d", hc_face.id); + INFO("Deleted face id=%d", face->id); break; @@ -472,10 +470,9 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { /* Currently, only admin_state & priority are supported */ if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - hc_face.face = *face; - hc_face_t *face_found; + hc_data_t *face_found; - rc = hc_face_get(data->s, &hc_face, &face_found); + rc = hc_face_get(data->s, face, &face_found); if (rc < 0) { ERROR("Failed to find face\n"); ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; @@ -487,8 +484,10 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { goto ERR; } char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); + + const hc_object_t *object = hc_data_get_object(face_found, 0); + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", object->face.id); + hc_data_free(face_found); face_state_t admin_state; if (facelet_get_admin_state(facelet, &admin_state) < 0) { @@ -504,16 +503,14 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { goto ERR; } facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - admin_state=%s", hc_face.id, + INFO("Updated face id=%d - admin_state=%s", face->id, face_state_str(admin_state)); } -#ifdef WITH_POLICY if (facelet_get_netdevice_type_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - hc_face.face = *face; - hc_face_t *face_found; + hc_data_t *face_found; - rc = hc_face_get(data->s, &hc_face, &face_found); + rc = hc_face_get(data->s, face, &face_found); if (rc < 0) { ERROR("Failed to find face\n"); goto ERR; @@ -523,8 +520,9 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { goto ERR; } char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); + const hc_object_t *object = hc_data_get_object(face_found, 0); + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", object->face.id); + hc_data_free(face_found); netdevice_type_t netdevice_type; if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { @@ -565,15 +563,14 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { goto ERR; } facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - netdevice_type=%s", hc_face.id, + INFO("Updated face id=%d - netdevice_type=%s", face->id, netdevice_type_str(netdevice_type)); } if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { INFO("Updating priority..."); - hc_face.face = *face; - hc_face_t *face_found; + hc_data_t *face_found; - rc = hc_face_get(data->s, &hc_face, &face_found); + rc = hc_face_get(data->s, face, &face_found); if (rc < 0) { ERROR("Failed to find face\n"); goto ERR; @@ -583,8 +580,9 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { goto ERR; } char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); + const hc_object_t *object = hc_data_get_object(face_found, 0); + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", object->face.id); + hc_data_free(face_found); uint32_t priority; if (facelet_get_priority(facelet, &priority) < 0) { @@ -601,9 +599,8 @@ int hl_on_event(interface_t *interface, facelet_t *facelet) { } facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - priority=%d", hc_face.id, priority); + INFO("Updated face id=%d - priority=%d", face->id, priority); } -#endif /* WITH_POLICY */ break; default: @@ -637,7 +634,7 @@ int hl_callback(interface_t *interface, int fd, void *unused) { } /* In case of error, reconnect to forwarder */ - if (hc_sock_callback(data->sp, &results) < 0) { + if (hc_sock_receive_all(data->sp, &results) < 0) { INFO("Closing socket... reconnecting..."); if (interface_unregister_fd(interface, hc_sock_get_fd(data->sp)) < 0) { ERROR("[hl_callback] Error unregistering fd"); @@ -657,7 +654,7 @@ int hl_callback(interface_t *interface, int fd, void *unused) { } /* Shall we wait for more data ? */ - if (!results->complete) { + if (!hc_data_is_complete(results)) { INFO("[hl_callback] results incomplete"); return ret; } @@ -704,7 +701,7 @@ int hl_callback(interface_t *interface, int fd, void *unused) { /* We can ignore faces on localhost */ - facelet_t *facelet = facelet_create_from_face(&f->face); + facelet_t *facelet = facelet_create_from_face(f); if (!facelet) { ERROR("[hl_callback] Could not create facelet... skipping"); continue; @@ -725,7 +722,7 @@ int hl_callback(interface_t *interface, int fd, void *unused) { if (r->len == 0) continue; - ip_prefix_t prefix = { + hicn_ip_prefix_t prefix = { .family = r->family, .address = r->remote_addr, .len = r->len, diff --git a/ctrl/facemgr/src/interfaces/netlink/netlink.c b/ctrl/facemgr/src/interfaces/netlink/netlink.c index 11738d7ac..3c99dc5cc 100644 --- a/ctrl/facemgr/src/interfaces/netlink/netlink.c +++ b/ctrl/facemgr/src/interfaces/netlink/netlink.c @@ -257,7 +257,7 @@ ERR_ND: int parse_addr(struct nlmsghdr *h, facelet_t **facelet, char *interface_name, size_t interface_name_size, char *interface_address, size_t interface_address_size) { - ip_address_t local_addr = IP_ADDRESS_EMPTY; + hicn_ip_address_t local_addr = IP_ADDRESS_EMPTY; struct ifaddrmsg *ifa; // structure for network interface data struct rtattr *tba[IFA_MAX + 1]; @@ -298,8 +298,8 @@ int parse_addr(struct nlmsghdr *h, facelet_t **facelet, char *interface_name, /* See comment in parse_link */ if (interface_address) { assert(tba[IFA_ADDRESS]); - ip_address_snprintf(interface_address, interface_address_size, &local_addr, - ifa->ifa_family); + hicn_ip_address_snprintf(interface_address, interface_address_size, + &local_addr); } netdevice_t *netdevice = netdevice_create_from_index(ifa->ifa_index); diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c index e1f5575d3..7f4a26c56 100644 --- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c +++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c @@ -173,501 +173,499 @@ void dump_endpoint(nw_endpoint_t endpoint, int indent) { } } - void dump_path(nw_path_t path, int indent) { - /* nw_path_enumerate_interfaces : not interesting */ - nw_path_status_t path_status = nw_path_get_status(path); - printfi(indent, "Status: %s\n", path_status_str[path_status]); - printfi(indent, "Expensive: %s\n", - nw_path_is_expensive(path) ? "true" : "false"); - printfi(indent, "IPv4 enabled: %s\n", - nw_path_has_ipv4(path) ? "true" : "false"); - printfi(indent, "IPv6 enabled: %s\n", - nw_path_has_ipv6(path) ? "true" : "false"); - printfi(indent, "DNS: %s\n", nw_path_has_dns(path) ? "true" : "false"); - printfi(indent, "Interfaces:\n"); - nw_path_enumerate_interfaces( - path, - (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) { - dump_interface(interface, indent + 1); - return true; - }); - - nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); - printfi(indent, "Effective local endpoint:\n"); - dump_endpoint(local, indent + 1); - nw_release(local); - - nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); - printfi(indent, "Effective remote endpoint:\n"); - dump_endpoint(remote, indent + 1); - nw_release(remote); - } +void dump_path(nw_path_t path, int indent) { + /* nw_path_enumerate_interfaces : not interesting */ + nw_path_status_t path_status = nw_path_get_status(path); + printfi(indent, "Status: %s\n", path_status_str[path_status]); + printfi(indent, "Expensive: %s\n", + nw_path_is_expensive(path) ? "true" : "false"); + printfi(indent, "IPv4 enabled: %s\n", + nw_path_has_ipv4(path) ? "true" : "false"); + printfi(indent, "IPv6 enabled: %s\n", + nw_path_has_ipv6(path) ? "true" : "false"); + printfi(indent, "DNS: %s\n", nw_path_has_dns(path) ? "true" : "false"); + printfi(indent, "Interfaces:\n"); + nw_path_enumerate_interfaces( + path, + (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) { + dump_interface(interface, indent + 1); + return true; + }); - void dump_connection(nw_connection_t connection, int indent) { - nw_endpoint_t remote = nw_connection_copy_endpoint(connection); - nw_path_t path = nw_connection_copy_current_path(connection); + nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); + printfi(indent, "Effective local endpoint:\n"); + dump_endpoint(local, indent + 1); + nw_release(local); - printfi(indent, "Remote endpoint:\n"); - dump_endpoint(remote, indent + 1); - printfi(indent, "Path:\n"); - dump_path(path, indent + 1); + nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); + printfi(indent, "Effective remote endpoint:\n"); + dump_endpoint(remote, indent + 1); + nw_release(remote); +} - /* - nw_connection_copy_protocol_metadata(); - nw_connection_get_maximum_datagram_size(); - */ +void dump_connection(nw_connection_t connection, int indent) { + nw_endpoint_t remote = nw_connection_copy_endpoint(connection); + nw_path_t path = nw_connection_copy_current_path(connection); - nw_release(remote); - nw_release(path); - } + printfi(indent, "Remote endpoint:\n"); + dump_endpoint(remote, indent + 1); + printfi(indent, "Path:\n"); + dump_path(path, indent + 1); + + /* + nw_connection_copy_protocol_metadata(); + nw_connection_get_maximum_datagram_size(); + */ + + nw_release(remote); + nw_release(path); +} #if defined(MAC_OS_X_VERSION_10_15) - void dump_browse_result(nw_browse_result_t result, int indent) { - /* Endpoint */ - nw_endpoint_t browse_endpoint = nw_browse_result_copy_endpoint(result); - if (!browse_endpoint) { - ERROR( - "[network_framework.dump_result] Failed to retrieve endpoint from " - "Bonjour browse result"); - return; - } - printfi(indent + 1, "Endpoint:"); - dump_endpoint(browse_endpoint, indent + 2); - - /* Interfaces */ - printfi(indent + 1, "Interfaces:"); - nw_browse_result_enumerate_interfaces( - result, - (nw_browse_result_enumerate_interface_t) ^ (nw_interface_t interface) { - dump_interface(interface, indent + 2); - return true; - }); +void dump_browse_result(nw_browse_result_t result, int indent) { + /* Endpoint */ + nw_endpoint_t browse_endpoint = nw_browse_result_copy_endpoint(result); + if (!browse_endpoint) { + ERROR( + "[network_framework.dump_result] Failed to retrieve endpoint from " + "Bonjour browse result"); + return; } + printfi(indent + 1, "Endpoint:"); + dump_endpoint(browse_endpoint, indent + 2); + + /* Interfaces */ + printfi(indent + 1, "Interfaces:"); + nw_browse_result_enumerate_interfaces( + result, + (nw_browse_result_enumerate_interface_t) ^ (nw_interface_t interface) { + dump_interface(interface, indent + 2); + return true; + }); +} #endif /* defined(MAC_OS_X_VERSION_10_15) */ - facelet_t *facelet_create_from_connection(nw_connection_t connection) { - facelet_t *facelet; - ip_address_t local_addr, remote_addr; - uint16_t remote_port; - - nw_path_t path = nw_connection_copy_current_path(connection); - nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); - nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); - __block nw_interface_t interface; - - const struct sockaddr *local_sa = nw_endpoint_get_address(local); - const struct sockaddr *remote_sa = nw_endpoint_get_address(remote); - - assert(local_sa->sa_family == remote_sa->sa_family); - switch (local_sa->sa_family) { - case AF_INET: - local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr; - remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr; - remote_port = ((struct sockaddr_in *)remote_sa)->sin_port; - break; - case AF_INET6: - local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr; - remote_addr.v6.as_in6addr = - ((struct sockaddr_in6 *)remote_sa)->sin6_addr; - remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port; - break; - default: - ERROR("Unsupported address family: %d\n", local_sa->sa_family); - return NULL; - } - - /* Retrieving path interface type (a single one expected */ - nw_path_enumerate_interfaces( - path, (nw_path_enumerate_interfaces_block_t) ^ - (nw_interface_t path_interface) { - interface = path_interface; - return false; - }); - - const char *name = nw_interface_get_name(interface); - netdevice_t netdevice; - snprintf(netdevice.name, IFNAMSIZ, "%s", name); - netdevice_update_index(&netdevice); - - netdevice_type_t netdevice_type; - nw_interface_type_t type = nw_interface_get_type(interface); - - switch (type) { - case INTERFACE_TYPE_OTHER: - netdevice_type = NETDEVICE_TYPE_UNDEFINED; - break; - case INTERFACE_TYPE_WIFI: - netdevice_type = NETDEVICE_TYPE_WIFI; - break; - case INTERFACE_TYPE_CELLULAR: - netdevice_type = NETDEVICE_TYPE_CELLULAR; - break; - case INTERFACE_TYPE_WIRED: - netdevice_type = NETDEVICE_TYPE_WIRED; - break; - case INTERFACE_TYPE_LOOPBACK: - netdevice_type = NETDEVICE_TYPE_LOOPBACK; - break; - default: - break; - } +facelet_t *facelet_create_from_connection(nw_connection_t connection) { + facelet_t *facelet; + hicn_ip_address_t local_addr, remote_addr; + uint16_t remote_port; + + nw_path_t path = nw_connection_copy_current_path(connection); + nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); + nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); + __block nw_interface_t interface; + + const struct sockaddr *local_sa = nw_endpoint_get_address(local); + const struct sockaddr *remote_sa = nw_endpoint_get_address(remote); + + assert(local_sa->sa_family == remote_sa->sa_family); + switch (local_sa->sa_family) { + case AF_INET: + local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr; + remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr; + remote_port = ((struct sockaddr_in *)remote_sa)->sin_port; + break; + case AF_INET6: + local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr; + remote_addr.v6.as_in6addr = ((struct sockaddr_in6 *)remote_sa)->sin6_addr; + remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port; + break; + default: + ERROR("Unsupported address family: %d\n", local_sa->sa_family); + return NULL; + } - nw_release(local); - nw_release(remote); - nw_release(path); + /* Retrieving path interface type (a single one expected */ + nw_path_enumerate_interfaces( + path, + (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t path_interface) { + interface = path_interface; + return false; + }); - facelet = facelet_create(); - if (!facelet) return NULL; + const char *name = nw_interface_get_name(interface); + netdevice_t netdevice; + snprintf(netdevice.name, IFNAMSIZ, "%s", name); + netdevice_update_index(&netdevice); - facelet_set_netdevice(facelet, netdevice); - facelet_set_netdevice_type(facelet, netdevice_type); - facelet_set_family(facelet, local_sa->sa_family); - facelet_set_local_addr(facelet, local_addr); - facelet_set_remote_addr(facelet, remote_addr); - facelet_set_remote_port(facelet, remote_port); + netdevice_type_t netdevice_type; + nw_interface_type_t type = nw_interface_get_type(interface); - return facelet; + switch (type) { + case INTERFACE_TYPE_OTHER: + netdevice_type = NETDEVICE_TYPE_UNDEFINED; + break; + case INTERFACE_TYPE_WIFI: + netdevice_type = NETDEVICE_TYPE_WIFI; + break; + case INTERFACE_TYPE_CELLULAR: + netdevice_type = NETDEVICE_TYPE_CELLULAR; + break; + case INTERFACE_TYPE_WIRED: + netdevice_type = NETDEVICE_TYPE_WIRED; + break; + case INTERFACE_TYPE_LOOPBACK: + netdevice_type = NETDEVICE_TYPE_LOOPBACK; + break; + default: + break; } - void on_connection_state_event( - interface_t * interface, nw_interface_t iface, nw_connection_t cnx, - nw_connection_state_t state, nw_error_t error) { + nw_release(local); + nw_release(remote); + nw_release(path); + + facelet = facelet_create(); + if (!facelet) return NULL; + + facelet_set_netdevice(facelet, netdevice); + facelet_set_netdevice_type(facelet, netdevice_type); + facelet_set_family(facelet, local_sa->sa_family); + facelet_set_local_addr(facelet, local_addr); + facelet_set_remote_addr(facelet, remote_addr); + facelet_set_remote_port(facelet, remote_port); + + return facelet; +} + +void on_connection_state_event(interface_t *interface, nw_interface_t iface, + nw_connection_t cnx, nw_connection_state_t state, + nw_error_t error) { #if 1 - DEBUG("Connection [new state = %s]:\n", connection_state_str[state]); - nw_path_t path = nw_connection_copy_current_path(cnx); - nw_path_enumerate_interfaces( - path, - (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) { - const char *name = nw_interface_get_name(interface); - printf("NAME=%s\n", name); - return true; - }); + DEBUG("Connection [new state = %s]:\n", connection_state_str[state]); + nw_path_t path = nw_connection_copy_current_path(cnx); + nw_path_enumerate_interfaces( + path, + (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) { + const char *name = nw_interface_get_name(interface); + printf("NAME=%s\n", name); + return true; + }); #endif - /* We should get enough information to create the face and set if up - * asap */ + /* We should get enough information to create the face and set if up + * asap */ - nw_endpoint_t remote = nw_connection_copy_endpoint(cnx); - errno = error ? nw_error_get_error_code(error) : 0; + nw_endpoint_t remote = nw_connection_copy_endpoint(cnx); + errno = error ? nw_error_get_error_code(error) : 0; - switch (state) { - case nw_connection_state_waiting: - warn("connect to %s port %u (%s) failed, is waiting", - nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote), - BONJOUR_PROTOCOL_NAME); - break; + switch (state) { + case nw_connection_state_waiting: + warn("connect to %s port %u (%s) failed, is waiting", + nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote), + BONJOUR_PROTOCOL_NAME); + break; - case nw_connection_state_preparing: - break; + case nw_connection_state_preparing: + break; - case nw_connection_state_ready: { - printf("info:\n"); - warn("connection ready"); + case nw_connection_state_ready: { + printf("info:\n"); + warn("connection ready"); #if 1 - WITH_DEBUG({ dump_connection(cnx, 1); }); + WITH_DEBUG({ dump_connection(cnx, 1); }); #endif - facelet_t *facelet = facelet_create_from_connection(cnx); - if (!facelet) return; - facelet_set_event(facelet, FACELET_EVENT_CREATE); - interface_raise_event(interface, facelet); - break; - } - case nw_connection_state_failed: - /* Can we fail with bonjour, or are we always waiting ? */ - warn("connect to %s port %u (%s) failed", - nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote), - BONJOUR_PROTOCOL_NAME); - break; - - case nw_connection_state_cancelled: - // Release the primary reference on the connection - // that was taken at creation time - nw_release(cnx); - break; - - default: /* nw_connection_state_invalid */ - /* Should never be called */ - break; + facelet_t *facelet = facelet_create_from_connection(cnx); + if (!facelet) return; + facelet_set_event(facelet, FACELET_EVENT_CREATE); + interface_raise_event(interface, facelet); + break; } - - nw_release(remote); + case nw_connection_state_failed: + /* Can we fail with bonjour, or are we always waiting ? */ + warn("connect to %s port %u (%s) failed", + nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote), + BONJOUR_PROTOCOL_NAME); + break; + + case nw_connection_state_cancelled: + // Release the primary reference on the connection + // that was taken at creation time + nw_release(cnx); + break; + + default: /* nw_connection_state_invalid */ + /* Should never be called */ + break; } - void on_connection_path_event(interface_t * interface, nw_interface_t iface, - nw_connection_t cnx, nw_path_t path) { + nw_release(remote); +} + +void on_connection_path_event(interface_t *interface, nw_interface_t iface, + nw_connection_t cnx, nw_path_t path) { #if 1 - DEBUG("Connection [path changed]:\n"); - WITH_DEBUG({ dump_connection(cnx, 1); }); + DEBUG("Connection [path changed]:\n"); + WITH_DEBUG({ dump_connection(cnx, 1); }); #endif - /* redundant */ /* - DEBUG(1, "Path:\n"); - dump_path(path, 2); - */ - } + /* redundant */ /* + DEBUG(1, "Path:\n"); + dump_path(path, 2); + */ +} - /** - * Enumerate main path interfaces +/** + * Enumerate main path interfaces + * + * We need to create specific dummy connections for each newly discovered + * interface + * + * Currently we only use Bonjour/TCP for remote hICN discovery and connection + * path monitoring. + */ +void on_interface_event(interface_t *interface, nw_interface_t iface) { + /* We can create an hICN face on this interface that will be down until + * connected + * It is however possible to have two default gateways on the same + * interface, or more, or even zero. Somehow we need a strategy, timers, etc + * to properly do the job. * - * We need to create specific dummy connections for each newly discovered - * interface + * We have to determine: + * - how many faces to build + * - the face type : hICN, tunnel (TCP/UDP) + * - the underlying protocol : v4, v6 * - * Currently we only use Bonjour/TCP for remote hICN discovery and connection - * path monitoring. + * This depends on the configuration, end host and network capabilities. + * + * We can rely on several types of discovery: + * - DHCP + * - Bonjour + * - ... + * + * So far: + * - bonjour discovery attempt, we expect to discover one hICN interface + * (how bonjour works with more than one is unclear), after a certain + * time, if none is discovered, we cannot do any tunnel face. */ - void on_interface_event(interface_t * interface, nw_interface_t iface) { - /* We can create an hICN face on this interface that will be down until - * connected - * It is however possible to have two default gateways on the same - * interface, or more, or even zero. Somehow we need a strategy, timers, etc - * to properly do the job. - * - * We have to determine: - * - how many faces to build - * - the face type : hICN, tunnel (TCP/UDP) - * - the underlying protocol : v4, v6 - * - * This depends on the configuration, end host and network capabilities. - * - * We can rely on several types of discovery: - * - DHCP - * - Bonjour - * - ... - * - * So far: - * - bonjour discovery attempt, we expect to discover one hICN interface - * (how bonjour works with more than one is unclear), after a certain - * time, if none is discovered, we cannot do any tunnel face. - */ - // OLD CODE + // OLD CODE - /* nw_parameters_create_secure_{udp,tcp} */ - nw_parameters_t parameters = nw_parameters_create_fn( - NW_PARAMETERS_DISABLE_PROTOCOL, /* no (d)tls */ - NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */); + /* nw_parameters_create_secure_{udp,tcp} */ + nw_parameters_t parameters = nw_parameters_create_fn( + NW_PARAMETERS_DISABLE_PROTOCOL, /* no (d)tls */ + NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */); - if (!parameters) goto ERR_PARAMETERS; + if (!parameters) goto ERR_PARAMETERS; - nw_parameters_require_interface(parameters, iface); - nw_parameters_set_reuse_local_address(parameters, true); + nw_parameters_require_interface(parameters, iface); + nw_parameters_set_reuse_local_address(parameters, true); #if defined(MAC_OS_X_VERSION_10_15) - /* - * Before being able to create a bonjour endpoint, we need to browse for - * available services on the local network using the parameters specified - * before. - */ - nw_browse_descriptor_t descriptor = - nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE, - BONJOUR_SERVICE_DOMAIN); - if (!descriptor) { - ERROR( - "[network_framework.on_interface_event] Failed to create a bonjour " - "browse descriptor"); - goto ERR_DESCRIPTOR; - } + /* + * Before being able to create a bonjour endpoint, we need to browse for + * available services on the local network using the parameters specified + * before. + */ + nw_browse_descriptor_t descriptor = + nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE, + BONJOUR_SERVICE_DOMAIN); + if (!descriptor) { + ERROR( + "[network_framework.on_interface_event] Failed to create a bonjour " + "browse descriptor"); + goto ERR_DESCRIPTOR; + } - nw_browser_t browser = nw_browser_create(descriptor, parameters); - nw_browser_set_queue(browser, dispatch_get_main_queue()); - nw_browser_set_browse_results_changed_handler(browser, ^( - nw_browse_result_t result, - nw_browse_result_t - result2, - bool flag) { - /* Dump result */ - printfi(0, "NEW BROWSE RESULT"); - printfi(1, "Result:"); - dump_browse_result(result, 2); - printfi(1, "Result2:"); - dump_browse_result(result2, 2); - printfi(1, "Flag: %s\n", (flag ? "ON" : "OFF")); - - /* Changes */ - nw_browse_result_change_t change = - nw_browse_result_get_changes(result, result2); - switch (change) { - case nw_browse_result_change_identical: - printfi(2, "The compared services are identical."); - break; - case nw_browse_result_change_result_added: - printfi(2, "A new service was discovered."); - break; + nw_browser_t browser = nw_browser_create(descriptor, parameters); + nw_browser_set_queue(browser, dispatch_get_main_queue()); + nw_browser_set_browse_results_changed_handler(browser, ^( + nw_browse_result_t result, + nw_browse_result_t result2, + bool flag) { + /* Dump result */ + printfi(0, "NEW BROWSE RESULT"); + printfi(1, "Result:"); + dump_browse_result(result, 2); + printfi(1, "Result2:"); + dump_browse_result(result2, 2); + printfi(1, "Flag: %s\n", (flag ? "ON" : "OFF")); + + /* Changes */ + nw_browse_result_change_t change = + nw_browse_result_get_changes(result, result2); + switch (change) { + case nw_browse_result_change_identical: + printfi(2, "The compared services are identical."); + break; + case nw_browse_result_change_result_added: + printfi(2, "A new service was discovered."); + break; - case nw_browse_result_change_result_removed: - printfi(2, "A previously discovered service was removed."); - break; + case nw_browse_result_change_result_removed: + printfi(2, "A previously discovered service was removed."); + break; - case nw_browse_result_change_txt_record_changed: - printfi(2, "The service's associated TXT record changed."); - break; + case nw_browse_result_change_txt_record_changed: + printfi(2, "The service's associated TXT record changed."); + break; - case nw_browse_result_change_interface_added: - printfi(2, "The service was discovered over a new interface."); - break; + case nw_browse_result_change_interface_added: + printfi(2, "The service was discovered over a new interface."); + break; - case nw_browse_result_change_interface_removed: - printfi( - 2, - "The service was no longer discovered over a certain interface."); - break; - } - }); + case nw_browse_result_change_interface_removed: + printfi( + 2, + "The service was no longer discovered over a certain interface."); + break; + } + }); - nw_browser_start(browser); + nw_browser_start(browser); //#else //#warning "Bonjour discovery only available in MacOS 10.15+" #endif /* defined(MAC_OS_X_VERSION_10_15) */ - /* - * Now that we have resolve the name of a bonjour remote, we can create a - * connection to the corresponding endpoint identified by its name. - */ - nw_endpoint_t endpoint; + /* + * Now that we have resolve the name of a bonjour remote, we can create a + * connection to the corresponding endpoint identified by its name. + */ + nw_endpoint_t endpoint; - DEBUG("Creating bonjour service towards NAME=%s TYPE=%s DOMAIN=%s", - BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); - endpoint = nw_endpoint_create_bonjour_service( + DEBUG("Creating bonjour service towards NAME=%s TYPE=%s DOMAIN=%s", BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); + endpoint = nw_endpoint_create_bonjour_service( + BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); - if (!endpoint) { - ERROR( - "[network_framework.on_interface_event] Failed to create bound " - "Bonjour " - "connection"); - goto ERR_ENDPOINT; - } + if (!endpoint) { + ERROR( + "[network_framework.on_interface_event] Failed to create bound " + "Bonjour " + "connection"); + goto ERR_ENDPOINT; + } - nw_connection_t connection = nw_connection_create(endpoint, parameters); - if (!connection) goto ERR_CONNECTION; + nw_connection_t connection = nw_connection_create(endpoint, parameters); + if (!connection) goto ERR_CONNECTION; - nw_release(endpoint); - nw_release(parameters); + nw_release(endpoint); + nw_release(parameters); - /* Remember not to recreate connection */ - // XXX TODO + /* Remember not to recreate connection */ + // XXX TODO - /* Setup connection handlers */ + /* Setup connection handlers */ - nw_connection_set_state_changed_handler( - connection, ^(nw_connection_state_t state, nw_error_t error) { - on_connection_state_event(interface, iface, connection, state, error); - }); + nw_connection_set_state_changed_handler( + connection, ^(nw_connection_state_t state, nw_error_t error) { + on_connection_state_event(interface, iface, connection, state, error); + }); - nw_connection_set_path_changed_handler(connection, ^(nw_path_t path) { - on_connection_path_event(interface, iface, connection, path); - }); + nw_connection_set_path_changed_handler(connection, ^(nw_path_t path) { + on_connection_path_event(interface, iface, connection, path); + }); - nw_connection_set_better_path_available_handler(connection, ^(bool value) { + nw_connection_set_better_path_available_handler(connection, ^(bool value) { #if 1 - DEBUG("Connection [better path = %s]\n", (value ? "true" : "false")); - WITH_DEBUG({ dump_connection(connection, 1); }); + DEBUG("Connection [better path = %s]\n", (value ? "true" : "false")); + WITH_DEBUG({ dump_connection(connection, 1); }); #endif - }); + }); - nw_connection_set_viability_changed_handler(connection, ^(bool value) { + nw_connection_set_viability_changed_handler(connection, ^(bool value) { #if 1 - DEBUG("Connection [viable = %s]\n", (value ? "true" : "false")); - WITH_DEBUG({ - // dump_connection(connection, 1); - }); + DEBUG("Connection [viable = %s]\n", (value ? "true" : "false")); + WITH_DEBUG({ + // dump_connection(connection, 1); + }); #endif - /* - * This is the first time we have a connection with address and port - * and thus the full identification of an hICN face - */ - facelet_t *facelet = facelet_create_from_connection(connection); - if (!facelet) return; - facelet_set_event(facelet, - value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE); - interface_raise_event(interface, facelet); - }); + /* + * This is the first time we have a connection with address and port + * and thus the full identification of an hICN face + */ + facelet_t *facelet = facelet_create_from_connection(connection); + if (!facelet) return; + facelet_set_event(facelet, + value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE); + interface_raise_event(interface, facelet); + }); - nw_connection_start(connection); + nw_connection_start(connection); - nw_connection_set_queue(connection, dispatch_get_main_queue()); - nw_retain(connection); // Hold a reference until cancelled + nw_connection_set_queue(connection, dispatch_get_main_queue()); + nw_retain(connection); // Hold a reference until cancelled #if 1 - DEBUG("Created Bonjour cnx on interface:"); - WITH_DEBUG({ dump_interface(iface, 1); }); + DEBUG("Created Bonjour cnx on interface:"); + WITH_DEBUG({ dump_interface(iface, 1); }); #endif - return; + return; - nw_release(connection); - ERR_CONNECTION: - nw_release(endpoint); - ERR_ENDPOINT: + nw_release(connection); +ERR_CONNECTION: + nw_release(endpoint); +ERR_ENDPOINT: #if defined(MAC_OS_X_VERSION_10_15) - nw_release(descriptor); - ERR_DESCRIPTOR: + nw_release(descriptor); +ERR_DESCRIPTOR: #endif /* defined(MAC_OS_X_VERSION_10_15) */ - nw_release(parameters); + nw_release(parameters); - ERR_PARAMETERS: - return; - } +ERR_PARAMETERS: + return; +} - void on_path_event(interface_t * interface, nw_path_t path) { - /* Simplification: we handle path event only once. - * Ideally, test whether we discover new interfaces or not - */ +void on_path_event(interface_t *interface, nw_path_t path) { + /* Simplification: we handle path event only once. + * Ideally, test whether we discover new interfaces or not + */ #if 1 - DEBUG("Path [event]:\n"); - WITH_DEBUG({ dump_path(path, 1); }); + DEBUG("Path [event]:\n"); + WITH_DEBUG({ dump_path(path, 1); }); #endif - nw_path_enumerate_interfaces( - path, (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t iface) { - on_interface_event(interface, iface); - return true; - }); - } + nw_path_enumerate_interfaces( + path, (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t iface) { + on_interface_event(interface, iface); + return true; + }); +} - int nf_initialize(interface_t * interface, void *cfg) { - nf_data_t *data = malloc(sizeof(nf_data_t)); - if (!data) goto ERR_MALLOC; +int nf_initialize(interface_t *interface, void *cfg) { + nf_data_t *data = malloc(sizeof(nf_data_t)); + if (!data) goto ERR_MALLOC; - if (cfg) data->cfg = *(network_framework_cfg_t *)cfg; + if (cfg) data->cfg = *(network_framework_cfg_t *)cfg; - data->pm = nw_path_monitor_create(); - if (!data->pm) goto ERR_PM; + data->pm = nw_path_monitor_create(); + if (!data->pm) goto ERR_PM; - nw_path_monitor_set_queue(data->pm, dispatch_get_main_queue()); - nw_path_monitor_set_cancel_handler(data->pm, ^(){ - }); - nw_path_monitor_set_update_handler(data->pm, ^(nw_path_t path) { - on_path_event(interface, path); - }); + nw_path_monitor_set_queue(data->pm, dispatch_get_main_queue()); + nw_path_monitor_set_cancel_handler(data->pm, ^(){ + }); + nw_path_monitor_set_update_handler(data->pm, ^(nw_path_t path) { + on_path_event(interface, path); + }); - // XXX NEEDED ? - nw_retain(data->pm); + // XXX NEEDED ? + nw_retain(data->pm); - DEBUG("Starting network path monitor"); - nw_path_monitor_start(data->pm); + DEBUG("Starting network path monitor"); + nw_path_monitor_start(data->pm); - interface->data = data; - return 0; + interface->data = data; + return 0; - ERR_PM: - free(data); - ERR_MALLOC: - return -1; - } +ERR_PM: + free(data); +ERR_MALLOC: + return -1; +} - int nf_finalize(interface_t * interface) { - nf_data_t *data = (nf_data_t *)interface->data; - if (data->pm) { - nw_path_monitor_cancel(data->pm); - data->pm = NULL; - } - return 0; +int nf_finalize(interface_t *interface) { + nf_data_t *data = (nf_data_t *)interface->data; + if (data->pm) { + nw_path_monitor_cancel(data->pm); + data->pm = NULL; } + return 0; +} - const interface_ops_t network_framework_ops = { - .type = "network_framework", - .initialize = nf_initialize, - .finalize = nf_finalize, - .on_event = NULL, - }; +const interface_ops_t network_framework_ops = { + .type = "network_framework", + .initialize = nf_initialize, + .finalize = nf_finalize, + .on_event = NULL, +}; diff --git a/ctrl/libhicnctrl/examples/Makefile b/ctrl/libhicnctrl/examples/Makefile index ad0e46a1e..1c1eb64e1 100644 --- a/ctrl/libhicnctrl/examples/Makefile +++ b/ctrl/libhicnctrl/examples/Makefile @@ -1,7 +1,7 @@ EXEC = $(shell basename $$(pwd)) CC = gcc -CFLAGS = -std=gnu11 -g -Wall -Wextra -Wpedantic -Wstrict-aliasing -DWITH_POLICY=1 +CFLAGS = -std=gnu11 -g -Wall -Wextra -Wpedantic -Wstrict-aliasing LDFLAGS = -lhicn -lhicnctrl SRC = $(wildcard *.c) diff --git a/ctrl/libhicnctrl/examples/create_face.c b/ctrl/libhicnctrl/examples/create_face.c index ebd451de1..2152ff1e3 100644 --- a/ctrl/libhicnctrl/examples/create_face.c +++ b/ctrl/libhicnctrl/examples/create_face.c @@ -104,10 +104,8 @@ int main() { .remote_port = 6000, .admin_state = FACE_STATE_UNDEFINED, .state = FACE_STATE_UNDEFINED, -#ifdef WITH_POLICY .priority = 0, .tags = POLICY_TAGS_EMPTY, -#endif /* WITH_POLICY */ }, }; if (netdevice_set_name(&face.face.netdevice, if_name) < 0) { diff --git a/ctrl/libhicnctrl/includes/CMakeLists.txt b/ctrl/libhicnctrl/includes/CMakeLists.txt index 1a90690a4..554021c48 100644 --- a/ctrl/libhicnctrl/includes/CMakeLists.txt +++ b/ctrl/libhicnctrl/includes/CMakeLists.txt @@ -27,8 +27,29 @@ set(Libhicnctrl_INCLUDE_DIRS set(TO_INSTALL_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/ctrl.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/api.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/action.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/callback.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/command.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/data.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/fw_interface.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/hicn-light.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/hicn-light-ng.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/object.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/object_type.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/active_interface.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/base.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/cache.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/connection.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/listener.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/mapme.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/policy.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/punting.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/strategy.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/objects/subscription.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/parse.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ctrl/socket.h PARENT_SCOPE ) diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl.h b/ctrl/libhicnctrl/includes/hicn/ctrl.h index 477afd152..4decdf10f 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl.h @@ -21,5 +21,6 @@ #define HICNCTRL_H #include <hicn/ctrl/api.h> +#include <hicn/ctrl/socket.h> #endif /* HICNCTRL_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/action.h b/ctrl/libhicnctrl/includes/hicn/ctrl/action.h new file mode 100644 index 000000000..55c4ebf77 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/action.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file action.h + * \brief Actions. + */ + +#ifndef HICNCTRL_ACTION_H +#define HICNCTRL_ACTION_H + +#define foreach_action \ + _(UNDEFINED) \ + _(CREATE) \ + _(UPDATE) \ + _(DELETE) \ + _(LIST) \ + _(GET) \ + _(SET) \ + _(SERVE) \ + _(STORE) \ + _(CLEAR) \ + _(SUBSCRIBE) \ + _(N) + +typedef enum { +#define _(x) ACTION_##x, + foreach_action +#undef _ +} hc_action_t; + +extern const char *action_str[]; + +#define action_str(x) action_str[x] + +hc_action_t action_from_str(const char *action_str); + +#endif /* HICNCTRL_ACTION_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h index c259fc10c..21a5e548f 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/api.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/api.h @@ -58,8 +58,6 @@ * provide a set of defines to preserve backwards compatibility. At the * moment, those defines are : * - * WITH_POLICY: - * */ #ifndef HICNTRL_API @@ -69,9 +67,17 @@ #include <stdint.h> #include <stddef.h> // object_offset_t +#include <hicn/ctrl/action.h> +#include <hicn/ctrl/callback.h> +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/object_type.h> +#include <hicn/ctrl/objects.h> +#include <hicn/ctrl/socket.h> #include <hicn/util/ip_address.h> #include <hicn/face.h> #include <hicn/strategy.h> + #include <hicn/base.h> /* * This has to be common between hicn-light and hicn-plugin. We now we keep the @@ -79,13 +85,12 @@ */ #define SYMBOLIC_NAME_LEN 16 +#include <hicn/ctrl/objects.h> + #define HICN_DEFAULT_PORT 9695 #define HOTFIXMARGIN 0 -#define INVALID_FACE_ID ~0 -#define INVALID_NETDEVICE_ID ~0 - /** * \brief Defines the default size for the allocated data arrays holding the * results of API calls. @@ -105,336 +110,21 @@ })x) \ .b) #endif + +#define MAX2(x1, x2) (x1 > x2 ? x1 : x2) +#define MAX4(x1, x2, x3, x4) (MAX2(MAX2(x1, x2), MAX2(x3, x4))) +#define MAX8(x1, x2, x3, x4, x5, x6, x7, x8) \ + (MAX2(MAX4(x1, x2, x3, x4), MAX4(x5, x6, x7, x8))) + /****************************************************************************** * Message helper types and aliases ******************************************************************************/ -/* Action */ - -#define foreach_action \ - _(UNDEFINED) \ - _(CREATE) \ - _(UPDATE) \ - _(DELETE) \ - _(LIST) \ - _(SET) \ - _(SERVE) \ - _(STORE) \ - _(CLEAR) \ - _(GET) \ - _(N) - -typedef enum { -#define _(x) ACTION_##x, - foreach_action -#undef _ -} hc_action_t; - -extern const char *action_str[]; - -#define action_str(x) action_str[x] - -hc_action_t action_from_str(const char *action_str); - -/* Object type */ - -#define foreach_object \ - _(UNDEFINED) \ - _(CONNECTION) \ - _(LISTENER) \ - _(ROUTE) \ - _(FACE) \ - _(STRATEGY) \ - _(PUNTING) \ - _(POLICY) \ - _(CACHE) \ - _(MAPME) \ - _(LOCAL_PREFIX) \ - _(PROBE) \ - _(SUBSCRIPTION) \ - _(STATS) \ - _(N) - -typedef enum { -#define _(x) OBJECT_##x, - foreach_object -#undef _ -} hc_object_type_t; - -extern const char *object_str[]; - -#define object_str(x) object_str[x] - -hc_object_type_t object_from_str(const char *object_str); - -#define IS_VALID_OBJECT_TYPE(x) IS_VALID_ENUM_TYPE(OBJECT, x) -#define IS_VALID_ACTION(x) IS_VALID_ENUM_TYPE(ACTION, x) - /** * \brief hICN control message header */ typedef struct hc_msg_s hc_msg_t; typedef struct hc_result_s hc_result_t; -/****************************************************************************** - * Control Data - ******************************************************************************/ - -struct hc_data_s; -typedef int (*data_callback_t)(struct hc_data_s *, void *); - -/** - * \brief Holds the results of an hICN control request - */ -typedef struct hc_data_s { - size_t size; - size_t current; - size_t max_size_log; - size_t in_element_size; - size_t out_element_size; - u8 command_id; /**< Expected message type (should give element size) */ - u8 *buffer; - bool complete; - - /* Callbacks */ - data_callback_t - complete_cb; // XXX int (*complete_cb)(struct hc_data_s * data); - void *complete_cb_data; - int ret; -} hc_data_t; - -/** - * Create a structure holding the results of an hICN control request. - * \result The newly create data structure. - */ -hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size, - data_callback_t complete_cb); - -/** - * Free a structure holding the results of an hICN control request. - * \param [in] data - The data structure to free. - */ -void hc_data_free(hc_data_t *data); - -/** - * \brief Adds many new results at the end of the data structure, eventually - * allocating buffer space for it. - * \param [in] data - The data structure to which to add elements. - * \param [in] elements - The array of elements to add. - * \param [in] count - The number of elements to add. - * \return Error code - * - * NOTE: The size of the element should match the one declared at structure - * initialization. - */ -int hc_data_push_many(hc_data_t *data, const void *elements, size_t count); - -/** - * \brief Adds a new result at the end of the data structure, eventually - * allocating buffer space for it. - * \param [in] data - The data structure to which to add an element. - * \param [in] element - The element to add - * \return Error code - * - * NOTE: The size of the element should match the one declared at structure - * initialization. - */ -int hc_data_push(hc_data_t *data, const void *element); - -/** - * \brief Configure a callback (along with private data) to be called upon - * completion of a request - * \param [in] data - hICN control data - * \param [in] cb - Callback function - * \param [in] cb_data - Callback private data - */ -int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data); - -/** - * \brief Mark the data structure as complete. - * \param [in] data - The data structure to which to add an element. - * \return The error code resulting from callback execution if any. 0 is - * returned if the callback executed successfully, or if no callback were - * defined. - */ -int hc_data_set_complete(hc_data_t *data); - -/** - * \brief Reset the data structure holding control data - * \param [in] data - hICN control data - * \return Error code - */ -int hc_data_reset(hc_data_t *data); - -/** - * \brief Find en element in the data structure - * \param [in] data - The data structure in which to find - * \param [in] element - The element to find - * \param [out] found - A pointer to the element, or NULL if not found. - * \return Error code - */ -#define GENERATE_FIND_HEADER(TYPE) \ - int hc_##TYPE##_find(hc_data_t *data, const hc_##TYPE##_t *element, \ - hc_##TYPE##_t **found) - -#define GENERATE_FIND(TYPE) \ - int hc_##TYPE##_find(hc_data_t *data, const hc_##TYPE##_t *element, \ - hc_##TYPE##_t **found) { \ - foreach_type(hc_##TYPE##_t, x, data) { \ - if (hc_##TYPE##_cmp(x, element) == 0) { \ - *found = x; \ - return 0; \ - } \ - }; \ - *found = NULL; /* this is optional */ \ - return 0; \ - } - -/****************************************************************************** - * Control socket - ******************************************************************************/ - -/* With UDP, the buffer should be able to receieve a full packet, and thus MTU - * (max 9000) is sufficient. Messages will be received fully one by one. - * With TCP, the buffer should be at least able to receive a message header and - * the maximum size of a data element, so any reasonable size will be correct, - * it might just optimize performance. Messages might arrive in chunks that the - * library is able to parse. - */ -#define JUMBO_MTU 9000 -#define RECV_BUFLEN 65535 - -#define foreach_forwarder_type \ - _(UNDEFINED) \ - _(HICNLIGHT) \ - _(HICNLIGHT_NG) \ - _(VPP) \ - _(N) - -typedef enum { -#define _(x) x, - foreach_forwarder_type -#undef _ -} forwarder_type_t; - -/** - * \brief Holds the state of an hICN control socket - */ -typedef struct hc_sock_s hc_sock_t; - -/** - * \brief Create an hICN control socket using the specified URL. - * \param [in] url - The URL to connect to. - * \return an hICN control socket - */ -hc_sock_t *hc_sock_create_url(const char *url); - -/** - * \brief Create an hICN control socket using the provided forwarder. - * \return an hICN control socket - */ -hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder); - -/** - * \brief Create an hICN control socket using the provided forwarder and a URL. - * \return an hICN control socket - */ -hc_sock_t *hc_sock_create_forwarder_url(forwarder_type_t forwarder, - const char *url); - -/** - * \brief Create an hICN control socket using the default connection type. - * \return an hICN control socket - */ -hc_sock_t *hc_sock_create(void); - -/** - * \brief Frees an hICN control socket - * \param [in] s - hICN control socket - */ -void hc_sock_free(hc_sock_t *s); - -/** - * \brief Returns the next available sequence number to use for requests to the - * API. - * \param [in] s - hICN control socket - */ -int hc_sock_get_next_seq(hc_sock_t *s); - -/** - * \brief Sets the socket as non-blocking - * \param [in] s - hICN control socket - * \return Error code - */ -int hc_sock_set_nonblocking(hc_sock_t *s); - -/** - * \brief Return the file descriptor associated to the hICN contorl sock - * \param [in] s - hICN control socket - * \return The file descriptor (positive value), or a negative integer in case - * of error - */ -int hc_sock_get_fd(hc_sock_t *s); - -/** - * \brief Connect the socket - * \return Error code - */ -int hc_sock_connect(hc_sock_t *s); - -/** - * \brief Return the offset and size of available buffer space - * \param [in] s - hICN control socket - * \param [out] buffer - Offset in buffer - * \param [out] size - Remaining size - * \return Error code - */ -int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size); - -/** - * \brief Write/read iexchance on the control socket (internal helper function) - * \param [in] s - hICN control socket - * \param [in] msg - Message to send - * \param [in] msglen - Length of the message to send - * \return Error code - */ -int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq); - -/** - * \brief Helper for reading socket contents - * \param [in] s - hICN control socket - * \return Error code - */ -int hc_sock_recv(hc_sock_t *s); - -/** - * \brief Processing data received by socket - * \param [in] s - hICN control socket - * \param [in] parse - Parse function to convert remote types into lib native - * types, or NULL not to perform any translation. - * \return Error code - */ -int hc_sock_process(hc_sock_t *s, hc_data_t **data); - -/** - * \brief Callback used in async mode when data is available on the socket - * \param [in] s - hICN control socket - * \return Error code - */ -int hc_sock_callback(hc_sock_t *s, hc_data_t **data); - -/** - * \brief Reset the state of the sock (eg. to handle a reconnecton) - * \param [in] s - hICN control socket - * \return Error code - */ -int hc_sock_reset(hc_sock_t *s); - -void hc_sock_increment_woff(hc_sock_t *s, size_t bytes); - -int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result, - data_callback_t complete_cb, void *complete_cb_data); - -int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms); /****************************************************************************** * Command-specific structures and functions @@ -448,7 +138,8 @@ int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms); * * We redefine command struct: * - for uniformization - * - to use enum instead of type specifiers more appropriate for packet format + * - to use enum instead of type specifiers more appropriate for packet + * format * - to use more flexible types such as for manipulating IP addresses * - host endianness * - more intuitive field name, ordering, consistency, and hierarchy removal @@ -460,9 +151,9 @@ int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms); * * RETURN DATA FIXME * - * \param [out] pdata - Pointer to the structure storing the results of the call - * (NULL if no data has been received). If the pointer is NULL, no result will - * be stored and only the error code will be exposed to the caller. It is + * \param [out] pdata - Pointer to the structure storing the results of the + * call (NULL if no data has been received). If the pointer is NULL, no result + * will be stored and only the error code will be exposed to the caller. It is * expected that the caller frees this structure using hc_data_free() after * usage. * \see hc_data_free. @@ -487,147 +178,134 @@ int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms); #define NULLTERM 1 #endif -#define INTERFACE_LEN 16 - #define MAXSZ_HC_NAME_ SYMBOLIC_NAME_LEN #define MAXSZ_HC_NAME MAXSZ_HC_NAME_ + NULLTERM #define MAXSZ_HC_ID_ 10 /* Number of digits for MAX_INT */ #define MAXSZ_HC_ID MAXSZ_HC_ID_ + NULLTERM -#define foreach_type(TYPE, VAR, data) \ - for (TYPE *VAR = (TYPE *)data->buffer; \ - VAR < (TYPE *)(data->buffer + data->size * data->out_element_size); \ - VAR++) - -typedef int (*HC_PARSE)(const u8 *, u8 *); +#if 0 +#define foreach_type(TYPE, VAR, data) \ + for (TYPE *VAR = (TYPE *)data->buffer; \ + VAR < (TYPE *)((data)->buffer + (data)->size * sizeof(TYPE)); VAR++) +#endif #define INPUT_ERROR -2 #define UNSUPPORTED_CMD_ERROR -3 /*----------------------------------------------------------------------------* - * Listeners + * Strategy *----------------------------------------------------------------------------*/ -// FIXME the listener should not require any port for hICN... -typedef struct { - char name[SYMBOLIC_NAME_LEN]; /* K.w */ // XXX clarify what used for - char interface_name[INTERFACE_LEN]; /* Kr. */ - u32 id; - face_type_t type; /* .rw */ - int family; /* .rw */ - ip_address_t local_addr; /* .rw */ - u16 local_port; /* .rw */ -} hc_listener_t; +/*----------------------------------------------------------------------------* + * WLDR + *----------------------------------------------------------------------------*/ -int hc_listener_create(hc_sock_t *s, hc_listener_t *listener); -/* listener_found might eventually be allocated, and needs to be freed */ -hc_result_t *hc_listener_create_conf(hc_sock_t *s, hc_listener_t *listener); -int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, - hc_listener_t **listener_found); -int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener); -int hc_listener_list(hc_sock_t *s, hc_data_t **pdata); -hc_result_t *hc_listener_list_conf(hc_sock_t *s); +// per connection +int hc_wldr_set(hc_sock_t *s /* XXX */); -int hc_listener_validate(const hc_listener_t *listener); -int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2); +/*----------------------------------------------------------------------------* + * MAP-Me + *----------------------------------------------------------------------------*/ -#define foreach_listener(VAR, data) foreach_type(hc_listener_t, VAR, data) +/*----------------------------------------------------------------------------* + * Policies + *----------------------------------------------------------------------------*/ -#define MAXSZ_HC_LISTENER_ \ - INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_FACE_TYPE_ -#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM +/*----------------------------------------------------------------------------* + * Subscription + *----------------------------------------------------------------------------*/ +// Topics -GENERATE_FIND_HEADER(listener); +#if 0 +/* Result */ -int hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener); +hc_msg_t *hc_result_get_msg(hc_sock_t *s, hc_result_t *result); +int hc_result_get_cmd_id(hc_sock_t *s, hc_result_t *result); +bool hc_result_get_success(hc_sock_t *s, hc_result_t *result); +void hc_result_free(hc_result_t *result); +#endif -/*----------------------------------------------------------------------------* - * Connections - *----------------------------------------------------------------------------*/ +/* Object */ + +// FIXME +#define MAXSZ_HC_SUBSCRIPTION 1 + +#define MAXSZ_HC_OBJECT \ + MAX8(MAXSZ_HC_CONNECTION, MAXSZ_HC_LISTENER, MAXSZ_HC_ROUTE, MAXSZ_HC_FACE, \ + MAXSZ_HC_PUNTING, MAXSZ_HC_STRATEGY, MAXSZ_HC_POLICY, \ + MAXSZ_HC_SUBSCRIPTION) -/* - * NOTE : - * - interface_name is mainly used to derive listeners from connections, - * but is not itself used to create connections. - */ typedef struct { - u32 id; /* Kr. */ - char name[SYMBOLIC_NAME_LEN]; /* K.w */ - char interface_name[INTERFACE_LEN]; /* Kr. */ - face_type_t type; /* .rw */ - int family; /* .rw */ - ip_address_t local_addr; /* .rw */ - u16 local_port; /* .rw */ - ip_address_t remote_addr; /* .rw */ - u16 remote_port; /* .rw */ - face_state_t admin_state; /* .rw */ -#ifdef WITH_POLICY - uint32_t priority; /* .rw */ - policy_tags_t tags; /* .rw */ -#endif /* WITH_POLICY */ - face_state_t state; /* .r. */ -} hc_connection_t; + hc_action_t action; + hc_object_type_t object_type; + hc_object_t object; +} hc_command_t; + +// NEW API CALLS + +// XXX private ? +int _hc_execute(hc_sock_t *s, hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_result_callback_t callback, + void *callback_data, hc_data_t **pdata); +int hc_execute(hc_sock_t *s, hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_data_t **pdata); +int hc_execute_async(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, + hc_result_callback_t callback, void *callback_data); + +int hc_object_create(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object); +int hc_object_get(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object, hc_object_t **found); +int hc_object_delete(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object); +int hc_object_list(hc_sock_t *s, hc_object_type_t object_type, + hc_data_t **pdata); + +/* Former API */ + +int hc_listener_create(hc_sock_t *s, hc_listener_t *listener); +/* listener_found might eventually be allocated, and needs to be freed */ +int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, hc_data_t **pdata); +int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener); +int hc_listener_list(hc_sock_t *s, hc_data_t **pdata); int hc_connection_create(hc_sock_t *s, hc_connection_t *connection); -hc_result_t *hc_connection_create_conf(hc_sock_t *s, - hc_connection_t *connection); -/* connection_found will be allocated, and must be freed */ +/* connection_found might eventually be allocated, and needs to be freed */ int hc_connection_get(hc_sock_t *s, hc_connection_t *connection, - hc_connection_t **connection_found); + hc_data_t **pdata); +int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection); int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, hc_connection_t *connection); int hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, hc_connection_t *connection_updated); -int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection); -hc_result_t *hc_connection_delete_conf(hc_sock_t *s, - hc_connection_t *connection); +int hc_connection_list(hc_sock_t *s, hc_data_t **pdata); + +int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state); +int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name, + uint32_t priority); +int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, + policy_tags_t tags); + /* int hc_connection_remove_by_id(hc_sock_t * s, char * name); int hc_connection_remove_by_name(hc_sock_t * s, char * name); */ -int hc_connection_list(hc_sock_t *s, hc_data_t **pdata); - -int hc_connection_validate(const hc_connection_t *connection); -int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2); int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, face_state_t state); -#ifdef WITH_POLICY int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name, uint32_t priority); int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, policy_tags_t tags); -#endif /* WITH_POLICY */ - -#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data) - -#define MAXSZ_HC_CONNECTION_ \ - MAXSZ_FACE_STATE_ + INTERFACE_LEN + SPACE + 2 * MAXSZ_URL_ + \ - MAXSZ_FACE_TYPE_ + SPACES(3) -#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM - -GENERATE_FIND_HEADER(connection); -int hc_connection_snprintf(char *s, size_t size, - const hc_connection_t *connection); - -/*----------------------------------------------------------------------------* - * Faces - * - * A face is an abstraction introduced by the control library to abstract the - * forwarder implementation details. It encompasses connections and listeners - * and ensures the right dependencies are enforced, eg that we always have a - * listener when a connection is created. - * - *----------------------------------------------------------------------------*/ - -typedef struct { - face_id_t id; - char name[SYMBOLIC_NAME_LEN]; - face_t face; // or embed ? - // face_id_t parent; /* Pointer from connection to listener */ -} hc_face_t; +int hc_route_create(hc_sock_t *s, hc_route_t *route); +// hc_result_t *hc_route_create_conf(hc_sock_t *s, hc_route_t *route); +int hc_route_delete(hc_sock_t *s, hc_route_t *route); +int hc_route_list(hc_sock_t *s, hc_data_t **pdata); +int hc_route_list_async(hc_sock_t *s); /** * \brief Create a face @@ -638,194 +316,27 @@ typedef struct { * The face parameters will be updated with the face ID. */ int hc_face_create(hc_sock_t *s, hc_face_t *face); -int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found); -int hc_face_delete(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener); +int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_data_t **pdata); +int hc_face_delete(hc_sock_t *s, + hc_face_t *face); //, uint8_t delete_listener); int hc_face_list(hc_sock_t *s, hc_data_t **pdata); -int hc_face_list_async(hc_sock_t *s); //, hc_data_t ** pdata); +int hc_face_list_async(hc_sock_t *s); int hc_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, face_state_t state); -#ifdef WITH_POLICY int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name, uint32_t priority); int hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name, policy_tags_t tags); -#endif /* WITH_POLICY */ - -#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data) - -#define MAX_FACE_ID 255 -#define MAXSZ_FACE_ID_ 3 -#define MAXSZ_FACE_ID MAXSZ_FACE_ID_ + NULLTERM -#define MAXSZ_FACE_NAME_ SYMBOLIC_NAME_LEN -#define MAXSZ_FACE_NAME MAXSZ_FACE_NAME_ + NULLTERM - -#define MAXSZ_HC_FACE_ \ - MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5 + HOTFIXMARGIN -#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM - -int hc_face_snprintf(char *s, size_t size, hc_face_t *face); -/*----------------------------------------------------------------------------* - * Routes - *----------------------------------------------------------------------------*/ - -typedef struct { - face_id_t face_id; /* Kr. use when name == NULL */ - char name[SYMBOLIC_NAME_LEN]; /* Kr. use by default vs face_id */ - int family; /* Krw */ - ip_address_t remote_addr; /* krw */ - u8 len; /* krw */ - u16 cost; /* .rw */ - hc_face_t face; /* TODO remove, used by hicn_plugin_api */ -} hc_route_t; - -int hc_route_create(hc_sock_t *s, hc_route_t *route); -hc_result_t *hc_route_create_conf(hc_sock_t *s, hc_route_t *route); -int hc_route_delete(hc_sock_t *s, hc_route_t *route); -int hc_route_list(hc_sock_t *s, hc_data_t **pdata); -int hc_route_list_async(hc_sock_t *s); - -#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data) - -#define MAX_COST 65535 -#define MAXSZ_COST 5 -#define MAX_LEN 255 -#define MAXSZ_LEN 3 - -#define MAXSZ_HC_ROUTE_ \ - MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN -#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM - -int hc_route_snprintf(char *s, size_t size, hc_route_t *route); -int hc_route_validate(const hc_route_t *route); - -/*----------------------------------------------------------------------------* - * Punting - *----------------------------------------------------------------------------*/ - -typedef struct { - face_id_t face_id; /* Kr. */ // XXX listener id, could be NULL for all ? - int family; /* Krw */ - ip_address_t prefix; /* krw */ - u8 prefix_len; /* krw */ -} hc_punting_t; - -int hc_punting_create(hc_sock_t *s, hc_punting_t *punting); -int hc_punting_get(hc_sock_t *s, hc_punting_t *punting, - hc_punting_t **punting_found); -int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting); -int hc_punting_list(hc_sock_t *s, hc_data_t **pdata); - -int hc_punting_validate(const hc_punting_t *punting); -int hc_punting_cmp(const hc_punting_t *c1, const hc_punting_t *c2); - -#define foreach_punting(VAR, data) foreach_type(hc_punting_t, VAR, data) - -#define MAXSZ_HC_PUNTING_ 0 -#define MAXSZ_HC_PUNTING MAXSZ_HC_PUNTING_ + NULLTERM - -GENERATE_FIND_HEADER(punting); - -int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting); - -/*----------------------------------------------------------------------------* - * Cache - *----------------------------------------------------------------------------*/ - -typedef struct { - uint8_t serve; // 1 = on, 0 = off - uint8_t store; // 1 = on, 0 = off -} hc_cache_t; - -typedef struct { - bool store; - bool serve; - size_t cs_size; - size_t num_stale_entries; -} hc_cache_info_t; +int hc_strategy_list(hc_sock_t *s, hc_data_t **data); +int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy); +int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy); int hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache); int hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache); int hc_cache_clear(hc_sock_t *s, hc_cache_t *cache); int hc_cache_list(hc_sock_t *s, hc_data_t **pdata); -int hc_cache_snprintf(char *s, size_t size, const hc_cache_info_t *cache_info); - -/*----------------------------------------------------------------------------* - * Strategy - *----------------------------------------------------------------------------*/ - -#define MAXSZ_STRATEGY_NAME 255 - -typedef struct { - // The name is not set by the controller - // but populated by the daemon - char name[MAXSZ_STRATEGY_NAME]; - strategy_type_t type; - ip_address_t address, local_address; - int family, local_family; - u8 len, local_len; -} hc_strategy_t; - -int hc_strategy_list(hc_sock_t *s, hc_data_t **data); - -#define foreach_strategy(VAR, data) foreach_type(hc_strategy_t, VAR, data) - -#define MAXSZ_HC_STRATEGY_ MAXSZ_STRATEGY_NAME -#define MAXSZ_HC_STRATEGY MAXSZ_HC_STRATEGY_ + NULLTERM - -int hc_strategy_snprintf(char *s, size_t size, hc_strategy_t *strategy); - -// per prefix -int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy); -hc_result_t *hc_strategy_set_conf(hc_sock_t *s, hc_strategy_t *strategy); -int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy); -hc_result_t *hc_strategy_add_local_prefix_conf(hc_sock_t *s, - hc_strategy_t *strategy); -/*----------------------------------------------------------------------------* - * WLDR - *----------------------------------------------------------------------------*/ - -// per connection -int hc_wldr_set(hc_sock_t *s /* XXX */); - -/*----------------------------------------------------------------------------* - * MAP-Me - *----------------------------------------------------------------------------*/ - -typedef enum { - MAPME_TARGET_ENABLE, - MAPME_TARGET_DISCOVERY, - MAPME_TARGET_TIMESCALE, - MAPME_TARGET_RETX, -} mapme_target_t; - -static inline mapme_target_t mapme_target_from_str(char *mapme_target_str) { - if (strcasecmp(mapme_target_str, "enable") == 0) - return MAPME_TARGET_ENABLE; - else if (strcasecmp(mapme_target_str, "discovery") == 0) - return MAPME_TARGET_DISCOVERY; - else if (strcasecmp(mapme_target_str, "timescale") == 0) - return MAPME_TARGET_TIMESCALE; - else - return MAPME_TARGET_RETX; -} - -#define MAX_MAPME_ARG_LEN 30 - -typedef struct { - mapme_target_t target; - // Command argument stored as a string - // before being parsed into 'enabled' or 'timescale' - char unparsed_arg[MAX_MAPME_ARG_LEN]; - - uint8_t enabled; // 1 = on, 0 = off - uint32_t timescale; // Milliseconds - - ip_address_t address; - int family; - u8 len; -} hc_mapme_t; int hc_mapme_set(hc_sock_t *s, hc_mapme_t *mapme); int hc_mapme_set_discovery(hc_sock_t *s, hc_mapme_t *mapme); @@ -833,145 +344,21 @@ int hc_mapme_set_timescale(hc_sock_t *s, hc_mapme_t *mapme); int hc_mapme_set_retx(hc_sock_t *s, hc_mapme_t *mapme); int hc_mapme_send_update(hc_sock_t *s, hc_mapme_t *mapme); -/*----------------------------------------------------------------------------* - * Policies - *----------------------------------------------------------------------------*/ - -#ifdef WITH_POLICY - -typedef struct { - int family; /* Krw */ - ip_address_t remote_addr; /* krw */ - u8 len; /* krw */ - hicn_policy_t policy; /* .rw */ -} hc_policy_t; - int hc_policy_create(hc_sock_t *s, hc_policy_t *policy); int hc_policy_delete(hc_sock_t *s, hc_policy_t *policy); int hc_policy_list(hc_sock_t *s, hc_data_t **pdata); -#define foreach_policy(VAR, data) foreach_type(hc_policy_t, VAR, data) - -/* TODO */ -#define MAXSZ_HC_POLICY_ 0 -#define MAXSZ_HC_POLICY MAXSZ_HC_POLICY_ + NULLTERM - -int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy); -int hc_policy_validate(const hc_policy_t *policy); - -#endif /* WITH_POLICY */ - -/*----------------------------------------------------------------------------* - * Subscription - *----------------------------------------------------------------------------*/ -// Topics - -#undef PUNTING // TODO(eloparco): Undefined to avoid collisions - // Fix the collision - -// Used only to create 'hc_topic_t' -typedef struct { -#define _(x) char x; - foreach_object -#undef _ -} object_offset_t; - -// Flags for topic subscriptions -typedef enum { -#define _(x) TOPIC_##x = (1 << offsetof(object_offset_t, x)), - foreach_object -#undef _ -} hc_topic_t; - -static inline hc_object_type_t object_from_topic(hc_topic_t topic) { -#define _(x) \ - if (topic == TOPIC_##x) return OBJECT_##x; - foreach_object -#undef _ - return OBJECT_UNDEFINED; -} - -#define NUM_TOPICS OBJECT_N // Because a topic is created for each object -#define ALL_TOPICS ~0 - -// Subscriptions -typedef uint32_t hc_topics_t; -typedef struct { - hc_topics_t topics; -} hc_subscription_t; +int hc_punting_create(hc_sock_t *s, hc_punting_t *punting); +int hc_punting_get(hc_sock_t *s, hc_punting_t *punting, + hc_punting_t **punting_found); +int hc_punting_delete(hc_sock_t *s, hc_punting_t *punting); +int hc_punting_list(hc_sock_t *s, hc_data_t **pdata); int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription); int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription); -hc_result_t *hc_subscription_create_conf(hc_sock_t *s, - hc_subscription_t *subscription); -hc_result_t *hc_subscription_delete_conf(hc_sock_t *s, - hc_subscription_t *subscription); - -/*----------------------------------------------------------------------------* - * Events - *----------------------------------------------------------------------------*/ -#define foreach_event_type \ - _(UNDEFINED) \ - _(INTERFACE_UPDATE) \ - _(N) -typedef enum { -#define _(x) EVENT_##x, - foreach_event_type -#undef _ -} event_type_t; - -extern const char *event_str[]; -#define event_str(x) event_str[x] - -typedef enum { - FLAG_INTERFACE_TYPE_WIRED = 0x1, - FLAG_INTERFACE_TYPE_WIFI = 0x2, - FLAG_INTERFACE_TYPE_CELLULAR = 0x4, -} flag_interface_type_t; - -typedef struct { - flag_interface_type_t interface_type; -} hc_event_interface_update_t; -/*----------------------------------------------------------------------------* - * Statistics - *----------------------------------------------------------------------------*/ int hc_stats_get(hc_sock_t *s, hc_data_t **pdata); // General stats int hc_stats_list(hc_sock_t *s, hc_data_t **pdata); // Per-face stats int hc_stats_snprintf(char *s, size_t size, const hicn_light_stats_t *stats); -/* Result */ - -hc_msg_t *hc_result_get_msg(hc_sock_t *s, hc_result_t *result); -int hc_result_get_cmd_id(hc_sock_t *s, hc_result_t *result); -bool hc_result_get_success(hc_sock_t *s, hc_result_t *result); -void hc_result_free(hc_result_t *result); - -/* Object */ - -typedef struct { - hc_object_type_t type; - union { - hc_connection_t connection; - hc_listener_t listener; - hc_route_t route; - hc_face_t face; - // hc_data_t *data; - hc_punting_t punting; - hc_strategy_t strategy; -#ifdef WITH_POLICY - hc_policy_t policy; -#endif /* WITH_POLICY */ - hc_subscription_t subscription; - hc_cache_t cache; - hc_mapme_t mapme; - uint8_t as_uint8; - }; -} hc_object_t; - -typedef struct { - hc_action_t action; - hc_object_t object; -} hc_command_t; - #endif /* HICNTRL_API */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/callback.h b/ctrl/libhicnctrl/includes/hicn/ctrl/callback.h new file mode 100644 index 000000000..5b7f424d6 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/callback.h @@ -0,0 +1,13 @@ +#ifndef HICNCTRL_CALLBACK_H +#define HICNCTRL_CALLBACK_H + +#include <stdbool.h> + +#include <hicn/ctrl/data.h> + +typedef int (*hc_enable_callback_t)(bool enable); +typedef void (*hc_state_callback_t)(bool enable, void *user_data); +typedef void (*hc_result_callback_t)(hc_data_t *data, void *user_data); +typedef void (*hc_notification_callback_t)(hc_data_t *data, void *user_data); + +#endif /* HICNCTRL_CALLBACK_H */ diff --git a/hicn-light/src/hicn/config/command.h b/ctrl/libhicnctrl/includes/hicn/ctrl/command.h index 73d8edb1f..1824d14c2 100644 --- a/hicn-light/src/hicn/config/command.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/command.h @@ -21,6 +21,8 @@ typedef enum { TYPENAME_UNDEFINED, TYPENAME_INT, TYPENAME_UINT, + TYPENAME_INT16, + TYPENAME_UINT16, TYPENAME_STR, TYPENAME_SYMBOLIC_OR_ID, TYPENAME_INTERFACE_NAME, @@ -40,11 +42,7 @@ typedef struct { struct { int min; int max; - } sint; - struct { - int min; - int max; - } uint; + } integer; struct { int (*from_str)(const char *str); } enum_; @@ -69,12 +67,18 @@ typedef struct { typedef struct { hc_action_t action; - hc_object_type_t object; + hc_object_type_t object_type; unsigned nparams; command_parameter_t parameters[MAX_PARAMETERS]; parser_hook_t post_hook; } command_parser_t; +/* + * NOTE: we now use strings everywhere to parse in the same way parameters + * coming from the commandline through getopt (strings), and those coming from + * sscanf (used to be variables, now all strings also. + */ + #define TYPE_STRN(N) \ (parser_type_t) { \ .name = TYPENAME_STR, \ @@ -82,45 +86,55 @@ typedef struct { .max_size = N, \ }, \ } -#define TYPE_FMT_STRN(N) "%s" #define TYPE_INT(MIN, MAX) \ (parser_type_t) { \ .name = TYPENAME_INT, \ - .sint = { \ + .integer = { \ .min = (MIN), \ .max = (MAX), \ }, \ } -#define TYPE_FMT_INT "%d" -#define TYPE_UINT(min, max) \ +#define TYPE_UINT(MIN, MAX) \ (parser_type_t) { \ .name = TYPENAME_UINT, \ - .uint = { \ - .min = min, \ - .max = max, \ + .integer = { \ + .min = (MIN), \ + .max = (MAX), \ }, \ } -#define TYPE_FMT_UINT "%u" + +#define TYPE_INT16(MIN, MAX) \ + (parser_type_t) { \ + .name = TYPENAME_INT16, \ + .integer = { \ + .min = (MIN), \ + .max = (MAX), \ + }, \ + } + +#define TYPE_UINT16(MIN, MAX) \ + (parser_type_t) { \ + .name = TYPENAME_UINT16, \ + .integer = { \ + .min = (MIN), \ + .max = (MAX), \ + }, \ + } #define TYPE_SYMBOLIC_OR_ID TYPE_STRN(SYMBOLIC_NAME_LEN) -#define TYPE_FMT_SYMBOLIC_OR_ID "%s" #define TYPE_INTERFACE_NAME TYPE_STRN(INTERFACE_LEN) -#define TYPE_FMT_INTERFACE_NAME "%s" #define TYPE_IP_ADDRESS \ (parser_type_t) { .name = TYPENAME_IP_ADDRESS, } -#define TYPE_FMT_IP_ADDRESS "%s" #define TYPE_IP_PREFIX \ (parser_type_t) { .name = TYPENAME_IP_PREFIX, } -#define TYPE_FMT_IP_PREFIX "%s" #define TYPE_ON_OFF \ (parser_type_t) { .name = TYPENAME_ON_OFF, } -#define TYPE_FMT_ON_OFF "%s" #define TYPE_ENUM(x) \ (parser_type_t) { \ @@ -130,7 +144,6 @@ typedef struct { }, \ } /* We need to allocate room for the intermediate string */ -#define TYPE_FMT_ENUM "%s" #define TYPE_POLICY_STATE(TAG) \ (parser_type_t) { \ @@ -140,7 +153,6 @@ typedef struct { }, \ } /* We need to allocate room for the intermediate string */ -#define TYPE_FMT_POLICY_STATE "%s" /** * \brief Register a protocol diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/data.h b/ctrl/libhicnctrl/includes/hicn/ctrl/data.h new file mode 100644 index 000000000..d2696db1c --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/data.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file data.h + * \brief Request result data. + */ + +#ifndef HICNCTRL_DATA_H +#define HICNCTRL_DATA_H + +#include <stdbool.h> +#include <stddef.h> // size_t +#include <stdint.h> // uint*_t +#include <sys/types.h> +#include <unistd.h> + +#include <hicn/ctrl/object_type.h> +#include <hicn/ctrl/object.h> + +/** + * \brief Holds the results of an hICN control request + */ +typedef struct hc_data_s hc_data_t; + +/** + * Create a structure holding the results of an hICN control request. + * \result The newly create data structure. + */ +hc_data_t *hc_data_create(hc_object_type_t object_type); + +/** + * Free a structure holding the results of an hICN control request. + * \param [in] data - The data structure to free. + */ +void hc_data_free(hc_data_t *data); + +/* + * This function can fail if the current data size is bigger than the requested + * maximum size + */ +int hc_data_set_max_size(hc_data_t *data, size_t max_size); + +const uint8_t *hc_data_get_buffer(hc_data_t *data); +const uint8_t *hc_data_get_free(hc_data_t *data); +void hc_data_inc_size(hc_data_t *data); + +hc_object_type_t hc_data_get_object_type(const hc_data_t *data); + +void hc_data_set_object_type(hc_data_t *data, hc_object_type_t object_type); + +ssize_t hc_data_get_size(const hc_data_t *data); + +/* + * This is used to perform manual allocation once after initialization is the + * size of the data to store is known in advance. This does not prevent future + * reallocations (in the limit though of the value in max_size, if applicable). + */ +int hc_data_allocate(hc_data_t *data, size_t size); + +int hc_data_clear(hc_data_t *data); + +#if 0 +int hc_data_ensure_available(hc_data_t *data, size_t count); +#endif + +/** + * \brief Adds many new results at the end of the data structure, eventually + * allocating buffer space for it. + * \param [in] data - The data structure to which to add elements. + * \param [in] elements - The array of elements to add. + * \param [in] count - The number of elements to add. + * \return Error code + * + * NOTE: The size of the element should match the one declared at structure + * initialization. + */ +int hc_data_push_many(hc_data_t *data, const void *elements, size_t count); + +/** + * \brief Adds a new result at the end of the data structure, eventually + * allocating buffer space for it. + * \param [in] data - The data structure to which to add an element. + * \param [in] element - The element to add + * \return Error code + * + * NOTE: The size of the element should match the one declared at structure + * initialization. + */ +int hc_data_push(hc_data_t *data, const void *element); + +#if 0 +uint8_t *hc_data_get_next(hc_data_t *data); + +/** + * \brief Configure a callback (along with private data) to be called upon + * completion of a request + * \param [in] data - hICN control data + * \param [in] cb - Callback function + * \param [in] cb_data - Callback private data + */ +int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data); + +void hc_data_set_size(hc_data_t *data, int size); +#endif + +void hc_data_set_complete(hc_data_t *data); +bool hc_data_is_complete(const hc_data_t *data); + +void hc_data_set_error(hc_data_t *data); + +bool hc_data_get_result(hc_data_t *data); + +#if 0 +/** + * \brief Reset the data structure holding control data + * \param [in] data - hICN control data + * \return Error code + */ +int hc_data_reset(hc_data_t *data); +#endif + +#define VAR(x) __##x +#define hc_data_foreach(DATA, OBJECT, BODY) \ + do { \ + hc_object_t *OBJECT; \ + size_t VAR(size) = hc_object_size(hc_data_get_object_type(DATA)); \ + for (unsigned VAR(i) = 0; VAR(i) < hc_data_get_size(DATA); VAR(i)++) { \ + OBJECT = (hc_object_t *)(hc_data_get_buffer(DATA) + VAR(i) * VAR(size)); \ + BODY \ + } \ + } while (0) + +hc_object_t *hc_data_find(hc_data_t *data, hc_object_t *object); + +const hc_object_t *hc_data_get_object(const hc_data_t *data, off_t pos); + +#endif /* HICNCTRL_DATA_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/fw_interface.h b/ctrl/libhicnctrl/includes/hicn/ctrl/fw_interface.h new file mode 100644 index 000000000..0656de080 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/fw_interface.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HICNCTRL_FW_INTERFACE_H +#define HICNCTRL_FW_INTERFACE_H + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/callback.h> + +/** + * \file fw_interface.h + * \brief Forwarder interface + * + * Forwarder interface is designed to be a reusable module (that might be + * wrapped in a C++ class), providing a fw-agnostic interface with the + * following goals: + * - maintaining a permanent connection to the fw (and keep track of the + * fw state, eventually caching some aspects) + * - allowing the tracking of multiplexed requests + * - supporting a stream of concurrent notifications that might be needed to + * synchronize states. + * + * It is design to be easily integrated with the different event loops used + * across the projects (libevent for C, asio for C++). + */ + +#define foreach_fw_state \ + _(UNDEFINED) \ + _(DISABLED) /* stack is stopped */ \ + _(REQUESTED) /* stack is starting */ \ + _(AVAILABLE) /* forwarder is running */ \ + _(CONNECTING) /* XXX NEW */ \ + _(CONNECTED) /* control socket connected */ \ + _(READY) /* listener is present */ \ + _(N) + +typedef enum { +#define _(x) FW_STATE_##x, + foreach_fw_state +#undef _ +} fw_state_t; + +extern const char *fw_state_str[]; + +#define fw_state_str(x) fw_state_str[x] + +typedef struct fw_interface_s fw_interface_t; + +fw_interface_t *fw_interface_create_url(forwarder_type_t type, const char *url); +fw_interface_t *fw_interface_create(forwarder_type_t type); + +void fw_interface_free(fw_interface_t *fi); + +int fw_interface_get_fd(const fw_interface_t *fi); + +/* + * Enable the stack + */ +int fw_interface_enable(fw_interface_t *fi); + +/* + * Disable the stack + */ +int fw_interface_disable(fw_interface_t *fi); + +/* + * Request a permanent connection to the forwarder, starting it if needed. + */ +int fw_interface_connect(fw_interface_t *fi); + +/* + * Disconnect from the forwarder + */ +int fw_interface_disconnect(fw_interface_t *fi); + +fw_state_t fw_interface_get_state(const fw_interface_t *fi); + +int fw_interface_subscribe_all(fw_interface_t *fi); + +int fw_interface_unsubscribe_all(fw_interface_t *fi); + +int fw_interface_execute(fw_interface_t *fi, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, + hc_data_t **pdata); + +int fw_interface_execute_async(fw_interface_t *fi, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data); + +int fw_interface_set_enable_callback(fw_interface_t *fi, + hc_enable_callback_t callback); + +int fw_interface_set_state_callback(fw_interface_t *fi, + hc_state_callback_t callback, + void *callback_data); + +int fw_interface_set_result_callback(fw_interface_t *fi, + hc_result_callback_t callback, + void *callback_data); + +int fw_interface_set_notification_callback(fw_interface_t *fi, + hc_notification_callback_t callback, + void *callback_data); + +// manage stack [android] +// - not needed for face mgr +// operations +// - create face/route : facemgr, hproxy +// - set fw strategy +// - get listeners, hicn listener port +// subscribe all +// callbacks: +// - forwarder available/unavailable +// timers & reattempts : clarify +// XXX remove_self on sock disconnect... should be in libhicnctrl + +int fw_interface_on_receive(fw_interface_t *fi, size_t count); +int fw_interface_get_recv_buffer(fw_interface_t *fi, uint8_t **buffer, + size_t *size); + +#endif /* HICNCTRL_FW_INTERFACE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h deleted file mode 100644 index 783eab086..000000000 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light-ng.h +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * @file commands.h - * @brief All hicn-light commands: 14 in total. - * - * Header and payload in binary format. - */ - -#ifndef HICN_CTRL_HICNLIGHTNG_H -#define HICN_CTRL_HICNLIGHTNG_H - -#ifndef _WIN32 -#include <netinet/in.h> -#include <sys/socket.h> -#endif - -#include <stdint.h> -#include <stdlib.h> - -#include <hicn/policy.h> -#include <hicn/strategy.h> -#include <hicn/util/ip_address.h> - -#define SYMBOLIC_NAME_LEN 16 - -typedef struct in6_addr ipv6_addr_t; -typedef uint32_t ipv4_addr_t; - -typedef enum { - MESSAGE_COMMAND_SUBTYPE_UNDEFINED, - REQUEST_LIGHT = 0xc0, // this is a command - RESPONSE_LIGHT, - ACK_LIGHT, - NACK_LIGHT, - NOTIFICATION_LIGHT, - MESSAGE_COMMAND_SUBTYPE_N -} message_command_subtype_t; - -#define message_type_is_valid(message_type) \ - ((message_type != MESSAGE_TYPE_UNDEFINED) && \ - (message_type != MESSAGE_COMMAND_SUBTYPE_N)) - -#define message_type_from_uchar(x) \ - (((x) < REQUEST_LIGHT) || (((x) >= MESSAGE_COMMAND_SUBTYPE_N)) \ - ? MESSAGE_COMMAND_SUBTYPE_N \ - : (message_command_subtype_t)(x)) - -#define foreach_command_type \ - _(listener_add, LISTENER_ADD) \ - _(listener_remove, LISTENER_REMOVE) \ - _(listener_list, LISTENER_LIST) \ - _(connection_add, CONNECTION_ADD) \ - _(connection_remove, CONNECTION_REMOVE) \ - _(connection_list, CONNECTION_LIST) \ - _(connection_set_admin_state, CONNECTION_SET_ADMIN_STATE) \ - _(connection_update, CONNECTION_UPDATE) \ - _(connection_set_priority, CONNECTION_SET_PRIORITY) \ - _(connection_set_tags, CONNECTION_SET_TAGS) \ - _(route_add, ROUTE_ADD) \ - _(route_remove, ROUTE_REMOVE) \ - _(route_list, ROUTE_LIST) \ - _(cache_set_store, CACHE_SET_STORE) \ - _(cache_set_serve, CACHE_SET_SERVE) \ - _(cache_clear, CACHE_CLEAR) \ - _(cache_list, CACHE_LIST) \ - _(strategy_set, STRATEGY_SET) \ - _(strategy_add_local_prefix, STRATEGY_ADD_LOCAL_PREFIX) \ - _(wldr_set, WLDR_SET) \ - _(punting_add, PUNTING_ADD) \ - _(mapme_enable, MAPME_ENABLE) \ - _(mapme_set_discovery, MAPME_SET_DISCOVERY) \ - _(mapme_set_timescale, MAPME_SET_TIMESCALE) \ - _(mapme_set_retx, MAPME_SET_RETX) \ - _(mapme_send_update, MAPME_SEND_UPDATE) \ - _(policy_add, POLICY_ADD) \ - _(policy_remove, POLICY_REMOVE) \ - _(policy_list, POLICY_LIST) \ - _(subscription_add, SUBSCRIPTION_ADD) \ - _(subscription_remove, SUBSCRIPTION_REMOVE) \ - _(stats_get, STATS_GET) \ - _(stats_list, STATS_LIST) - -typedef enum { - COMMAND_TYPE_UNDEFINED, -#define _(l, u) COMMAND_TYPE_##u, - foreach_command_type -#undef _ - COMMAND_TYPE_N, -} command_type_t; - -extern const char *command_type_str[]; - -#define command_type_str(x) command_type_str[x] - -#define command_type_is_valid(command_type) \ - ((command_type != COMMAND_TYPE_UNDEFINED) && (command_type != COMMAND_TYPE_N)) - -#define command_type_from_uchar(x) \ - (((x) >= COMMAND_TYPE_N) ? COMMAND_TYPE_N : (command_type_t)(x)) - -/* Should be at least 8 bytes */ -typedef struct { - uint8_t message_type; - uint8_t command_id; - uint16_t length; /* Number of structures in the payload */ - uint32_t seq_num; -} cmd_header_t; - -typedef struct { - cmd_header_t header; -} msg_header_t; - -/* Listener */ - -typedef struct { - char symbolic[SYMBOLIC_NAME_LEN]; - char interface_name[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint16_t port; - uint8_t family; - uint8_t type; -} cmd_listener_add_t; - -typedef struct { - char symbolicOrListenerid[SYMBOLIC_NAME_LEN]; -} cmd_listener_remove_t; - -typedef struct { - void *_; // Otherwise empty structs result in clang build error -} cmd_listener_list_t; - -// Sync this struct with `hc_listener_t` in `api.h` -typedef struct { - char name[SYMBOLIC_NAME_LEN]; - char interface_name[SYMBOLIC_NAME_LEN]; - uint32_t id; - uint8_t type; - uint8_t family; - ip_address_t address; - uint16_t port; -} cmd_listener_list_item_t; - -/* Connection */ - -typedef struct { - char symbolic[SYMBOLIC_NAME_LEN]; - // char interface_name[SYMBOLIC_NAME_LEN]; - ip_address_t remote_ip; - ip_address_t local_ip; - uint16_t remote_port; - uint16_t local_port; - uint8_t family; - uint8_t type; - uint8_t admin_state; -#ifdef WITH_POLICY - uint32_t priority; - policy_tags_t tags; -#endif /* WITH_POLICY */ -} cmd_connection_add_t; - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; -} cmd_connection_remove_t; - -typedef struct { - void *_; -} cmd_connection_list_t; - -// Sync this struct with `hc_connection_t` in `api.h` -typedef struct { - uint32_t id; - char name[SYMBOLIC_NAME_LEN]; - char interface_name[SYMBOLIC_NAME_LEN]; - uint8_t type; - uint8_t family; - ip_address_t local_addr; - uint16_t local_port; - ip_address_t remote_addr; - uint16_t remote_port; - uint8_t admin_state; -#ifdef WITH_POLICY - uint32_t priority; - policy_tags_t tags; -#endif /* WITH_POLICY */ - uint8_t state; -} cmd_connection_list_item_t; - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; - uint8_t admin_state; - uint8_t pad8[3]; -} cmd_connection_set_admin_state_t; - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; - uint8_t admin_state; -#ifdef WITH_POLICY - uint32_t priority; - policy_tags_t tags; -#endif /* WITH_POLICY */ -} cmd_connection_update_t; - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; - uint32_t priority; -} cmd_connection_set_priority_t; - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; - policy_tags_t tags; -} cmd_connection_set_tags_t; - -/* Route */ - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint16_t cost; - uint8_t family; - uint8_t len; -} cmd_route_add_t; - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint8_t family; - uint8_t len; -} cmd_route_remove_t; - -typedef struct { - void *_; -} cmd_route_list_t; - -// Sync this struct with `hc_route_t` in `api.h` -typedef struct { - ip_address_t address; - uint32_t connection_id; - uint16_t cost; - uint8_t family; - uint8_t len; -} cmd_route_list_item_t; - -/* Cache */ - -typedef struct { - uint8_t activate; -} cmd_cache_set_store_t; - -typedef struct { - uint8_t activate; -} cmd_cache_set_serve_t; - -typedef struct { - void *_; -} cmd_cache_clear_t; - -typedef struct { - void *_; -} cmd_cache_list_t; - -typedef struct { - uint8_t store_in_cs; - uint8_t serve_from_cs; - uint32_t cs_size; - uint32_t num_stale_entries; -} cmd_cache_list_reply_t; - -typedef struct { - cmd_header_t header; - cmd_cache_list_reply_t payload; -} msg_cache_list_reply_t; - -/* Statistics */ - -// General stats -typedef struct { - void *_; -} cmd_stats_get_t; - -typedef struct { - cmd_header_t header; - hicn_light_stats_t payload; -} msg_stats_get_reply_t; - -// Per-face stats -typedef struct { - void *_; -} cmd_stats_list_t; - -typedef struct { - uint32_t id; - connection_stats_t stats; -} cmd_stats_list_item_t; - -typedef struct { - cmd_header_t header; - cmd_stats_list_item_t payload; -} msg_stats_list_reply_t; - -/* WLDR */ - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; - uint8_t activate; -} cmd_wldr_set_t; - -/* Strategy */ - -typedef struct { - ip_address_t address; - uint8_t family; - uint8_t len; - uint8_t type; - uint8_t related_prefixes; - union { - struct { - ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - uint8_t families[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - } low_latency; - }; -} cmd_strategy_set_t; - -typedef struct { - uint8_t type; - ip_address_t address; - uint8_t family; - uint8_t len; - ip_address_t local_address; - uint8_t local_family; - uint8_t local_len; -} cmd_strategy_add_local_prefix_t; - -/* Punting */ - -typedef struct { - char symbolic_or_connid[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint8_t family; - uint8_t len; -} cmd_punting_add_t; - -/* MAP-Me */ - -typedef struct { - uint8_t activate; -} cmd_mapme_activator_t; - -typedef cmd_mapme_activator_t cmd_mapme_enable_t; -typedef cmd_mapme_activator_t cmd_mapme_set_discovery_t; - -typedef struct { - uint32_t timePeriod; -} cmd_mapme_timing_t; - -typedef cmd_mapme_timing_t cmd_mapme_set_timescale_t; -typedef cmd_mapme_timing_t cmd_mapme_set_retx_t; - -typedef struct { - void *_; -} cmd_mapme_send_update_t; - -/* Policy */ - -typedef struct { - ip_address_t address; - uint8_t family; - uint8_t len; - hicn_policy_t policy; -} cmd_policy_add_t; - -typedef struct { - ip_address_t address; - uint8_t family; - uint8_t len; -} cmd_policy_remove_t; - -typedef struct { - void *_; -} cmd_policy_list_t; - -typedef struct { - ip_address_t address; - uint8_t family; - uint8_t len; - hicn_policy_t policy; -} cmd_policy_list_item_t; - -/* Subscription */ - -typedef struct { - uint32_t topics; -} cmd_subscription_add_t; - -typedef struct { - uint32_t topics; -} cmd_subscription_remove_t; - -/* Full messages */ - -#define _(l, u) \ - typedef struct { \ - cmd_header_t header; \ - cmd_##l##_t payload; \ - } msg_##l##_t; -foreach_command_type; -#undef _ - -typedef struct { - cmd_header_t header; - cmd_listener_list_item_t payload; -} msg_listener_list_reply_t; - -typedef struct { - cmd_header_t header; - cmd_connection_list_item_t payload; -} msg_connection_list_reply_t; - -typedef struct { - cmd_header_t header; - cmd_route_list_item_t payload; -} msg_route_list_reply_t; - -typedef struct { - cmd_header_t header; - cmd_policy_list_item_t payload; -} msg_policy_list_reply_t; - -//===== size of commands ====== -// REMINDER: when a new_command is added, the following switch has to be -// updated. -static inline int command_get_payload_len(command_type_t command_type) { - switch (command_type) { -#define _(l, u) \ - case COMMAND_TYPE_##u: \ - return sizeof(cmd_##l##_t); - foreach_command_type -#undef _ - case COMMAND_TYPE_UNDEFINED : case COMMAND_TYPE_N : return 0; - } -} -#endif /* HICN_CTRL_HICNLIGHTNG_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h index 69ede1985..34667cc1b 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/hicn-light.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -20,8 +20,8 @@ * Header and payload in binary format. */ -#ifndef HICN_CTRL_HICNLIGHT_H -#define HICN_CTRL_HICNLIGHT_H +#ifndef HICN_CTRL_HICNLIGHTNG_H +#define HICN_CTRL_HICNLIGHTNG_H #ifndef _WIN32 #include <netinet/in.h> @@ -31,404 +31,506 @@ #include <stdint.h> #include <stdlib.h> -#include <hicn/util/ip_address.h> -#ifdef WITH_POLICY #include <hicn/policy.h> -#endif /* WITH_POLICY */ +#include <hicn/strategy.h> +#include <hicn/util/ip_address.h> + +#include "api.h" #define SYMBOLIC_NAME_LEN 16 -#define MAX_FWD_STRATEGY_RELATED_PREFIXES 10 typedef struct in6_addr ipv6_addr_t; typedef uint32_t ipv4_addr_t; typedef enum { + MESSAGE_COMMAND_SUBTYPE_UNDEFINED, REQUEST_LIGHT = 0xc0, // this is a command RESPONSE_LIGHT, ACK_LIGHT, NACK_LIGHT, - LAST_MSG_TYPE_VALUE -} message_type; + NOTIFICATION_LIGHT, + MESSAGE_COMMAND_SUBTYPE_N +} message_command_subtype_t; + +#define message_type_is_valid(message_type) \ + ((message_type != MESSAGE_TYPE_UNDEFINED) && \ + (message_type != MESSAGE_COMMAND_SUBTYPE_N)) + +#define message_type_from_uchar(x) \ + (((x) < REQUEST_LIGHT) || (((x) >= MESSAGE_COMMAND_SUBTYPE_N)) \ + ? MESSAGE_COMMAND_SUBTYPE_N \ + : (message_command_subtype_t)(x)) + +#define foreach_command_type \ + _(listener_add, LISTENER_ADD) \ + _(listener_remove, LISTENER_REMOVE) \ + _(listener_list, LISTENER_LIST) \ + _(connection_add, CONNECTION_ADD) \ + _(connection_remove, CONNECTION_REMOVE) \ + _(connection_list, CONNECTION_LIST) \ + _(connection_update, CONNECTION_UPDATE) \ + _(route_add, ROUTE_ADD) \ + _(route_remove, ROUTE_REMOVE) \ + _(route_list, ROUTE_LIST) \ + _(cache_set_store, CACHE_SET_STORE) \ + _(cache_set_serve, CACHE_SET_SERVE) \ + _(cache_clear, CACHE_CLEAR) \ + _(cache_list, CACHE_LIST) \ + _(strategy_set, STRATEGY_SET) \ + _(strategy_add_local_prefix, STRATEGY_ADD_LOCAL_PREFIX) \ + _(wldr_set, WLDR_SET) \ + _(punting_add, PUNTING_ADD) \ + _(mapme_enable, MAPME_ENABLE) \ + _(mapme_set_discovery, MAPME_SET_DISCOVERY) \ + _(mapme_set_timescale, MAPME_SET_TIMESCALE) \ + _(mapme_set_retx, MAPME_SET_RETX) \ + _(mapme_send_update, MAPME_SEND_UPDATE) \ + _(policy_add, POLICY_ADD) \ + _(policy_remove, POLICY_REMOVE) \ + _(policy_list, POLICY_LIST) \ + _(active_interface_update, ACTIVE_INTERFACE_UPDATE) \ + _(subscription_add, SUBSCRIPTION_ADD) \ + _(subscription_remove, SUBSCRIPTION_REMOVE) \ + _(stats_get, STATS_GET) \ + _(stats_list, STATS_LIST) typedef enum { - ADD_LISTENER = 0, - ADD_CONNECTION, - LIST_CONNECTIONS, - ADD_ROUTE, - LIST_ROUTES, - REMOVE_CONNECTION, - REMOVE_LISTENER, - REMOVE_ROUTE, - CACHE_STORE, - CACHE_SERVE, - CACHE_CLEAR, - SET_STRATEGY, - SET_WLDR, - ADD_PUNTING, - LIST_LISTENERS, - MAPME_ENABLE, - MAPME_DISCOVERY, - MAPME_TIMESCALE, - MAPME_RETX, - MAPME_SEND_UPDATE, - CONNECTION_SET_ADMIN_STATE, -#ifdef WITH_POLICY - ADD_POLICY, - LIST_POLICIES, - REMOVE_POLICY, - UPDATE_CONNECTION, - CONNECTION_SET_PRIORITY, - CONNECTION_SET_TAGS, -#endif /* WITH_POLICY */ - LAST_COMMAND_VALUE -} command_id; + COMMAND_TYPE_UNDEFINED, +#define _(l, u) COMMAND_TYPE_##u, + foreach_command_type +#undef _ + COMMAND_TYPE_N, +} command_type_t; -typedef enum { - ADDR_INET = 1, - ADDR_INET6, - ADDR_LINK, - ADDR_IFACE, - ADDR_UNIX /* PF_UNIX */ -} address_type; +extern const char *command_type_str[]; -typedef enum { - UDP_CONN, - TCP_CONN, - GRE_CONN, // not implemented - HICN_CONN -} connection_type; +#define command_type_str(x) command_type_str[x] -typedef enum { ACTIVATE_ON, ACTIVATE_OFF } activate_type; +#define command_type_is_valid(command_type) \ + ((command_type != COMMAND_TYPE_UNDEFINED) && (command_type != COMMAND_TYPE_N)) -//========== HEADER ========== +#define command_type_from_uchar(x) \ + (((x) >= COMMAND_TYPE_N) ? COMMAND_TYPE_N : (command_type_t)(x)) +/* Should be at least 8 bytes */ typedef struct { - uint8_t messageType; - uint8_t commandID; - uint16_t length; // tells the number of structures in the payload - uint32_t seqNum; -} header_control_message; -// for the moment has to be at least 8 bytes - -// SIZE=8 + uint8_t message_type; + uint8_t command_id; + uint16_t length; /* Number of structures in the payload */ + uint32_t seq_num; +} cmd_header_t; -//========== [00] ADD LISTENER ========== +typedef struct { + cmd_header_t header; +} msg_header_t; -typedef enum { ETHER_MODE, IP_MODE, HICN_MODE } listener_mode; +/* Listener */ typedef struct { char symbolic[SYMBOLIC_NAME_LEN]; - char interfaceName[SYMBOLIC_NAME_LEN]; - ip_address_t address; + char interface_name[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t address; uint16_t port; - // uint16_t etherType; - uint8_t addressType; - uint8_t listenerMode; - uint8_t connectionType; -} add_listener_command; + uint8_t family; + uint8_t type; +} cmd_listener_add_t; -// SIZE=56 +typedef struct { + char symbolicOrListenerid[SYMBOLIC_NAME_LEN]; +} cmd_listener_remove_t; + +typedef struct { + void *_; // Otherwise empty structs result in clang build error +} cmd_listener_list_t; -//========== [01] ADD CONNECTION ========== +/* Connection */ typedef struct { char symbolic[SYMBOLIC_NAME_LEN]; - // char interfaceName[SYMBOLIC_NAME_LEN]; - ip_address_t remoteIp; - ip_address_t localIp; - uint16_t remotePort; - uint16_t localPort; - uint8_t ipType; - uint8_t connectionType; + // char interface_name[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t remote_ip; + hicn_ip_address_t local_ip; + uint16_t remote_port; + uint16_t local_port; + uint8_t family; + uint8_t type; uint8_t admin_state; -#ifdef WITH_POLICY + uint8_t __pad; uint32_t priority; policy_tags_t tags; -#endif /* WITH_POLICY */ -} add_connection_command; +} cmd_connection_add_t; -// SIZE=56 +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; +} cmd_connection_remove_t; -//========== [02] LIST CONNECTIONS ========== +typedef struct { + void *_; +} cmd_connection_list_t; -typedef enum { - CONN_GRE, - CONN_TCP, - CONN_UDP, - CONN_MULTICAST, - CONN_L2, - CONN_HICN -} list_connections_type; +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + uint8_t admin_state; + uint8_t pad8[3]; +} cmd_connection_set_admin_state_t; -typedef enum { - IFACE_UP = 0, - IFACE_DOWN = 1, - IFACE_UNKNOWN = 2 // not used actually -} connection_state; +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + uint8_t admin_state; + uint32_t priority; + policy_tags_t tags; +} cmd_connection_update_t; typedef struct { - add_connection_command connectionData; - uint32_t connid; - uint8_t state; - char interfaceName[SYMBOLIC_NAME_LEN]; - char connectionName[SYMBOLIC_NAME_LEN]; -} list_connections_command; + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + uint32_t priority; +} cmd_connection_set_priority_t; -// SIZE=80 +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + policy_tags_t tags; +} cmd_connection_set_tags_t; -//========== [03] ADD ROUTE ========== +/* Route */ typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - ip_address_t address; + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t address; uint16_t cost; - uint8_t addressType; + uint8_t family; uint8_t len; -} add_route_command; - -// SIZE=36 - -//========== [04] LIST ROUTE ========== +} cmd_route_add_t; typedef struct { - ip_address_t address; - uint32_t connid; - uint16_t cost; - uint8_t addressType; + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t address; + uint8_t family; uint8_t len; -} list_routes_command; +} cmd_route_remove_t; -// SIZE=24 +typedef struct { + void *_; +} cmd_route_list_t; + +/* Cache */ -//========== [05] REMOVE CONNECTION ========== typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; -} remove_connection_command; + uint8_t activate; +} cmd_cache_set_store_t; -//========== [06] REMOVE LISTENER ========== typedef struct { - char symbolicOrListenerid[SYMBOLIC_NAME_LEN]; -} remove_listener_command; + uint8_t activate; +} cmd_cache_set_serve_t; -// SIZE=16 +typedef struct { + void *_; +} cmd_cache_clear_t; -//========== [07] REMOVE ROUTE ========== +typedef struct { + void *_; +} cmd_cache_list_t; typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint8_t addressType; - uint8_t len; -} remove_route_command; + uint8_t store_in_cs; + uint8_t serve_from_cs; + uint32_t cs_size; + uint32_t num_stale_entries; +} cmd_cache_list_reply_t; -// SIZE=36 +typedef struct { + cmd_header_t header; + cmd_cache_list_reply_t payload; +} msg_cache_list_reply_t; -//========== [08] CACHE STORE ========== +/* WLDR */ typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; uint8_t activate; -} cache_store_command; +} cmd_wldr_set_t; -// SIZE=1 +/* Strategy */ -//========== [09] CACHE SERVE ========== +typedef struct { + hicn_ip_address_t address; + uint8_t family; + uint8_t len; + uint8_t type; + uint8_t related_prefixes; + union { + struct { + hicn_ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES]; + uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES]; + uint8_t families[MAX_FWD_STRATEGY_RELATED_PREFIXES]; + } low_latency; + }; +} cmd_strategy_set_t; typedef struct { - uint8_t activate; -} cache_serve_command; + uint8_t type; + hicn_ip_address_t address; + uint8_t family; + uint8_t len; + hicn_ip_address_t local_address; + uint8_t local_family; + uint8_t local_len; +} cmd_strategy_add_local_prefix_t; -// SIZE=1 +/* Punting */ -//========== [10] SET STRATEGY ========== +typedef struct { + char symbolic_or_connid[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t address; + uint8_t family; + uint8_t len; +} cmd_punting_add_t; -typedef enum { - SET_STRATEGY_LOADBALANCER, - SET_STRATEGY_RANDOM, - SET_STRATEGY_LOW_LATENCY, - LAST_STRATEGY_VALUE -} strategy_type; +/* MAP-Me */ typedef struct { - ip_address_t address; - uint8_t strategyType; - uint8_t addressType; - uint8_t len; - uint8_t related_prefixes; - ip_address_t addresses[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - uint8_t lens[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - uint8_t addresses_type[MAX_FWD_STRATEGY_RELATED_PREFIXES]; -} set_strategy_command; + uint8_t activate; +} cmd_mapme_activator_t; + +typedef cmd_mapme_activator_t cmd_mapme_enable_t; +typedef cmd_mapme_activator_t cmd_mapme_set_discovery_t; -// SIZE=208 +typedef struct { + uint32_t timePeriod; +} cmd_mapme_timing_t; -//========== [11] SET WLDR ========== +typedef cmd_mapme_timing_t cmd_mapme_set_timescale_t; +typedef cmd_mapme_timing_t cmd_mapme_set_retx_t; typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - uint8_t activate; -} set_wldr_command; + void *_; +} cmd_mapme_send_update_t; -// SIZE=17 +/* Policy */ -//========== [12] ADD PUNTING ========== +typedef struct { + hicn_ip_address_t address; + uint8_t family; + uint8_t len; + hicn_policy_t policy; +} cmd_policy_add_t; typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - ip_address_t address; - uint8_t addressType; + hicn_ip_address_t address; + uint8_t family; uint8_t len; -} add_punting_command; +} cmd_policy_remove_t; -// SIZE=36 +typedef struct { + void *_; +} cmd_policy_list_t; -//========== [13] LIST LISTENER ========== +/* Subscription */ typedef struct { - ip_address_t address; - char listenerName[SYMBOLIC_NAME_LEN]; - char interfaceName[SYMBOLIC_NAME_LEN]; - uint32_t connid; - uint16_t port; - uint8_t addressType; - uint8_t encapType; -} list_listeners_command; + uint32_t topics; +} cmd_subscription_add_t; -// SIZE=56 +typedef struct { + uint32_t topics; +} cmd_subscription_remove_t; -//========== [14] MAPME ========== +/* Statistics */ -// (enable/discovery/timescale/retx) +// General stats +typedef struct { + void *_; +} cmd_stats_get_t; +// Per-face stats typedef struct { - uint8_t activate; -} mapme_activator_command; + void *_; +} cmd_stats_list_t; + +typedef void *cmd_active_interface_update_t; + +/* Full messages */ + +#define _(l, u) \ + typedef struct { \ + cmd_header_t header; \ + cmd_##l##_t payload; \ + } msg_##l##_t; +foreach_command_type +#undef _ + + /* Serialized version of hc_listener_t */ + typedef struct { + char name[SYMBOLIC_NAME_LEN]; + char interface_name[INTERFACE_LEN]; + hicn_ip_address_t local_addr; + uint32_t id; + uint16_t local_port; + uint8_t type; + uint8_t family; +} cmd_listener_list_item_t; + +static_assert(sizeof(cmd_listener_list_item_t) == 56, ""); -// SIZE=1 +typedef struct { + cmd_header_t header; + cmd_listener_list_item_t payload; +} msg_listener_list_reply_t; +/* Serialized version of hc_connection_t */ typedef struct { - uint32_t timePeriod; -} mapme_timing_command; + char name[SYMBOLIC_NAME_LEN]; + char interface_name[INTERFACE_LEN]; + hicn_ip_address_t local_addr; + hicn_ip_address_t remote_addr; + uint32_t id; + uint32_t priority; + uint16_t local_port; + uint16_t remote_port; + uint8_t netdevice_type; + uint8_t type; + uint8_t family; + uint8_t admin_state; + uint8_t tags; + uint8_t state; + uint8_t __pad[6]; +} cmd_connection_list_item_t; + +static_assert(POLICY_TAG_N <= 8, ""); +static_assert(sizeof(cmd_connection_list_item_t) == 88, ""); typedef struct { - ip_address_t address; - uint8_t addressType; - uint8_t len; -} mapme_send_update_command; + cmd_header_t header; + cmd_connection_list_item_t payload; +} msg_connection_list_reply_t; -// SIZE=1 +typedef msg_connection_list_reply_t msg_connection_notify_t; typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; + char interface_name[INTERFACE_LEN]; + hicn_ip_address_t local_addr; + hicn_ip_address_t remote_addr; + uint32_t id; + uint32_t priority; + uint16_t local_port; + uint16_t remote_port; + uint8_t netdevice_type; + uint8_t type; + uint8_t family; uint8_t admin_state; - uint8_t pad8[3]; -} connection_set_admin_state_command; + uint8_t tags; + uint8_t state; + uint8_t __pad[6]; +} cmd_face_list_item_t; -#ifdef WITH_POLICY +static_assert(sizeof(cmd_face_list_item_t) == 72, ""); typedef struct { - ip_address_t address; - uint8_t addressType; + char face_name[SYMBOLIC_NAME_LEN]; + hicn_ip_address_t remote_addr; + uint32_t face_id; + uint16_t cost; + uint8_t family; uint8_t len; - hicn_policy_t policy; -} add_policy_command; + cmd_face_list_item_t face; +} cmd_route_list_item_t; + +static_assert(sizeof(cmd_route_list_item_t) == 112, ""); typedef struct { - ip_address_t address; - uint8_t addressType; - uint8_t len; - hicn_policy_t policy; -} list_policies_command; + cmd_header_t header; + cmd_route_list_item_t payload; +} msg_route_list_reply_t; + +typedef msg_route_list_reply_t msg_route_notify_t; typedef struct { - ip_address_t address; - uint8_t addressType; + uint8_t state; + uint8_t disabled; + uint16_t __pad; +} _policy_tag_state_t; + +typedef struct { + uint32_t throughput; + uint32_t latency; + uint32_t loss_rate; +} _interface_stats_t; + +typedef struct { + _interface_stats_t wired; + _interface_stats_t wifi; + _interface_stats_t cellular; + _interface_stats_t all; +} _policy_stats_t; + +typedef struct { + char app_name[APP_NAME_LEN]; + _policy_tag_state_t tags[POLICY_TAG_N]; + _policy_stats_t stats; + uint8_t __pad[4]; +} _hicn_policy_t; + +static_assert(sizeof(_hicn_policy_t) == 208, ""); + +typedef struct { + uint8_t policy[208]; + hicn_ip_address_t remote_addr; + uint8_t family; uint8_t len; -} remove_policy_command; + uint8_t __pad[6]; +} cmd_policy_list_item_t; + +static_assert(sizeof(cmd_policy_list_item_t) == 232, ""); typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - uint8_t admin_state; - uint32_t priority; - policy_tags_t tags; -} update_connection_command; + cmd_header_t header; + cmd_policy_list_item_t payload; +} msg_policy_list_reply_t; + +typedef msg_policy_list_reply_t msg_policy_notify_t; +/* Those are needed to build but not used */ typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - uint32_t priority; -} connection_set_priority_command; + uint8_t _; +} cmd_strategy_list_item_t; +typedef struct { + uint8_t _; +} cmd_subscription_list_item_t; + +/* Statistics */ typedef struct { - char symbolicOrConnid[SYMBOLIC_NAME_LEN]; - policy_tags_t tags; -} connection_set_tags_command; + cmd_header_t header; + hicn_light_stats_t payload; +} msg_stats_get_reply_t; -#endif /* WITH_POLICY */ +typedef struct { + uint32_t id; + connection_stats_t stats; +} cmd_stats_list_item_t; + +typedef struct { + cmd_header_t header; + cmd_stats_list_item_t payload; +} msg_stats_list_reply_t; //===== size of commands ====== // REMINDER: when a new_command is added, the following switch has to be // updated. -static inline int payloadLengthDaemon(command_id id) { - switch (id) { - case ADD_LISTENER: - return sizeof(add_listener_command); - case ADD_CONNECTION: - return sizeof(add_connection_command); - case LIST_CONNECTIONS: - return 0; // list connections: payload always 0 - case ADD_ROUTE: - return sizeof(add_route_command); - case LIST_ROUTES: - return 0; // list routes: payload always 0 - case REMOVE_CONNECTION: - return sizeof(remove_connection_command); - case REMOVE_LISTENER: - return sizeof(remove_listener_command); - case REMOVE_ROUTE: - return sizeof(remove_route_command); - case CACHE_STORE: - return sizeof(cache_store_command); - case CACHE_SERVE: - return sizeof(cache_serve_command); - case CACHE_CLEAR: - return 0; // cache clear - case SET_STRATEGY: - return sizeof(set_strategy_command); - case SET_WLDR: - return sizeof(set_wldr_command); - case ADD_PUNTING: - return sizeof(add_punting_command); - case LIST_LISTENERS: - return 0; // list listeners: payload always 0 - case MAPME_ENABLE: - return sizeof(mapme_activator_command); - case MAPME_DISCOVERY: - return sizeof(mapme_activator_command); - case MAPME_TIMESCALE: - return sizeof(mapme_timing_command); - case MAPME_RETX: - return sizeof(mapme_timing_command); - case MAPME_SEND_UPDATE: - return sizeof(mapme_send_update_command); - case CONNECTION_SET_ADMIN_STATE: - return sizeof(connection_set_admin_state_command); -#ifdef WITH_POLICY - case ADD_POLICY: - return sizeof(add_policy_command); - case LIST_POLICIES: - return 0; // list policies: payload always 0 - case REMOVE_POLICY: - return sizeof(remove_policy_command); - case UPDATE_CONNECTION: - return sizeof(update_connection_command); - case CONNECTION_SET_PRIORITY: - return sizeof(connection_set_priority_command); - case CONNECTION_SET_TAGS: - return sizeof(connection_set_tags_command); -#endif /* WITH_POLICY */ - case LAST_COMMAND_VALUE: - return 0; - default: - return 0; +static inline int command_get_payload_len(command_type_t command_type) { + switch (command_type) { +#define _(l, u) \ + case COMMAND_TYPE_##u: \ + return sizeof(cmd_##l##_t); + foreach_command_type +#undef _ + case COMMAND_TYPE_UNDEFINED : case COMMAND_TYPE_N : return 0; } } -#endif /* HICN_CTRL_HICNLIGHT_H */ + +ssize_t hc_light_command_serialize(hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg); + +int hc_sock_initialize_module(hc_sock_t *s); + +#endif /* HICN_CTRL_HICNLIGHTNG_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/object.h b/ctrl/libhicnctrl/includes/hicn/ctrl/object.h new file mode 100644 index 000000000..c659d1824 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/object.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file object.h + * \brief API object representation. + */ + +#ifndef HICNCTRL_OBJECT_H +#define HICNCTRL_OBJECT_H + +#include <hicn/ctrl/object_type.h> + +#include <hicn/ctrl/objects/listener.h> +#include <hicn/ctrl/objects/connection.h> +#include <hicn/ctrl/objects/route.h> +#include <hicn/ctrl/objects/punting.h> +#include <hicn/ctrl/objects/strategy.h> +#include <hicn/ctrl/objects/policy.h> +#include <hicn/ctrl/objects/subscription.h> +#include <hicn/ctrl/objects/cache.h> +#include <hicn/ctrl/objects/mapme.h> +#include <hicn/ctrl/objects/active_interface.h> + +typedef union { + hc_connection_t connection; + hc_listener_t listener; + hc_route_t route; + hc_face_t face; + // hc_data_t *data; + hc_punting_t punting; + hc_strategy_t strategy; + hc_policy_t policy; + hc_subscription_t subscription; + hc_cache_t cache; + hc_mapme_t mapme; + hc_active_interface_t active_interface; + uint8_t as_uint8; +} hc_object_t; + +#define MAXSZ_OBJECT_T MAX + +#define IS_VALID_ACTION(x) IS_VALID_ENUM_TYPE(ACTION, x) + +bool hc_object_is_empty(const hc_object_t *object); + +size_t hc_object_size(hc_object_type_t object_type); + +int hc_object_validate(hc_object_type_t object_type, hc_object_t *object, + bool allow_partial); +int hc_object_cmp(hc_object_type_t object_type, hc_object_t *object1, + hc_object_t *object2); +int hc_object_snprintf(char *s, size_t size, hc_object_type_t object_type, + hc_object_t *object); + +#define foreach_object(VAR, data) foreach_type(hc_object_t, VAR, data) + +#define foreach_type(TYPE, VAR, DATA) \ + for (TYPE *VAR = (TYPE *)hc_data_get_buffer(DATA); \ + VAR < (TYPE *)(hc_data_get_buffer(DATA) + \ + hc_data_get_size(DATA) * sizeof(TYPE)); \ + VAR++) + +#endif /* HICNCTRL_OBJECT_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/object_type.h b/ctrl/libhicnctrl/includes/hicn/ctrl/object_type.h new file mode 100644 index 000000000..39a2d188e --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/object_type.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file object_type.h + * \brief Object type. + */ + +#ifndef HICNCTRL_OBJECT_TYPE_H +#define HICNCTRL_OBJECT_TYPE_H + +#define foreach_object_type \ + _(UNDEFINED) \ + _(CONNECTION) \ + _(LISTENER) \ + _(ROUTE) \ + _(FACE) \ + _(STRATEGY) \ + _(PUNTING) \ + _(POLICY) \ + _(CACHE) \ + _(MAPME) \ + _(WLDR) \ + _(LOCAL_PREFIX) \ + _(PROBE) \ + _(SUBSCRIPTION) \ + _(ACTIVE_INTERFACE) \ + _(STATS) \ + _(N) + +typedef enum { +#define _(x) OBJECT_TYPE_##x, + foreach_object_type +#undef _ +} hc_object_type_t; + +extern const char *object_type_str[]; + +#define object_type_str(x) object_type_str[x] + +hc_object_type_t object_type_from_str(const char *object_str); + +#define IS_VALID_OBJECT_TYPE(x) IS_VALID_ENUM_TYPE(OBJECT_TYPE, x) + +#endif /* HICNCTRL_OBJECT_TYPE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects.h new file mode 100644 index 000000000..4f560a2f3 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects.h @@ -0,0 +1,11 @@ +#ifndef HICNCTRL_OBJECTS_H +#define HICNCTRL_OBJECTS_H + +#include <hicn/ctrl/objects/connection.h> +#include <hicn/ctrl/objects/face.h> +#include <hicn/ctrl/objects/listener.h> +#include <hicn/ctrl/objects/route.h> +#include <hicn/ctrl/objects/strategy.h> +#include <hicn/ctrl/objects/subscription.h> + +#endif /* HICNCTRL_OBJECTS_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/active_interface.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/active_interface.h new file mode 100644 index 000000000..56a1d8cd5 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/active_interface.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/active_interface.h + * \brief Route. + */ + +#ifndef HICNCTRL_OBJECTS_ACTIVE_INTERFACE_H +#define HICNCTRL_OBJECTS_ACTIVE_INTERFACE_H + +#include <hicn/ctrl/objects/face.h> + +typedef struct { + hicn_ip_prefix_t prefix; + netdevice_flags_t interface_types; +} hc_active_interface_t; + +#define foreach_active_interface(VAR, data) \ + foreach_type(hc_active_interface_t, VAR, data) + +// XXX WRONG +#define MAXSZ_HC_ACTIVE_INTERFACE_ \ + MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN +#define MAXSZ_HC_ACTIVE_INTERFACE MAXSZ_HC_ACTIVE_INTERFACE_ + NULLTERM + +int hc_active_interface_snprintf(char *s, size_t size, + const hc_active_interface_t *active_interface); +int hc_active_interface_validate(const hc_active_interface_t *active_interface, + bool allow_partial); + +#endif diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/base.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/base.h new file mode 100644 index 000000000..fc40f680e --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/base.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file base.h + * \brief Base definitions for objects. + */ +#ifndef HICNCTRL_OBJECTS_BASE +#define HICNCTRL_OBJECTS_BASE + +#define INTERFACE_LEN 16 + +#endif /* HICNCTRL_OBJECTS_BASE */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/cache.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/cache.h new file mode 100644 index 000000000..1f8691be6 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/cache.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/cache.h + * \brief Cache. + */ + +#ifndef HICNCTRL_OBJECTS_CACHE_H +#define HICNCTRL_OBJECTS_CACHE_H + +typedef struct { + uint8_t serve; // 1 = on, 0 = off + uint8_t store; // 1 = on, 0 = off +} hc_cache_t; + +typedef struct { + bool store; + bool serve; + size_t cs_size; + size_t num_stale_entries; +} hc_cache_info_t; + +int hc_cache_snprintf(char *s, size_t size, const hc_cache_info_t *cache_info); + +#endif /* HICNCTRL_OBJECTS_CACHE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/connection.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/connection.h new file mode 100644 index 000000000..771b48c20 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/connection.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/connection.h + * \brief Connection. + */ + +#ifndef HICNCTRL_OBJECTS_CONNECTION_H +#define HICNCTRL_OBJECTS_CONNECTION_H + +#include <stdint.h> +#include <hicn/face.h> + +#include "base.h" + +/* + * NOTE : + * - interface_name is mainly used to derive listeners from connections, + * but is not itself used to create connections. + */ +typedef struct { + uint32_t id; /* Kr. */ + char name[SYMBOLIC_NAME_LEN]; /* K.w */ + char interface_name[INTERFACE_LEN]; /* Kr. */ + netdevice_type_t netdevice_type; /* .r. */ + face_type_t type; /* .rw */ + int family; /* .rw */ + hicn_ip_address_t local_addr; /* .rw */ + uint16_t local_port; /* .rw */ + hicn_ip_address_t remote_addr; /* .rw */ + uint16_t remote_port; /* .rw */ + face_state_t admin_state; /* .rw */ + uint32_t priority; /* .rw */ + policy_tags_t tags; /* .rw */ + face_state_t state; /* .r. */ +} hc_connection_t; + +#define foreach_connection(VAR, data) foreach_type(hc_connection_t, VAR, data) + +#define MAXSZ_HC_CONNECTION_ \ + MAXSZ_FACE_STATE_ + INTERFACE_LEN + SPACE + 2 * MAXSZ_URL_ + \ + MAXSZ_FACE_TYPE_ + SPACES(3) +#define MAXSZ_HC_CONNECTION MAXSZ_HC_CONNECTION_ + NULLTERM + +int hc_connection_validate(const hc_connection_t *connection, + bool allow_partial); +int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2); +int hc_connection_snprintf(char *s, size_t size, + const hc_connection_t *connection); + +#endif /* HICNCTRL_OBJECTS_CONNECTION_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/face.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/face.h new file mode 100644 index 000000000..1aa122f37 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/face.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/face.h + * \brief Face. + * + * A face is an abstraction introduced by the control library to abstract the + * forwarder implementation details. It encompasses connections and listeners + * and ensures the right dependencies are enforced, eg that we always have a + * listener when a connection is created. + */ + +#ifndef HICNCTRL_OBJECTS_FACE_H +#define HICNCTRL_OBJECTS_FACE_H + +#include <hicn/face.h> + +#include "base.h" + +typedef face_t hc_face_t; + +#define foreach_face(VAR, data) foreach_type(hc_face_t, VAR, data) + +#define MAX_FACE_ID 255 +#define MAXSZ_FACE_ID_ 3 +#define MAXSZ_FACE_ID MAXSZ_FACE_ID_ + NULLTERM +#define MAXSZ_FACE_NAME_ SYMBOLIC_NAME_LEN +#define MAXSZ_FACE_NAME MAXSZ_FACE_NAME_ + NULLTERM + +#define MAXSZ_HC_FACE_ \ + MAXSZ_FACE_ID_ + MAXSZ_FACE_NAME_ + MAXSZ_FACE_ + 5 + HOTFIXMARGIN +#define MAXSZ_HC_FACE MAXSZ_HC_FACE_ + NULLTERM + +int hc_face_snprintf(char *s, size_t size, const hc_face_t *face); + +#endif /* HICNCTRL_OBJECTS_FACE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/listener.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/listener.h new file mode 100644 index 000000000..0fb74f558 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/listener.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/listener.h + * \brief Listener. + */ + +#ifndef HICNCTRL_OBJECTS_LISTENER_H +#define HICNCTRL_OBJECTS_LISTENER_H + +#include <stddef.h> // offsetof +#include <stdint.h> +#include <hicn/face.h> + +#include "base.h" + +// FIXME the listener should not require any port for hICN... +typedef struct { + char name[SYMBOLIC_NAME_LEN]; /* K.w */ + char interface_name[INTERFACE_LEN]; /* Kr. */ + uint32_t id; /* Kr. */ + face_type_t type; /* .rw */ + int family; /* .rw */ + hicn_ip_address_t local_addr; /* .rw */ + uint16_t local_port; /* .rw */ +} hc_listener_t; + +int hc_listener_validate(const hc_listener_t *listener, bool allow_partial); +int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2); + +#define foreach_listener(VAR, data) foreach_type(hc_listener_t, VAR, data) + +#define MAXSZ_HC_LISTENER_ \ + INTERFACE_LEN + SPACE + MAXSZ_URL_ + SPACE + MAXSZ_FACE_TYPE_ +#define MAXSZ_HC_LISTENER MAXSZ_HC_LISTENER_ + NULLTERM + +int hc_listener_snprintf(char *s, size_t size, const hc_listener_t *listener); + +#endif /* HICNCTRL_OBJECTS_LISTENER_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/mapme.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/mapme.h new file mode 100644 index 000000000..37623ebfe --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/mapme.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/mapme.h + * \brief MAP-Me. + */ + +#ifndef HICNCTRL_OBJECTS_MAPME_H +#define HICNCTRL_OBJECTS_MAPME_H + +typedef enum { + MAPME_TARGET_ENABLE, + MAPME_TARGET_DISCOVERY, + MAPME_TARGET_TIMESCALE, + MAPME_TARGET_RETX, +} mapme_target_t; + +static inline mapme_target_t mapme_target_from_str(char *mapme_target_str) { + if (strcasecmp(mapme_target_str, "enable") == 0) + return MAPME_TARGET_ENABLE; + else if (strcasecmp(mapme_target_str, "discovery") == 0) + return MAPME_TARGET_DISCOVERY; + else if (strcasecmp(mapme_target_str, "timescale") == 0) + return MAPME_TARGET_TIMESCALE; + else + return MAPME_TARGET_RETX; +} + +#define MAX_MAPME_ARG_LEN 30 + +typedef struct { + mapme_target_t target; + // Command argument stored as a string + // before being parsed into 'enabled' or 'timescale' + char unparsed_arg[MAX_MAPME_ARG_LEN]; + + uint8_t enabled; // 1 = on, 0 = off + uint32_t timescale; // Milliseconds + + hicn_ip_address_t address; + int family; + u8 len; +} hc_mapme_t; + +#endif /* HICNCTRL_OBJECTS_MAPME_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/policy.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/policy.h new file mode 100644 index 000000000..437387e4a --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/policy.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/policy.h + * \brief Policy. + */ + +#ifndef HICNCTRL_OBJECTS_POLICY_H +#define HICNCTRL_OBJECTS_POLICY_H + +typedef struct { + int family; /* Krw */ + hicn_ip_address_t remote_addr; /* krw */ + uint8_t len; /* krw */ + hicn_policy_t policy; /* .rw */ +} hc_policy_t; + +#define foreach_policy(VAR, data) foreach_type(hc_policy_t, VAR, data) + +/* TODO */ +#define MAXSZ_HC_POLICY_ 0 +#define MAXSZ_HC_POLICY MAXSZ_HC_POLICY_ + NULLTERM + +int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy); +int hc_policy_validate(const hc_policy_t *policy); + +#endif /* HICNCTRL_OBJECTS_POLICY_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/punting.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/punting.h new file mode 100644 index 000000000..d18e596b1 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/punting.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/punting.h + * \brief Punting + */ + +#ifndef HICNCTRL_OBJECTS_PUNTING_H +#define HICNCTRL_OBJECTS_PUNTING_H + +typedef struct { + face_id_t face_id; /* Kr. */ // XXX listener id, could be NULL for all ? + int family; /* Krw */ + hicn_ip_address_t prefix; /* krw */ + u8 prefix_len; /* krw */ +} hc_punting_t; + +int hc_punting_validate(const hc_punting_t *punting); +int hc_punting_cmp(const hc_punting_t *c1, const hc_punting_t *c2); + +#define foreach_punting(VAR, data) foreach_type(hc_punting_t, VAR, data) + +#define MAXSZ_HC_PUNTING_ 0 +#define MAXSZ_HC_PUNTING MAXSZ_HC_PUNTING_ + NULLTERM + +int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting); + +#endif /* HICNCTRL_OBJECTS_PUNTING_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/route.h new file mode 100644 index 000000000..fb68e9430 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/route.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/route.h + * \brief Route. + */ + +#ifndef HICNCTRL_OBJECTS_ROUTE_H +#define HICNCTRL_OBJECTS_ROUTE_H + +#include <hicn/ctrl/objects/face.h> + +typedef struct { + face_id_t face_id; /* Kr. ID (used when face and face_name == NULL) */ + char face_name[SYMBOLIC_NAME_LEN]; /* Kr. a name or an ID (if integer), used + if face is NULL */ + int family; /* Krw */ + hicn_ip_address_t remote_addr; /* krw */ + uint8_t len; /* krw */ + uint16_t cost; /* .rw */ + hc_face_t face; /* use by default if not NULL, otherwise look at face_name, + then face_id */ +} hc_route_t; + +#define foreach_route(VAR, data) foreach_type(hc_route_t, VAR, data) + +#define MAX_COST 65535 +#define MAXSZ_COST 5 +#define MAX_LEN 255 +#define MAXSZ_LEN 3 + +#define MAXSZ_HC_ROUTE_ \ + MAXSZ_FACE_ID + 1 + MAXSZ_COST + 1 + MAXSZ_IP_ADDRESS + 1 + MAXSZ_LEN +#define MAXSZ_HC_ROUTE MAXSZ_HC_ROUTE_ + NULLTERM + +int hc_route_snprintf(char *s, size_t size, const hc_route_t *route); +int hc_route_validate(const hc_route_t *route, bool allow_partial); + +#endif /* HICNCTRL_OBJECTS_ROUTE_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/strategy.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/strategy.h new file mode 100644 index 000000000..208f4620b --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/strategy.h @@ -0,0 +1,46 @@ + +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/strategy.h + * \brief Strategy. + */ + +#ifndef HICNCTRL_OBJECTS_STRATEGY_H +#define HICNCTRL_OBJECTS_STRATEGY_H + +#include <hicn/strategy.h> + +#define MAXSZ_STRATEGY_NAME 255 + +typedef struct { + // The name is not set by the controller + // but populated by the daemon + char name[MAXSZ_STRATEGY_NAME]; + strategy_type_t type; + hicn_ip_address_t address, local_address; + int family, local_family; + u8 len, local_len; +} hc_strategy_t; + +#define foreach_strategy(VAR, data) foreach_type(hc_strategy_t, VAR, data) + +#define MAXSZ_HC_STRATEGY_ MAXSZ_STRATEGY_NAME +#define MAXSZ_HC_STRATEGY MAXSZ_HC_STRATEGY_ + NULLTERM + +int hc_strategy_snprintf(char *s, size_t size, const hc_strategy_t *strategy); + +#endif /* HICNCTRL_OBJECTS_STRATEGY_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/objects/subscription.h b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/subscription.h new file mode 100644 index 000000000..861341160 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/objects/subscription.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file objects/subscription.h + * \brief Subscription. + */ + +#ifndef HICNCTRL_OBJECTS_SUBSCRIPTION_H +#define HICNCTRL_OBJECTS_SUBSCRIPTION_H + +#include <limits.h> +#include <stddef.h> +#include <hicn/ctrl/object_type.h> + +#undef PUNTING // TODO(eloparco): Undefined to avoid collisions + // Fix the collision + +// Used only to create 'hc_topic_t' +typedef struct { +#define _(x) char x; + foreach_object_type +#undef _ +} object_offset_t; + +// Flags for topic subscriptions +typedef enum { +#define _(x) TOPIC_##x = (1 << offsetof(object_offset_t, x)), + foreach_object_type +#undef _ + TOPIC_ALL = INT_MAX, +} hc_topic_t; + +static inline hc_object_type_t object_from_topic(hc_topic_t topic) { +#define _(x) \ + if (topic == TOPIC_##x) return OBJECT_TYPE_##x; + foreach_object_type +#undef _ + return OBJECT_TYPE_UNDEFINED; +} + +static inline hc_topic_t topic_from_object_type(hc_object_type_t object_type) { + if (object_type == OBJECT_TYPE_UNDEFINED) return TOPIC_ALL; +#define _(x) \ + if (object_type == OBJECT_TYPE_##x) return TOPIC_##x; + foreach_object_type +#undef _ + return TOPIC_UNDEFINED; +} + +#define NUM_TOPICS OBJECT_TYPE_N // Because a topic is created for each object +#define ALL_TOPICS ~0 + +// Subscriptions +typedef uint32_t hc_topics_t; +typedef struct { + hc_topics_t topics; +} hc_subscription_t; + +#if 0 +typedef struct { + netdevice_type_t interface_type; +} hc_event_interface_update_t; + +typedef struct { + ip_prefix_t prefix; + netdevice_type_t interface_type; +} hc_event_active_interface_update_t; +#endif + +#endif /* HICNCTRL_OBJECTS_SUBSCRIPTION_H */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/parse.h b/ctrl/libhicnctrl/includes/hicn/ctrl/parse.h new file mode 100644 index 000000000..8921d25ed --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/parse.h @@ -0,0 +1,116 @@ +#ifndef HICNLIGHT_PARSE_CMD +#define HICNLIGHT_PARSE_CMD + +#include <hicn/ctrl/api.h> + +#include "command.h" + +/* Update sscanf accordingly in parse_cmd.c */ +#define MAX_PARAMETERS 10 +#define MAX_SCANF_PARAM_LEN 100 + +typedef int (*parser_hook_t)(void* arg); + +#if 0 +typedef struct { + const char* name; + const char* help; + parser_type_t type; + size_t offset; + /* + * quick hack to let the functions update two or more parameters, like for + * IP_ADDRESS or IP_PREFIX types + */ + size_t offset2; + size_t offset3; +} command_parameter_t; + +typedef struct { + hc_action_t action; + hc_object_type_t object; + unsigned nparams; + command_parameter_t parameters[MAX_PARAMETERS]; + parser_hook_t post_hook; +} command_parser_t; + +#define TYPE_STRN(N) \ + (parser_type_t) { \ + .name = TYPENAME_STR, \ + .str = { \ + .max_size = N, \ + }, \ + } +#define TYPE_FMT_STRN(N) "%s" + +#define TYPE_INT(MIN, MAX) \ + (parser_type_t) { \ + .name = TYPENAME_INT, \ + .sint = { \ + .min = (MIN), \ + .max = (MAX), \ + }, \ + } +#define TYPE_FMT_INT "%d" + +#define TYPE_UINT(min, max) \ + (parser_type_t) { \ + .name = TYPENAME_UINT, \ + .uint = { \ + .min = min, \ + .max = max, \ + }, \ + } +#define TYPE_FMT_UINT "%u" + +#define TYPE_SYMBOLIC_OR_ID TYPE_STRN(SYMBOLIC_NAME_LEN) +#define TYPE_FMT_SYMBOLIC_OR_ID "%s" + +#define TYPE_INTERFACE_NAME TYPE_STRN(INTERFACE_LEN) +#define TYPE_FMT_INTERFACE_NAME "%s" + +#define TYPE_IP_ADDRESS \ + (parser_type_t) { .name = TYPENAME_IP_ADDRESS, } +#define TYPE_FMT_IP_ADDRESS "%s" + +#define TYPE_IP_PREFIX \ + (parser_type_t) { .name = TYPENAME_IP_PREFIX, } +#define TYPE_FMT_IP_PREFIX "%s" + +#define TYPE_ON_OFF \ + (parser_type_t) { .name = TYPENAME_ON_OFF, } +#define TYPE_FMT_ON_OFF "%s" + +#define TYPE_ENUM(x) \ + (parser_type_t) { \ + .name = TYPENAME_ENUM, \ + .enum_ = { \ + .from_str = (int (*)(const char*))x##_from_str, \ + }, \ + } +/* We need to allocate room for the intermediate string */ +#define TYPE_FMT_ENUM "%s" + +#define TYPE_POLICY_STATE(TAG) \ + (parser_type_t) { \ + .name = TYPENAME_POLICY_STATE, \ + .policy_state = { \ + .tag = TAG, \ + }, \ + } +/* We need to allocate room for the intermediate string */ +#define TYPE_FMT_POLICY_STATE "%s" +#endif + +int parse_getopt_args(const command_parser_t* parser, int argc, char* argv[], + hc_command_t* command); + +int parse(const char* cmd, hc_command_t* command); +int help(const char* cmd); + +/** + * @brief Convert the action enum to the action name used in the commands (e.g. + * from ACTION_CREATE to "add"). + */ +const char* action_to_cmd_action(hc_action_t action); + +#endif /* HICNLIGHT_PARSE_CMD */ diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h index 81f011d4d..f1801d772 100644 --- a/ctrl/libhicnctrl/includes/hicn/ctrl/route.h +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/route.h @@ -34,15 +34,15 @@ typedef struct hicn_route_s hicn_route_t; #define MAX_ROUTE_COST 255 #define IS_VALID_ROUTE_COST(x) ((x >= MIN_ROUTE_COST) && (x <= MAX_ROUTE_COST)) -hicn_route_t* hicn_route_create(ip_prefix_t* prefix, face_id_t face_id, +hicn_route_t* hicn_route_create(hicn_ip_prefix_t* prefix, face_id_t face_id, route_cost_t cost); hicn_route_t* hicn_route_dup(const hicn_route_t* route); void hicn_route_free(hicn_route_t* route); int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2); -int hicn_route_get_prefix(const hicn_route_t* route, ip_prefix_t* prefix); -int hicn_route_set_prefix(hicn_route_t* route, const ip_prefix_t prefix); +int hicn_route_get_prefix(const hicn_route_t* route, hicn_ip_prefix_t* prefix); +int hicn_route_set_prefix(hicn_route_t* route, const hicn_ip_prefix_t prefix); int hicn_route_get_cost(const hicn_route_t* route, int* cost); int hicn_route_set_cost(hicn_route_t* route, const int cost); diff --git a/ctrl/libhicnctrl/includes/hicn/ctrl/socket.h b/ctrl/libhicnctrl/includes/hicn/ctrl/socket.h new file mode 100644 index 000000000..2503fadd0 --- /dev/null +++ b/ctrl/libhicnctrl/includes/hicn/ctrl/socket.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file socket.h + * \brief Control socket + */ + +#ifndef HICNCTRL_SOCKET_H +#define HICNCTRL_SOCKET_H + +#include <hicn/ctrl/data.h> + +/* With UDP, the buffer should be able to receieve a full packet, and thus MTU + * (max 9000) is sufficient. Messages will be received fully one by one. + * With TCP, the buffer should be at least able to receive a message header and + * the maximum size of a data element, so any reasonable size will be correct, + * it might just optimize performance. Messages might arrive in chunks that the + * library is able to parse. + */ +#define JUMBO_MTU 9000 +#define RECV_BUFLEN 65535 + +#define foreach_forwarder_type \ + _(UNDEFINED) \ + _(HICNLIGHT) \ + _(VPP) \ + _(N) + +typedef enum { +#define _(x) FORWARDER_TYPE_##x, + foreach_forwarder_type +#undef _ +} forwarder_type_t; + +extern const char *forwarder_type_str[]; + +#define forwarder_type_str(x) forwarder_type_str[x] + +forwarder_type_t forwarder_type_from_str(const char *str); + +/** + * \brief Holds the state of an hICN control socket + */ +typedef struct hc_sock_s hc_sock_t; + +/** + * \brief Create an hICN control socket using the specified URL. + * \param [in] url - The URL to connect to. + * \return an hICN control socket + */ +hc_sock_t *hc_sock_create_url(const char *url); + +/** + * \brief Create an hICN control socket using the provided forwarder. + * \return an hICN control socket + */ +hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder); + +/** + * \brief Create an hICN control socket using the provided forwarder and a + * URL. \return an hICN control socket + */ +hc_sock_t *hc_sock_create_forwarder_url(forwarder_type_t forwarder, + const char *url); + +/** + * \brief Create an hICN control socket using the default connection type. + * XXX doc + * \return an hICN control socket + */ +hc_sock_t *hc_sock_create(forwarder_type_t forwarder, const char *url); + +/** + * \brief Frees an hICN control socket + * \param [in] s - hICN control socket + */ +void hc_sock_free(hc_sock_t *s); + +/** + * \brief Returns the next available sequence number to use for requests to + * the API. \param [in] s - hICN control socket + */ +int hc_sock_get_next_seq(hc_sock_t *s); + +/** + * \brief Sets the socket as non-blocking + * \param [in] s - hICN control socket + * \return Error code + */ +int hc_sock_set_nonblocking(hc_sock_t *s); + +/** + * \brief Return the file descriptor associated to the hICN contorl sock + * \param [in] s - hICN control socket + * \return The file descriptor (positive value), or a negative integer in case + * of error + */ +int hc_sock_get_fd(hc_sock_t *s); + +/** + * \brief Connect the socket + * \return Error code + */ +int hc_sock_connect(hc_sock_t *s); + +/** + * \brief Return the offset and size of available buffer space + * \param [in] s - hICN control socket + * \param [out] buffer - Offset in buffer + * \param [out] size - Remaining size + * \return Error code + */ +int hc_sock_get_recv_buffer(hc_sock_t *s, uint8_t **buffer, size_t *size); + +#if 0 +/** + * \brief Write/read iexchance on the control socket (internal helper + * function) \param [in] s - hICN control socket \param [in] msg - Message to + * send \param [in] msglen - Length of the message to send \return Error code + */ +int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq); +#endif + +/** + * \brief Processing data received by socket + * \param [in] s - hICN control socket + * \param [in] parse - Parse function to convert remote types into lib native + * types, or NULL not to perform any translation. + * \return Error code + */ +int hc_sock_process(hc_sock_t *s, hc_data_t **data); + +int hc_sock_receive(hc_sock_t *s, hc_data_t **data); +int hc_sock_receive_all(hc_sock_t *s, hc_data_t **data); + +#if 0 +/** + * \brief Callback used in async mode when data is available on the socket + * \param [in] s - hICN control socket + * \return Error code + */ +int hc_sock_callback(hc_sock_t *s, hc_data_t **data); +#endif + +/** + * \brief Reset the state of the sock (eg. to handle a reconnecton) + * \param [in] s - hICN control socket + * \return Error code + */ +int hc_sock_reset(hc_sock_t *s); + +void hc_sock_increment_woff(hc_sock_t *s, size_t bytes); + +#if 0 +int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result, + data_callback_t complete_cb, void *complete_cb_data); + +#endif + +int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms); + +int hc_sock_set_async(hc_sock_t *s); + +int hc_sock_is_async(hc_sock_t *s); + +int hc_sock_on_receive(hc_sock_t *s, size_t count); + +#endif /* HICNCTRL_SOCKET_H */ diff --git a/ctrl/libhicnctrl/src/CMakeLists.txt b/ctrl/libhicnctrl/src/CMakeLists.txt index 1bec03d50..a9a7d3db4 100644 --- a/ctrl/libhicnctrl/src/CMakeLists.txt +++ b/ctrl/libhicnctrl/src/CMakeLists.txt @@ -15,11 +15,50 @@ # Source files ############################################################## set(SOURCE_FILES - route.c + action.c api.c + command.c + commands/command_cache.c + commands/command_connection.c + commands/command_face.c + commands/command_listener.c + commands/command_mapme.c + commands/command_policy.c + commands/command_punting.c + commands/command_route.c + commands/command_stats.c + commands/command_strategy.c + commands/command_subscription.c + data.c + fw_interface.c + object.c + object_type.c + object_vft.c + objects/active_interface.c + objects/base.c + objects/connection.c + objects/face.c + objects/listener.c + objects/route.c + objects/strategy.c + objects/subscription.c + parse.c + request.c + route.c + socket.c ) set(HEADER_FILES + object_vft.h + objects/active_interface.h + objects/base.h + objects/connection.h + objects/face.h + objects/listener.h + objects/route.h + objects/strategy.h + objects/subscription.h + request.h api_private.h ) @@ -58,13 +97,33 @@ endif () ############################################################## +# Compiler options +############################################################## +set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} +) + +############################################################## # Do not use modules if Android ############################################################## if (${CMAKE_SYSTEM_NAME} MATCHES Android OR ${CMAKE_SYSTEM_NAME} MATCHES iOS) list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_common.c - ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light_ng_api.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/connection.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/strategy.c + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/subscription.c + ) + list(APPEND HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/connection.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/listener.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/strategy.h + ${CMAKE_CURRENT_SOURCE_DIR}/modules/hicn_light/subscription.h ) else() add_subdirectory(modules) @@ -72,14 +131,6 @@ endif() ############################################################## -# Compiler options -############################################################## -set(COMPILER_OPTIONS - ${DEFAULT_COMPILER_OPTIONS} -) - - -############################################################## # Build main hicnctrl library ############################################################## build_library(${LIBHICNCTRL} @@ -96,6 +147,12 @@ build_library(${LIBHICNCTRL} COMPILE_OPTIONS ${COMPILER_OPTIONS} ) +############################################################## +# Unit tests +############################################################## +if (${BUILD_TESTS}) + add_subdirectory(test) +endif() ############################################################## # Cmake config files diff --git a/ctrl/libhicnctrl/src/action.c b/ctrl/libhicnctrl/src/action.c new file mode 100644 index 000000000..c8834d90c --- /dev/null +++ b/ctrl/libhicnctrl/src/action.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file action.c + * \brief Implementation of actions. + */ + +#include <strings.h> + +#include <hicn/ctrl/action.h> + +const char *action_str[] = { +#define _(x) [ACTION_##x] = #x, + foreach_action +#undef _ +}; + +hc_action_t action_from_str(const char *action_str) { +#define _(x) \ + if (strcasecmp(action_str, #x) == 0) \ + return ACTION_##x; \ + else + foreach_action +#undef _ + if (strcasecmp(action_str, "add") == 0) return ACTION_CREATE; + else if (strcasecmp(action_str, "remove") == 0) return ACTION_DELETE; + else return ACTION_UNDEFINED; +} diff --git a/ctrl/libhicnctrl/src/api.c b/ctrl/libhicnctrl/src/api.c index d68dc830e..c93853dd1 100644 --- a/ctrl/libhicnctrl/src/api.c +++ b/ctrl/libhicnctrl/src/api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -26,6 +26,13 @@ #include <math.h> // log2 #include "api_private.h" +#include "object_vft.h" +#include "request.h" + +#include <hicn/ctrl/socket.h> +#include "socket_private.h" + +#define ENOIMPL 42 #if 0 /* /!\ Please update constants in public header file upon changes */ @@ -60,685 +67,282 @@ connection_type_from_str(const char * str) * Control Data ******************************************************************************/ -hc_data_t *hc_data_create(size_t in_element_size, size_t out_element_size, - data_callback_t complete_cb) { - hc_data_t *data = malloc(sizeof(hc_data_t)); - if (!data) goto ERR_MALLOC; - - /* FIXME Could be NULL thanks to realloc provided size is 0 */ - data->max_size_log = DEFAULT_SIZE_LOG; - data->in_element_size = in_element_size; - data->out_element_size = out_element_size; - data->size = 0; - data->complete = false; - data->command_id = 0; // TODO this could also be a busy mark in the socket - /* No callback needed in blocking code for instance */ - data->complete_cb = complete_cb; - - data->buffer = malloc((1 << data->max_size_log) * data->out_element_size); - if (!data->buffer) goto ERR_BUFFER; - data->ret = 0; - data->current = 0; - - return data; - -ERR_BUFFER: - hc_data_free(data); -ERR_MALLOC: - return NULL; -} - -void hc_data_free(hc_data_t *data) { - if (data) free(data->buffer); - free(data); -} - -int hc_data_ensure_available(hc_data_t *data, size_t count) { - size_t new_size_log = - (data->size + count - 1 > 0) ? log2(data->size + count - 1) + 1 : 0; - if (new_size_log > data->max_size_log) { - data->max_size_log = new_size_log; - data->buffer = - realloc(data->buffer, (1 << new_size_log) * data->out_element_size); - if (!data->buffer) return -1; - } +/*----------------------------------------------------------------------------* + * Object model + *----------------------------------------------------------------------------*/ - return 0; -} +/*----------------------------------------------------------------------------* + * Entry point + *----------------------------------------------------------------------------*/ -int hc_data_push_many(hc_data_t *data, const void *elements, size_t count) { - if (hc_data_ensure_available(data, count) < 0) return -1; +int hc_sock_on_init(hc_sock_t *s, hc_request_t *request) { + int rc; + ssize_t size; - memcpy(data->buffer + data->size * data->out_element_size, elements, - count * data->out_element_size); - data->size += count; + uint8_t *buffer; - return 0; -} + size = s->ops.prepare(s, request, &buffer); + if (size < 0) goto ERR_PREPARE; -int hc_data_push(hc_data_t *data, const void *element) { - return hc_data_push_many(data, element, 1); -} + if (size == 0) return 1; /* Done */ -/** - * - * NOTE: This function make sure there is enough room available in the data - * structure. - */ -u8 *hc_data_get_next(hc_data_t *data) { - if (hc_data_ensure_available(data, 1) < 0) return NULL; + assert(hc_request_get_data(hc_request_get_current(request))); - return data->buffer + data->size * data->out_element_size; -} + rc = s->ops.send(s, buffer, size); + if (rc < 0) goto ERR_SEND; -int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data) { - data->complete_cb = cb; - data->complete_cb_data = cb_data; return 0; -} -int hc_data_set_complete(hc_data_t *data) { - data->complete = true; - data->ret = 0; - if (data->complete_cb) return data->complete_cb(data, data->complete_cb_data); - return 0; -} - -int hc_data_set_error(hc_data_t *data) { - data->ret = -1; - return 0; +ERR_PREPARE: +ERR_SEND: + return -1; } -int hc_data_reset(hc_data_t *data) { - data->size = 0; - return 0; -} +int hc_sock_on_receive(hc_sock_t *s, size_t count) { + int rc; -static hc_sock_t *_open_module(const char *name, const char *url) { - char complete_name[128]; -#ifdef __APPLE__ - snprintf(complete_name, 128, "%s.dylib", name); -#elif defined(__linux__) - snprintf(complete_name, 128, "%s.so", name); -#else -#error "System not supported for dynamic lynking" + DEBUG("hc_sock_on_receive: calling process with count=%ld", count); + rc = s->ops.process(s, count); + if (rc < 0) goto ERR_PROCESS; + + hc_request_t *request = hc_sock_get_request(s); + hc_request_t *current_request = hc_request_get_current(request); + hc_data_t *data = hc_request_get_data(current_request); + if (hc_data_is_complete(data)) { + /* + * We only notice a request is complete when trying to send the second + * time... either the state machine reaches the end, or in case of generic + * requests, we mark it as such. + */ +#if 0 + if (hc_request_is_complete(current_request)) { + if (!hc_request_pop(request)) { + /* Free request context */ + /* In case of error, data is NULL */ + // XXX bug if we free request XXX + // hc_sock_free_request(s, request); + if (!hc_request_is_subscription(request)) + hc_request_set_complete(request); + return 1; /* Done */ + } + } else { #endif - - void *handle = 0; - const char *error = 0; - hc_sock_t *(*creator)(const char *) = 0; - hc_sock_t *ret = 0; - - // open module - handle = dlopen(complete_name, RTLD_LAZY); - if (!handle) { - if ((error = dlerror()) != 0) { - ERROR("%s", error); + ON_INIT: + rc = hc_sock_on_init(s, request); + if (rc < 0) goto ERR_INIT; + if (rc == 1) { + if (!hc_request_pop(request)) { + /* Free request context */ + /* In case of error, data is NULL */ + // hc_sock_free_request(s, request); + if (!hc_request_is_subscription(request)) + hc_request_set_complete(request); + return 1; /* Done */ + } + goto ON_INIT; } - return 0; - } - - // get factory method - creator = - (hc_sock_t * (*)(const char *)) dlsym(handle, "_hc_sock_create_url"); - if (!creator) { - if ((error = dlerror()) != 0) { - ERROR("%s", error); +#if 0 } - return 0; - } - - ret = (*creator)(NULL); - ret->handle = handle; - - return ret; -} - -hc_sock_t *hc_sock_create_forwarder_url(forwarder_type_t forwarder, - const char *url) { - switch (forwarder) { - case HICNLIGHT: - return _open_module("hicnlightctrl_module", url); - case HICNLIGHT_NG: - return _open_module("hicnlightngctrl_module", url); - case VPP: - return _open_module("vppctrl_module", url); - default: - return NULL; - } -} - -#ifdef ANDROID -// In android we do not load a module at runtime -// but we link the hicnlight implmentation directly -// to the main library -extern hc_sock_t *_hc_sock_create_url(const char *url); #endif - -hc_sock_t *hc_sock_create_forwarder(forwarder_type_t forwarder) { -#ifdef ANDROID - assert(forwarder == HICNLIGHT_NG); - hc_sock_t *ret = _hc_sock_create_url(NULL); - ret->handle = NULL; - return ret; -#else - return hc_sock_create_forwarder_url(forwarder, NULL); -#endif -} - -hc_sock_t *hc_sock_create(void) { - return hc_sock_create_forwarder(HICNLIGHT_NG); -} - -void hc_sock_free(hc_sock_t *s) { - void *handle = s->handle; - s->hc_sock_free(s); - - if (handle) { - dlclose(handle); - } -} - -int hc_sock_get_next_seq(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); } - -int hc_sock_set_nonblocking(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); } - -int hc_sock_get_fd(hc_sock_t *s) { return s->hc_sock_get_fd(s); } - -int hc_sock_connect(hc_sock_t *s) { return s->hc_sock_connect(s); } - -int hc_sock_get_available(hc_sock_t *s, u8 **buffer, size_t *size) { - return s->hc_sock_get_available(s, buffer, size); -} - -int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq) { - return s->hc_sock_send(s, msg, msglen, seq); -} - -int hc_sock_recv(hc_sock_t *s) { return s->hc_sock_recv(s); } - -int hc_sock_process(hc_sock_t *s, hc_data_t **data) { - return s->hc_sock_process(s, data); -} - -int hc_sock_callback(hc_sock_t *s, hc_data_t **data) { - return s->hc_sock_callback(s, data); -} - -int hc_sock_reset(hc_sock_t *s) { return s->hc_sock_reset(s); } - -void hc_sock_increment_woff(hc_sock_t *s, size_t bytes) { - s->hc_sock_increment_woff(s, bytes); -} - -int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result, - data_callback_t complete_cb, void *complete_cb_data) { - return s->hc_sock_prepare_send(s, result, complete_cb, complete_cb_data); -} - -int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms) { - return s->hc_sock_set_recv_timeout_ms(s, timeout_ms); -} - -/*----------------------------------------------------------------------------* - * LISTENER - *----------------------------------------------------------------------------*/ - -int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) { - return s->hc_listener_create(s, listener); -} - -hc_result_t *hc_listener_create_conf(hc_sock_t *s, hc_listener_t *listener) { - return s->hc_listener_create_conf(s, listener); -} - -int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, - hc_listener_t **listener_found) { - return s->hc_listener_get(s, listener, listener_found); -} - -int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) { - return s->hc_listener_delete(s, listener); -} - -int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) { - return s->hc_listener_list(s, pdata); -} - -GENERATE_FIND(listener); - -/* LISTENER VALIDATE */ - -int hc_listener_validate(const hc_listener_t *listener) { - if (!IS_VALID_NAME(listener->name)) { - ERROR("[hc_listener_validate] Invalid name specified"); - return -1; - } - if (!IS_VALID_INTERFACE_NAME(listener->interface_name)) { - ERROR("[hc_listener_validate] Invalid interface_name specified"); - return -1; - } - if (!IS_VALID_TYPE(listener->type)) { - ERROR("[hc_listener_validate] Invalid type specified"); - return -1; - } - if (!IS_VALID_FAMILY(listener->family)) { - ERROR("[hc_listener_validate] Invalid family specified"); - return -1; - } - if (!IS_VALID_ADDRESS(&listener->local_addr, listener->family)) { - ERROR("[hc_listener_validate] Invalid local_addr specified"); - return -1; - } - if (!IS_VALID_PORT(listener->local_port)) { - ERROR("[hc_listener_validate] Invalid local_port specified"); - return -1; } + return 0; /* Continue processing */ - return 0; +ERR_INIT: +ERR_PROCESS: + return -1; } -/* LISTENER CMP */ - -int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2) { +// -1 error +// 0 = request is not yet complete +// 1 request is complete +int hc_sock_receive(hc_sock_t *s, hc_data_t **pdata) { int rc; + DEBUG("Waiting for data..."); + rc = s->ops.recv(s); + if (rc < 0) return -1; - rc = INT_CMP(l1->type, l2->type); - if (rc != 0) return rc; - - rc = INT_CMP(l1->family, l2->family); - if (rc != 0) return rc; - - rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN); - if (rc != 0) return rc; - - rc = ip_address_cmp(&l1->local_addr, &l2->local_addr, l1->family); - if (rc != 0) return rc; - - rc = INT_CMP(l1->local_port, l2->local_port); - if (rc != 0) return rc; - - return rc; -} - -/* LISTENER SNPRINTF */ - -/* /!\ Please update constants in header file upon changes */ -int hc_listener_snprintf(char *s, size_t size, hc_listener_t *listener) { - char local[MAXSZ_URL]; - int rc; - rc = url_snprintf(local, MAXSZ_URL, listener->family, &listener->local_addr, - listener->local_port); - if (rc >= MAXSZ_URL) - WARN("[hc_listener_snprintf] Unexpected truncation of URL string"); - if (rc < 0) return rc; - - return snprintf(s, size, "%s %s %s interface=%s", listener->name, local, - face_type_str(listener->type), listener->interface_name); -} + rc = hc_sock_on_receive(s, 0); + if (rc < 0) return -1; -/*----------------------------------------------------------------------------* - * CONNECTION - *----------------------------------------------------------------------------*/ - -int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) { - return s->hc_connection_create(s, connection); -} - -hc_result_t *hc_connection_create_conf(hc_sock_t *s, - hc_connection_t *connection) { - return s->hc_connection_create_conf(s, connection); -} - -int hc_connection_get(hc_sock_t *s, hc_connection_t *connection, - hc_connection_t **connection_found) { - return s->hc_connection_get(s, connection, connection_found); -} - -int hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, - hc_connection_t *connection) { - return s->hc_connection_update_by_id(s, hc_connection_id, connection); -} - -int hc_connection_update(hc_sock_t *s, hc_connection_t *connection_current, - hc_connection_t *connection_updated) { - return s->hc_connection_update(s, connection_current, connection_updated); -} - -int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) { - return s->hc_connection_delete(s, connection); -} - -hc_result_t *hc_connection_delete_conf(hc_sock_t *s, - hc_connection_t *connection) { - return s->hc_connection_delete_conf(s, connection); -} - -int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) { - return s->hc_connection_list(s, pdata); -} - -int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, - face_state_t state) { - return s->hc_connection_set_admin_state(s, conn_id_or_name, state); -} + hc_request_t *request = hc_sock_get_request(s); + /* + * If notification, display it, ideally callback. What to do with + * allocated data ? + */ + // XXX problem we display object on ACK... but not subsequent + // notifications + // XXX we should rely on callback here in addition, even for a synchronous + // request + if (hc_request_is_subscription(request)) { + hc_data_t *data = hc_request_get_data(request); + assert(data); + hc_object_t *obj = (hc_object_t *)hc_data_get_buffer(data); + char buf[MAXSZ_HC_OBJECT]; + hc_object_type_t object_type = hc_data_get_object_type(data); + if (hc_object_snprintf(buf, sizeof(buf), object_type, obj) > 0) { + ; + INFO("%s %s", object_type_str(object_type), buf); + } + } -#ifdef WITH_POLICY -int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name, - uint32_t priority) { - return s->hc_connection_set_priority(s, conn_id_or_name, priority); -} + // XXX need same for async + if (rc != 1) return 0; -int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags) { - return s->hc_connection_set_tags(s, conn_id_or_name, tags); + hc_request_t *current_request = hc_request_get_current(request); + if (hc_request_is_complete(current_request)) { + /* We either return the (last) allocated data, or free it */ + if (pdata) { + *pdata = hc_request_get_data(request); + } else { + hc_request_reset_data(request); + } + hc_request_on_complete(request); + // hc_sock_free_request(s, request); + } + return 1; } -#endif // WITH_POLICY - -GENERATE_FIND(connection); -/* CONNECTION VALIDATE */ +int hc_sock_receive_all(hc_sock_t *s, hc_data_t **pdata) { + for (;;) { + int rc = hc_sock_receive(s, pdata); + if (rc < 0) return -1; -int hc_connection_validate(const hc_connection_t *connection) { - if (connection->name[0] != '\0' && !IS_VALID_NAME(connection->name)) { - ERROR("[hc_connection_validate] Invalid name specified"); - return -1; - } - if (!IS_VALID_INTERFACE_NAME(connection->interface_name)) { - ERROR("[hc_connection_validate] Invalid interface_name specified"); - return -1; - } - if (!IS_VALID_TYPE(connection->type)) { - ERROR("[hc_connection_validate] Invalid type specified"); - return -1; - } - if (!IS_VALID_FAMILY(connection->family)) { - ERROR("[hc_connection_validate] Invalid family specified"); - return -1; + /* If request is complete, stop */ + if (rc == 1) break; } - if (!IS_VALID_ADDRESS(&connection->local_addr, connection->family)) { - ERROR("[hc_connection_validate] Invalid local_addr specified"); - return -1; - } - if (!IS_VALID_PORT(connection->local_port)) { - ERROR("[hc_connection_validate] Invalid local_port specified"); - return -1; - } - if (!IS_VALID_ADDRESS(&connection->remote_addr, connection->family)) { - ERROR("[hc_connection_validate] Invalid remote_addr specified"); - return -1; - } - if (!IS_VALID_PORT(connection->remote_port)) { - ERROR("[hc_connection_validate] Invalid remote_port specified"); - return -1; - } - return 0; } -/* CONNECTION CMP */ - -/* - * hICN light uses ports even for hICN connections, but their value is ignored. - * As connections are specific to hicn-light, we can safely use IP and ports for - * comparison independently of the face type. +/** + * @return <0 in case of error + * -1 : validation error + * -2 : error during send + * -3 : error receiving or parsing + * + * If the caller provider a non-NULL hc_data_t pointer to receive results + * back, it is responsible for freeing it. */ -int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2) { - int rc; - - rc = INT_CMP(c1->type, c2->type); - if (rc != 0) return rc; - - rc = INT_CMP(c1->family, c2->family); - if (rc != 0) return rc; - - rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN); - if (rc != 0) return rc; - - rc = ip_address_cmp(&c1->local_addr, &c2->local_addr, c1->family); - if (rc != 0) return rc; - - rc = INT_CMP(c1->local_port, c2->local_port); - if (rc != 0) return rc; - - rc = ip_address_cmp(&c1->remote_addr, &c2->remote_addr, c1->family); - if (rc != 0) return rc; +int _hc_execute(hc_sock_t *s, hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_result_callback_t callback, + void *callback_data, hc_data_t **pdata) { + assert(!(hc_sock_is_async(s) && pdata)); - rc = INT_CMP(c1->remote_port, c2->remote_port); - if (rc != 0) return rc; - - return rc; -} - -/* CONNECTION SNPRINTF */ - -/* /!\ Please update constants in header file upon changes */ -int hc_connection_snprintf(char *s, size_t size, - const hc_connection_t *connection) { - char local[MAXSZ_URL]; - char remote[MAXSZ_URL]; - int rc; - - // assert(connection->connection_state) - if (strcmp(connection->name, "SELF") == 0) { - return snprintf(s, size, "%s", connection->name); + if (hc_sock_is_async(s) && !s->ops.get_fd) { + return -1; /* No async support */ } - rc = url_snprintf(local, MAXSZ_URL, connection->family, - &connection->local_addr, connection->local_port); - if (rc >= MAXSZ_URL) - WARN("[hc_connection_snprintf] Unexpected truncation of URL string"); - if (rc < 0) return rc; - rc = url_snprintf(remote, MAXSZ_URL, connection->family, - &connection->remote_addr, connection->remote_port); - if (rc >= MAXSZ_URL) - WARN("[hc_connection_snprintf] Unexpected truncation of URL string"); - if (rc < 0) return rc; - - return snprintf(s, size, "%s %s %s %s", connection->name, local, remote, - face_type_str(connection->type)); -} - -int hc_face_create(hc_sock_t *s, hc_face_t *face) { - return s->hc_face_create(s, face); -} - -int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found) { - return s->hc_face_get(s, face, face_found); -} - -int hc_face_delete(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener) { - return s->hc_face_delete(s, face, delete_listener); -} - -int hc_face_list(hc_sock_t *s, hc_data_t **pdata) { - return s->hc_face_list(s, pdata); -} - -int hc_face_list_async(hc_sock_t *s) { return s->hc_face_list_async(s); } + // XXX no need to pass pdata to the request + // XXX sync socket, no multiplexed requests, no notifications + /* + * The request will contain all state needed to identify and demultiplex + * replies and notifications arriving on the socket. We assume there is at + * most a single request/reply in progress for a given request, and that + * requests involving multiple queries will run them sequentially. The use + * of a sequence number that is transported by the requests and reply is + * thus sufficient to disambiguate them. + */ + hc_request_t *request = hc_sock_create_request(s, action, object_type, object, + callback, callback_data); + if (!request) { + goto ERR_REQUEST; + } -int hc_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, - face_state_t state) { - return s->hc_face_set_admin_state(s, conn_id_or_name, state); -} + if (hc_request_requires_object(request)) { + if (hc_object_is_empty(object) || + hc_object_validate(object_type, object, true) < 0) { + goto ERR_VALIDATE; + } + } else { + if (object && !hc_object_is_empty(object)) { + goto ERR_CHECK; + } + } -#ifdef WITH_POLICY -int hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name, - uint32_t priority) { - return s->hc_face_set_priority(s, conn_id_or_name, priority); -} + /* Workaround for non-fd based modules */ + if (s->ops.prepare && s->ops.send && s->ops.recv && s->ops.process) { + if (hc_sock_on_init(s, request) < 0) goto ERR_INIT; -int hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags) { - return s->hc_face_set_tags(s, conn_id_or_name, tags); -} -#endif /* WITH_POLICY */ + if (hc_sock_is_async(s)) return 0; -/* /!\ Please update constants in header file upon changes */ -int hc_face_snprintf(char *s, size_t size, hc_face_t *face) { - /* URLs are also big enough to contain IP addresses in the hICN case */ - char local[MAXSZ_URL]; - char remote[MAXSZ_URL]; -#ifdef WITH_POLICY - char tags[MAXSZ_POLICY_TAGS]; -#endif /* WITH_POLICY */ - int rc; + /* Case in which no reply is expected */ + if (!pdata) return 0; - switch (face->face.type) { - case FACE_TYPE_HICN: - case FACE_TYPE_HICN_LISTENER: - rc = ip_address_snprintf(local, MAXSZ_URL, &face->face.local_addr, - face->face.family); - if (rc >= MAXSZ_URL) - WARN("[hc_face_snprintf] Unexpected truncation of URL string"); - if (rc < 0) return rc; - rc = ip_address_snprintf(remote, MAXSZ_URL, &face->face.remote_addr, - face->face.family); - if (rc >= MAXSZ_URL) - WARN("[hc_face_snprintf] Unexpected truncation of URL string"); - if (rc < 0) return rc; - break; - case FACE_TYPE_TCP: - case FACE_TYPE_UDP: - case FACE_TYPE_TCP_LISTENER: - case FACE_TYPE_UDP_LISTENER: - rc = url_snprintf(local, MAXSZ_URL, face->face.family, - &face->face.local_addr, face->face.local_port); - if (rc >= MAXSZ_URL) - WARN("[hc_face_snprintf] Unexpected truncation of URL string"); - if (rc < 0) return rc; - rc = url_snprintf(remote, MAXSZ_URL, face->face.family, - &face->face.remote_addr, face->face.remote_port); - if (rc >= MAXSZ_URL) - WARN("[hc_face_snprintf] Unexpected truncation of URL string"); - if (rc < 0) return rc; - break; - default: - return -1; + if (hc_sock_receive_all(s, pdata) < 0) goto ERR_RECV; + } else if (s->ops.prepare) { + // hc_data_t *data = hc_data_create(OBJECT_TYPE_LISTENER); + // hc_data_push(data, NULL); + // No nested requests for now... + ssize_t size = s->ops.prepare(s, request, NULL); + _ASSERT(size == 0); /* Done */ + if (hc_request_is_complete(request)) { + if (pdata) { + *pdata = hc_request_get_data(request); + } else { + hc_request_reset_data(request); + } + hc_request_on_complete(request); + } } - // [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS) -#ifdef WITH_POLICY - rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->face.tags); - if (rc >= MAXSZ_POLICY_TAGS) - WARN("[hc_face_snprintf] Unexpected truncation of policy tags string"); - if (rc < 0) return rc; - - return snprintf( - s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)", face->id, face->name, - face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX - ? face->face.netdevice.name - : "*", - face_type_str(face->face.type), local, remote, - face_state_str(face->face.state), face_state_str(face->face.admin_state), - face->face.priority, tags); -#else - return snprintf(s, size, "[#%d %s] %s %s %s %s %s/%s", face->id, face->name, - face->face.netdevice.index != NETDEVICE_UNDEFINED_INDEX - ? face->face.netdevice.name - : "*", - face_type_str(face->face.type), local, remote, - face_state_str(face->face.state), - face_state_str(face->face.admin_state)); -#endif /* WITH_POLICY */ -} - -/*----------------------------------------------------------------------------* - * ROUTE - *----------------------------------------------------------------------------*/ - -int hc_route_create(hc_sock_t *s, hc_route_t *route) { - return s->hc_route_create(s, route); -} + return 0; -hc_result_t *hc_route_create_conf(hc_sock_t *s, hc_route_t *route) { - return s->hc_route_create_conf(s, route); +ERR_RECV: + hc_request_reset_data(request); +ERR_INIT: + hc_sock_free_request(s, request, true); +ERR_CHECK: +ERR_REQUEST: +ERR_VALIDATE: + if (pdata) *pdata = NULL; + return -1; } -int hc_route_delete(hc_sock_t *s, hc_route_t *route) { - return s->hc_route_delete(s, route); +int hc_execute(hc_sock_t *s, hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_data_t **pdata) { + return _hc_execute(s, action, object_type, object, NULL, NULL, pdata); } -int hc_route_list(hc_sock_t *s, hc_data_t **pdata) { - return s->hc_route_list(s, pdata); +int hc_execute_async(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, + hc_result_callback_t callback, void *callback_data) { + return _hc_execute(s, action, object_type, object, callback, callback_data, + NULL); } -int hc_route_list_async(hc_sock_t *s) { return s->hc_route_list_async(s); } - -/* ROUTE SNPRINTF */ - -/* /!\ Please update constants in header file upon changes */ -int hc_route_snprintf(char *s, size_t size, hc_route_t *route) { - /* interface cost prefix length */ - - char prefix[MAXSZ_IP_ADDRESS]; - int rc; - - rc = ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr, - route->family); - if (rc >= MAXSZ_IP_ADDRESS) - ; - if (rc < 0) return rc; - - return snprintf(s, size, "%s %*d %s %*d conn_id=%d", route->name, MAXSZ_COST, - route->cost, prefix, MAXSZ_LEN, route->len, route->face_id); -} +/* This function has to be called after the first execute until data and + * request are complete */ +// execute is just setting things up so that we can keep on calling this +// function repeatedly until completion. +// +// in the caller, we don't know how much we will receive in advance... so in +// asio for instance, we will use async_receive rather than async_read. +// XXX the question remains about the buffers... -int hc_route_validate(const hc_route_t *route) { - if (!IS_VALID_ID(route->connection_id)) { - ERROR("[hc_route_validate] Invalid connection id"); - return -1; - } - if (route->name[0] == '\0') { - if (!IS_VALID_FACE_ID(route->face_id)) { - ERROR("[hc_route_validate] Invalid face_id"); - return -1; - } - } else if (!IS_VALID_NAME(route->name) && !IS_VALID_STR_ID(route->name)) { - ERROR("[hc_route_validate] Invalid name specified"); - return -1; - } - if (!IS_VALID_FAMILY(route->family)) { - ERROR("[hc_route_validate] Invalid family specified"); - return -1; - } - if (!IS_VALID_ADDRESS(&route->remote_addr, route->family)) { - ERROR("[hc_route_validate] Invalid remote_addr specified"); - return -1; - } - if (!IS_VALID_ROUTE_COST(route->cost)) { - ERROR("[hc_route_validate] Invalid cost"); - return -1; - } - if (!IS_VALID_PREFIX_LEN(route->len)) { - ERROR("[hc_route_validate] Invalid len"); - return -1; - } +/* + * request -> write command + * + * SYNC : hc_data_t + * ASYNC : provide socket-level callback + * + * socket available -> read -> parse -> populate data + * data complete -> + */ - return 0; -} +/****************************************************************************** + * OBJECT-SPECIFIC FUNCTIONS (backwards compatibility) + ******************************************************************************/ /*----------------------------------------------------------------------------* * FACE + * + * This is an abstraction provided for when the module does not implement + *it. Alternative is to move it to hicn light *----------------------------------------------------------------------------*/ +#if 0 + /* FACE -> LISTENER */ -int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener) { - const face_t *f = &face->face; - - switch (f->type) { - case FACE_TYPE_HICN_LISTENER: - break; - case FACE_TYPE_TCP_LISTENER: - break; - case FACE_TYPE_UDP_LISTENER: - break; - default: - return -1; - } - return -1; /* XXX Not implemented */ -} /* LISTENER -> FACE */ @@ -748,225 +352,10 @@ int hc_listener_to_face(const hc_listener_t *listener, hc_face_t *face) { /* FACE -> CONNECTION */ -int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection, - bool generate_name) { - int rc; - - const face_t *f = &face->face; - switch (f->type) { - case FACE_TYPE_HICN: - *connection = (hc_connection_t){ - .type = FACE_TYPE_HICN, - .family = f->family, - .local_addr = f->local_addr, - .local_port = 0, - .remote_addr = f->remote_addr, - .remote_port = 0, - .admin_state = f->admin_state, - .state = f->state, -#ifdef WITH_POLICY - .priority = f->priority, - .tags = f->tags, -#endif /* WITH_POLICY */ - }; - rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", - f->netdevice.name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[hc_face_to_connection] Unexpected truncation of symbolic " - "name string"); - break; - case FACE_TYPE_TCP: - *connection = (hc_connection_t){ - .type = FACE_TYPE_TCP, - .family = f->family, - .local_addr = f->local_addr, - .local_port = f->local_port, - .remote_addr = f->remote_addr, - .remote_port = f->remote_port, - .admin_state = f->admin_state, - .state = f->state, -#ifdef WITH_POLICY - .priority = f->priority, - .tags = f->tags, -#endif /* WITH_POLICY */ - }; - if (generate_name) { - rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE()); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[hc_face_to_connection] Unexpected truncation of " - "symbolic name string"); - } else { - memset(connection->name, 0, SYMBOLIC_NAME_LEN); - } - break; - case FACE_TYPE_UDP: - *connection = (hc_connection_t){ - .type = FACE_TYPE_UDP, - .family = f->family, - .local_addr = f->local_addr, - .local_port = f->local_port, - .remote_addr = f->remote_addr, - .remote_port = f->remote_port, - .admin_state = f->admin_state, - .state = f->state, -#ifdef WITH_POLICY - .priority = f->priority, - .tags = f->tags, -#endif /* WITH_POLICY */ - }; - if (generate_name) { - rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE()); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[hc_face_to_connection] Unexpected truncation of " - "symbolic name string"); - } else { - memset(connection->name, 0, SYMBOLIC_NAME_LEN); - } - snprintf(connection->interface_name, INTERFACE_LEN, "%s", - f->netdevice.name); - break; - default: - return -1; - } - - connection->id = face->id; - rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", - f->netdevice.name); - if (rc >= INTERFACE_LEN) - WARN( - "hc_face_to_connection] Unexpected truncation of interface name " - "string"); - - return 0; -} /* CONNECTION -> FACE */ - -int hc_connection_to_face(const hc_connection_t *connection, hc_face_t *face) { - int rc; - switch (connection->type) { - case FACE_TYPE_TCP: - *face = (hc_face_t){ - .id = connection->id, - .face = - { - .type = FACE_TYPE_TCP, - .family = connection->family, - .local_addr = connection->local_addr, - .local_port = connection->local_port, - .remote_addr = connection->remote_addr, - .remote_port = connection->remote_port, - .admin_state = connection->admin_state, - .state = connection->state, -#ifdef WITH_POLICY - .priority = connection->priority, - .tags = connection->tags, -#endif /* WITH_POLICY */ - }, - }; - break; - case FACE_TYPE_UDP: - *face = (hc_face_t){ - .id = connection->id, - .face = - { - .type = FACE_TYPE_UDP, - .family = connection->family, - .local_addr = connection->local_addr, - .local_port = connection->local_port, - .remote_addr = connection->remote_addr, - .remote_port = connection->remote_port, - .admin_state = connection->admin_state, - .state = connection->state, -#ifdef WITH_POLICY - .priority = connection->priority, - .tags = connection->tags, -#endif /* WITH_POLICY */ - }, - }; - break; - case FACE_TYPE_HICN: - *face = (hc_face_t){ - .id = connection->id, - .face = - { - .type = FACE_TYPE_HICN, - .family = connection->family, - .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX - .local_addr = connection->local_addr, - .remote_addr = connection->remote_addr, - .admin_state = connection->admin_state, - .state = connection->state, -#ifdef WITH_POLICY - .priority = connection->priority, - .tags = connection->tags, -#endif /* WITH_POLICY */ - }, - }; - break; - default: - return -1; - } - face->face.netdevice.name[0] = '\0'; - face->face.netdevice.index = 0; - rc = snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[hc_connection_to_face] Unexpected truncation of symbolic name " - "string"); - rc = snprintf(face->face.netdevice.name, INTERFACE_LEN, "%s", - connection->interface_name); - if (rc >= INTERFACE_LEN) - WARN( - "[hc_connection_to_face] Unexpected truncation of interface name " - "string"); - netdevice_update_index(&face->face.netdevice); - return 0; -} - /* CONNECTION -> LISTENER */ -int hc_connection_to_local_listener(const hc_connection_t *connection, - hc_listener_t *listener) { - int rc; - - face_type_t listener_type; - switch (connection->type) { - case FACE_TYPE_UDP: - listener_type = FACE_TYPE_UDP_LISTENER; - break; - case FACE_TYPE_TCP: - listener_type = FACE_TYPE_TCP_LISTENER; - break; - default: - return -1; - } - - *listener = (hc_listener_t){ - .id = ~0, - .type = listener_type, - .family = connection->family, - .local_addr = connection->local_addr, - .local_port = connection->local_port, - }; - rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u", - RANDBYTE()); // generate name - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[hc_connection_to_local_listener] Unexpected truncation of " - "symbolic name string"); - rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", - connection->interface_name); - if (rc >= INTERFACE_LEN) - WARN( - "[hc_connection_to_local_listener] Unexpected truncation of " - "interface name string"); - - return 0; -} /*----------------------------------------------------------------------------* * Punting @@ -1013,7 +402,7 @@ int hc_punting_cmp(const hc_punting_t *p1, const hc_punting_t *p2) { rc = INT_CMP(p1->family, p2->family); if (rc != 0) return rc; - rc = ip_address_cmp(&p1->prefix, &p2->prefix, p1->family); + rc = ip_address_cmp(&p1->prefix, &p2->prefix); if (rc != 0) return rc; rc = INT_CMP(p1->prefix_len, p2->prefix_len); @@ -1022,10 +411,12 @@ int hc_punting_cmp(const hc_punting_t *p1, const hc_punting_t *p2) { return rc; } +#if 0 int hc_punting_parse(void *in, hc_punting_t *punting) { ERROR("hc_punting_parse not (yet) implemented."); return -1; } +#endif int hc_punting_snprintf(char *s, size_t size, hc_punting_t *punting) { ERROR("hc_punting_snprintf not (yet) implemented."); @@ -1083,36 +474,6 @@ int hc_stats_snprintf(char *s, size_t size, const hicn_light_stats_t *stats) { } /*----------------------------------------------------------------------------* - * Strategy - *----------------------------------------------------------------------------*/ - -int hc_strategy_list(hc_sock_t *s, hc_data_t **data) { - return s->hc_strategy_list(s, data); -} - -int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) { - return s->hc_strategy_set(s, strategy); -} - -int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy) { - return s->hc_strategy_add_local_prefix(s, strategy); -} - -hc_result_t *hc_strategy_set_conf(hc_sock_t *s, hc_strategy_t *strategy) { - return s->hc_strategy_set_conf(s, strategy); -} - -hc_result_t *hc_strategy_add_local_prefix_conf(hc_sock_t *s, - hc_strategy_t *strategy) { - return s->hc_strategy_add_local_prefix_conf(s, strategy); -} - -/* /!\ Please update constants in header file upon changes */ -int hc_strategy_snprintf(char *s, size_t size, hc_strategy_t *strategy) { - return snprintf(s, size, "%s", strategy->name); -} - -/*----------------------------------------------------------------------------* * WLDR *----------------------------------------------------------------------------*/ @@ -1146,67 +507,55 @@ int hc_mapme_send_update(hc_sock_t *s, hc_mapme_t *mapme) { * Policy *----------------------------------------------------------------------------*/ -#ifdef WITH_POLICY /* POLICY SNPRINTF */ /* /!\ Please update constants in header file upon changes */ int hc_policy_snprintf(char *s, size_t size, hc_policy_t *policy) { return 0; } -int hc_policy_validate(const hc_policy_t *policy) { +int hc_policy_validate(const hc_policy_t *policy, bool allow_partial) { if (!IS_VALID_FAMILY(policy->family)) return -1; return 0; } -#endif /* WITH_POLICY */ +#endif /*----------------------------------------------------------------------------* - * SUBSCRIPTION + * VFT *----------------------------------------------------------------------------*/ -int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription) { - return s->hc_subscription_create(s, subscription); -} - -int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription) { - return s->hc_subscription_delete(s, subscription); -} -hc_result_t *hc_subscription_create_conf(hc_sock_t *s, - hc_subscription_t *subscription) { - return s->hc_subscription_create_conf(s, subscription); -} - -hc_result_t *hc_subscription_delete_conf(hc_sock_t *s, - hc_subscription_t *subscription) { - return s->hc_subscription_delete_conf(s, subscription); -} - -/*----------------------------------------------------------------------------* - * STATISTICS - *----------------------------------------------------------------------------*/ -int hc_stats_get(hc_sock_t *s, hc_data_t **pdata) { - return s->hc_stats_get(s, pdata); +int hc_object_create(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object) { + return hc_execute(s, ACTION_CREATE, object_type, object, NULL); } -int hc_stats_list(hc_sock_t *s, hc_data_t **pdata) { - return s->hc_stats_list(s, pdata); +int hc_object_get(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object, hc_object_t **found) { + return hc_execute(s, ACTION_GET, object_type, object, NULL); } -/*----------------------------------------------------------------------------* - * Result - *----------------------------------------------------------------------------*/ - -hc_msg_t *hc_result_get_msg(hc_sock_t *s, hc_result_t *result) { - return s->hc_result_get_msg(result); +int hc_object_find(hc_sock_t *s, hc_object_type_t object_type, hc_data_t *data, + const hc_object_t *element, hc_object_t **found) { +// XXX NOT IMPLEMENTED +#if 0 + foreach_type(hc_object_t, x, data) { + if (hc_object_cmp(x, element) == 0) { + *found = x; + return 0; + } + }; +#endif + *found = NULL; /* this is optional */ + return 0; } -int hc_result_get_cmd_id(hc_sock_t *s, hc_result_t *result) { - return s->hc_result_get_cmd_id(result); +int hc_object_delete(hc_sock_t *s, hc_object_type_t object_type, + hc_object_t *object) { + return hc_execute(s, ACTION_DELETE, object_type, object, NULL); } -bool hc_result_get_success(hc_sock_t *s, hc_result_t *result) { - return s->hc_result_get_success(result); +int hc_object_list(hc_sock_t *s, hc_object_type_t object_type, + hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, object_type, NULL, pdata); } - -void hc_result_free(hc_result_t *result) { free(result); } diff --git a/ctrl/libhicnctrl/src/api_private.h b/ctrl/libhicnctrl/src/api_private.h index c708e1eb5..53be809da 100644 --- a/ctrl/libhicnctrl/src/api_private.h +++ b/ctrl/libhicnctrl/src/api_private.h @@ -20,30 +20,22 @@ #include <hicn/util/token.h> #include <hicn/util/log.h> #include <hicn/util/map.h> +#ifndef HICN_VPP_PLUGIN #include <hicn/util/sstrncpy.h> +#endif #include <hicn/validation.h> #include <ctype.h> -#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0) #define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array)) -#if 0 -#ifdef __APPLE__ -#define RANDBYTE() (u8)(arc4random() & 0xFF) -#else -#define RANDBYTE() (u8)(random() & 0xFF) -#endif -#endif -#define RANDBYTE() (u8)(rand() & 0xFF) - /* * Input validation */ -static inline bool IS_VALID_ADDRESS(const ip_address_t *addr, int family) { +static inline bool IS_VALID_ADDRESS(const hicn_ip_address_t *addr, int family) { char addr_str[INET6_ADDRSTRLEN]; - return !ip_address_empty(addr) && - ip_address_ntop(addr, addr_str, INET6_ADDRSTRLEN, family) >= 0; + return !hicn_ip_address_empty(addr) && + hicn_ip_address_ntop(addr, addr_str, INET6_ADDRSTRLEN, family) >= 0; } static inline bool IS_VALID_PREFIX_LEN(u8 len) { @@ -82,7 +74,6 @@ typedef struct hc_sock_impl_s hc_sock_impl_t; int hc_data_ensure_available(hc_data_t *data, size_t count); u8 *hc_data_get_next(hc_data_t *data); -int hc_data_set_error(hc_data_t *data); int hc_listener_to_face(const hc_listener_t *listener, hc_face_t *face); @@ -96,178 +87,4 @@ int hc_connection_to_local_listener(const hc_connection_t *connection, int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection, bool generate_name); -struct hc_sock_s { - int (*hc_sock_get_next_seq)(hc_sock_t *s); - int (*hc_sock_set_nonblocking)(hc_sock_t *s); - int (*hc_sock_get_fd)(hc_sock_t *s); - int (*hc_sock_connect)(hc_sock_t *s); - int (*hc_sock_get_available)(hc_sock_t *s, u8 **buffer, size_t *size); - int (*hc_sock_send)(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq); - int (*hc_sock_recv)(hc_sock_t *s); - int (*hc_sock_process)(hc_sock_t *s, hc_data_t **data); - int (*hc_sock_callback)(hc_sock_t *s, hc_data_t **data); - int (*hc_sock_reset)(hc_sock_t *s); - void (*hc_sock_free)(hc_sock_t *s); - void (*hc_sock_increment_woff)(hc_sock_t *s, size_t bytes); - int (*hc_sock_prepare_send)(hc_sock_t *s, hc_result_t *result, - data_callback_t complete_cb, - void *complete_cb_data); - int (*hc_sock_set_recv_timeout_ms)(hc_sock_t *s, long timeout_ms); - int (*hc_listener_create)(hc_sock_t *s, hc_listener_t *listener); - int (*hc_listener_create_async)(hc_sock_t *s, hc_listener_t *listener); - int (*hc_listener_get)(hc_sock_t *s, hc_listener_t *listener, - hc_listener_t **listener_found); - int (*hc_listener_delete)(hc_sock_t *s, hc_listener_t *listener); - int (*hc_listener_delete_async)(hc_sock_t *s, hc_listener_t *listener); - int (*hc_listener_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_listener_list_async)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_listener_validate)(const hc_listener_t *listener); - int (*hc_listener_cmp)(const hc_listener_t *l1, const hc_listener_t *l2); - int (*hc_listener_parse)(void *in, hc_listener_t *listener); - - int (*hc_connection_create)(hc_sock_t *s, hc_connection_t *connection); - int (*hc_connection_create_async)(hc_sock_t *s, hc_connection_t *connection); - int (*hc_connection_get)(hc_sock_t *s, hc_connection_t *connection, - hc_connection_t **connection_found); - int (*hc_connection_update_by_id)(hc_sock_t *s, int hc_connection_id, - hc_connection_t *connection); - int (*hc_connection_update)(hc_sock_t *s, hc_connection_t *connection_current, - hc_connection_t *connection_updated); - int (*hc_connection_delete)(hc_sock_t *s, hc_connection_t *connection); - int (*hc_connection_delete_async)(hc_sock_t *s, hc_connection_t *connection); - int (*hc_connection_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_connection_list_async)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_connection_validate)(const hc_connection_t *connection); - int (*hc_connection_cmp)(const hc_connection_t *c1, - const hc_connection_t *c2); - int (*hc_connection_parse)(void *in, hc_connection_t *connection); - int (*hc_connection_set_admin_state)(hc_sock_t *s, - const char *conn_id_or_name, - face_state_t state); - int (*hc_connection_set_admin_state_async)(hc_sock_t *s, - const char *conn_id_or_name, - face_state_t state); - -#ifdef WITH_POLICY - int (*hc_connection_set_priority)(hc_sock_t *s, const char *conn_id_or_name, - uint32_t priority); - int (*hc_connection_set_priority_async)(hc_sock_t *s, - const char *conn_id_or_name, - uint32_t priority); - int (*hc_connection_set_tags)(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags); - int (*hc_connection_set_tags_async)(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags); -#endif // WITH_POLICY - - int (*hc_connection_snprintf)(char *s, size_t size, - const hc_connection_t *connection); - - int (*hc_face_create)(hc_sock_t *s, hc_face_t *face); - int (*hc_face_get)(hc_sock_t *s, hc_face_t *face, hc_face_t **face_found); - int (*hc_face_delete)(hc_sock_t *s, hc_face_t *face, uint8_t delete_listener); - int (*hc_face_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_face_list_async)(hc_sock_t *s); - int (*hc_face_set_admin_state)(hc_sock_t *s, const char *conn_id_or_name, - face_state_t state); - int (*hc_face_set_admin_state_async)(hc_sock_t *s, - const char *conn_id_or_name, - face_state_t state); - -#ifdef WITH_POLICY - int (*hc_face_set_priority)(hc_sock_t *s, const char *conn_id_or_name, - uint32_t priority); - int (*hc_face_set_priority_async)(hc_sock_t *s, const char *conn_id_or_name, - uint32_t priority); - int (*hc_face_set_tags)(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags); - int (*hc_face_set_tags_async)(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags); -#endif // WITH_POLICY - - int (*hc_face_snprintf)(char *s, size_t size, hc_face_t *face); - - int (*hc_route_parse)(void *in, hc_route_t *route); - int (*hc_route_create)(hc_sock_t *s, hc_route_t *route); - int (*hc_route_create_async)(hc_sock_t *s, hc_route_t *route); - int (*hc_route_delete)(hc_sock_t *s, hc_route_t *route); - int (*hc_route_delete_async)(hc_sock_t *s, hc_route_t *route); - int (*hc_route_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_route_list_async)(hc_sock_t *s); - - int (*hc_punting_create)(hc_sock_t *s, hc_punting_t *punting); - int (*hc_punting_create_async)(hc_sock_t *s, hc_punting_t *punting); - int (*hc_punting_get)(hc_sock_t *s, hc_punting_t *punting, - hc_punting_t **punting_found); - int (*hc_punting_delete)(hc_sock_t *s, hc_punting_t *punting); - int (*hc_punting_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_punting_validate)(const hc_punting_t *punting); - int (*hc_punting_cmp)(const hc_punting_t *c1, const hc_punting_t *c2); - int (*hc_punting_parse)(void *in, hc_punting_t *punting); - - int (*hc_cache_parse)(void *in, hc_cache_info_t *cache_info); - int (*hc_cache_set_store)(hc_sock_t *s, hc_cache_t *cache); - int (*hc_cache_set_serve)(hc_sock_t *s, hc_cache_t *cache); - int (*hc_cache_clear)(hc_sock_t *s, hc_cache_t *cache); - int (*hc_cache_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_cache_set_store_async)(hc_sock_t *s, hc_cache_t *cache); - int (*hc_cache_set_serve_async)(hc_sock_t *s, hc_cache_t *cache); - int (*hc_cache_snprintf)(char *s, size_t size, - const hc_cache_info_t *cache_info); - - int (*hc_strategy_list)(hc_sock_t *s, hc_data_t **data); - int (*hc_strategy_snprintf)(char *s, size_t size, hc_strategy_t *strategy); - int (*hc_strategy_set)(hc_sock_t *s, hc_strategy_t *strategy); - int (*hc_strategy_add_local_prefix)(hc_sock_t *s, hc_strategy_t *strategy); - - int (*hc_wldr_set)(hc_sock_t *s /* XXX */); - - int (*hc_mapme_set)(hc_sock_t *s, int enabled); - int (*hc_mapme_set_discovery)(hc_sock_t *s, int enabled); - int (*hc_mapme_set_timescale)(hc_sock_t *s, uint32_t timescale); - int (*hc_mapme_set_retx)(hc_sock_t *s, uint32_t timescale); - int (*hc_mapme_send_update)(hc_sock_t *s, hc_mapme_t *mapme); - -#ifdef WITH_POLICY - int (*hc_policy_parse)(void *in, hc_policy_t *policy); - int (*hc_policy_create)(hc_sock_t *s, hc_policy_t *policy); - int (*hc_policy_create_async)(hc_sock_t *s, hc_policy_t *policy); - int (*hc_policy_delete)(hc_sock_t *s, hc_policy_t *policy); - int (*hc_policy_delete_async)(hc_sock_t *s, hc_policy_t *policy); - int (*hc_policy_list)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_policy_list_async)(hc_sock_t *s, hc_data_t **pdata); - int (*hc_policy_snprintf)(char *s, size_t size, hc_policy_t *policy); -#endif // WITH_POLICY - - int (*hc_subscription_create)(hc_sock_t *s, hc_subscription_t *subscription); - int (*hc_subscription_delete)(hc_sock_t *s, hc_subscription_t *subscription); - - int (*hc_stats_get)(hc_sock_t *s, hc_data_t **data); - int (*hc_stats_list)(hc_sock_t *s, hc_data_t **data); - - hc_result_t *(*hc_listener_create_conf)(hc_sock_t *s, - hc_listener_t *listener); - hc_result_t *(*hc_listener_list_conf)(hc_sock_t *s, hc_data_t **pdata); - hc_result_t *(*hc_connection_create_conf)(hc_sock_t *s, - hc_connection_t *connection); - hc_result_t *(*hc_connection_delete_conf)(hc_sock_t *s, - hc_connection_t *connection); - hc_result_t *(*hc_route_create_conf)(hc_sock_t *s, hc_route_t *route); - hc_result_t *(*hc_strategy_set_conf)(hc_sock_t *s, hc_strategy_t *strategy); - hc_result_t *(*hc_strategy_add_local_prefix_conf)(hc_sock_t *s, - hc_strategy_t *strategy); - hc_result_t *(*hc_subscription_create_conf)(hc_sock_t *s, - hc_subscription_t *subscription); - hc_result_t *(*hc_subscription_delete_conf)(hc_sock_t *s, - hc_subscription_t *subscription); - - hc_msg_t *(*hc_result_get_msg)(hc_result_t *result); - bool (*hc_result_get_success)(hc_result_t *result); - int (*hc_result_get_cmd_id)(hc_result_t *result); - void (*hc_result_free)(hc_result_t *result); - - // Reference to module containing the implementation - void *handle; -}; - #endif // HICN_API_PRIVATE_H diff --git a/ctrl/libhicnctrl/src/cli.h b/ctrl/libhicnctrl/src/cli.h new file mode 100644 index 000000000..b04448a6e --- /dev/null +++ b/ctrl/libhicnctrl/src/cli.h @@ -0,0 +1,4 @@ +#include <hicn/ctrl.h> + +typedef int (*command_function)(hc_sock_t *, hc_command_t *); +extern command_function command_vft[][ACTION_N]; diff --git a/hicn-light/src/hicn/config/command.c b/ctrl/libhicnctrl/src/command.c index bee0d2663..77b6eb7e8 100644 --- a/hicn-light/src/hicn/config/command.c +++ b/ctrl/libhicnctrl/src/command.c @@ -4,11 +4,17 @@ * @brief Implementation of commands. */ +#ifdef __linux__ +#define _GNU_SOURCE +#endif /* __linux__ */ #include <search.h> /* tfind, tdestroy, twalk */ #include <stdio.h> #include <ctype.h> -#include "command.h" -#include "parse.h" +#include <hicn/ctrl/command.h> + +#include <hicn/util/log.h> + +#include <hicn/ctrl/parse.h> /* Commands are registered in the following tree. */ static void *commands_root = NULL; /**< Tree ordered by name */ @@ -23,7 +29,8 @@ __attribute__((destructor)) static void command_clear() { static int _command_compare(const command_parser_t *c1, const command_parser_t *c2) { - if (c1->object != c2->object) return c2->object - c1->object; + if (c1->object_type != c2->object_type) + return c2->object_type - c1->object_type; if (c1->action != c2->action) return c2->action - c1->action; if (c1->nparams != c2->nparams) return c2->nparams - c1->nparams; return 0; @@ -37,12 +44,12 @@ void command_register(const command_parser_t *command) { } const command_parser_t *command_search(const hc_action_t action, - hc_object_type_t object, + hc_object_type_t object_type, unsigned nparams) { command_parser_t **command, search; search.action = action; - search.object = object; + search.object_type = object_type; search.nparams = nparams; command = tfind(&search, &commands_root, command_compare); @@ -54,11 +61,11 @@ static inline void to_lowercase(char *p) { } typedef struct { - hc_object_type_t object; + hc_object_type_t object_type; hc_action_t action; } cmd_search_params_t; -static hc_object_type_t prev_obj = OBJECT_UNDEFINED; +static hc_object_type_t prev_obj = OBJECT_TYPE_UNDEFINED; static hc_action_t prev_action = ACTION_UNDEFINED; static void traversal_action(const void *nodep, VISIT which, void *cmd_params0) { @@ -69,21 +76,21 @@ static void traversal_action(const void *nodep, VISIT which, command_parser_t *datap; datap = *(command_parser_t **)nodep; - char *obj_str = strdup(object_str(datap->object)); + char *obj_str = strdup(object_type_str(datap->object_type)); to_lowercase(obj_str); // List all objects - if (cmd_params->object == OBJECT_UNDEFINED && + if (cmd_params->object_type == OBJECT_TYPE_UNDEFINED && cmd_params->action == ACTION_UNDEFINED) { - if (datap->object == prev_obj) goto FREE_STR; - prev_obj = datap->object; + if (datap->object_type == prev_obj) goto FREE_STR; + prev_obj = datap->object_type; printf("\thelp %s\n", obj_str); goto FREE_STR; } // List actions for specific object - if (datap->object != cmd_params->object) goto FREE_STR; + if (datap->object_type != cmd_params->object_type) goto FREE_STR; if (cmd_params->action == ACTION_UNDEFINED) { if (datap->action == prev_action) goto FREE_STR; prev_action = datap->action; @@ -108,9 +115,10 @@ FREE_STR: free(obj_str); } -void command_list(hc_object_type_t object, hc_action_t action) { +void command_list(hc_object_type_t object_type, hc_action_t action) { #if defined(__linux__) && !defined(__ANDROID__) - cmd_search_params_t cmd_params = {.object = object, .action = action}; + cmd_search_params_t cmd_params = {.object_type = object_type, + .action = action}; twalk_r(commands_root, traversal_action, &cmd_params); #else fprintf(stderr, "twalk_r() function only available on linux"); diff --git a/hicn-light/src/hicn/config/command_cache.c b/ctrl/libhicnctrl/src/commands/command_cache.c index 073221cf0..124fcd761 100644 --- a/hicn-light/src/hicn/config/command_cache.c +++ b/ctrl/libhicnctrl/src/commands/command_cache.c @@ -1,5 +1,5 @@ #include <math.h> -#include "command.h" +#include <hicn/ctrl/command.h> /* Parameters */ @@ -25,7 +25,7 @@ static const command_parser_t command_cache_set_serve = { .action = ACTION_SERVE, - .object = OBJECT_CACHE, + .object_type = OBJECT_TYPE_CACHE, .nparams = 1, .parameters = {serve}, }; @@ -33,7 +33,7 @@ COMMAND_REGISTER(command_cache_set_serve); static const command_parser_t command_cache_set_store = { .action = ACTION_STORE, - .object = OBJECT_CACHE, + .object_type = OBJECT_TYPE_CACHE, .nparams = 1, .parameters = {store}, }; @@ -41,14 +41,14 @@ COMMAND_REGISTER(command_cache_set_store); static const command_parser_t command_cache_clear = { .action = ACTION_CLEAR, - .object = OBJECT_CACHE, + .object_type = OBJECT_TYPE_CACHE, .nparams = 0, }; COMMAND_REGISTER(command_cache_clear); static const command_parser_t command_cache_list = { .action = ACTION_LIST, - .object = OBJECT_CACHE, + .object_type = OBJECT_TYPE_CACHE, .nparams = 0, }; COMMAND_REGISTER(command_cache_list); diff --git a/hicn-light/src/hicn/config/command_connection.c b/ctrl/libhicnctrl/src/commands/command_connection.c index 069bf55a6..30b3c3bf1 100644 --- a/hicn-light/src/hicn/config/command_connection.c +++ b/ctrl/libhicnctrl/src/commands/command_connection.c @@ -1,5 +1,5 @@ #include <math.h> -#include "command.h" +#include <hicn/ctrl/command.h> /* Parameters */ @@ -32,7 +32,7 @@ #define local_port \ { \ .name = "local_port", .help = "Local port.", \ - .type = TYPE_INT(1, UINT16_MAX), \ + .type = TYPE_UINT16(1, UINT16_MAX), \ .offset = offsetof(hc_connection_t, local_port), \ } @@ -47,7 +47,7 @@ #define remote_port \ { \ .name = "remote_port", .help = "Remote port.", \ - .type = TYPE_INT(1, UINT16_MAX), \ + .type = TYPE_UINT16(1, UINT16_MAX), \ .offset = offsetof(hc_connection_t, remote_port), \ } @@ -74,7 +74,7 @@ int on_connection_create(hc_connection_t* connection) { #if 0 static command_parser_t command_connection_create4 = { .action = ACTION_CREATE, - .object = OBJECT_CONNECTION, + .object_type = OBJECT_TYPE_CONNECTION, .nparams = 4, .parameters = {type_hicn, symbolic, local_address, remote_address}, .post_hook = (parser_hook_t)on_connection_create, @@ -83,7 +83,7 @@ COMMAND_REGISTER(command_connection_create4); static const command_parser_t command_connection_create5 = { .action = ACTION_CREATE, - .object = OBJECT_CONNECTION, + .object = OBJECT_TYPE_CONNECTION, .nparams = 5, .parameters = {type_hicn, symbolic, local_address, remote_address, interface}, @@ -92,9 +92,28 @@ static const command_parser_t command_connection_create5 = { COMMAND_REGISTER(command_connection_create5); #endif +static const command_parser_t command_connection_create4 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 4, + .parameters = {type_tcp_udp, symbolic, remote_address, remote_port}, + .post_hook = (parser_hook_t)on_connection_create, +}; +COMMAND_REGISTER(command_connection_create4); + +static const command_parser_t command_connection_create5 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_CONNECTION, + .nparams = 5, + .parameters = {type_tcp_udp, symbolic, remote_address, remote_port, + interface}, + .post_hook = (parser_hook_t)on_connection_create, +}; +COMMAND_REGISTER(command_connection_create5); + static const command_parser_t command_connection_create6 = { .action = ACTION_CREATE, - .object = OBJECT_CONNECTION, + .object_type = OBJECT_TYPE_CONNECTION, .nparams = 6, .parameters = {type_tcp_udp, symbolic, remote_address, remote_port, local_address, local_port}, @@ -104,7 +123,7 @@ COMMAND_REGISTER(command_connection_create6); static const command_parser_t command_connection_create7 = { .action = ACTION_CREATE, - .object = OBJECT_CONNECTION, + .object_type = OBJECT_TYPE_CONNECTION, .nparams = 7, .parameters = {type_tcp_udp, symbolic, remote_address, remote_port, local_address, local_port, interface}, @@ -114,14 +133,14 @@ COMMAND_REGISTER(command_connection_create7); static const command_parser_t command_connection_list = { .action = ACTION_LIST, - .object = OBJECT_CONNECTION, + .object_type = OBJECT_TYPE_CONNECTION, .nparams = 0, }; COMMAND_REGISTER(command_connection_list); static const command_parser_t command_connection_remove = { .action = ACTION_DELETE, - .object = OBJECT_CONNECTION, + .object_type = OBJECT_TYPE_CONNECTION, .nparams = 1, .parameters = {symbolic_or_id}, }; diff --git a/ctrl/libhicnctrl/src/commands/command_face.c b/ctrl/libhicnctrl/src/commands/command_face.c new file mode 100644 index 000000000..68a6abefe --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_face.c @@ -0,0 +1,112 @@ +#include <hicn/ctrl/command.h> + +/* Parameters */ + +#define type_hicn \ + { \ + .name = "type", .help = "face type (hICN)", .type = TYPE_ENUM(face_type), \ + .offset = offsetof(hc_face_t, type), \ + } + +#define type_tcp_udp \ + { \ + .name = "type", .help = "face type [tcp | udp]", \ + .type = TYPE_ENUM(face_type), .offset = offsetof(hc_face_t, type), \ + } + +#define local_address \ + { \ + .name = "local_addr", .help = "local IP address on which to bind.", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_face_t, local_addr), \ + .offset2 = offsetof(hc_face_t, family), \ + } + +#define local_port \ + { \ + .name = "local_port", .help = "Local port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_face_t, local_port), \ + } + +#define remote_address \ + { \ + .name = "remote_address", \ + .help = "The IPv4 or IPv6 or hostname of the remote system.", \ + .type = TYPE_IP_ADDRESS, .offset = offsetof(hc_face_t, remote_addr), \ + .offset2 = offsetof(hc_face_t, family), \ + } + +#define remote_port \ + { \ + .name = "remote_port", .help = "Remote port.", \ + .type = TYPE_UINT16(1, UINT16_MAX), \ + .offset = offsetof(hc_face_t, remote_port), \ + } + +#define interface \ + { \ + .name = "interface", .help = "Interface on which to bind", \ + .type = TYPE_INTERFACE_NAME, \ + .offset = offsetof(hc_face_t, netdevice) + offsetof(netdevice_t, name), \ + } + +#define symbolic_or_id \ + { \ + .name = "symbolic", .help = "The face symbolic name or id", \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_face_t, name), \ + } + +/* Commands */ + +int on_face_create(hc_face_t* face) { + face->admin_state = FACE_STATE_UP; + return 0; +} + +static command_parser_t command_face_create3 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 3, + .parameters = {type_hicn, local_address, remote_address}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create3); + +#if 0 +static const command_parser_t command_face_create4 = { + .action = ACTION_CREATE, + .object = OBJECT_TYPE_FACE, + .nparams = 4, + .parameters = {type_hicn, local_address, remote_address, + interface}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create4); +#endif + +static const command_parser_t command_face_create5 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 5, + .parameters = {type_tcp_udp, remote_address, remote_port, local_address, + local_port}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create5); + +static const command_parser_t command_face_create6 = { + .action = ACTION_CREATE, + .object_type = OBJECT_TYPE_FACE, + .nparams = 6, + .parameters = {type_tcp_udp, remote_address, remote_port, local_address, + local_port, interface}, + .post_hook = (parser_hook_t)on_face_create, +}; +COMMAND_REGISTER(command_face_create6); + +static const command_parser_t command_face_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_FACE, + .nparams = 0, +}; +COMMAND_REGISTER(command_face_list); diff --git a/hicn-light/src/hicn/config/command_listener.c b/ctrl/libhicnctrl/src/commands/command_listener.c index 8ad7c94be..bba4f4541 100644 --- a/hicn-light/src/hicn/config/command_listener.c +++ b/ctrl/libhicnctrl/src/commands/command_listener.c @@ -1,5 +1,5 @@ #include <math.h> -#include "command.h" +#include <hicn/ctrl/command.h> /* Parameters */ @@ -37,7 +37,7 @@ #define local_port \ { \ .name = "local_port", .help = "Local port.", \ - .type = TYPE_INT(1, UINT16_MAX), \ + .type = TYPE_UINT16(1, UINT16_MAX), \ .offset = offsetof(hc_listener_t, local_port), \ } @@ -77,7 +77,7 @@ int on_listener_create(hc_listener_t* listener) { #if 0 static const command_parser_t command_listener_create4 = { .action = ACTION_CREATE, - .object = OBJECT_LISTENER, + .object = OBJECT_TYPE_LISTENER, .nparams = 4, .parameters = {protocol_hicn, symbolic, local_address, interface}, .post_hook = (parser_hook_t)on_listener_create, @@ -87,7 +87,7 @@ COMMAND_REGISTER(command_listener_create4); static const command_parser_t command_listener_create6 = { .action = ACTION_CREATE, - .object = OBJECT_LISTENER, + .object_type = OBJECT_TYPE_LISTENER, .nparams = 5, .parameters = {protocol_tcp_udp, symbolic, local_address, local_port, interface}, @@ -97,14 +97,14 @@ COMMAND_REGISTER(command_listener_create6); static const command_parser_t command_listener_list = { .action = ACTION_LIST, - .object = OBJECT_LISTENER, + .object_type = OBJECT_TYPE_LISTENER, .nparams = 0, }; COMMAND_REGISTER(command_listener_list); static const command_parser_t command_listener_remove = { .action = ACTION_DELETE, - .object = OBJECT_LISTENER, + .object_type = OBJECT_TYPE_LISTENER, .nparams = 1, .parameters = {symbolic_or_id}, }; diff --git a/hicn-light/src/hicn/config/command_mapme.c b/ctrl/libhicnctrl/src/commands/command_mapme.c index a22e8b340..c67b7704f 100644 --- a/hicn-light/src/hicn/config/command_mapme.c +++ b/ctrl/libhicnctrl/src/commands/command_mapme.c @@ -1,5 +1,5 @@ #include <math.h> -#include "command.h" +#include <hicn/ctrl/command.h> /* Parameters */ @@ -43,7 +43,7 @@ int parse_args(hc_mapme_t* mapme) { static const command_parser_t command_mapme_set = { .action = ACTION_SET, - .object = OBJECT_MAPME, + .object_type = OBJECT_TYPE_MAPME, .nparams = 2, .parameters = {target, value}, .post_hook = (parser_hook_t)parse_args, @@ -52,8 +52,8 @@ COMMAND_REGISTER(command_mapme_set); static const command_parser_t command_mapme_update = { .action = ACTION_UPDATE, - .object = OBJECT_MAPME, + .object_type = OBJECT_TYPE_MAPME, .nparams = 1, .parameters = {prefix}, }; -COMMAND_REGISTER(command_mapme_update);
\ No newline at end of file +COMMAND_REGISTER(command_mapme_update); diff --git a/hicn-light/src/hicn/config/command_policy.c b/ctrl/libhicnctrl/src/commands/command_policy.c index 1e802c3f5..2fc7a0a42 100644 --- a/hicn-light/src/hicn/config/command_policy.c +++ b/ctrl/libhicnctrl/src/commands/command_policy.c @@ -1,7 +1,7 @@ #if 0 #include <hicn/policy.h> -#include "command.h" +#include <hicn/ctrl/command.h> /* Parameters */ @@ -49,4 +49,4 @@ static const command_parser_t command_policy_list = { .nparams = 0, }; COMMAND_REGISTER(command_policy_list); -#endif
\ No newline at end of file +#endif diff --git a/hicn-light/src/hicn/config/command_punting.c b/ctrl/libhicnctrl/src/commands/command_punting.c index 8c7a6dec3..b845c52ee 100644 --- a/hicn-light/src/hicn/config/command_punting.c +++ b/ctrl/libhicnctrl/src/commands/command_punting.c @@ -1,5 +1,5 @@ #if 0 -#include "command.h" +#include <hicn/ctrl/command.h> /* Parameters */ @@ -37,4 +37,4 @@ static const command_parser_t command_punting_list = { .nparams = 0, }; COMMAND_REGISTER(command_punting_list); -#endif
\ No newline at end of file +#endif diff --git a/hicn-light/src/hicn/config/command_route.c b/ctrl/libhicnctrl/src/commands/command_route.c index dfbea101f..8e7db8192 100644 --- a/hicn-light/src/hicn/config/command_route.c +++ b/ctrl/libhicnctrl/src/commands/command_route.c @@ -1,5 +1,5 @@ #include <math.h> -#include "command.h" +#include <hicn/ctrl/command.h> /* Parameters */ @@ -9,7 +9,7 @@ .help = \ "The symbolic name for an egress, or the egress route id (see 'help " \ "list routes')", \ - .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_route_t, name), \ + .type = TYPE_SYMBOLIC_OR_ID, .offset = offsetof(hc_route_t, face_name), \ } #define prefix \ @@ -31,7 +31,7 @@ static const command_parser_t command_route_create = { .action = ACTION_CREATE, - .object = OBJECT_ROUTE, + .object_type = OBJECT_TYPE_ROUTE, .nparams = 3, .parameters = {symbolic_or_id, prefix, cost}, }; @@ -39,14 +39,14 @@ COMMAND_REGISTER(command_route_create); static const command_parser_t command_route_list = { .action = ACTION_LIST, - .object = OBJECT_ROUTE, + .object_type = OBJECT_TYPE_ROUTE, .nparams = 0, }; COMMAND_REGISTER(command_route_list); static const command_parser_t command_route_remove = { .action = ACTION_DELETE, - .object = OBJECT_ROUTE, + .object_type = OBJECT_TYPE_ROUTE, .nparams = 2, .parameters = {symbolic_or_id, prefix}, }; diff --git a/ctrl/libhicnctrl/src/commands/command_stats.c b/ctrl/libhicnctrl/src/commands/command_stats.c new file mode 100644 index 000000000..7c58b105e --- /dev/null +++ b/ctrl/libhicnctrl/src/commands/command_stats.c @@ -0,0 +1,18 @@ +#include <math.h> +#include <hicn/ctrl/command.h> + +/* Commands */ + +static const command_parser_t command_stats_get = { + .action = ACTION_GET, + .object_type = OBJECT_TYPE_STATS, + .nparams = 0, +}; +COMMAND_REGISTER(command_stats_get); + +static const command_parser_t command_stats_list = { + .action = ACTION_LIST, + .object_type = OBJECT_TYPE_STATS, + .nparams = 0, +}; +COMMAND_REGISTER(command_stats_list); diff --git a/hicn-light/src/hicn/config/command_strategy.c b/ctrl/libhicnctrl/src/commands/command_strategy.c index 2341ac830..5605822e7 100644 --- a/hicn-light/src/hicn/config/command_strategy.c +++ b/ctrl/libhicnctrl/src/commands/command_strategy.c @@ -1,4 +1,4 @@ -#include "command.h" +#include <hicn/ctrl/command.h> /* Parameters */ #define prefix \ @@ -32,7 +32,7 @@ static const command_parser_t command_strategy_list = { .action = ACTION_SET, - .object = OBJECT_STRATEGY, + .object_type = OBJECT_TYPE_STRATEGY, .nparams = 2, .parameters = {prefix, strategy}, }; @@ -40,7 +40,7 @@ COMMAND_REGISTER(command_strategy_list); static const command_parser_t local_prefix_add = { .action = ACTION_CREATE, - .object = OBJECT_LOCAL_PREFIX, + .object_type = OBJECT_TYPE_LOCAL_PREFIX, .nparams = 3, .parameters = {prefix, strategy, local_prefix}, }; diff --git a/hicn-light/src/hicn/config/command_subscription.c b/ctrl/libhicnctrl/src/commands/command_subscription.c index 89e3dcd98..886ee454a 100644 --- a/hicn-light/src/hicn/config/command_subscription.c +++ b/ctrl/libhicnctrl/src/commands/command_subscription.c @@ -1,4 +1,6 @@ -#include "command.h" +#include <limits.h> + +#include <hicn/ctrl/command.h> /* Parameters */ @@ -9,15 +11,16 @@ "Topics to subscribe to, e.g. 6 (110 in binary) means topic 2 (10 in " \ "binary, TOPIC_CONNECTION) and topic 4 (100 in binary, " \ "TOPIC_LISTENER).", \ - .type = TYPE_INT(1, 255), .offset = offsetof(hc_subscription_t, topics), \ + .type = TYPE_INT(1, INT_MAX), \ + .offset = offsetof(hc_subscription_t, topics), \ } /* Commands */ static const command_parser_t command_subscription_create = { .action = ACTION_CREATE, - .object = OBJECT_SUBSCRIPTION, + .object_type = OBJECT_TYPE_SUBSCRIPTION, .nparams = 1, .parameters = {topics}, }; -COMMAND_REGISTER(command_subscription_create);
\ No newline at end of file +COMMAND_REGISTER(command_subscription_create); diff --git a/ctrl/libhicnctrl/src/data.c b/ctrl/libhicnctrl/src/data.c new file mode 100644 index 000000000..605e23601 --- /dev/null +++ b/ctrl/libhicnctrl/src/data.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file data.c + * \brief Implementation of request result data. + */ + +#include <assert.h> +#include <stdlib.h> + +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> +#include <hicn/util/log.h> + +#define MIN_ALLOC_SIZE 8 +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + +struct hc_data_s { + hc_object_type_t object_type; + bool complete; + + /** + * >=0 success, indicates the number of records in array + * <0 error + */ + ssize_t size; + size_t alloc_size; /** Allocated size (a power of 2 when managed + automatically) */ + size_t max_size; /** Maximum size defined at creation (0 = unlimited) */ + + uint8_t *buffer; +}; + +void _hc_data_clear(hc_data_t *data) { + data->complete = false; + data->buffer = NULL; + data->max_size = 0; + data->alloc_size = 0; + data->size = 0; +} + +hc_data_t *hc_data_create(hc_object_type_t object_type) { + hc_data_t *data = malloc(sizeof(hc_data_t)); + if (!data) return NULL; + + data->object_type = object_type; + + _hc_data_clear(data); + + return data; + // data->buffer = malloc((1 << data->max_size_log) * data->out_element_size); + // if (!data->buffer) goto ERR_BUFFER; +} + +void hc_data_free(hc_data_t *data) { + assert(data); + + if (data->buffer) free(data->buffer); + free(data); +} + +int hc_data_set_max_size(hc_data_t *data, size_t max_size) { + if (data->size > max_size) return -1; + data->max_size = max_size; + return 0; +} + +const uint8_t *hc_data_get_buffer(hc_data_t *data) { return data->buffer; } + +const uint8_t *hc_data_get_free(hc_data_t *data) { + if (!data) return NULL; + if (data->max_size > 0 && data->size >= data->max_size) return NULL; + hc_object_type_t object_type = hc_data_get_object_type(data); + size_t object_size = hc_object_size(object_type); + return data->buffer + data->size * object_size; +} + +void hc_data_inc_size(hc_data_t *data) { data->size++; } + +hc_object_type_t hc_data_get_object_type(const hc_data_t *data) { + return data->object_type; +} + +void hc_data_set_object_type(hc_data_t *data, hc_object_type_t object_type) { + data->object_type = object_type; +} + +ssize_t hc_data_get_size(const hc_data_t *data) { return data->size; } + +int hc_data_clear(hc_data_t *data) { + free(data->buffer); + _hc_data_clear(data); + return 0; +} + +int _hc_data_allocate(hc_data_t *data, size_t size) { + data->buffer = + realloc(data->buffer, size * hc_object_size(data->object_type)); + if (!data->buffer) goto ERR; + data->alloc_size = size; + return 0; +ERR: + data->alloc_size = 0; + return -1; +} + +int hc_data_allocate(hc_data_t *data, size_t size) { + /* Do not allocate twice */ + if (data->buffer) return -1; + if (data->max_size > 0 && size > data->max_size) return -1; + return _hc_data_allocate(data, size); +} + +int hc_data_ensure_available(hc_data_t *data, size_t count) { + size_t new_size = data->size + count; + if (new_size < data->alloc_size) return 0; + if (data->max_size > 0 && new_size > data->max_size) return -1; + + size_t new_alloc_size = MAX(MIN_ALLOC_SIZE, next_pow2(new_size)); + if (data->max_size > 0 && new_alloc_size > data->max_size) + new_alloc_size = data->max_size; + + return _hc_data_allocate(data, new_alloc_size); +} + +int hc_data_push_many(hc_data_t *data, const void *elements, size_t count) { + if (!data) return -1; + if (!elements) return -1; + if (count < 1) return -1; + + if (hc_data_ensure_available(data, count) < 0) return -1; + + hc_object_type_t object_type = hc_data_get_object_type(data); + size_t object_size = hc_object_size(object_type); + + uint8_t *dst = data->buffer + data->size * object_size; + memcpy(dst, elements, count * object_size); + data->size += count; + + return 0; +} + +int hc_data_push(hc_data_t *data, const void *element) { + return hc_data_push_many(data, element, 1); +} +#if 0 +/** + * + * NOTE: This function make sure there is enough room available in the data + * structure. + */ +u8 *hc_data_get_next(hc_data_t *data) { + if (hc_data_ensure_available(data, 1) < 0) return NULL; + + return data->buffer + data->size * data->out_element_size; +} + +int hc_data_set_callback(hc_data_t *data, data_callback_t cb, void *cb_data) { + data->complete_cb = cb; + data->complete_cb_data = cb_data; + return 0; +} +#endif + +void hc_data_set_complete(hc_data_t *data) { data->complete = true; } + +bool hc_data_is_complete(const hc_data_t *data) { return data->complete; } + +void hc_data_set_error(hc_data_t *data) { + data->size = -1; + data->complete = true; +} + +bool hc_data_get_result(hc_data_t *data) { return (data->size >= 0); } + +hc_object_t *hc_data_find(hc_data_t *data, hc_object_t *object) { + hc_object_type_t object_type = hc_data_get_object_type(data); + hc_data_foreach(data, found, { + if (hc_object_cmp(object_type, object, found) == 0) return found; + }); + return NULL; +} + +const hc_object_t *hc_data_get_object(const hc_data_t *data, off_t pos) { + size_t size = hc_data_get_size(data); + if (pos >= size) return NULL; + + hc_object_type_t object_type = hc_data_get_object_type(data); + size_t object_size = hc_object_size(object_type); + + return (const hc_object_t *)(data->buffer + pos * object_size); +} + +#if 0 +int hc_data_reset(hc_data_t *data) { + data->size = 0; + return 0; +} +#endif diff --git a/ctrl/libhicnctrl/src/fw_interface.c b/ctrl/libhicnctrl/src/fw_interface.c new file mode 100644 index 000000000..6d5e5fb34 --- /dev/null +++ b/ctrl/libhicnctrl/src/fw_interface.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file fw_interface.c + * \brief Implementation of fw interface + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/callback.h> +#include <hicn/util/log.h> +#include <hicn/ctrl/fw_interface.h> + +const char *fw_state_str[] = { +#define _(x) [FW_STATE_##x] = #x, + foreach_fw_state +#undef _ +}; + +struct fw_interface_s { + /* + * Type of forwarder to which we are connecting/connected : HICNLIGHT, VPP + */ + forwarder_type_t type; + fw_state_t state; + + hc_sock_t *sock; + char *url; + + bool has_subscribe_all; + + hc_enable_callback_t enable_callback; + hc_state_callback_t state_callback; + void *state_callback_data; + hc_result_callback_t result_callback; + void *result_callback_data; + hc_notification_callback_t notification_callback; + void *notification_callback_data; +}; + +fw_interface_t *fw_interface_create_url(forwarder_type_t type, + const char *url) { + fw_interface_t *fi = malloc(sizeof(fw_interface_t)); + if (!fi) goto ERR_MALLOC; + + fi->type = type; + /* Let's assume for now the forwarder is always on */ + fi->state = FW_STATE_AVAILABLE; + fi->sock = NULL; + fi->has_subscribe_all = false; + fi->url = NULL; + + // XXX make a single request to probe for forwarder size? + + return fi; + +ERR_MALLOC: + return NULL; +} + +fw_interface_t *fw_interface_create(forwarder_type_t type) { + return fw_interface_create_url(type, NULL); +} + +void fw_interface_free(fw_interface_t *fi) { + fw_interface_disconnect(fi); + free(fi); +} + +int fw_interface_get_fd(const fw_interface_t *fi) { + if (!fi) return 0; + return hc_sock_get_fd(fi->sock); +} + +int fw_interface_set_enable_callback(fw_interface_t *fi, + hc_enable_callback_t callback) { + fi->enable_callback = callback; + return 0; +} + +int fw_interface_set_state_callback(fw_interface_t *fi, + hc_state_callback_t callback, + void *callback_data) { + fi->state_callback = callback; + fi->state_callback_data = callback_data; + return 0; +} + +int fw_interface_set_result_callback(fw_interface_t *fi, + hc_result_callback_t callback, + void *callback_data) { + fi->result_callback = callback; + fi->result_callback_data = callback_data; + return 0; +} + +int fw_interface_set_notification_callback(fw_interface_t *fi, + hc_notification_callback_t callback, + void *callback_data) { + fi->notification_callback = callback; + fi->notification_callback_data = callback_data; + return 0; +} + +int fw_interface_enable(fw_interface_t *fi) { + // TODO + return 0; +} + +int fw_interface_disable(fw_interface_t *fi) { + // TODO + return 0; +} + +// XXX blocking or non blocking ? +int fw_interface_reschedule_connect(fw_interface_t *fi) { + INFO("Scheduling reconnect..."); + // XXX TODO timer + return 0; +} + +int _fw_interface_connect(fw_interface_t *fi, bool reattempt) { + fi->sock = hc_sock_create(fi->type, fi->url); + if (!fi->sock) goto ERR_SOCK; + + if (hc_sock_set_async(fi->sock) < 0) goto ERR_ASYNC; + + if (hc_sock_connect(fi->sock) < 0) { + ERROR("Error connecting to forwarder"); + return -1; + } + + return 0; + +ERR_ASYNC: + hc_sock_free(fi->sock); +ERR_SOCK: + + if (reattempt) return fw_interface_reschedule_connect(fi); + return -1; +} + +int fw_interface_connect(fw_interface_t *fi) { + switch (fi->state) { + case FW_STATE_UNDEFINED: + // XXX connect, enable, (poll)? + break; + case FW_STATE_DISABLED: + fw_interface_enable(fi); + break; + case FW_STATE_REQUESTED: + // XXX waiting ? polling connect ? + break; + case FW_STATE_AVAILABLE: + _fw_interface_connect(fi, true); + // XXX + break; + case FW_STATE_CONNECTING: + case FW_STATE_CONNECTED: + case FW_STATE_READY: + /* Nothing to do */ + return 0; + case FW_STATE_N: + return -1; + } + return 0; +} + +int _fw_interface_disconnect(fw_interface_t *fi) { + if (fi->has_subscribe_all) fw_interface_unsubscribe_all(fi); + hc_sock_free(fi->sock); + return 0; +} + +int fw_interface_disconnect(fw_interface_t *fi) { + switch (fi->state) { + case FW_STATE_UNDEFINED: + case FW_STATE_DISABLED: + case FW_STATE_REQUESTED: + case FW_STATE_AVAILABLE: + /* Nothing to do */ + return 0; + case FW_STATE_CONNECTING: + case FW_STATE_CONNECTED: + case FW_STATE_READY: + _fw_interface_disconnect(fi); + return 0; + case FW_STATE_N: + return -1; + } + return 0; +} + +fw_state_t fw_interface_get_state(const fw_interface_t *fi) { + return fi->state; +} + +bool fw_interface_is_connected(const fw_interface_t *fi) { + return ((fi->state == FW_STATE_CONNECTED) || (fi->state == FW_STATE_READY)); +} + +bool fw_interface_is_ready(const fw_interface_t *fi) { + return (fi->state == FW_STATE_READY); +} + +int fw_interface_subscribe_all(fw_interface_t *fi) { + INFO("fw_interface_subscribe_all"); + int rc = hc_execute_async(fi->sock, ACTION_SUBSCRIBE, OBJECT_TYPE_UNDEFINED, + NULL, fi->notification_callback, + fi->notification_callback_data); + if (rc < 0) { + return -1; + } + fi->has_subscribe_all = true; + return 0; +} + +int fw_interface_unsubscribe_all(fw_interface_t *fi) { + fi->has_subscribe_all = false; + return 0; +} + +// face manager : upon completion, same as notification, CREATE/GET FACE +// hproxy = event = function to call to proceed through state machine (also +// depends if we handle face+route), for notifications, telemetry. +// NOTE we should have a notif for our own events. how to handle ? +// XXX user_data .... or user_callback +int fw_interface_execute(fw_interface_t *fi, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, + hc_data_t **pdata) { + return hc_execute(fi->sock, action, object_type, object, pdata); +} + +int fw_interface_execute_async(fw_interface_t *fi, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data) { + if (!callback) { + callback = fi->result_callback; + callback_data = fi->result_callback_data; + } + return hc_execute_async(fi->sock, action, object_type, object, callback, + callback_data); +} + +int fw_interface_on_receive(fw_interface_t *fi, size_t count) { + return hc_sock_on_receive(fi->sock, count); +} + +int fw_interface_get_recv_buffer(fw_interface_t *fi, uint8_t **buffer, + size_t *size) { + return hc_sock_get_recv_buffer(fi->sock, buffer, size); +} diff --git a/ctrl/libhicnctrl/src/hicnctrl.c b/ctrl/libhicnctrl/src/hicnctrl.c index 99d67b19f..c771bde69 100644 --- a/ctrl/libhicnctrl/src/hicnctrl.c +++ b/ctrl/libhicnctrl/src/hicnctrl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -24,20 +24,18 @@ #include <hicn/ctrl.h> #include <hicn/util/ip_address.h> +#include <hicn/util/log.h> #include <hicn/util/token.h> #include <hicn/validation.h> +#include <hicn/ctrl/parse.h> + #define die(LABEL, MESSAGE) \ do { \ printf(MESSAGE "\n"); \ - rc = -1; \ goto ERR_##LABEL; \ } while (0) -const char HICNLIGHT_PARAM[] = "hicnlight"; -const char HICNLIGHT_NG_PARAM[] = "hicnlightng"; -const char VPP_PARAM[] = "vpp"; - void usage_header() { fprintf(stderr, "Usage:\n"); } void usage_face_create(const char *prog, bool header, bool verbose) { @@ -201,69 +199,66 @@ void usage(const char *prog) { usage_connection(prog, false, true); } -#if 0 -typedef struct { - hc_action_t action; - hc_object_t object; - union { - hc_face_t face; - hc_route_t route; - hc_connection_t connection; - hc_listener_t listener; - }; -} hc_command_t; -#endif +/* + * We only allow settings commands and object types once, with the default + * action being set to CREATE + */ +#define set_command(ACTION, OBJECT_TYPE) \ + do { \ + if ((ACTION) != ACTION_UNDEFINED) { \ + if (command->action != ACTION_CREATE) goto USAGE; \ + command->action = (ACTION); \ + } \ + if ((OBJECT_TYPE) != OBJECT_TYPE_UNDEFINED) { \ + if (command->object_type != OBJECT_TYPE_UNDEFINED) goto USAGE; \ + command->object_type = (OBJECT_TYPE); \ + } \ + } while (0) int parse_options(int argc, char *argv[], hc_command_t *command, forwarder_type_t *forwarder) { - command->object.type = OBJECT_UNDEFINED; + command->object_type = OBJECT_TYPE_UNDEFINED; command->action = ACTION_CREATE; int opt; - int family; - while ((opt = getopt(argc, argv, "dflcrFLCRShz:")) != -1) { + while ((opt = getopt(argc, argv, "cCdfFlLrRsShz:")) != -1) { switch (opt) { case 'z': - if (strncmp(optarg, VPP_PARAM, strlen(VPP_PARAM)) == 0) { - *forwarder = VPP; - } else if (strncmp(optarg, HICNLIGHT_PARAM, strlen(HICNLIGHT_PARAM))) { - *forwarder = HICNLIGHT; - } else if (strncmp(optarg, HICNLIGHT_NG_PARAM, - strlen(HICNLIGHT_NG_PARAM))) { - *forwarder = HICNLIGHT_NG; - } else { - usage(argv[0]); - exit(EXIT_FAILURE); - } + *forwarder = forwarder_type_from_str(optarg); + if (*forwarder == FORWARDER_TYPE_UNDEFINED) goto USAGE; break; case 'd': - command->action = ACTION_DELETE; + set_command(ACTION_DELETE, OBJECT_TYPE_UNDEFINED); + break; + case 's': + set_command(ACTION_SUBSCRIBE, OBJECT_TYPE_UNDEFINED); break; case 'f': - command->object.type = OBJECT_FACE; + set_command(ACTION_UNDEFINED, OBJECT_TYPE_FACE); break; case 'c': - command->object.type = OBJECT_CONNECTION; + set_command(ACTION_UNDEFINED, OBJECT_TYPE_CONNECTION); + break; + case 'l': + set_command(ACTION_UNDEFINED, OBJECT_TYPE_LISTENER); + break; + case 'r': + set_command(ACTION_UNDEFINED, OBJECT_TYPE_ROUTE); break; case 'F': - command->action = ACTION_LIST; - command->object.type = OBJECT_FACE; + set_command(ACTION_LIST, OBJECT_TYPE_FACE); break; case 'L': - command->action = ACTION_LIST; - command->object.type = OBJECT_LISTENER; + set_command(ACTION_LIST, OBJECT_TYPE_LISTENER); break; case 'C': - command->action = ACTION_LIST; - command->object.type = OBJECT_CONNECTION; + set_command(ACTION_LIST, OBJECT_TYPE_CONNECTION); break; case 'R': - command->action = ACTION_LIST; - command->object.type = OBJECT_ROUTE; + set_command(ACTION_LIST, OBJECT_TYPE_ROUTE); break; case 'S': - command->action = ACTION_LIST; - command->object.type = OBJECT_STRATEGY; + set_command(ACTION_LIST, OBJECT_TYPE_STRATEGY); break; default: /* "h" */ usage(argv[0]); @@ -271,535 +266,129 @@ int parse_options(int argc, char *argv[], hc_command_t *command, } } - if (command->object.type == OBJECT_UNDEFINED) { - fprintf(stderr, - "Missing object specification: connection | listener | route\n"); - return -1; + // XXX The rest could be made a single parse function + + /* A default action is always defined, let's verify we have an object type, + * unless we are subscribing to notifications. In that case, we can monitor + * all objects. + * XXX handle later + */ + if ((command->object_type == OBJECT_TYPE_UNDEFINED) && + (command->action != ACTION_SUBSCRIBE)) { + ERROR("Missing object specification"); + goto USAGE; } - /* Parse and validate parameters for add/delete */ - switch (command->object.type) { - case OBJECT_FACE: - switch (command->action) { - case ACTION_CREATE: - if ((argc - optind != 5) && (argc - optind != 6)) { - usage_face_create(argv[0], true, false); - goto ERR_PARAM; - } - /* NAME will be autogenerated (and currently not used) */ - // snprintf(command->face.name, SYMBOLIC_NAME_LEN, "%s", - // argv[optind++]); - command->object.face.face.type = face_type_from_str(argv[optind++]); - if (command->object.face.face.type == FACE_TYPE_UNDEFINED) - goto ERR_PARAM; - command->object.face.face.family = - ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->object.face.face.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.face.face.local_addr) < 0) - goto ERR_PARAM; - command->object.face.face.local_port = atoi(argv[optind++]); - family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(family) || - (command->object.face.face.family != family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.face.face.remote_addr) < 0) - goto ERR_PARAM; - command->object.face.face.remote_port = atoi(argv[optind++]); - if (argc != optind) { - // netdevice_set_name(&command->object.face.face.netdevice, - // argv[optind++]); - command->object.face.face.netdevice.index = atoi(argv[optind++]); - } - - break; - case ACTION_DELETE: - if ((argc - optind != 1) && (argc - optind != 5) && - (argc - optind != 6)) { - usage_face_delete(argv[0], true, false); - goto ERR_PARAM; - } - - if (argc - optind == 1) { - /* Id or name */ - if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) { - command->object.face.id = atoi(argv[optind++]); - snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s", - argv[optind++]); - //} else if (is_symbolic_name(argv[optind])) { - // snprintf(command->object.face.name, SYMBOLIC_NAME_LEN, "%s", - // argv[optind++]); - } else { - fprintf(stderr, "Invalid argument\n"); - goto ERR_PARAM; - } - } else { - command->object.face.face.type = face_type_from_str(argv[optind++]); - if (command->object.face.face.type == FACE_TYPE_UNDEFINED) - goto ERR_PARAM; - command->object.face.face.family = - ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->object.face.face.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.face.face.local_addr) < 0) - goto ERR_PARAM; - command->object.face.face.local_port = atoi(argv[optind++]); - family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(family) || - (command->object.face.face.family != family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.face.face.remote_addr) < 0) - goto ERR_PARAM; - command->object.face.face.remote_port = atoi(argv[optind++]); - if (argc != optind) { - command->object.face.face.netdevice.index = atoi(argv[optind++]); - // netdevice_set_name(&command->object.face.face.netdevice, - // argv[optind++]); - } - } - break; - - case ACTION_LIST: - if (argc - optind != 0) { - usage_face_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - - default: - goto ERR_COMMAND; - } - break; - - case OBJECT_ROUTE: - switch (command->action) { - case ACTION_CREATE: - if ((argc - optind != 2) && (argc - optind != 3)) { - usage_route_create(argv[0], true, false); - goto ERR_PARAM; - } - - command->object.route.face_id = atoi(argv[optind++]); - - { - ip_prefix_t prefix; - ip_prefix_pton(argv[optind++], &prefix); - command->object.route.family = prefix.family; - command->object.route.remote_addr = prefix.address; - command->object.route.len = prefix.len; - } - - if (argc != optind) { - printf("parse cost\n"); - command->object.route.cost = atoi(argv[optind++]); - } - break; - - case ACTION_DELETE: - if (argc - optind != 2) { - usage_route_delete(argv[0], true, false); - goto ERR_PARAM; - } - - command->object.route.face_id = atoi(argv[optind++]); - - { - ip_prefix_t prefix; - ip_prefix_pton(argv[optind++], &prefix); - command->object.route.family = prefix.family; - command->object.route.remote_addr = prefix.address; - command->object.route.len = prefix.len; - } - break; - - case ACTION_LIST: - if (argc - optind != 0) { - usage_route_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - - default: - goto ERR_COMMAND; - } - break; - - case OBJECT_STRATEGY: - switch (command->action) { - case ACTION_LIST: - if (argc - optind != 0) { - usage_forwarding_strategy_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - default: - goto ERR_COMMAND; - } - break; - - case OBJECT_LISTENER: - switch (command->action) { - case ACTION_CREATE: - if ((argc - optind != 4) && (argc - optind != 5)) { - usage_listener_create(argv[0], true, false); - goto ERR_PARAM; - } - - snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s", - argv[optind++]); - command->object.listener.type = face_type_from_str(argv[optind++]); - if (command->object.listener.type == FACE_TYPE_UNDEFINED) - goto ERR_PARAM; - command->object.listener.family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->object.listener.family)) goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.listener.local_addr) < 0) - goto ERR_PARAM; - command->object.listener.local_port = atoi(argv[optind++]); - if (argc != optind) { - snprintf(command->object.listener.interface_name, INTERFACE_LEN, - "%s", argv[optind++]); - } - break; - - case ACTION_DELETE: - if ((argc - optind != 1) && (argc - optind != 3) && - (argc - optind != 4)) { - usage_listener_delete(argv[0], true, false); - goto ERR_PARAM; - } - - if (argc - optind == 1) { - /* Id or name */ - if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) { - command->object.listener.id = atoi(argv[optind++]); - snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s", - argv[optind++]); - } else if (is_symbolic_name(argv[optind], SYMBOLIC_NAME_LEN)) { - snprintf(command->object.listener.name, SYMBOLIC_NAME_LEN, "%s", - argv[optind++]); - } else { - fprintf(stderr, "Invalid argument\n"); - goto ERR_PARAM; - } - } else { - command->object.listener.type = face_type_from_str(argv[optind++]); - if (command->object.listener.type == FACE_TYPE_UNDEFINED) - goto ERR_PARAM; - command->object.listener.family = - ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->object.listener.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.listener.local_addr) < 0) - goto ERR_PARAM; - command->object.listener.local_port = atoi(argv[optind++]); - if (argc != optind) { - snprintf(command->object.listener.interface_name, INTERFACE_LEN, - "%s", argv[optind++]); - } - } - break; - - case ACTION_LIST: - if (argc - optind != 0) { - usage_listener_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - - default: - goto ERR_COMMAND; - } - break; - - case OBJECT_CONNECTION: - switch (command->action) { - case ACTION_CREATE: - /* NAME TYPE LOCAL_ADDRESS LOCAL_PORT REMOTE_ADDRESS REMOTE_PORT */ - if ((argc - optind != 6) && (argc - optind != 7)) { - usage_connection_create(argv[0], true, false); - goto ERR_PARAM; - } - snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s", - argv[optind++]); - command->object.connection.type = face_type_from_str(argv[optind++]); - if (command->object.connection.type == FACE_TYPE_UNDEFINED) - goto ERR_PARAM; - command->object.connection.family = - ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->object.connection.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.connection.local_addr) < 0) - goto ERR_PARAM; - command->object.connection.local_port = atoi(argv[optind++]); - family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(family) || - (command->object.connection.family != family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.connection.remote_addr) < 0) - goto ERR_PARAM; - command->object.connection.remote_port = atoi(argv[optind++]); - - break; - - case ACTION_DELETE: - if ((argc - optind != 1) && (argc - optind != 5) && - (argc - optind != 6)) { - usage_connection_delete(argv[0], true, false); - goto ERR_PARAM; - } - - if (argc - optind == 1) { - /* Id or name */ - if (is_number(argv[optind], SYMBOLIC_NAME_LEN)) { - command->object.connection.id = atoi(argv[optind++]); - snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s", - argv[optind++]); - } else if (is_symbolic_name(argv[optind], SYMBOLIC_NAME_LEN)) { - snprintf(command->object.connection.name, SYMBOLIC_NAME_LEN, "%s", - argv[optind++]); - } else { - fprintf(stderr, "Invalid argument\n"); - goto ERR_PARAM; - } - } else { - command->object.connection.type = - face_type_from_str(argv[optind++]); - if (command->object.connection.type == FACE_TYPE_UNDEFINED) - goto ERR_PARAM; - command->object.connection.family = - ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(command->object.connection.family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.connection.local_addr) < 0) - goto ERR_PARAM; - command->object.connection.local_port = atoi(argv[optind++]); - family = ip_address_get_family(argv[optind]); - if (!IS_VALID_FAMILY(family) || - (command->object.connection.family != family)) - goto ERR_PARAM; - if (ip_address_pton(argv[optind++], - &command->object.connection.remote_addr) < 0) - goto ERR_PARAM; - command->object.connection.remote_port = atoi(argv[optind++]); - } - break; - - case ACTION_LIST: - if (argc - optind != 0) { - usage_connection_list(argv[0], true, false); - goto ERR_PARAM; - } - break; - - default: - goto ERR_COMMAND; - } - break; + /* Check the adequation between the number of parameters and the command */ + size_t nparams = argc - optind; + if (nparams > 0) { + if (command->action == ACTION_LIST) command->action = ACTION_GET; + } else { + if ((command->action != ACTION_LIST) && + (command->action != ACTION_SUBSCRIBE)) + goto USAGE; + } - default: - goto ERR_COMMAND; + /* + * This checks is important even with 0 parameters as it checks whether the + * command exists. + */ + if (command->action != ACTION_SUBSCRIBE) { + const command_parser_t *parser = + command_search(command->action, command->object_type, nparams); + if (!parser) { + ERROR("Could not find parser for command '%s %s'", + action_str(command->action), object_type_str(command->object_type)); + return -1; + } + + if (nparams > 0) { + if (parse_getopt_args(parser, argc - optind, argv + optind, command) < + 0) { + ERROR("Error parsing command arguments"); + goto USAGE; + } + } } return 0; -ERR_PARAM: -ERR_COMMAND: - return -1; +USAGE: + usage(argv[0]); + exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { - hc_data_t *data; int rc = 1; hc_command_t command = {0}; - char buf_listener[MAXSZ_HC_LISTENER]; - char buf_connection[MAXSZ_HC_CONNECTION]; - char buf_route[MAXSZ_HC_ROUTE]; - char buf_strategy[MAXSZ_HC_STRATEGY]; + char buf[MAXSZ_HC_OBJECT]; - forwarder_type_t forwarder = HICNLIGHT; + forwarder_type_t forwarder = FORWARDER_TYPE_VPP; if (parse_options(argc, argv, &command, &forwarder) < 0) die(OPTIONS, "Bad arguments"); - hc_sock_t *s = hc_sock_create_forwarder(forwarder); + hc_sock_t *s = hc_sock_create(forwarder, /* url= */ NULL); if (!s) die(SOCKET, "Error creating socket."); if (hc_sock_connect(s) < 0) die(CONNECT, "Error connecting to the forwarder."); - switch (command.object.type) { - case OBJECT_FACE: - switch (command.action) { - case ACTION_CREATE: - if (hc_face_create(s, &command.object.face) < 0) - die(COMMAND, "Error creating face"); - printf("OK\n"); - break; - - case ACTION_DELETE: - if (hc_face_delete(s, &command.object.face, 1) < 0) - die(COMMAND, "Error creating face"); - printf("OK\n"); - break; - - case ACTION_LIST: - if (hc_face_list(s, &data) < 0) - die(COMMAND, "Error getting connections."); - - printf("Faces:\n"); - foreach_face(f, data) { - if (hc_face_snprintf(buf_connection, MAXSZ_HC_FACE, f) >= - MAXSZ_HC_FACE) - die(COMMAND, "Display error"); - printf("[%s] %s\n", f->name, buf_connection); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for connection"); - break; - } - break; - - case OBJECT_ROUTE: - switch (command.action) { - case ACTION_CREATE: - if (hc_route_create(s, &command.object.route) < 0) - die(COMMAND, "Error creating route"); - printf("OK\n"); - break; - - case ACTION_DELETE: - if (hc_route_delete(s, &command.object.route) < 0) - die(COMMAND, "Error creating route"); - printf("OK\n"); - break; - - case ACTION_LIST: - if (hc_route_list(s, &data) < 0) - die(COMMAND, "Error getting routes."); - - printf("Routes:\n"); - foreach_route(r, data) { - if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >= - MAXSZ_HC_ROUTE) - die(COMMAND, "Display error"); - printf("%s\n", buf_route); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for route"); - break; - } - break; - - case OBJECT_STRATEGY: - switch (command.action) { - case ACTION_LIST: - if (hc_strategy_list(s, &data) < 0) - die(COMMAND, "Error getting routes."); - - printf("Forwarding strategies:\n"); - foreach_strategy(st, data) { - if (hc_strategy_snprintf(buf_strategy, MAXSZ_HC_STRATEGY, st) >= - MAXSZ_HC_STRATEGY) - die(COMMAND, "Display error"); - printf("%s\n", buf_strategy); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for strategy"); - break; - } - break; - - case OBJECT_LISTENER: - switch (command.action) { - case ACTION_CREATE: - if (hc_listener_create(s, &command.object.listener) < 0) - die(COMMAND, "Error creating listener"); - printf("OK\n"); - break; - case ACTION_DELETE: - if (hc_listener_delete(s, &command.object.listener) < 0) - die(COMMAND, "Error deleting listener"); - printf("OK\n"); - break; - case ACTION_LIST: - if (hc_listener_list(s, &data) < 0) - die(COMMAND, "Error getting listeners."); - - printf("Listeners:\n"); - foreach_listener(l, data) { - if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER + 17, l) >= - MAXSZ_HC_LISTENER) - die(COMMAND, "Display error"); - printf("[%d] %s\n", l->id, buf_listener); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for listener"); - break; - } - break; - - case OBJECT_CONNECTION: - switch (command.action) { - case ACTION_CREATE: - if (hc_connection_create(s, &command.object.connection) < 0) - die(COMMAND, "Error creating connection"); - printf("OK\n"); - break; - case ACTION_DELETE: - if (hc_connection_delete(s, &command.object.connection) < 0) - die(COMMAND, "Error creating connection"); - printf("OK\n"); - break; - case ACTION_LIST: - if (hc_connection_list(s, &data) < 0) - die(COMMAND, "Error getting connections."); - - printf("Connections:\n"); - foreach_connection(c, data) { - if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, - c) >= MAXSZ_HC_CONNECTION) - die(COMMAND, "Display error"); - printf("[%s] %s\n", c->name, buf_connection); - } - - hc_data_free(data); - break; - default: - die(COMMAND, "Unsupported command for connection"); - break; - } - break; + hc_data_t *data = NULL; + + rc = hc_execute(s, command.action, command.object_type, &command.object, + &data); + + if (rc < 0) { + switch (rc) { + case INPUT_ERROR: + ERROR("Wrong input parameters"); + break; + case UNSUPPORTED_CMD_ERROR: + ERROR("Unsupported command"); + break; + default: + ERROR("Error executing command"); + break; + } + goto ERR_COMMAND; + } + + if (!data) goto ERR_QUERY; + + if (!hc_data_get_result(data)) goto ERR_DATA; - default: - die(COMMAND, "Unsupported object"); - break; + size_t size = hc_data_get_size(data); + if (size > 0) { + printf("Success: got %ld %s\n", size, object_type_str(command.object_type)); + } else { + printf("Success.\n"); } + if (command.action == ACTION_LIST) { + hc_data_foreach(data, obj, { + rc = hc_object_snprintf(buf, MAXSZ_HC_OBJECT, command.object_type, obj); + if (rc < 0) + WARN("Display error"); + else if (rc >= MAXSZ_HC_OBJECT) + WARN("Output truncated"); + else + printf("%s\n", buf); + }); + } + + hc_data_free(data); + hc_sock_free(s); + return EXIT_SUCCESS; + +ERR_DATA: + hc_data_free(data); +ERR_QUERY: ERR_COMMAND: ERR_CONNECT: hc_sock_free(s); ERR_SOCKET: ERR_OPTIONS: - return (rc < 0) ? EXIT_FAILURE : EXIT_SUCCESS; + printf("Error.\n"); + return EXIT_FAILURE; } diff --git a/ctrl/libhicnctrl/src/module.h b/ctrl/libhicnctrl/src/module.h new file mode 100644 index 000000000..44ba5ddbb --- /dev/null +++ b/ctrl/libhicnctrl/src/module.h @@ -0,0 +1,131 @@ +#ifndef HICNCTRL_MODULE_H +#define HICNCTRL_MODULE_H + +#include <stdint.h> + +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/socket.h> + +#include "request.h" + +/* + * execute is used for sync code (eg. in VPP), while serialize/parse for + * sync/async code (eg. in hicn-light). + */ +typedef int (*hc_execute_t)(hc_sock_t *, hc_object_t *, hc_data_t *); +typedef int (*hc_serialize_t)(const hc_object_t *, uint8_t *); + +typedef struct { + int (*parse)(const uint8_t *buffer, size_t size, hc_object_t *object); + size_t serialized_size; + hc_serialize_t serialize[ACTION_N]; + hc_execute_t execute[ACTION_N]; +} hc_module_object_ops_t; + +#define HC_MODULE_OBJECT_OPS_EMPTY \ + (hc_module_object_ops_t) { \ + .parse = NULL, .serialized_size = 0, \ + .execute = \ + { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + }, \ + .serialize = { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + }, \ + } + +#define DECLARE_MODULE_OBJECT_OPS_H(PREFIX, NAME) \ + extern const hc_module_object_ops_t PREFIX##_##NAME##_module_ops; + +/* Underscore'd functions take a hc_object_t as a parameter */ + +#define HC_MODULE_OBJECT_OPS(PREFIX, NAME) \ + (hc_module_object_ops_t) { \ + .parse = _##PREFIX##_##NAME##_parse, \ + .serialized_size = sizeof(cmd_##NAME##_list_item_t), \ + .execute = \ + { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + }, \ + .serialize = { \ + [ACTION_CREATE] = PREFIX##_##NAME##_serialize_create, \ + [ACTION_DELETE] = PREFIX##_##NAME##_serialize_delete, \ + [ACTION_LIST] = PREFIX##_##NAME##_serialize_list, \ + } \ + } + +#define DECLARE_MODULE_OBJECT_OPS(PREFIX, NAME) \ + const hc_module_object_ops_t PREFIX##_##NAME##_module_ops = { \ + .parse = _##PREFIX##_##NAME##_parse, \ + .serialized_size = sizeof(cmd_##NAME##_list_item_t), \ + .execute = \ + { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + }, \ + .serialize = { \ + [ACTION_CREATE] = PREFIX##_##NAME##_serialize_create, \ + [ACTION_DELETE] = PREFIX##_##NAME##_serialize_delete, \ + [ACTION_LIST] = PREFIX##_##NAME##_serialize_list, \ + }}; + +#define DECLARE_VPP_MODULE_OBJECT_OPS(PREFIX, NAME) \ + const hc_module_object_ops_t PREFIX##_##NAME##_module_ops = { \ + .execute = \ + { \ + [ACTION_CREATE] = PREFIX##_##NAME##_create, \ + [ACTION_DELETE] = PREFIX##_##NAME##_delete, \ + [ACTION_LIST] = PREFIX##_##NAME##_list, \ + }, \ + .serialize = \ + { \ + [ACTION_CREATE] = NULL, \ + [ACTION_DELETE] = NULL, \ + [ACTION_LIST] = NULL, \ + }, \ + }; + +typedef struct { + /** Create module-specific data storage */ + void *(*create_data)(const char *); + + /** Release module-specific data storage */ + void (*free_data)(void *); + + /** Retrieve underlying file descriptor */ + int (*get_fd)(hc_sock_t *); + + /** Retrieve underlying receive buffer */ + int (*get_recv_buffer)(hc_sock_t *, uint8_t **buffer, size_t *size); + + /** Connect control socket to the forwarder */ + int (*connect)(hc_sock_t *); + + /** Disconnect control socket from forwarder */ + int (*disconnect)(hc_sock_t *); + + /** Populate the TX buffer with the serialization of the next request to be + * sent */ + ssize_t (*prepare)(hc_sock_t *, hc_request_t *, uint8_t **buffer); + + /** Send the content of the TX buffer */ + int (*send)(hc_sock_t *, uint8_t *buffer, size_t size); + + /** Receive responses in the RX buffer */ + int (*recv)(hc_sock_t *); + + /** Process the content of the RX buffer to populate result data */ + int (*process)(hc_sock_t *, size_t count); + + hc_module_object_ops_t object_vft[OBJECT_TYPE_N]; +} hc_sock_ops_t; + +#endif /* HICNCTRL_MODULE_H */ diff --git a/ctrl/libhicnctrl/src/module_object.c b/ctrl/libhicnctrl/src/module_object.c new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ctrl/libhicnctrl/src/module_object.c @@ -0,0 +1 @@ + diff --git a/ctrl/libhicnctrl/src/module_object.h b/ctrl/libhicnctrl/src/module_object.h new file mode 100644 index 000000000..5081aa715 --- /dev/null +++ b/ctrl/libhicnctrl/src/module_object.h @@ -0,0 +1,10 @@ +#ifndef HICNCTRL_MODULES_OBJECT_H +#define HICNCTRL_MODULES_OBJECT_H + +ssize_t hc_object_serialize(hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, hc_msg_t *msg); + +int hc_object_parse(hc_object_type_t object_type, uint8_t *buffer, + hc_object_t *object); + +#endif /* HICNCTRL_MODULES_OBJECT_H */ diff --git a/ctrl/libhicnctrl/src/module_object_vft.h b/ctrl/libhicnctrl/src/module_object_vft.h new file mode 100644 index 000000000..2651b50a3 --- /dev/null +++ b/ctrl/libhicnctrl/src/module_object_vft.h @@ -0,0 +1,4 @@ +#ifndef HICNCTRL_MODULES_OBJECT_MODULE_VFT_H +#define HICNCTRL_MODULES_OBJECT_MODULE_VFT_H + +#endif /* HICNCTRL_MODULES_OBJECT_MODULE_VFT_H */ diff --git a/ctrl/libhicnctrl/src/modules/CMakeLists.txt b/ctrl/libhicnctrl/src/modules/CMakeLists.txt index 8f7916d14..682192c6c 100644 --- a/ctrl/libhicnctrl/src/modules/CMakeLists.txt +++ b/ctrl/libhicnctrl/src/modules/CMakeLists.txt @@ -14,13 +14,28 @@ ############################################################## # Hicn Light NG Module ############################################################## -list(APPEND HICNLIGHTNG_MODULE_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_common.c - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light_ng_api.c +list(APPEND HICNLIGHT_MODULE_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/connection.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/strategy.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/subscription.c ) -build_module(hicnlightngctrl_module - SOURCES ${HICNLIGHTNG_MODULE_SOURCE_FILES} +list(APPEND HICNLIGHT_MODULE_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/connection.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/face.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/listener.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/route.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/strategy.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/subscription.h + ) + +build_module(hicnlightctrl_module + SOURCES ${HICNLIGHT_MODULE_SOURCE_FILES} ${HICNLIGHT_MODULE_HEADER_FILES} DEPENDS ${DEPENDENCIES} COMPONENT ${LIBHICNCTRL_COMPONENT} LINK_LIBRARIES PRIVATE ${HICN_LIBRARIES} @@ -44,12 +59,37 @@ if(BUILD_HICNPLUGIN AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux") ) endif() + list(APPEND HICN_PLUGIN_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin_api.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_plugin/route.c + ) + + list(APPEND HICN_PLUGIN_HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/base.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/listener.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light/route.h + ) + + ############################################################## + # Compiler Options + ############################################################## + set(COMPILER_OPTIONS + ${DEFAULT_COMPILER_OPTIONS} + ${MARCH_COMPILER_OPTIONS} + PRIVATE "-Wno-address-of-packed-member" + ) + + ############################################################## + # Compiler Definitions + ############################################################## + list(APPEND COMPILER_DEFINITIONS + PRIVATE "-DHICN_VPP_PLUGIN=1" ) build_module(vppctrl_module - SOURCES ${HICN_PLUGIN_SOURCE_FILES} + SOURCES ${HICN_PLUGIN_SOURCE_FILES} ${HICN_PLUGIN_HEADER_FILES} DEPENDS ${DEPENDENCIES} LINK_LIBRARIES PRIVATE ${HICN_LIBRARIES} @@ -58,6 +98,6 @@ if(BUILD_HICNPLUGIN AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux") COMPONENT ${LIBHICNCTRL_COMPONENT_MODULES} INCLUDE_DIRS PRIVATE ${INCLUDE_DIRS} DEFINITIONS PRIVATE ${COMPILER_DEFINITIONS} - COMPILE_OPTIONS ${COMPILER_OPTIONS} ${MARCH_COMPILER_OPTIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) endif() diff --git a/ctrl/libhicnctrl/src/modules/hicn_light.c b/ctrl/libhicnctrl/src/modules/hicn_light.c new file mode 100644 index 000000000..1af6c79e2 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light.c @@ -0,0 +1,1255 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file modules/hicn_light.c + * \brief Implementation of hicn-light module. + */ + +#include <assert.h> // assert +#include <fcntl.h> // fcntl +#include <stdbool.h> +#include <stdio.h> // snprintf +#include <string.h> // memmove, strcasecmp +#include <sys/socket.h> // socket +#include <sys/types.h> // getpid +#include <unistd.h> // close, fcntl, getpid + +#ifdef __linux__ +#include <sys/syscall.h> +#define gettid() syscall(SYS_gettid) +#endif /* __linux__ */ + +#include <strings.h> + +#include <hicn/ctrl/hicn-light.h> +#include <hicn/ctrl/socket.h> + +#include "../api_private.h" +#include "../objects/connection.h" // hc_connection_has_local +#include "../objects/listener.h" // hc_listener_is_local +#include "../objects/route.h" // hc_route_has_face +#include "../request.h" +#include "../socket_private.h" +#include "hicn_light.h" + +#include "hicn_light/base.h" +#include "hicn_light/connection.h" +#include "hicn_light/listener.h" +#include "hicn_light/face.h" +#include "hicn_light/route.h" +#include "hicn_light/strategy.h" +#include "hicn_light/subscription.h" + +#pragma GCC diagnostic ignored "-Warray-bounds" + +#define DEFAULT_SOCK_RECV_TIMEOUT_MS 100 + +#define PORT 9695 + +#define BOOLSTR(x) ((x) ? "true" : "false") + +hc_sock_light_data_t *hc_sock_light_data_create(const char *url) { + hc_sock_light_data_t *s = malloc(sizeof(hc_sock_light_data_t)); + if (!s) goto ERR_MALLOC; + + s->roff = s->woff = 0; + s->remaining = 0; + s->got_header = false; + + s->url = url ? strdup(url) : NULL; + + s->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (s->fd < 0) goto ERR_SOCKET; + +#if 0 + struct timeval tv = {.tv_sec = 0, + .tv_usec = DEFAULT_SOCK_RECV_TIMEOUT_MS * 1000}; + if (setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + perror("setsockopt"); + goto ERR_TIMEOUT; + } +#endif + + return s; + +#if 0 +ERR_TIMEOUT: +#endif + close(s->fd); +ERR_SOCKET: + if (s->url) free(s->url); + free(s); +ERR_MALLOC: + return NULL; +} + +void hc_sock_light_data_free(hc_sock_light_data_t *data) { + if (data->url) free(data->url); + free(data); +} + +static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; + +/****************************************************************************** + * Control socket + ******************************************************************************/ + +#define AVAILABLE(s) ((s)->woff - (s)->roff) + +/** + * \brief Parse a connection URL into a sockaddr + * \param [in] url - URL + * \param [out] sa - Resulting struct sockaddr, expected zero'ed. + * \return 0 if parsing succeeded, a negative error value otherwise. + */ +static int hicnlight_parse_url(const char *url, struct sockaddr *sa) { + /* FIXME URL parsing is currently not implemented */ + _ASSERT(!url); + +#ifdef __linux__ + srand(time(NULL) ^ getpid() ^ gettid()); +#else + srand((unsigned int)(time(NULL) ^ getpid())); +#endif /* __linux__ */ + + /* + * A temporary solution is to inspect the sa_family fields of the passed in + * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP + * connection to localhost. + */ + switch (sa->sa_family) { + case AF_UNSPEC: + case AF_INET: { + struct sockaddr_in *sai = (struct sockaddr_in *)sa; + sai->sin_family = AF_INET; + sai->sin_port = htons(PORT); + sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + break; + } + case AF_INET6: { + struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *)sa; + sai6->sin6_family = AF_INET6; + sai6->sin6_port = htons(PORT); + sai6->sin6_addr = loopback_addr; + break; + } + default: + return -1; + } + + return 0; +} + +/* + * Return codes: + * < 0 : error; invalid buffer data -> flush + * otherwise, seq_num of the identified request + */ +static int hicnlight_process_header(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + hc_object_type_t object_type = OBJECT_TYPE_UNDEFINED; + + /* Check we have at least a header's worth of data, and consume it */ + if (AVAILABLE(s) < sizeof(hc_msg_header_t)) return 0; + + hc_msg_t *msg = (hc_msg_t *)(s->buf + s->roff); + + // INFO("Processing header header %s", command_type_str(msg->hdr.command_id)); + s->roff += sizeof(hc_msg_header_t); + s->got_header = true; + + /* How many elements are we expecting in the reply ? */ + s->remaining = msg->header.length; + + /* Identify request being parsed */ + int seq = msg->header.seq_num; + hc_request_t *request = NULL; + if (hc_sock_map_get(sock->map, seq, &request) < 0) { + ERROR("[hc_sock_light_process] Error searching for matching request"); + return -1; + } + if (!request) { + ERROR("[hc_sock_light_process] No request matching sequence number"); + return -1; + } + sock->current_request = request; + hc_request_t *current_request = hc_request_get_current(request); + hc_data_t *data = hc_request_get_data(current_request); + _ASSERT(data); + + switch (msg->header.message_type) { + case ACK_LIGHT: + _ASSERT(s->remaining == 0); + + s->got_header = false; + if (!hc_request_is_subscription(request)) hc_data_set_complete(data); + break; + + case NACK_LIGHT: + _ASSERT(s->remaining == 0); + + s->got_header = false; + hc_data_set_error(data); + break; + + case RESPONSE_LIGHT: + if (s->remaining == 0) { + /* Empty response (i.e. containing 0 elements) */ + s->got_header = false; + hc_data_set_complete(data); + return 0; + } + + /* Allocate buffer for response */ + if (hc_data_allocate(data, s->remaining) < 0) { + ERROR("[hc_sock_light_process] Cannot allocate result buffer"); + return -99; + } + break; + + case NOTIFICATION_LIGHT: { + _ASSERT(s->remaining == 1); + /* + * Assumption: the whole notification data is returned in a single read + * and we immediately parse it. + */ + // XXX assert enough buffer for object type + validate returned object + object_type = (hc_object_type_t)msg->header.command_id; + hc_data_clear(data); + hc_data_set_object_type(data, object_type); + if (hc_data_allocate(data, s->remaining) < 0) { + ERROR("[hc_sock_light_process] Cannot allocate result buffer"); + return -1; + } + + hc_data_push(data, s->buf + s->roff); + + s->roff += AVAILABLE(s); + + hc_request_on_notification(request); + + /* + * The buffer is cleared just before the next notification, which means + * it will have to be released upon exit. Otherwise we break the code + * dumping the notification synchronously (eg. hicnctrl -s). + */ + // hc_data_clear(data); + + s->got_header = false; + break; + } + + default: + ERROR("[hc_sock_light_process] Invalid response received"); + return -99; + } + + return 0; +} + +size_t hc_light_object_size(hc_object_type_t object_type); + +static int hicnlight_process_payload(hc_sock_t *sock) { + int err = 0; + int rc; + + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + hc_request_t *request = hc_sock_get_request(sock); + hc_request_t *current_request = hc_request_get_current(request); + hc_data_t *data = hc_request_get_data(current_request); + + hc_object_type_t object_type = hc_data_get_object_type(data); + size_t object_size = hc_light_object_size(object_type); + if (object_size == 0) return -1; + + /* We only process full elements (size is stored in data) */ + size_t num_chunks = AVAILABLE(s) / object_size; + + /* Check whether we have enough data to process */ + if (num_chunks == 0) return 0; + + /* Safeguard: _ASSERT(num_chunks < s->remaining); */ + if (num_chunks > s->remaining) { + WARN( + "[hicnlight_process_payload] Unexpected num_chunks > " + "s->remaining"); + num_chunks = s->remaining; + } + + for (size_t i = 0; i < num_chunks; i++) { + /* + * Get storage offset in hc_data_t, which we assume is correctly + * provisioned. + * XXX + */ + u8 *src = s->buf + s->roff; + hc_object_t *dst = (hc_object_t *)hc_data_get_free(data); + if (!dst) { + ERROR("[hc_sock_light_process] Error in hc_data_get_next"); + err = -2; + break; + } + + // XXX we might want to display even incomplete data when printing (eg. + // string truncation), and be very strict when processing. + rc = hc_sock_parse_object(sock, hc_data_get_object_type(data), src, + object_size, dst); + s->roff += object_size; + if (rc < 0) { + ERROR("Error parsing received object"); + continue; + } + hc_data_inc_size(data); + } + + /* + * If we are not expecting any more data, mark the reply as complete + */ + s->remaining -= num_chunks; + if (s->remaining == 0) { + s->got_header = false; + hc_data_set_complete(data); + } + + return err; +} + +/*---------------------------------------------------------------------------- + * Socket operations + *----------------------------------------------------------------------------*/ + +static int hicnlight_get_fd(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + return s->fd; +} + +static int hicnlight_get_recv_buffer(hc_sock_t *sock, uint8_t **buffer, + size_t *size) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + *buffer = s->buf + s->woff; + *size = RECV_BUFLEN - s->woff; + + return 0; +} + +static int hicnlight_connect(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + struct sockaddr_storage ss; + memset(&ss, 0, sizeof(struct sockaddr_storage)); + + if (hicnlight_parse_url(s->url, (struct sockaddr *)&ss) < 0) goto ERR_PARSE; + + size_t size = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) + : sizeof(struct sockaddr_in6); + if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) { + perror("connect error"); + goto ERR_CONNECT; + } + return 0; + +ERR_CONNECT: +ERR_PARSE: + return -1; +} + +static int hicnlight_disconnect(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + + /* Remove the connection created to send the command. + * + * Note this is done as a best effort and we don't expect to receive any + * answer from the forwarder (hence the NULL pdata pointer in the request). + */ + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.connection.id = 0; + int rc = + strcpy_s(object.connection.name, sizeof(object.connection.name), "SELF"); + if (rc == EOK) + hc_execute_async(sock, ACTION_DELETE, OBJECT_TYPE_CONNECTION, &object, NULL, + NULL); + + close(s->fd); + + return 0; +} + +static ssize_t hicnlight_prepare_generic(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + /* Dispatch to subrequest if any */ + hc_request_t *current_request = hc_request_get_current(request); + + _ASSERT(!hc_request_get_data(current_request)); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + + _ASSERT(hc_request_get_data(current_request) == NULL); + hc_data_t *data = hc_data_create(object_type); + if (!data) { + ERROR("[hicnlight_prepare_generic] Could not create data storage"); + return -1; + } + hc_request_set_data(current_request, data); + + /* Serialize request into message */ + DEBUG("Calling serialize on %s %s", action_str(action), + object_type_str(object_type)); + ssize_t msg_len = hc_sock_serialize_object(sock, action, object_type, object, + (uint8_t *)&s->msg); + if (msg_len < 0) { + ERROR("[hicnlight_prepare_generic] Could not serialize command %s %s", + action_str(action), object_type_str(object_type)); + return INPUT_ERROR; + } + + s->msg.header.seq_num = hc_request_get_seq(current_request); + + *buffer = (uint8_t *)&s->msg; + return msg_len; +} + +static int hicnlight_send(hc_sock_t *sock, uint8_t *buffer, size_t size) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + + int rc = (int)send(s->fd, buffer, size, 0); + if (rc < 0) { + perror("[hicnlight_send] Error sending message"); + return -1; + } + + // XXX regular behaviour for others + return 0; +} + +// Example : face create udp +// 1) face to connection (immediate) +// connection to local listener (immediate) : why not both at the same +// time listener get +// listener create / nothing +// connection create +// connection get (if needed for populating face_id for instance, aka +// if we +// need to return data) + +static ssize_t hicnlight_prepare(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer); + +static ssize_t hicnlight_prepare_subrequest( + hc_sock_t *sock, hc_request_t *request, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object, uint8_t **buffer) { + WITH_DEBUG({ + if (object) { + char buf[MAXSZ_HC_OBJECT]; + hc_object_snprintf(buf, sizeof(buf), object_type, object); + DEBUG("Creating subrequest %s/%s %s", action_str(action), + object_type_str(object_type), buf); + } + }); + hc_request_make_subrequest(request, action, object_type, object); + return hicnlight_prepare(sock, request, buffer); +} + +/* + * XXX shall we update the object in the request for faces ? it is not done + * for other objects, but for faces it is needed to further add a route !!! + */ +static ssize_t hicnlight_prepare_face_create(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + hc_object_t *object = hc_request_get_object(current_request); + hc_data_t *data = hc_request_get_data(current_request); + hc_face_t *face = &object->face; + + // XXX those objects are created on stack and expected to be valid across + // several calls. A quick fix is to make them static + static hc_object_t connection; + static hc_object_t listener; + + hc_request_state_t state; + const hc_connection_t *conn; + +NEXT: + state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_face_create > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + _ASSERT(!data); + + switch (face->type) { + case FACE_TYPE_HICN: + case FACE_TYPE_TCP: + case FACE_TYPE_UDP: + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_CONNECTION_CREATE); + goto NEXT; + case FACE_TYPE_HICN_LISTENER: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_UDP_LISTENER: + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_LISTENER_CREATE); + goto NEXT; + case FACE_TYPE_UNDEFINED: + case FACE_TYPE_N: + return -99; // Not implemented + } + + case REQUEST_STATE_FACE_CREATE_CONNECTION_CREATE: + if (hc_face_to_connection(face, &connection.connection, true) < 0) { + ERROR("[hc_face_create] Could not convert face to connection."); + return -1; + } + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_CONNECTION_CHECK); + + return hicnlight_prepare_subrequest(sock, request, ACTION_CREATE, + OBJECT_TYPE_CONNECTION, &connection, + buffer); + + case REQUEST_STATE_FACE_CREATE_CONNECTION_CHECK: + /* + * If the newly created face_id was not need, we would only + * need to return the same data result, which contains a ack/nack, + * simply updating the object type. + * + * With the current API, once the connection is created, our only + * solution is to list all connections and compare with the current one + * to find the created connection ID, and thus face ID. + */ + /* Has the connection been successfully created ? */ + if (!data || !hc_data_get_result(data)) return -1; + + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_CONNECTION_GET); + goto NEXT; + + case REQUEST_STATE_FACE_CREATE_CONNECTION_GET: + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_CONNECTION_VERIFY); + return hicnlight_prepare_subrequest(sock, request, ACTION_GET, + OBJECT_TYPE_CONNECTION, &connection, + buffer); + + case REQUEST_STATE_FACE_CREATE_CONNECTION_VERIFY: + if (!data || hc_data_get_size(data) != 1) return -1; + + /* Newly created connection was found */ + conn = (hc_connection_t *)hc_data_get_buffer(data); + DEBUG("created connection id=%d", conn->id); + object->face.id = conn->id; + + break; + + case REQUEST_STATE_FACE_CREATE_LISTENER_CREATE: + if (hc_face_to_listener(face, &listener.listener) < 0) { + ERROR("Could not convert face to listener."); + return -1; + } + + hc_request_set_state(current_request, + REQUEST_STATE_FACE_CREATE_LISTENER_CHECK); + return hicnlight_prepare_subrequest(sock, request, ACTION_CREATE, + OBJECT_TYPE_LISTENER, &listener, + buffer); + + break; + + case REQUEST_STATE_FACE_CREATE_LISTENER_CHECK: + /* + * No need for face id here, simply return the hc_data_t structure + * with the ack/nack, and the proper object type + */ + if (!data) return -1; + hc_data_set_object_type(data, OBJECT_TYPE_FACE); + break; + +#if 0 + case REQUEST_STATE_COMPLETE: + hc_data_set_complete(data); + break; +#endif + + default: + return -1; + } + return 0; +} + +static ssize_t hicnlight_prepare_face_list(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + hc_data_t *data = hc_request_get_data(current_request); + hc_face_t face; + + _ASSERT(action == ACTION_LIST); + _ASSERT(object_type == OBJECT_TYPE_FACE); + + hc_request_state_t state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_face_list > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + _ASSERT(!data); + + hc_request_set_state(current_request, + REQUEST_STATE_FACE_LIST_CONNECTION_LIST); + return hicnlight_prepare_subrequest( + sock, request, ACTION_LIST, OBJECT_TYPE_CONNECTION, object, buffer); + + case REQUEST_STATE_FACE_LIST_CONNECTION_LIST: + _ASSERT(data); + /* + * 'list connection' succeeded, we just need to allocate hc_data_t, + * create faces from connections, and return the data structure as if it + * was created by the query + */ + hc_data_t *face_data = hc_data_create(object_type); + hc_data_allocate(face_data, hc_data_get_size(data)); + foreach_connection(c, data) { + if (hc_face_from_connection(c, &face) < 0) { + ERROR("[hc_face_list] Could not convert connection to face."); + return -1; + } + hc_data_push(face_data, &face); + } + hc_data_set_complete(face_data); + + hc_request_reset_data(request); + hc_request_set_data(request, face_data); + + /* FACE/LIST could be part of FACE/GET */ + break; + + default: + return -1; + } + + return 0; +} + +static ssize_t hicnlight_prepare_get(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + hc_data_t *data = hc_request_get_data(current_request); + hc_object_t *found; + + hc_request_state_t state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_get > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + _ASSERT(!data); + hc_request_set_state(current_request, REQUEST_STATE_GET_LIST); + return hicnlight_prepare_subrequest(sock, request, ACTION_LIST, + object_type, NULL, buffer); + case REQUEST_STATE_GET_LIST: + _ASSERT(data); + + found = hc_data_find(data, object); + hc_data_t *found_data = hc_data_create(object_type); + if (found) { + hc_data_allocate(found_data, 1); + hc_data_push(found_data, found); + } + hc_data_set_complete(found_data); + hc_request_reset_data(current_request); + hc_request_set_data(current_request, found_data); + return 0; + default: + return -1; /* Unexpected */ + } +} + +// XXX This should process the content of pdata (unless at init), and +// terminate by sending something +static ssize_t hicnlight_prepare_face(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(request); + + _ASSERT(object_type == OBJECT_TYPE_FACE); + + switch (action) { + case ACTION_CREATE: + return hicnlight_prepare_face_create(sock, request, buffer); + case ACTION_LIST: + return hicnlight_prepare_face_list(sock, request, buffer); + default: + return -99; // Not implemented + } + return 0; +} + +static ssize_t hicnlight_prepare_connection_create(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + _ASSERT(action == ACTION_CREATE); + _ASSERT(object_type == OBJECT_TYPE_CONNECTION); + + hc_data_t *data = hc_request_get_data(current_request); + + size_t size; + unsigned pos; + static hc_object_t listener; + const hc_object_t *obj_listener; + hc_data_t *listener_data = NULL; + + hc_request_state_t state; + +NEXT: + state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_connection_create > %s", + hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + /* Two behaviours depending on the content of local_addr and local_port: + * - empty : create connection on all existing listeners, and raise an + * error if none + * - otherwise, check whether a corresponding listener exists, and + * create it if necessary + * + * We assume connection has been already validated. + */ + if (hc_connection_has_local(&object->connection)) { + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_GET); + } else { + /* + * At least part of the local socket specification is missing, match + * against existing listeners + */ + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_LIST); + } + goto NEXT; + + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_LIST: + + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_ITERATE); + // XXX We are currently assuming an object is present for rewrite, fix + // this + return hicnlight_prepare_subrequest(sock, request, ACTION_LIST, + OBJECT_TYPE_LISTENER, NULL, buffer); + + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_ITERATE: + /* + * NOTE: we could create all connections in parallel to speed up + * processing + */ + size = hc_data_get_size(data); + if (size < 0) return -1; + if (size == 0) + /* We are done, we cannot create a connection, return a Nack */ + ; // XXX TODO + // + /* Save the list of listeners for later iteration */ + listener_data = data; + hc_request_clear_data(current_request); // don't free data + data = NULL; + hc_request_set_state_count(current_request, 0); + hc_request_set_state(current_request, REQUEST_STATE_CONNECTION_CREATE_N); + goto NEXT; /* Start iteration */ + + case REQUEST_STATE_CONNECTION_CREATE_N: + /* + * IMPORTANT + * + * For now we only create a connection with the first non-local + * listener. + * + * Creating N connections in a single commands requires other + * changes to the code that we might done later: + * - ack/nack is not sufficient, all create function should return the + * list of created connections + * - this would allow us to avoid a GET at the end of face creation to + * retrieve the connection id. + * - face create should correspond to N connection create (should work + * out of the box provided we don't expect a single connection back). + * - route+face creation might then create N faces, and thus we would + * have to add N routes. + */ + assert(listener_data); + + // We need to back it up as the subrequest will clear the results + pos = hc_request_get_state_count(current_request); + size = hc_data_get_size(listener_data); + /* We have data if pos > 0, and we did not skipped previous ones */ + if (data && !hc_data_get_result(data)) { + INFO("Failed to create connection for listener %d / %d", pos - 1, size); + // XXX we might allow connections that already exist... how to manage + // the names + return -1; + } + + /* + * Previous connection was successfully created, let's continue but + * first check whether we reached the last one, which would complete the + * request. + */ + if (pos >= size) { + hc_data_free(listener_data); + hc_request_set_state(request, REQUEST_STATE_COMPLETE); + goto NEXT; + } + + /* Sending count'th connection creation */ + obj_listener = hc_data_get_object(listener_data, pos); + + // Filter which listener we use + // same protocol ? ip ? port ? + // avoid local ? + if (hc_listener_is_local(&obj_listener->listener)) { + /* Skip listener */ + DEBUG("Skipped local listener"); + hc_request_set_state_count(current_request, pos + 1); + goto NEXT; + } + + DEBUG("Creating connection with listener # %d / %d", pos, size); + /* We complement missing information from listener */ + // XXX is_family, etc. + object->connection.family = obj_listener->listener.family; + object->connection.local_addr = obj_listener->listener.local_addr; + object->connection.local_port = obj_listener->listener.local_port; + snprintf(object->connection.interface_name, INTERFACE_LEN, "%s", + obj_listener->listener.interface_name); + + hc_request_set_state_count(current_request, pos + 1); + return hicnlight_prepare_subrequest( + sock, request, ACTION_CREATE, OBJECT_TYPE_CONNECTION, object, buffer); + + /* Request listener to further check existence */ + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_GET: + /* Ensure we have a corresponding local listener */ + if (hc_connection_to_local_listener(&object->connection, + &listener.listener) < 0) { + ERROR( + "[hicnlight_prepare_connection_create] Could not convert face " + "to " + "local listener."); + return -1; + } + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_VERIFY); + return hicnlight_prepare_subrequest( + sock, request, ACTION_GET, OBJECT_TYPE_LISTENER, &listener, buffer); + + break; + + /* Check whether listener exists in GET results */ + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_VERIFY: + if (!data) return -1; + switch (hc_data_get_size(data)) { + case 0: + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_CREATE); + break; + case 1: + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE); + break; + default: + return -1; + } + goto NEXT; + + /* Create associated listener */ + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_CREATE: + hc_request_set_state(current_request, + REQUEST_STATE_CONNECTION_CREATE_LISTENER_CHECK); + return hicnlight_prepare_subrequest(sock, request, ACTION_CREATE, + OBJECT_TYPE_LISTENER, &listener, + buffer); + + /* Check whether listener creation succeeded */ + case REQUEST_STATE_CONNECTION_CREATE_LISTENER_CHECK: + if (!data || hc_data_get_result(data)) return -1; + hc_request_set_state(current_request, REQUEST_STATE_CONNECTION_CREATE); + goto NEXT; + + /* Create connection */ + case REQUEST_STATE_CONNECTION_CREATE: + /* + * Break recursion by directly calling hicnlight_prepare_generic on + * the initial request, that can now be executed since all + * prerequisites are validated. + */ + // return hicnlight_prepare_subrequest( + // sock, request, ACTION_CREATE, OBJECT_TYPE_CONNECTION, object, + // buffer); + hc_request_reset_data(current_request); + hc_request_set_state(current_request, REQUEST_STATE_COMPLETE); + return hicnlight_prepare_generic(sock, request, buffer); + + case REQUEST_STATE_COMPLETE: + if (data) { + hc_data_set_complete(data); + } else { + /* + * No connection has been created, and we freed the data due to + * subrequest + */ + data = hc_data_create(OBJECT_TYPE_CONNECTION); + hc_data_set_error(data); + } + break; + + default: + return -1; + } + return 0; +} + +static ssize_t hicnlight_prepare_route_create(hc_sock_t *sock, + hc_request_t *request, + uint8_t **buffer) { + hc_request_t *current_request = hc_request_get_current(request); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + _ASSERT(action == ACTION_CREATE); + _ASSERT(object_type == OBJECT_TYPE_ROUTE); + + hc_data_t *data = hc_request_get_data(current_request); + const hc_object_t *face_obj; + + hc_request_state_t state; + +NEXT: + state = hc_request_get_state(current_request); + DEBUG("hicnlight_prepare_route_create > %s", hc_request_state_str(state)); + + switch (state) { + case REQUEST_STATE_INIT: + if (hc_route_has_face(&object->route)) + hc_request_set_state(current_request, + REQUEST_STATE_ROUTE_CREATE_FACE_CREATE); + else + hc_request_set_state(current_request, REQUEST_STATE_ROUTE_CREATE); + goto NEXT; + + case REQUEST_STATE_ROUTE_CREATE_FACE_CREATE: + hc_request_set_state(current_request, + REQUEST_STATE_ROUTE_CREATE_FACE_CHECK); + INFO(">>>>>>subrequest create face"); + return hicnlight_prepare_subrequest( + sock, request, ACTION_CREATE, OBJECT_TYPE_FACE, + (hc_object_t *)&object->route.face, buffer); + + case REQUEST_STATE_ROUTE_CREATE_FACE_CHECK: + if (!data) return -1; + int rc = hc_data_get_result(data); + if (rc < 0) return -1; + + if (hc_data_get_size(data) != 1) return -1; + + face_obj = hc_data_get_object(data, 0); + DEBUG("Created face id=%d", face_obj->face.id); + object->route.face_id = face_obj->face.id; + + hc_request_set_state(current_request, REQUEST_STATE_ROUTE_CREATE); + goto NEXT; + + /* Create route */ + case REQUEST_STATE_ROUTE_CREATE: + /* + * Break recursion by directly calling hicnlight_prepare_generic on the + * initial request, that can now be executed since all prerequisites are + * validated. + */ + hc_request_set_state(current_request, REQUEST_STATE_COMPLETE); + return hicnlight_prepare_generic(sock, request, buffer); + + case REQUEST_STATE_COMPLETE: + hc_data_set_complete(data); + break; + + default: + return -1; + } + return 0; +} + +static int hicnlight_recv(hc_sock_t *sock) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + int rc; + + /* + * This condition should be ensured to guarantee correct processing of + * messages. With TCP, we need at least a header as we will receive part of + * the stream. With UDP, we need the be able to receive the full datagram, + * otherwise the rest will be lost. + * + * Let's be sure to always be able to receive at least 1 JUMBO_MTU, which + * should be fine for al situations. + */ + _ASSERT(RECV_BUFLEN - s->woff > JUMBO_MTU); + + rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0); + if (rc == 0) { + /* Connection has been closed */ + return 0; + } + if (rc < 0) { + /* + * Let's not return 0 which currently means the socket has been closed + */ + if (errno == EWOULDBLOCK) { + // XXX TODO ?if (hc_request_get_action(request) == ACTION_SUBSCRIBE) + // return 0; + return -1; + } + if (errno == EINTR) { + WARN("recv has been stopped by signal"); + return -1; + } + perror("hc_sock_light_recv"); + return -1; + } + DEBUG("Received rc=%ld bytes", rc); + s->woff += rc; + + return rc; +} + +/* + * + * @param [in] data - hc_data_t structure allocated for the request + * + * This function is the entry point for all requests, and from there we will + * decide whether + * + */ +static ssize_t hicnlight_prepare(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + /* Dispatch to subrequest if any */ + hc_request_t *current_request = hc_request_get_current(request); + + // XXX when do we create data... once for every step + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + static hc_object_t object_subscribe; + + DEBUG("[hicnlight_prepare] %s %s", action_str(action), + object_type_str(object_type)); + + /* + * Here the request is in progress and we just need to iterate through the + * FSM, or complete it. + */ + /* + * Specific treatment for + * CREATE/ROUTE with face + * SUBSCRIBE/(*) + * GET/(*) + * (*)/FACE + */ + + /* + * Special treatment for faces. + * + * This function will be called multiple times in order to process the + * complex request, involving several calls to the API. The process is + * responsible for going through the related state machine, and complete the + * request when appropriate. + */ + if (object_type == OBJECT_TYPE_FACE) + return hicnlight_prepare_face(sock, request, buffer); + + switch (action) { + case ACTION_CREATE: + switch (object_type) { + case OBJECT_TYPE_ROUTE: + /* Route might require face creation */ + return hicnlight_prepare_route_create(sock, request, buffer); + case OBJECT_TYPE_CONNECTION: + /* Connection could have no corresponging listener, or no local info + * provided */ + return hicnlight_prepare_connection_create(sock, request, buffer); + default: + break; + } + break; + + case ACTION_GET: + return hicnlight_prepare_get(sock, request, buffer); + + case ACTION_SUBSCRIBE: + /* Transform subscription queries */ + memset(&object_subscribe, 0, sizeof(hc_object_t)); + object->subscription.topics = topic_from_object_type(object_type); + + hc_request_set(request, ACTION_CREATE, OBJECT_TYPE_SUBSCRIPTION, object); + break; + + default: + break; + } + + /* + * Generic requests should complete after a single call to hicnlight_send, + * with *pdata = NULL. If *pdata is not NULL, that means the request has + * completed and we can close it. + * It is the responsability of each state machine to complete the request + * otherwise. + */ +#if 1 + hc_data_t *data = hc_request_get_data(current_request); + if (data) { + hc_request_set_complete(current_request); + return 0; + } +#endif + + return hicnlight_prepare_generic(sock, request, buffer); +} + +/* + * This function processes incoming data in the ring buffer. Multiple requests + * might be interleaves, including regular requests and notifications. + * Responses might arrive fragment over several read events, but our + * assumption is that fragments arrive consecutively and are not interleaves + * with fragments from other requests... otherwise we would have to way to + * reconstruct a message. + * + * count != 0 when an external process has added data to the ring buffer + * without updating indices + */ +static int hicnlight_process(hc_sock_t *sock, size_t count) { + hc_sock_light_data_t *s = (hc_sock_light_data_t *)sock->data; + int rc; + + if (count > 0) s->woff += count; + + /* + * We loop consuming messages until there is no more data in the ring + * buffer, or that we can find an entire message. Messages are received + * sequentially, and we keep track of incomplete requests in s->cur_request. + */ + while (AVAILABLE(s) > 0) { + if (!s->got_header) { + rc = hicnlight_process_header(sock); + } else { + rc = hicnlight_process_payload(sock); + } + if (rc < 0) break; + } + + if ((rc == -99) || (s->roff == s->woff)) { + /* Flush buffer */ + s->woff = 0; + } else { + /* Clean up read data from buffer */ + memmove(s->buf, s->buf + s->roff, AVAILABLE(s)); + s->woff -= s->roff; + } + s->roff = 0; + + return rc; +} + +hc_sock_ops_t hc_sock_light = (hc_sock_ops_t) { + .create_data = (void *(*)(const char *))hc_sock_light_data_create, + .free_data = (void (*)(void *))hc_sock_light_data_free, + .get_fd = hicnlight_get_fd, .get_recv_buffer = hicnlight_get_recv_buffer, + .connect = hicnlight_connect, .disconnect = hicnlight_disconnect, + .prepare = hicnlight_prepare, .send = hicnlight_send, .recv = hicnlight_recv, + .process = hicnlight_process, +#if 0 + .object_vft = { + [OBJECT_TYPE_LISTENER] = HC_MODULE_OBJECT_OPS(hicnlight, listener), + [OBJECT_TYPE_CONNECTION] = HC_MODULE_OBJECT_OPS(hicnlight, connection), + [OBJECT_TYPE_FACE] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_PUNTING] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_CACHE] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_MAPME] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_WLDR] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_POLICY] = HC_MODULE_OBJECT_OPS_EMPTY, + [OBJECT_TYPE_ROUTE] = HC_MODULE_OBJECT_OPS(hicnlight, route), + [OBJECT_TYPE_STRATEGY] = HC_MODULE_OBJECT_OPS(hicnlight, strategy), + [OBJECT_TYPE_SUBSCRIPTION] = HC_MODULE_OBJECT_OPS(hicnlight, subscription), +} +#endif +}; + +size_t hc_light_object_size(hc_object_type_t object_type) { + hc_module_object_ops_t *vft = &hc_sock_light.object_vft[object_type]; + if (!vft) return 0; + return vft->serialized_size; +} + +ssize_t hc_light_command_serialize(hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg) { + hc_module_object_ops_t *vft = &hc_sock_light.object_vft[object_type]; + if (!vft || !vft->serialize[action]) return 0; + return vft->serialize[action](object, msg); +} + +// Public constructor + +int hc_sock_initialize_module(hc_sock_t *s) { + // + /* + * We do this because initialization in the static struct fails with + * 'initializer element is not constant' + */ +#if 1 + hc_sock_light.object_vft[OBJECT_TYPE_LISTENER] = + hicnlight_listener_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_CONNECTION] = + hicnlight_connection_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_FACE] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_PUNTING] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_CACHE] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_MAPME] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_WLDR] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_POLICY] = HC_MODULE_OBJECT_OPS_EMPTY; + hc_sock_light.object_vft[OBJECT_TYPE_ROUTE] = hicnlight_route_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_STRATEGY] = + hicnlight_strategy_module_ops; + hc_sock_light.object_vft[OBJECT_TYPE_SUBSCRIPTION] = + hicnlight_subscription_module_ops; +#endif + + if (s) s->ops = hc_sock_light; + return 0; +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light.h b/ctrl/libhicnctrl/src/modules/hicn_light.h new file mode 100644 index 000000000..0bdcf0b30 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file modules/hicn_light.h + * \brief hicn-light module. + */ + +#ifndef HICNCTRL_MODULES_HICN_LIGHT_H +#define HICNCTRL_MODULES_HICN_LIGHT_H + +#include "hicn_light/base.h" + +typedef struct { + char *url; + int fd; + + /* Send buffer */ + hc_msg_t msg; + + /* Partial receive buffer */ + u8 buf[RECV_BUFLEN]; + size_t roff; /**< Read offset */ + size_t woff; /**< Write offset */ + + bool got_header; + /* + * Because received messages are potentially unbounded in size, we might not + * guarantee that we can store a full packet before processing it. We must + * implement a very simple state machine remembering the current parsing + * status in order to partially process the packet. + */ + size_t remaining; + u32 send_id; + + /* Next sequence number to be used for requests */ + int seq; +} hc_sock_light_data_t; + +extern hc_sock_light_data_t *hc_sock_light_data_create(const char *url); +extern void hc_sock_light_data_free(hc_sock_light_data_t *data); + +ssize_t hc_light_command_serialize(hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg); + +#endif /* HICNCTRL_MODULES_HICN_LIGHT_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/base.h b/ctrl/libhicnctrl/src/modules/hicn_light/base.h new file mode 100644 index 000000000..fb6a68147 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/base.h @@ -0,0 +1,60 @@ +#ifndef HICNCTRL_MODULES_HICNLIGHT_BASE_H +#define HICNCTRL_MODULES_HICNLIGHT_BASE_H + +#include <hicn/ctrl/hicn-light.h> + +#if 1 +#ifdef __APPLE__ +#define RANDBYTE() (u8)(arc4random() & 0xFF) +#else +#define RANDBYTE() (u8)(random() & 0xFF) +#endif +#else +#define RANDBYTE() (u8)(rand() & 0xFF) +#endif + +#define foreach_hc_command \ + _(connection_add) \ + _(connection_remove) \ + _(connection_list) \ + _(listener_add) \ + _(listener_remove) \ + _(listener_list) \ + _(route_add) \ + _(route_remove) \ + _(route_list) \ + _(cache_set_store) \ + _(cache_set_serve) \ + _(cache_clear) \ + _(cache_list) \ + _(strategy_set) \ + _(strategy_add_local_prefix) \ + _(wldr_set) \ + _(punting_add) \ + _(mapme_activator) \ + _(mapme_timing) \ + _(subscription_add) \ + _(subscription_remove) + +#if 0 +const char *command_type_str[] = { +#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u), + foreach_command_type +#undef _ +}; +#endif + +typedef union { +#define _(x) cmd_##x##_t x; + foreach_hc_command +#undef _ +} hc_msg_payload_t; + +typedef cmd_header_t hc_msg_header_t; + +typedef struct hc_msg_s { + hc_msg_header_t header; + hc_msg_payload_t payload; +} hc_msg_t; + +#endif /* HICNCTRL_MODULES_HICNLIGHT_BASE_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/cache.c b/ctrl/libhicnctrl/src/modules/hicn_light/cache.c new file mode 100644 index 000000000..e085142d7 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/cache.c @@ -0,0 +1,178 @@ +#include "cache.h" + +/* CACHE SET STORE */ + +static int _hcng_cache_set_store_internal(hc_sock_t *socket, hc_cache_t *cache, + bool async) { +#if 0 + msg_cache_set_store_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CACHE_SET_STORE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .activate = cache->store, + }}; + + hc_command_params_t params = { + .cmd = ACTION_STORE, + .cmd_id = COMMAND_TYPE_CACHE_SET_STORE, + .size_in = sizeof(cmd_cache_set_store_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_cache_set_store(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_set_store_internal(s, cache, false); +} + +static int _hcng_cache_set_store_async(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_set_store_internal(s, cache, true); +} + +/* CACHE SET SERVE */ + +static int _hcng_cache_set_serve_internal(hc_sock_t *socket, hc_cache_t *cache, + bool async) { +#if 0 + msg_cache_set_serve_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CACHE_SET_SERVE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .activate = cache->serve, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SERVE, + .cmd_id = COMMAND_TYPE_CACHE_SET_SERVE, + .size_in = sizeof(cmd_cache_set_serve_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; /// added +} + +static int _hcng_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_set_serve_internal(s, cache, false); +} + +static int _hcng_cache_set_serve_async(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_set_serve_internal(s, cache, true); +} + +/* CACHE CLEAR */ + +static int _hcng_cache_clear_internal(hc_sock_t *socket, hc_cache_t *cache, + bool async) { +#if 0 + msg_cache_clear_t msg = {.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CACHE_CLEAR, + .length = 1, + .seq_num = 0, + }}; + + hc_command_params_t params = { + .cmd = ACTION_CLEAR, + .cmd_id = COMMAND_TYPE_CACHE_CLEAR, + .size_in = sizeof(cmd_cache_clear_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_cache_clear(hc_sock_t *s, hc_cache_t *cache) { + return _hcng_cache_clear_internal(s, cache, false); +} + +/* CACHE PARSE */ + +static int hc_cache_parse(void *in, hc_cache_info_t *cache_info) { + cmd_cache_list_reply_t *item = (cmd_cache_list_reply_t *)in; + *cache_info = (hc_cache_info_t){.store = item->store_in_cs, + .serve = item->serve_from_cs, + .cs_size = item->cs_size, + .num_stale_entries = item->num_stale_entries}; + + return 0; +} + +/* CACHE LIST */ + +static hc_result_t *_hcng_cache_list_serialize(hc_sock_t *socket, + hc_data_t **pdata, bool async) { + hc_result_t *res = malloc(sizeof(*res)); + DEBUG("[hc_cache_list] async=%s", BOOLSTR(async)); + + msg_cache_list_t msg = {.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CACHE_LIST, + .length = 0, + .seq_num = 0, + }}; + + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = COMMAND_TYPE_CACHE_LIST, + .size_in = sizeof(cmd_cache_list_reply_t), + .size_out = sizeof(hc_cache_info_t), + .parse = (HC_PARSE)hc_cache_parse, + }; + + *res = (hc_result_t){ + .msg = + (hc_msg_t){ + .header = msg.header, + .payload.cache_list = msg.payload, + }, + .params = params, + .async = async, + .success = true, + }; + return res; +} + +static int _hcng_cache_list_internal(hc_sock_t *socket, hc_data_t **pdata, + bool async) { +#if 0 + hc_result_t *result = _hcng_cache_list_serialize(socket, pdata, async); + + int ret = INPUT_ERROR; + if (result->success) { + ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, + sizeof(result->msg), &result->params, pdata, + result->async); + } + + hc_result_free(result); + return ret; +#endif + return 0; // XXX added +} + +static int _hcng_cache_list(hc_sock_t *s, hc_data_t **pdata) { + return _hcng_cache_list_internal(s, pdata, false); +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/connection.c b/ctrl/libhicnctrl/src/modules/hicn_light/connection.c new file mode 100644 index 000000000..c7d06415e --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/connection.c @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <assert.h> +#include <stdint.h> + +#include <hicn/util/log.h> + +#include "base.h" +#include "connection.h" +#include "../../object_private.h" + +int hc_connection_to_local_listener(const hc_connection_t *connection, + hc_listener_t *listener) { + int rc; + + face_type_t listener_type; + switch (connection->type) { + case FACE_TYPE_UDP: + listener_type = FACE_TYPE_UDP_LISTENER; + break; + case FACE_TYPE_TCP: + listener_type = FACE_TYPE_TCP_LISTENER; + break; + default: + return -1; + } + + *listener = (hc_listener_t){ + .id = ~0, + .type = listener_type, + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + }; + rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "lst%u", + RANDBYTE()); // generate name + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_connection_to_local_listener] Unexpected truncation of " + "symbolic name string"); + rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", + connection->interface_name); + if (rc >= INTERFACE_LEN) + WARN( + "[hc_connection_to_local_listener] Unexpected truncation of " + "interface name string"); + + return 0; +} + +/* CONNECTION PARSE */ + +static int hicnlight_connection_parse(const uint8_t *buffer, size_t size, + hc_connection_t *connection) { + int rc; + + if (size != sizeof(cmd_connection_list_item_t)) return -1; + cmd_connection_list_item_t *item = (cmd_connection_list_item_t *)buffer; + + if (!IS_VALID_ID(item->id)) { + ERROR("[hc_connection_parse] Invalid id received"); + return -1; + } + + if (!IS_VALID_NAME(item->name)) { + ERROR("[hc_connection_parse] Invalid name received"); + return -1; + } + if (!IS_VALID_INTERFACE_NAME(item->interface_name)) { + ERROR("[hc_connection_parse] Invalid interface_name received"); + return -1; + } + + if (!IS_VALID_TYPE(item->type)) { + ERROR("[hc_connection_parse] Invalid type received"); + return -1; + } + + if (!IS_VALID_FAMILY(item->family)) { + ERROR("[hc_connection_parse] Invalid family received"); + return -1; + } + + if (!IS_VALID_ADDRESS(item->local_address)) { + ERROR("[hc_connection_parse] Invalid address received"); + return -1; + } + + if (!IS_VALID_PORT(ntohs(item->local_port))) { + ERROR("[hc_connection_parse] Invalid port received"); + return -1; + } + + if (!IS_VALID_ADDRESS(item->remote_address)) { + ERROR("[hc_connection_parse] Invalid address received"); + return -1; + } + + if (!IS_VALID_PORT(ntohs(item->remote_port))) { + ERROR("[hc_connection_parse] Invalid port received"); + return -1; + } + + if (!IS_VALID_FACE_STATE(item->admin_state)) { + ERROR("[hc_connection_parse] Invalid admin_state received"); + return -1; + } + + // PRIORITY + // TAGS + + if (!IS_VALID_FACE_STATE(item->state)) { + ERROR("[hc_connection_parse] Invalid state received"); + return -1; + } + + *connection = (hc_connection_t){ + .id = item->id, + .type = (face_type_t)item->type, + .family = (int)item->family, + .local_addr = item->local_addr, + .local_port = ntohs(item->local_port), + .remote_addr = item->remote_addr, + .remote_port = ntohs(item->remote_port), + .admin_state = (face_state_t)item->admin_state, + .priority = item->priority, + .tags = item->tags, + .state = (face_state_t)item->state, + }; + rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", item->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", + item->interface_name); + if ((rc < 0) || (rc >= INTERFACE_LEN)) return -1; + + if (hc_connection_validate(connection, false) < 0) return -1; + return 0; +} + +int _hicnlight_connection_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_connection_parse(buffer, size, &object->connection); +} + +/* CONNECTION CREATE */ + +int hicnlight_connection_serialize_create(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_connection_t *connection = &object->connection; + + msg_connection_add_t *msg = (msg_connection_add_t *)packet; + *msg = (msg_connection_add_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = { + .remote_ip = connection->remote_addr, + .local_ip = connection->local_addr, + .remote_port = htons(connection->remote_port), + .local_port = htons(connection->local_port), + .family = (uint8_t)connection->family, + .type = (uint8_t)connection->type, + .admin_state = (uint8_t)connection->admin_state, + .__pad = 0, + .priority = connection->priority, + .tags = connection->tags, + }}; + + rc = snprintf(msg->payload.symbolic, SYMBOLIC_NAME_LEN, "%s", + connection->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + return sizeof(msg_connection_add_t); +} + +/* CONNECTION DELETE */ + +int hicnlight_connection_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_connection_t *connection = &object->connection; + + msg_connection_remove_t *msg = (msg_connection_remove_t *)packet; + *msg = (msg_connection_remove_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_REMOVE, + .length = 1, + .seq_num = 0, + }, + }; + + if (connection->id) { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + connection->id); + // XXX + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_delete] Unexpected truncation of symbolic name " + "string"); + } else if (*connection->name) { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + connection->name); + // XXX + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_delete] Unexpected truncation of symbolic name " + "string"); +#if 0 + } else { + hc_connection_t *connection_found; + if (hc_connection_get(socket, connection, &connection_found) < 0) + return res; + if (!connection_found) return res; + rc = snprintf(payload->symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + connection_found->id); + // XXX + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_delete] Unexpected truncation of symbolic name " + "string"); + free(connection_found); +#endif + } + + return sizeof(msg_connection_remove_t); +} + +// XXX How to update a connection XXX +// Key attributes are mandatory +// Enum can be undefined +// family UNSPEC +// ip address NULL +// port NULL +// priority = int ????????? specific negative value == unspec +// tags = bitmap ????????? 0xFFFFFF special value == unspec + +// u32 id; /* Kr. */ +// char name[SYMBOLIC_NAME_LEN]; /* K.w */ +// char interface_name[INTERFACE_LEN]; /* Kr. */ +// +// netdevice_type_t netdevice_type; undefined +// face_type_t type; +// int family; +// ip_address_t local_addr; +// u16 local_port; +// ip_address_t remote_addr; +// u16 remote_port; +// face_state_t admin_state; +// uint32_t priority; /* .rw */ +// policy_tags_t tags; /* .rw */ +// face_state_t state; /* .r. */ +int hicnlight_connection_serialize_update(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_connection_t *connection = &object->connection; + + msg_connection_update_t *msg = (msg_connection_update_t *)packet; + *msg = (msg_connection_update_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_UPDATE, + .length = 1, + .seq_num = 0, + }, + .payload = { + //.remote_ip = connection->remote_updater, + //.local_ip = connection->local_updater, + //.remote_port = htons(connection->remote_port), + //.local_port = htons(connection->local_port), + //.family = connection->family, + //.type = connection->type, + .admin_state = connection->admin_state, + .priority = connection->priority, + .tags = connection->tags, + }}; + + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + connection->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + // snprintf(msg.payload.interface_name, INTERFACE_NAME_LEN, "%s", + // connection->interface_name); + + return sizeof(msg_connection_update_t); +} + +#if 0 +/* CONNECTION SET ADMIN STATE */ + +static int _hicnlight_connection_set_admin_state_internal( + hc_sock_t *socket, const char *conn_id_or_name, face_state_t state, + bool async) { + int rc; + DEBUG( + "[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s " + "async=%s", + conn_id_or_name, face_state_str(state), BOOLSTR(async)); + + struct { + cmd_header_t hdr; + cmd_connection_set_admin_state_t payload; + } msg = { + .hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE, + .length = 1, + .seq_num = 0, + }, + .payload = + { + .admin_state = state, + }, + }; + rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_set_admin_state] Unexpected truncation of symbolic " + "name string"); + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE, + .size_in = sizeof(cmd_connection_set_admin_state_t), + .size_out = 0, + .parse = NULL, + }; + + return _hicnlight_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +} + +static int _hicnlight_connection_set_admin_state(hc_sock_t *s, + const char *conn_id_or_name, + face_state_t state) { + return _hicnlight_connection_set_admin_state_internal(s, conn_id_or_name, state, + false); +} + +static int _hicnlight_connection_set_admin_state_async(hc_sock_t *s, + const char *conn_id_or_name, + face_state_t state) { + return _hicnlight_connection_set_admin_state_internal(s, conn_id_or_name, state, + true); +} + + +static int _hicnlight_connection_set_priority_internal(hc_sock_t *socket, + const char *conn_id_or_name, + uint32_t priority, + bool async) { + int rc; + DEBUG( + "[hc_connection_set_priority] connection_id/name=%s priority=%d " + "async=%s", + conn_id_or_name, priority, BOOLSTR(async)); + struct { + cmd_header_t hdr; + cmd_connection_set_priority_t payload; + } msg = { + .hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY, + .length = 1, + .seq_num = 0, + }, + .payload = + { + .priority = priority, + }, + }; + rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_set_priority] Unexpected truncation of symbolic " + "name " + "string"); + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY, + .size_in = sizeof(cmd_connection_set_priority_t), + .size_out = 0, + .parse = NULL, + }; + + return _hicnlight_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +} + +static int _hicnlight_connection_set_priority(hc_sock_t *s, + const char *conn_id_or_name, + uint32_t priority) { + return _hicnlight_connection_set_priority_internal(s, conn_id_or_name, priority, + false); +} + +static int _hicnlight_connection_set_priority_async(hc_sock_t *s, + const char *conn_id_or_name, + uint32_t priority) { + return _hicnlight_connection_set_priority_internal(s, conn_id_or_name, priority, + true); +} + + +static int _hicnlight_connection_set_tags_internal(hc_sock_t *s, + const char *conn_id_or_name, + policy_tags_t tags, bool async) { + int rc; + DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s", + conn_id_or_name, tags, BOOLSTR(async)); + struct { + cmd_header_t hdr; + cmd_connection_set_tags_t payload; + } msg = { + .hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_SET_TAGS, + .length = 1, + .seq_num = 0, + }, + .payload = + { + .tags = tags, + }, + }; + rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[_hc_connection_set_tags] Unexpected truncation of symbolic name " + "string"); + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_CONNECTION_SET_TAGS, + .size_in = sizeof(cmd_connection_set_tags_t), + .size_out = 0, + .parse = NULL, + }; + + return _hicnlight_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL, + async); +} + +static int _hicnlight_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, + policy_tags_t tags) { + return _hicnlight_connection_set_tags_internal(s, conn_id_or_name, tags, false); +} + +static int _hicnlight_connection_set_tags_async(hc_sock_t *s, + const char *conn_id_or_name, + policy_tags_t tags) { + return _hicnlight_connection_set_tags_internal(s, conn_id_or_name, tags, true); +} +#endif + +/* CONNECTION LIST */ + +int hicnlight_connection_serialize_list(const hc_object_t *object, + uint8_t *packet) { + msg_connection_list_t *msg = (msg_connection_list_t *)packet; + *msg = (msg_connection_list_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_CONNECTION_LIST, + .length = 0, + .seq_num = 0, + }}; + return sizeof(msg_header_t); // Do not use msg_connection_list_t +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, connection); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/connection.h b/ctrl/libhicnctrl/src/modules/hicn_light/connection.h new file mode 100644 index 000000000..77204e6b2 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/connection.h @@ -0,0 +1,27 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_CONNECTION_H +#define HICNCTRL_MODULE_HICNLIGHT_CONNECTION_H + +#include "../../module.h" + +int hc_connection_to_local_listener(const hc_connection_t *connection, + hc_listener_t *listener); + +#if 1 + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, connection); +// extern const hc_module_object_ops_t hicnlight_connection_module_ops; + +#else + +int _hicnlight_connection_parse(const uint8_t *buffer, size_t size, + hc_object_t *object); + +int hicnlight_connection_serialize_create(const hc_object_t *object, + uint8_t *packet); +int hicnlight_connection_serialize_delete(const hc_object_t *object, + uint8_t *packet); +int hicnlight_connection_serialize_list(const hc_object_t *object, + uint8_t *packet); + +#endif +#endif /* HICNCTRL_MODULE_HICNLIGHT_CONNECTION_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/face.c b/ctrl/libhicnctrl/src/modules/hicn_light/face.c new file mode 100644 index 000000000..0d9475420 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/face.c @@ -0,0 +1,482 @@ +#include <hicn/ctrl/objects/listener.h> +#include <hicn/util/log.h> + +#include "base.h" +#include "face.h" + +int hc_face_from_connection(const hc_connection_t *connection, + hc_face_t *face) { + int rc; + switch (connection->type) { + case FACE_TYPE_TCP: + *face = (hc_face_t){ + .id = connection->id, + .type = FACE_TYPE_TCP, + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + .remote_addr = connection->remote_addr, + .remote_port = connection->remote_port, + .admin_state = connection->admin_state, + .state = connection->state, + .priority = connection->priority, + .tags = connection->tags, + }; + break; + case FACE_TYPE_UDP: + *face = (hc_face_t){ + .id = connection->id, + .type = FACE_TYPE_UDP, + .family = connection->family, + .local_addr = connection->local_addr, + .local_port = connection->local_port, + .remote_addr = connection->remote_addr, + .remote_port = connection->remote_port, + .admin_state = connection->admin_state, + .state = connection->state, + .priority = connection->priority, + .tags = connection->tags, + }; + break; + case FACE_TYPE_HICN: + *face = (hc_face_t){ + .id = connection->id, + .type = FACE_TYPE_HICN, + .family = connection->family, + .netdevice.index = NETDEVICE_UNDEFINED_INDEX, // XXX + .local_addr = connection->local_addr, + .remote_addr = connection->remote_addr, + .admin_state = connection->admin_state, + .state = connection->state, + .priority = connection->priority, + .tags = connection->tags, + }; + break; + default: + return -1; + } + face->netdevice.name[0] = '\0'; + face->netdevice.index = 0; + rc = snprintf(face->name, SYMBOLIC_NAME_LEN, "%s", connection->name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_connection_to_face] Unexpected truncation of symbolic name " + "string"); + rc = snprintf(face->netdevice.name, INTERFACE_LEN, "%s", + connection->interface_name); + if (rc >= INTERFACE_LEN) + WARN( + "[hc_connection_to_face] Unexpected truncation of interface name " + "string"); + netdevice_update_index(&face->netdevice); + return 0; +} + +int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection, + bool generate_name) { + int rc; + + switch (face->type) { + case FACE_TYPE_HICN: + *connection = (hc_connection_t){ + .type = FACE_TYPE_HICN, + .family = face->family, + .local_addr = face->local_addr, + .local_port = 0, + .remote_addr = face->remote_addr, + .remote_port = 0, + .admin_state = face->admin_state, + .state = face->state, + .priority = face->priority, + .tags = face->tags, + }; + rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", + face->netdevice.name); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_face_to_connection] Unexpected truncation of symbolic " + "name string"); + break; + case FACE_TYPE_TCP: + *connection = (hc_connection_t){ + .type = FACE_TYPE_TCP, + .family = face->family, + .local_addr = face->local_addr, + .local_port = face->local_port, + .remote_addr = face->remote_addr, + .remote_port = face->remote_port, + .admin_state = face->admin_state, + .state = face->state, + .priority = face->priority, + .tags = face->tags, + }; + if (generate_name) { + rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "tcp%u", RANDBYTE()); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_face_to_connection] Unexpected truncation of " + "symbolic name string"); + } else { + memset(connection->name, 0, SYMBOLIC_NAME_LEN); + } + break; + case FACE_TYPE_UDP: + *connection = (hc_connection_t){ + .type = FACE_TYPE_UDP, + .family = face->family, + .local_addr = face->local_addr, + .local_port = face->local_port, + .remote_addr = face->remote_addr, + .remote_port = face->remote_port, + .admin_state = face->admin_state, + .state = face->state, + .priority = face->priority, + .tags = face->tags, + }; + if (generate_name) { + rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "udp%u", RANDBYTE()); + if (rc >= SYMBOLIC_NAME_LEN) + WARN( + "[hc_face_to_connection] Unexpected truncation of " + "symbolic name string"); + } else { + memset(connection->name, 0, SYMBOLIC_NAME_LEN); + } + snprintf(connection->interface_name, INTERFACE_LEN, "%s", + face->netdevice.name); + break; + default: + return -1; + } + + connection->id = face->id; + rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", + face->netdevice.name); + if (rc >= INTERFACE_LEN) + WARN( + "hc_face_to_connection] Unexpected truncation of interface name " + "string"); + + return 0; +} + +int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener) { + switch (face->type) { + case FACE_TYPE_HICN_LISTENER: + break; + case FACE_TYPE_TCP_LISTENER: + break; + case FACE_TYPE_UDP_LISTENER: + break; + default: + return -1; + } + return -1; /* XXX Not implemented */ +} + +#if 0 +/*----------------------------------------------------------------------------* + * Face + * + * Face support is not directly available in hicn-light, but we can offer such + * an interface through a combination of listeners and connections. The code + * starts with some conversion functions between faces/listeners/connections. + * + * We also need to make sure that there always exist a (single) listener when + *a connection is created, and in the hICN face case, that there is a single + * connection attached to this listener. + * + *----------------------------------------------------------------------------*/ + +/* FACE CREATE */ + +static int _hcng_face_create(hc_sock_t *socket, hc_face_t *face) { +#if 0 + hc_listener_t listener; + hc_listener_t *listener_found; + + hc_connection_t connection; + hc_connection_t *connection_found; + + char face_s[MAXSZ_HC_FACE]; + int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); + if (rc >= MAXSZ_HC_FACE) + WARN("[hc_face_create] Unexpected truncation of face string"); + DEBUG("[hc_face_create] face=%s", face_s); + + switch (face->face.type) { + case FACE_TYPE_HICN: + case FACE_TYPE_TCP: + case FACE_TYPE_UDP: + if (hc_face_to_connection(face, &connection, true) < 0) { + ERROR("[hc_face_create] Could not convert face to connection."); + return -1; + } + + /* Ensure we have a corresponding local listener */ + if (hc_connection_to_local_listener(&connection, &listener) < 0) { + ERROR("[hc_face_create] Could not convert face to local listener."); + return -1; + } + + if (_hcng_listener_get(socket, &listener, &listener_found) < 0) { + ERROR("[hc_face_create] Could not retrieve listener"); + return -1; + } + + if (!listener_found) { + /* We need to create the listener if it does not exist */ + if (hc_listener_create(socket, &listener) < 0) { + ERROR("[hc_face_create] Could not create listener."); + free(listener_found); + return -1; + } + } else { + free(listener_found); + } + + /* Create corresponding connection */ + if (_hcng_connection_create(socket, &connection) < 0) { + ERROR("[hc_face_create] Could not create connection."); + return -1; + } + + /* + * Once the connection is created, we need to list all connections + * and compare with the current one to find the created face ID. + */ + if (_hcng_connection_get(socket, &connection, &connection_found) < 0) { + ERROR("[hc_face_create] Could not retrieve connection"); + return -1; + } + + if (!connection_found) { + ERROR("[hc_face_create] Could not find newly created connection."); + return -1; + } + + face->id = connection_found->id; + free(connection_found); + + break; + + case FACE_TYPE_HICN_LISTENER: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_UDP_LISTENER: + if (hc_face_to_listener(face, &listener) < 0) { + ERROR("Could not convert face to listener."); + return -1; + } + if (hc_listener_create(socket, &listener) < 0) { + ERROR("[hc_face_create] Could not create listener."); + return -1; + } + break; + default: + ERROR("[hc_face_create] Unknwon face type."); + + return -1; + }; + +#endif + return 0; +} + +static int _hcng_face_get(hc_sock_t *socket, hc_face_t *face, + hc_face_t **face_found) { +#if 0 + hc_listener_t listener; + hc_listener_t *listener_found; + + hc_connection_t connection; + hc_connection_t *connection_found; + + char face_s[MAXSZ_HC_FACE]; + int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); + if (rc >= MAXSZ_HC_FACE) + WARN("[hc_face_get] Unexpected truncation of face string"); + DEBUG("[hc_face_get] face=%s", face_s); + + switch (face->face.type) { + case FACE_TYPE_HICN: + case FACE_TYPE_TCP: + case FACE_TYPE_UDP: + if (hc_face_to_connection(face, &connection, false) < 0) return -1; + if (_hcng_connection_get(socket, &connection, &connection_found) < 0) + return -1; + if (!connection_found) { + *face_found = NULL; + return 0; + } + *face_found = malloc(sizeof(hc_face_t)); + hc_connection_to_face(connection_found, *face_found); + free(connection_found); + break; + + case FACE_TYPE_HICN_LISTENER: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_UDP_LISTENER: + if (hc_face_to_listener(face, &listener) < 0) return -1; + if (_hcng_listener_get(socket, &listener, &listener_found) < 0) return -1; + if (!listener_found) { + *face_found = NULL; + return 0; + } + *face_found = malloc(sizeof(hc_face_t)); + hc_listener_to_face(listener_found, *face_found); + free(listener_found); + break; + + default: + return -1; + } + +#endif + return 0; +} + +/* FACE DELETE */ + +static int _hcng_face_delete(hc_sock_t *socket, hc_face_t *face, + uint8_t delete_listener) { +#if 0 + char face_s[MAXSZ_HC_FACE]; + int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); + if (rc >= MAXSZ_HC_FACE) + WARN("[hc_face_delete] Unexpected truncation of face string"); + DEBUG("[hc_face_delete] face=%s", face_s); + + hc_connection_t connection; + if (hc_face_to_connection(face, &connection, false) < 0) { + ERROR("[hc_face_delete] Could not convert face to connection."); + return -1; + } + + if (_hcng_connection_delete(socket, &connection) < 0) { + ERROR("[hc_face_delete] Error removing connection"); + return -1; + } + + if (!delete_listener) { + return 0; + } + + /* If this is the last connection attached to the listener, remove it */ + + hc_data_t *connections; + hc_listener_t listener = {{0}}; + + /* + * Ensure we have a corresponding local listener + * NOTE: hc_face_to_listener is not appropriate + */ + if (hc_connection_to_local_listener(&connection, &listener) < 0) { + ERROR("[hc_face_create] Could not convert face to local listener."); + return -1; + } +#if 1 + /* + * The name is generated to prepare listener creation, we need it to be + * empty for deletion. The id should not need to be reset though. + */ + listener.id = 0; + memset(listener.name, 0, sizeof(listener.name)); +#endif + if (_hcng_connection_list(socket, &connections) < 0) { + ERROR("[hc_face_delete] Error getting the list of listeners"); + return -1; + } + + bool delete = true; + foreach_connection(c, connections) { + if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) == + 0) && + (c->local_port == listener.local_port) && + (strcmp(c->interface_name, listener.interface_name) == 0)) { + delete = false; + } + } + + if (delete) { + if (_hcng_listener_delete(socket, &listener) < 0) { + ERROR("[hc_face_delete] Error removing listener"); + return -1; + } + } + + hc_data_free(connections); + +#endif + return 0; +} + +/* FACE LIST */ + +static int _hcng_face_list(hc_sock_t *socket, hc_data_t **pdata) { +#if 0 + hc_data_t *connection_data; + hc_face_t face; + + DEBUG("[hc_face_list]"); + + if (_hcng_connection_list(socket, &connection_data) < 0) { + ERROR("[hc_face_list] Could not list connections."); + return -1; + } + + hc_data_t *face_data = + hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL); + foreach_connection(c, connection_data) { + if (hc_connection_to_face(c, &face) < 0) { + ERROR("[hc_face_list] Could not convert connection to face."); + goto ERR; + } + hc_data_push(face_data, &face); + } + + *pdata = face_data; + hc_data_free(connection_data); + DEBUG("[hc_face_list] done"); + return 0; + +ERR: + hc_data_free(connection_data); + DEBUG("[hc_face_list] error"); +#endif + return -1; +} + +static int hc_connection_parse_to_face(void *in, hc_face_t *face) { + hc_connection_t connection; + + if (hcng_connection_parse(in, &connection) < 0) { + ERROR("[hc_connection_parse_to_face] Could not parse connection"); + return -1; + } + + if (hc_connection_to_face(&connection, face) < 0) { + ERROR( + "[hc_connection_parse_to_face] Could not convert connection to " + "face."); + return -1; + } + + return 0; +} + +static int _hcng_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t admin_state) { + return hc_connection_set_admin_state(s, conn_id_or_name, admin_state); +} + +static int _hcng_face_set_priority(hc_sock_t *s, const char *conn_id_or_name, + uint32_t priority) { + return hc_connection_set_priority(s, conn_id_or_name, priority); +} + +static int _hcng_face_set_tags(hc_sock_t *s, const char *conn_id_or_name, + policy_tags_t tags) { + return hc_connection_set_tags(s, conn_id_or_name, tags); +} + +#endif diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/face.h b/ctrl/libhicnctrl/src/modules/hicn_light/face.h new file mode 100644 index 000000000..9e1cd48c2 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/face.h @@ -0,0 +1,14 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_FACE +#define HICNCTRL_MODULE_HICNLIGHT_FACE + +#include <hicn/ctrl/objects/connection.h> +#include <hicn/ctrl/objects/face.h> + +int hc_face_from_connection(const hc_connection_t *connection, hc_face_t *face); + +int hc_face_to_connection(const hc_face_t *face, hc_connection_t *connection, + bool generate_name); + +int hc_face_to_listener(const hc_face_t *face, hc_listener_t *listener); + +#endif /* HICNCTRL_MODULES_HICNLIGHT_FACE */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/listener.c b/ctrl/libhicnctrl/src/modules/hicn_light/listener.c new file mode 100644 index 000000000..68d4b8fcd --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/listener.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <assert.h> +#include <hicn/ctrl/api.h> +#include <hicn/util/log.h> + +#include "base.h" +#include "../../object_private.h" +#include "listener.h" + +static int hicnlight_listener_parse(const u8 *buffer, size_t size, + hc_listener_t *listener) { + int rc; + + if (size != sizeof(cmd_listener_list_item_t)) return -1; + cmd_listener_list_item_t *item = (cmd_listener_list_item_t *)buffer; + + if (!IS_VALID_ADDRESS(item->local_address)) { + ERROR("[hc_listener_parse] Invalid address received"); + return -1; + } + if (!IS_VALID_NAME(item->name)) { + ERROR("[hc_listener_parse] Invalid name received"); + return -1; + } + if (!IS_VALID_INTERFACE_NAME(item->interface_name)) { + ERROR("[hc_listener_parse] Invalid interface_name received"); + return -1; + } + if (!IS_VALID_ID(item->id)) { + ERROR("[hc_listener_parse] Invalid id received"); + return -1; + } + if (!IS_VALID_PORT(ntohs(item->local_port))) { + ERROR("[hc_listener_parse] Invalid port received"); + return -1; + } + if (!IS_VALID_FAMILY(item->family)) { + ERROR("[hc_listener_parse] Invalid family received"); + return -1; + } + if (!IS_VALID_TYPE(item->type)) { + ERROR("[hc_listener_parse] Invalid type received"); + return -1; + } + // if (!(IS_VALID_CONNECTION_TYPE(item->type))) + // return -1; + + *listener = (hc_listener_t){ + .id = item->id, + .type = (face_type_t)(item->type), + .family = (int)(item->family), + .local_addr = + item->local_addr, // UNION_CAST(item->local_addr, ip_address_t), + .local_port = ntohs(item->local_port), + }; + + rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", item->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", + item->interface_name); + if ((rc < 0) || (rc >= INTERFACE_LEN)) return -1; + + if (hc_listener_validate(listener, false) < 0) return -1; + return 0; +} + +int _hicnlight_listener_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_listener_parse(buffer, size, &object->listener); +} + +/* LISTENER CREATE */ + +int hicnlight_listener_serialize_create(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_listener_t *listener = &object->listener; + + msg_listener_add_t *msg = (msg_listener_add_t *)packet; + *msg = (msg_listener_add_t){.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_LISTENER_ADD, + .length = 1, + .seq_num = 0, + }, + + .payload = { + .address = listener->local_addr, + .port = htons(listener->local_port), + .family = (uint8_t)listener->family, + .type = (uint8_t)listener->type, + }}; + + rc = snprintf(msg->payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name); + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + rc = snprintf(msg->payload.interface_name, INTERFACE_LEN, "%s", + listener->interface_name); + if ((rc < 0) || (rc >= INTERFACE_LEN)) return -1; + + return sizeof(msg_listener_add_t); +} + +/* LISTENER DELETE */ + +int hicnlight_listener_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + int rc; + const hc_listener_t *listener = &object->listener; + + msg_listener_remove_t *msg = (msg_listener_remove_t *)packet; + *msg = (msg_listener_remove_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_LISTENER_REMOVE, + .length = 1, + .seq_num = 0, + }}; + + if (listener->id) { + rc = snprintf(msg->payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", + listener->id); + } else if (*listener->name) { + rc = snprintf(msg->payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", + listener->name); + } else { + return -1; + } + + // For now we only support delete by name or id +#if 0 + hc_listener_t *listener_found; + if (hc_listener_get(socket, listener, &listener_found) < 0) return -1; + if (!listener_found) return -1; + rc = snprintf(payload->symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", + listener_found->id); + free(listener_found); + } +#endif + + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + return sizeof(msg_listener_remove_t); +} + +/* LISTENER LIST */ + +int hicnlight_listener_serialize_list(const hc_object_t *object, + uint8_t *packet) { + msg_listener_list_t *msg = (msg_listener_list_t *)packet; + *msg = (msg_listener_list_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_LISTENER_LIST, + .length = 0, + .seq_num = 0, + }}; + + return sizeof(msg_header_t); // Do not use msg_listener_list_t +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, listener); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/listener.h b/ctrl/libhicnctrl/src/modules/hicn_light/listener.h new file mode 100644 index 000000000..27ef8434d --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/listener.h @@ -0,0 +1,21 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_LISTENER_H +#define HICNCTRL_MODULE_HICNLIGHT_LISTENER_H + +#include "../../module.h" + +#if 1 +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, listener); +#else + +int _hicnlight_listener_parse(const uint8_t *buffer, size_t size, + hc_object_t *object); + +int hicnlight_listener_serialize_create(const hc_object_t *object, + uint8_t *packet); +int hicnlight_listener_serialize_delete(const hc_object_t *object, + uint8_t *packet); +int hicnlight_listener_serialize_list(const hc_object_t *object, + uint8_t *packet); +#endif + +#endif /* HICNCTRL_MODULE_HICNLIGHT_LISTENER_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/mapme.c b/ctrl/libhicnctrl/src/modules/hicn_light/mapme.c new file mode 100644 index 000000000..de75d82a8 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/mapme.c @@ -0,0 +1,139 @@ +#include "mapme.h" + +static int _hcng_mapme_set(hc_sock_t *socket, int enabled) { +#if 0 + msg_mapme_enable_t msg = {.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_MAPME_ENABLE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .activate = enabled, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_MAPME_ENABLE, + .size_in = sizeof(cmd_mapme_enable_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, false); +#endif + return 0; // XXX added +} + +static int _hcng_mapme_set_discovery(hc_sock_t *socket, int enabled) { +#if 0 + msg_mapme_enable_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_MAPME_SET_DISCOVERY, + .length = 1, + .seq_num = 0, + }, + .payload = { + .activate = enabled, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_MAPME_SET_DISCOVERY, + .size_in = sizeof(cmd_mapme_set_discovery_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, false); +#endif + return 0; // XXX added +} + +static int _hcng_mapme_set_timescale(hc_sock_t *socket, uint32_t timescale) { +#if 0 + msg_mapme_set_timescale_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_MAPME_SET_TIMESCALE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .timePeriod = timescale, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_MAPME_SET_TIMESCALE, + .size_in = sizeof(cmd_mapme_set_timescale_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, false); +#endif + return 0; // XXX added +} + +static int _hcng_mapme_set_retx(hc_sock_t *socket, uint32_t timescale) { +#if 0 + msg_mapme_set_retx_t msg = {.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_MAPME_SET_RETX, + .length = 1, + .seq_num = 0, + }, + .payload = { + .timePeriod = timescale, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_MAPME_SET_RETX, + .size_in = sizeof(msg_mapme_set_retx_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, false); +#endif + return 0; // XXX added +} + +static int _hcng_mapme_send_update(hc_sock_t *socket, hc_mapme_t *mapme) { +#if 0 + if (!IS_VALID_FAMILY(mapme->family)) return -1; + + msg_mapme_send_update_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_MAPME_SEND_UPDATE, + .length = 1, + .seq_num = 0, + }, + }; + + hc_command_params_t params = { + .cmd = ACTION_UPDATE, + .cmd_id = COMMAND_TYPE_MAPME_SEND_UPDATE, + .size_in = sizeof(msg_mapme_send_update_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, false); +#endif + return 0; // XXX added +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/policy.c b/ctrl/libhicnctrl/src/modules/hicn_light/policy.c new file mode 100644 index 000000000..d48ce014d --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/policy.c @@ -0,0 +1,162 @@ +#include "policy.h" + +/* POLICY CREATE */ + +static int _hcng_policy_create_internal(hc_sock_t *socket, hc_policy_t *policy, + bool async) { +#if 0 + if (!IS_VALID_FAMILY(policy->family)) return -1; + + struct { + cmd_header_t hdr; + cmd_policy_add_t payload; + } msg = {.hdr = + { + .message_type = REQUEST_LIGHT, + COMMAND_TYPE_POLICY_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = policy->remote_addr, + .family = policy->family, + .len = policy->len, + .policy = policy->policy, + }}; + + hc_command_params_t params = { + .cmd = ACTION_CREATE, + .cmd_id = COMMAND_TYPE_POLICY_ADD, + .size_in = sizeof(cmd_policy_add_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_policy_create(hc_sock_t *s, hc_policy_t *policy) { + return _hcng_policy_create_internal(s, policy, false); +} + +static int _hcng_policy_create_async(hc_sock_t *s, hc_policy_t *policy) { + return _hcng_policy_create_internal(s, policy, true); +} + +/* POLICY DELETE */ + +static int _hcng_policy_delete_internal(hc_sock_t *socket, hc_policy_t *policy, + bool async) { +#if 0 + if (!IS_VALID_FAMILY(policy->family)) return -1; + + struct { + cmd_header_t hdr; + cmd_policy_remove_t payload; + } msg = {.hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_POLICY_REMOVE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = policy->remote_addr, + .family = policy->family, + .len = policy->len, + }}; + + hc_command_params_t params = { + .cmd = ACTION_DELETE, + .cmd_id = COMMAND_TYPE_POLICY_REMOVE, + .size_in = sizeof(cmd_policy_remove_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_policy_delete(hc_sock_t *s, hc_policy_t *policy) { + return _hcng_policy_delete_internal(s, policy, false); +} + +static int _hcng_policy_delete_async(hc_sock_t *s, hc_policy_t *policy) { + return _hcng_policy_delete_internal(s, policy, true); +} + +/* POLICY PARSE */ + +static int hc_policy_parse(void *in, hc_policy_t *policy) { + hc_policy_t *item = (hc_policy_t *)in; + + if (!IS_VALID_ADDRESS(item->address)) { + ERROR("[hc_policy_parse] Invalid address"); + return -1; + } + if (!IS_VALID_FAMILY(item->family)) { + ERROR("[hc_policy_parse] Invalid family"); + return -1; + } + if (!IS_VALID_PREFIX_LEN(item->len)) { + ERROR("[hc_policy_parse] Invalid len"); + return -1; + } + if (!IS_VALID_POLICY(item->policy)) { + ERROR("[hc_policy_parse] Invalid policy"); + return -1; + } + + *policy = (hc_policy_t){ + .family = item->family, + .remote_addr = item->remote_addr, + .len = item->len, + .policy = item->policy, + }; + return 0; +} + +/* POLICY LIST */ + +static int _hcng_policy_list_internal(hc_sock_t *socket, hc_data_t **pdata, + bool async) { +#if 0 + struct { + cmd_header_t hdr; + } msg = { + .hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_POLICY_LIST, + .length = 0, + .seq_num = 0, + }, + }; + + hc_command_params_t params = { + .cmd = ACTION_LIST, + .cmd_id = COMMAND_TYPE_POLICY_LIST, + .size_in = sizeof(hc_policy_t), + .size_out = sizeof(hc_policy_t), + .parse = (HC_PARSE)hc_policy_parse, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + pdata, async); +#endif + return 0; // XXX added +} + +static int _hcng_policy_list(hc_sock_t *s, hc_data_t **pdata) { + return _hcng_policy_list_internal(s, pdata, false); +} + +static int _hcng_policy_list_async(hc_sock_t *s, hc_data_t **pdata) { + return _hcng_policy_list_internal(s, pdata, true); +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/punting.c b/ctrl/libhicnctrl/src/modules/hicn_light/punting.c new file mode 100644 index 000000000..7886ff839 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/punting.c @@ -0,0 +1,74 @@ +#include "punting.h" + +static int _hcng_punting_create_internal(hc_sock_t *socket, + hc_punting_t *punting, bool async) { +#if 0 + int rc; + + if (hc_punting_validate(punting) < 0) return -1; + + struct { + cmd_header_t hdr; + cmd_punting_add_t payload; + } msg = {.hdr = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_PUNTING_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = punting->prefix, + .family = punting->family, + .len = punting->prefix_len, + }}; + rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + punting->face_id); + if (rc >= SYMBOLIC_NAME_LEN) + WARN("[_hc_punting_create] Unexpected truncation of symbolic name string"); + + hc_command_params_t params = { + .cmd = ACTION_CREATE, + .cmd_id = COMMAND_TYPE_PUNTING_ADD, + .size_in = sizeof(cmd_punting_add_t), + .size_out = 0, + .parse = NULL, + }; + + return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, + NULL, async); +#endif + return 0; // XXX added +} + +static int _hcng_punting_create(hc_sock_t *s, hc_punting_t *punting) { + return _hcng_punting_create_internal(s, punting, false); +} + +static int _hcng_punting_create_async(hc_sock_t *s, hc_punting_t *punting) { + return _hcng_punting_create_internal(s, punting, true); +} + +static int _hcng_punting_get(hc_sock_t *s, hc_punting_t *punting, + hc_punting_t **punting_found) { + ERROR("hc_punting_get not (yet) implemented."); + return -1; +} + +static int _hcng_punting_delete(hc_sock_t *s, hc_punting_t *punting) { + ERROR("hc_punting_delete not (yet) implemented."); + return -1; +} + +#if 0 +static int hc_punting_parse(void * in, hc_punting_t * punting) +{ + ERROR("hc_punting_parse not (yet) implemented."); + return -1; +} +#endif + +static int _hcng_punting_list(hc_sock_t *s, hc_data_t **pdata) { + ERROR("hc_punting_list not (yet) implemented."); + return -1; +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/route.c b/ctrl/libhicnctrl/src/modules/hicn_light/route.c new file mode 100644 index 000000000..1adfe4f36 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/route.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file modules/hicn_light/route.c + * \brief Implementation of route object VFT for hicn_light. + */ + +#include <assert.h> +#include <hicn/ctrl/api.h> +#include <hicn/util/log.h> +#include "base.h" +#include "route.h" +#include <hicn/ctrl/hicn-light.h> + +#include "../../object_private.h" + +static int hicnlight_route_parse(const uint8_t *buffer, size_t size, + hc_route_t *route) { + if (size != sizeof(cmd_route_list_item_t)) return -1; + cmd_route_list_item_t *item = (cmd_route_list_item_t *)buffer; + + if (!IS_VALID_NAME(item->face_name)) { + ERROR("[hc_connection_parse] Invalid face_name received"); + return -1; + } + + if (!IS_VALID_ID(item->face_id)) { + ERROR("[hc_connection_parse] Invalid face_id received"); + return -1; + } + + if (!IS_VALID_FAMILY(item->family)) { + ERROR("[hc_listener_parse] Invalid family received"); + return -1; + } + + if (!IS_VALID_ADDRESS(item->remote_addr)) { + ERROR("[hc_connection_parse] Invalid address received"); + return -1; + } + + // LEN + // COST + + *route = (hc_route_t){ + .face_name = "", /* This is not reported back */ + .face_id = item->face_id, + .family = (int)(item->family), + .remote_addr = item->remote_addr, + .len = item->len, + .cost = item->cost, + }; + + if (hc_route_validate(route, false) < 0) return -1; + return 0; +} + +int _hicnlight_route_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_route_parse(buffer, size, &object->route); +} + +/* ROUTE CREATE */ + +int hicnlight_route_serialize_create(const hc_object_t *object, + uint8_t *packet) { + const hc_route_t *route = &object->route; + int rc; + + msg_route_add_t *msg = (msg_route_add_t *)packet; + *msg = (msg_route_add_t){.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_ROUTE_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = route->remote_addr, + .cost = route->cost, + .family = route->family, + .len = route->len, + }}; + + /* + * The route commands expects the ID or name as part of the + * symbolic_or_connid attribute. + */ + if (route->face_name[0] != '\0') { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + route->face_name); + } else { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + route->face_id); + } + + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + return sizeof(msg_route_add_t); +} + +/* ROUTE DELETE */ + +int hicnlight_route_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + const hc_route_t *route = &object->route; + int rc; + + msg_route_remove_t *msg = (msg_route_remove_t *)packet; + memset(msg, 0, sizeof(msg_route_remove_t)); + *msg = (msg_route_remove_t){.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_ROUTE_REMOVE, + .length = 1, + .seq_num = 0, + }, + .payload = { + .family = (uint8_t)route->family, + .len = route->len, + }}; + + /* + * Direct copy as part of the previous assignment does not work correctly... + * to be investigated + */ + memcpy(&msg->payload.address, &route->remote_addr, sizeof(hicn_ip_address_t)); + + /* + * The route commands expects the ID or name as part of the + * symbolic_or_connid attribute. + */ + if (route->face_name[0] != '\0') { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", + route->face_name); + } else { + rc = snprintf(msg->payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", + route->face_id); + } + + if ((rc < 0) || (rc >= SYMBOLIC_NAME_LEN)) return -1; + + return sizeof(msg_route_remove_t); +} + +/* ROUTE LIST */ + +int hicnlight_route_serialize_list(const hc_object_t *object, uint8_t *packet) { + msg_route_list_t *msg = (msg_route_list_t *)packet; + *msg = (msg_route_list_t){.header = { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_ROUTE_LIST, + .length = 0, + .seq_num = 0, + }}; + + return sizeof(msg_header_t); // Do not use msg_route_list_t +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, route); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/route.h b/ctrl/libhicnctrl/src/modules/hicn_light/route.h new file mode 100644 index 000000000..e86e8b8c3 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/route.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file modules/hicn_light/route.h + * \brief route object VFT for hicn_light. + */ + +#ifndef HICNCTRL_MODULE_HICNLIGHT_ROUTE_H +#define HICNCTRL_MODULE_HICNLIGHT_ROUTE_H + +#include "../../module.h" + +#if 1 + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, route); + +#else + +int _hicnlight_route_parse(const uint8_t *buffer, size_t size, + hc_object_t *object); +int hicnlight_route_serialize_create(const hc_object_t *object, + uint8_t *packet); +int hicnlight_route_serialize_delete(const hc_object_t *object, + uint8_t *packet); +int hicnlight_route_serialize_list(const hc_object_t *object, uint8_t *packet); + +#endif + +#endif /* HICNCTRL_MODULE_HICNLIGHT_ROUTE_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/stats.h b/ctrl/libhicnctrl/src/modules/hicn_light/stats.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/stats.h diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/strategy.c b/ctrl/libhicnctrl/src/modules/hicn_light/strategy.c new file mode 100644 index 000000000..35e241f3e --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/strategy.c @@ -0,0 +1,205 @@ +#include <assert.h> +#include "strategy.h" + +#include <hicn/ctrl/hicn-light.h> + +static int hicnlight_strategy_parse(const u8 *buffer, size_t size, + hc_strategy_t *strategy) { + return -1; +} + +int _hicnlight_strategy_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_strategy_parse(buffer, size, &object->strategy); +} + +int hicnlight_strategy_serialize_create(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_strategy_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + return -1; +} + +int hicnlight_strategy_serialize_list(const hc_object_t *object, + uint8_t *packet) { + assert(!object); + return -1; +} +#if 0 +// per prefix +static hc_result_t *_strategy_set_serialize(hc_sock_t *socket, + hc_strategy_t *strategy) { + return -1; + hc_result_t *res = malloc(sizeof(*res)); + char strategy_s[MAXSZ_HC_STRATEGY]; + strncpy(strategy->name, strategy_str(strategy->type), + MAXSZ_STRATEGY_NAME - 1); + + int rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy); + if (rc >= MAXSZ_HC_STRATEGY) + WARN("[hicnlight_strategy_create] Unexpected truncation of strategy string"); + DEBUG("[hicnlight_strategy_create] strategy=%s", strategy_s); + + if (!IS_VALID_FAMILY(strategy->family) || + !IS_VALID_STRATEGY_TYPE(strategy->type)) { + res->success = false; + return res; + } + + msg_strategy_set_t msg = {.header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_STRATEGY_SET, + .length = 1, + .seq_num = 0, + }, + .payload = { + .address = strategy->address, + .family = strategy->family, + .len = strategy->len, + .type = strategy->type, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_STRATEGY_SET, + .size_in = sizeof(cmd_strategy_set_t), + .size_out = 0, + .parse = NULL, + }; + + *res = (hc_result_t){ + .msg = + (hc_msg_t){ + .header = msg.header, + .payload.strategy_set = msg.payload, + }, + .params = params, + .async = false, + .success = true, + }; + return res; +} +#endif + +#if 0 +static hc_result_t *_strategy_add_local_prefix_serialize( + hc_sock_t *socket, hc_strategy_t *strategy) { + hc_result_t *res = malloc(sizeof(*res)); + char strategy_s[MAXSZ_HC_STRATEGY]; + strncpy(strategy->name, strategy_str(strategy->type), + MAXSZ_STRATEGY_NAME - 1); + + int rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy); + if (rc >= MAXSZ_HC_STRATEGY) + WARN("[hicnlight_strategy_create] Unexpected truncation of strategy string"); + DEBUG("[hicnlight_strategy_create] strategy=%s", strategy_s); + + if (!IS_VALID_FAMILY(strategy->family) || + !IS_VALID_STRATEGY_TYPE(strategy->type) || + !IS_VALID_FAMILY(strategy->local_family)) { + res->success = false; + return res; + } + + msg_strategy_add_local_prefix_t msg = { + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX, + .length = 1, + .seq_num = 0, + }, + .payload = { + .type = strategy->type, + .address = strategy->address, + .family = strategy->family, + .len = strategy->len, + .local_address = strategy->local_address, + .local_family = strategy->local_family, + .local_len = strategy->local_len, + }}; + + hc_command_params_t params = { + .cmd = ACTION_SET, + .cmd_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX, + .size_in = sizeof(cmd_strategy_add_local_prefix_t), + .size_out = 0, + .parse = NULL, + }; + + *res = (hc_result_t){ + .msg = + (hc_msg_t){ + .header = msg.header, + .payload.strategy_add_local_prefix = msg.payload, + }, + .params = params, + .async = false, + .success = true, + }; + return res; +} +#endif + +#if 0 +static int hicnlight_strategy_set(hc_sock_t *socket, hc_strategy_t *strategy) { + hc_result_t *result = _strategy_set_serialize(socket, strategy); + + int ret = INPUT_ERROR; + if (result->success) { + ret = hicnlight_execute_command(socket, (hc_msg_t *)&result->msg, + sizeof(result->msg), &result->params, NULL, + result->async); + } + + hc_result_free(result); + return ret; + return -1; // XXX added +} + +static int hicnlight_strategy_add_local_prefix(hc_sock_t *socket, + hc_strategy_t *strategy) { + hc_result_t *result = _strategy_add_local_prefix_serialize(socket, strategy); + + int ret = INPUT_ERROR; + if (result->success) { + ret = hicnlight_execute_command(socket, (hc_msg_t *)&result->msg, + sizeof(result->msg), &result->params, NULL, + result->async); + } + + hc_result_free(result); + return ret; + return -1; // XXX added +} + +/* How to retrieve that from the forwarder ? */ +static const char *strategies[] = { + "random", + "load_balancer", +}; + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array)) + +static int hicnlight_strategy_list(hc_sock_t *s, hc_data_t **data) { + int rc; + + *data = hc_data_create(0, sizeof(hc_strategy_t), NULL); + + for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) { + hc_strategy_t *strategy = (hc_strategy_t *)hc_data_get_next(*data); + if (!strategy) return -1; + rc = snprintf(strategy->name, MAXSZ_STRATEGY_NAME, "%s", strategies[i]); + if (rc >= MAXSZ_STRATEGY_NAME) + WARN("[hc_strategy_list] Unexpected truncation of strategy name string"); + (*data)->size++; + } + return -1; +} +#endif + +DECLARE_MODULE_OBJECT_OPS(hicnlight, strategy); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/strategy.h b/ctrl/libhicnctrl/src/modules/hicn_light/strategy.h new file mode 100644 index 000000000..6b1933960 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/strategy.h @@ -0,0 +1,24 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_STRATEGY_H +#define HICNCTRL_MODULE_HICNLIGHT_STRATEGY_H + +#include "../../module.h" + +#if 1 + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, strategy); + +int _hicnlight_strategy_parse(const uint8_t *buffer, size_t size, + hc_object_t *object); + +int hicnlight_strategy_serialize_create(const hc_object_t *object, + uint8_t *packet); + +int hicnlight_strategy_serialize_delete(const hc_object_t *object, + uint8_t *packet); + +int hicnlight_strategy_serialize_list(const hc_object_t *object, + uint8_t *packet); + +#endif + +#endif /* HICNCTRL_MODULE_HICNLIGHT_STRATEGY_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/subscription.c b/ctrl/libhicnctrl/src/modules/hicn_light/subscription.c new file mode 100644 index 000000000..d00055e89 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/subscription.c @@ -0,0 +1,66 @@ +#include <assert.h> +#include <hicn/ctrl/api.h> +#include <hicn/util/log.h> + +#include "base.h" +#include "../../object_private.h" +#include "subscription.h" + +static int hicnlight_subscription_parse(const u8 *buffer, size_t size, + hc_subscription_t *subscription) { + /* We should never have to parse subscriptions */ + return -1; +} + +int _hicnlight_subscription_parse(const uint8_t *buffer, size_t size, + hc_object_t *object) { + return hicnlight_subscription_parse(buffer, size, &object->subscription); +} + +/* SUBSCRIPTION CREATE */ + +int hicnlight_subscription_serialize_create(const hc_object_t *object, + uint8_t *packet) { + const hc_subscription_t *subscription = &object->subscription; + + msg_subscription_add_t *msg = (msg_subscription_add_t *)packet; + *msg = (msg_subscription_add_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_SUBSCRIPTION_ADD, + .length = 1, + .seq_num = 0, + }, + .payload = {.topics = subscription->topics}}; + + return sizeof(msg_subscription_add_t); +} + +/* SUBSCRIPTION DELETE */ + +int hicnlight_subscription_serialize_delete(const hc_object_t *object, + uint8_t *packet) { + const hc_subscription_t *subscription = &object->subscription; + + msg_subscription_remove_t *msg = (msg_subscription_remove_t *)packet; + *msg = (msg_subscription_remove_t){ + .header = + { + .message_type = REQUEST_LIGHT, + .command_id = COMMAND_TYPE_SUBSCRIPTION_REMOVE, + .length = 1, + .seq_num = 0, + }, + .payload = {.topics = subscription->topics}}; + + return sizeof(msg_subscription_remove_t); +} + +int hicnlight_subscription_serialize_list(const hc_object_t *object, + uint8_t *packet) { + assert(!object); + return -1; +} + +DECLARE_MODULE_OBJECT_OPS(hicnlight, subscription); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/subscription.h b/ctrl/libhicnctrl/src/modules/hicn_light/subscription.h new file mode 100644 index 000000000..a4edf556b --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/subscription.h @@ -0,0 +1,26 @@ +#ifndef HICNCTRL_MODULE_HICNLIGHT_SUBSCRIPTION_H +#define HICNCTRL_MODULE_HICNLIGHT_SUBSCRIPTION_H + +#include "../../module.h" + +#if 1 + +DECLARE_MODULE_OBJECT_OPS_H(hicnlight, subscription); + +#else + +int _hicnlight_subscription_parse(const uint8_t *buffer, size_t size, + hc_object_t *object); + +int hicnlight_subscription_serialize_create(const hc_object_t *object, + uint8_t *packet); + +int hicnlight_subscription_serialize_delete(const hc_object_t *object, + uint8_t *packet); + +int hicnlight_subscription_serialize_list(const hc_object_t *object, + uint8_t *packet); + +#endif + +#endif /* HICNCTRL_MODULE_HICNLIGHT_SUBSCRIPTION_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light/wldr.c b/ctrl/libhicnctrl/src/modules/hicn_light/wldr.c new file mode 100644 index 000000000..7d1812ab2 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_light/wldr.c @@ -0,0 +1,3 @@ +#include "wldr.h" + +static int _hcng_wldr_set(hc_sock_t *s /* XXX */) { return 0; } diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_common.h b/ctrl/libhicnctrl/src/modules/hicn_light_common.h deleted file mode 100644 index d24b5bb2d..000000000 --- a/ctrl/libhicnctrl/src/modules/hicn_light_common.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef HICNCTRL_HICN_LIGHT_COMMON -#define HICNCTRL_HICN_LIGHT_COMMON - -#include <assert.h> // assert - -#include <hicn/util/khash.h> -#include "api_private.h" - -#define PORT 9695 - -#define BOOLSTR(x) ((x) ? "true" : "false") - -/* - * Internal state associated to a pending request - */ -typedef struct { - int seq; - hc_data_t *data; - int (*parse)(const u8 *src, u8 *dst); -} hc_sock_request_t; - -/** - * Messages to the forwarder might be multiplexed thanks to the seqNum fields in - * the header_control_message structure. The forwarder simply answers back the - * original sequence number. We maintain a map of such sequence number to - * outgoing queries so that replied can be demultiplexed and treated - * appropriately. - */ -KHASH_MAP_INIT_INT(sock_map, hc_sock_request_t *); - -struct hc_sock_light_s { - /* This must be the first element of the struct */ - hc_sock_t vft; - - char *url; - int fd; - - /* Partial receive buffer */ - u8 buf[RECV_BUFLEN]; - size_t roff; /**< Read offset */ - size_t woff; /**< Write offset */ - - /* - * Because received messages are potentially unbounded in size, we might not - * guarantee that we can store a full packet before processing it. We must - * implement a very simple state machine remembering the current parsing - * status in order to partially process the packet. - */ - size_t remaining; - u32 send_id; - - /* Next sequence number to be used for requests */ - int seq; - - /* Request being parsed (NULL if none) */ - hc_sock_request_t *cur_request; - - bool async; - kh_sock_map_t *map; -}; - -typedef struct hc_sock_light_s hc_sock_light_t; - -#define TO_HC_SOCK_LIGHT(s) (hc_sock_light_t *)(s) - -hc_sock_request_t *hc_sock_request_create(int seq, hc_data_t *data, - HC_PARSE parse); - -void hc_sock_light_request_free(hc_sock_request_t *request); - -/* - * list was working with all seq set to 0, but it seems hicnLightControl uses - * 1, and replies with the same seqno - */ -#define HICN_CTRL_SEND_SEQ_INIT 1 -#define HICN_CTRL_RECV_SEQ_INIT 1 - -#define MAX(x, y) ((x > y) ? x : y) - -static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; - -#endif /* HICNCTRL_HICN_LIGHT_COMMON */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c b/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c deleted file mode 100644 index 488b2edbf..000000000 --- a/ctrl/libhicnctrl/src/modules/hicn_light_ng_api.c +++ /dev/null @@ -1,3238 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * \file api.c - * \brief Implementation of hICN control library API - */ - -#include <assert.h> // assert -#include <fcntl.h> // fcntl -#include <stdbool.h> -#include <stdio.h> // snprintf -#include <string.h> // memmove, strcasecmp -#include <sys/socket.h> // socket -#include <sys/types.h> // getpid -#include <unistd.h> // close, fcntl -#include <unistd.h> // getpid - -#include "api_private.h" -#ifdef __linux__ -#include <sys/syscall.h> -#define gettid() syscall(SYS_gettid) -#endif /* __linux__ */ -#include <hicn/ctrl/hicn-light-ng.h> -#include <strings.h> - -#include "hicn_light_common.h" -#include <hicn/util/sstrncpy.h> - -#pragma GCC diagnostic ignored "-Warray-bounds" - -#if 0 -#ifdef __APPLE__ -#define RANDBYTE() (u8)(arc4random() & 0xFF) -#else -#define RANDBYTE() (u8)(random() & 0xFF) -#endif -#endif -#define RANDBYTE() (u8)(rand() & 0xFF) - -/** - * \brief Defines the default size for the allocated data arrays holding the - * results of API calls. - * - * This size should not be too small to avoid wasting memoyy, but also not too - * big to avoid unnecessary realloc's. Later on this size is doubled at each - * reallocation. - */ -#define DEFAULT_SIZE_LOG 3 - -#define connection_state_to_face_state(x) ((face_state_t)(x)) -#define face_state_to_connection_state(x) ((hc_connection_state_t)(x)) - -/****************************************************************************** - * Message helper types and aliases - ******************************************************************************/ - -#define foreach_hc_command \ - _(connection_add) \ - _(connection_remove) \ - _(connection_list) \ - _(listener_add) \ - _(listener_remove) \ - _(listener_list) \ - _(route_add) \ - _(route_remove) \ - _(route_list) \ - _(cache_set_store) \ - _(cache_set_serve) \ - _(cache_clear) \ - _(cache_list) \ - _(strategy_set) \ - _(strategy_add_local_prefix) \ - _(wldr_set) \ - _(punting_add) \ - _(mapme_activator) \ - _(mapme_timing) \ - _(subscription_add) \ - _(subscription_remove) \ - _(stats_get) \ - _(stats_list) - -const char *command_type_str[] = { -#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u), - foreach_command_type -#undef _ -}; - -typedef cmd_header_t hc_msg_header_t; - -typedef union { -#define _(x) cmd_##x##_t x; - foreach_hc_command -#undef _ -} hc_msg_payload_t; - -typedef struct hc_msg_s { - hc_msg_header_t hdr; - hc_msg_payload_t payload; -} hc_msg_t; - -/****************************************************************************** - * Control socket - ******************************************************************************/ - -#define AVAILABLE(s) ((s)->woff - (s)->roff) -#define DEFAULT_SOCK_RECV_TIMEOUT_MS 100 - -/** - * \brief Parse a connection URL into a sockaddr - * \param [in] url - URL - * \param [out] sa - Resulting struct sockaddr, expected zero'ed. - * \return 0 if parsing succeeded, a negative error value otherwise. - */ -static int _hcng_sock_light_parse_url(const char *url, struct sockaddr *sa) { - /* FIXME URL parsing is currently not implemented */ - assert(!url); - -#ifdef __linux__ - srand(time(NULL) ^ getpid() ^ gettid()); -#else - srand((unsigned int)(time(NULL) ^ getpid())); -#endif /* __linux__ */ - - /* - * A temporary solution is to inspect the sa_family fields of the passed in - * sockaddr, which defaults to AF_UNSPEC (0) and thus creates an IPv4/TCP - * connection to localhost. - */ - switch (sa->sa_family) { - case AF_UNSPEC: - case AF_INET: { - struct sockaddr_in *sai = (struct sockaddr_in *)sa; - sai->sin_family = AF_INET; - sai->sin_port = htons(PORT); - sai->sin_addr.s_addr = htonl(INADDR_LOOPBACK); - break; - } - case AF_INET6: { - struct sockaddr_in6 *sai6 = (struct sockaddr_in6 *)sa; - sai6->sin6_family = AF_INET6; - sai6->sin6_port = htons(PORT); - sai6->sin6_addr = loopback_addr; - break; - } - default: - return -1; - } - - return 0; -} - -static int _hcng_sock_light_reset(hc_sock_t *socket) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - s->roff = s->woff = 0; - s->remaining = 0; - return 0; -} - -void _hcng_sock_light_free(hc_sock_t *socket) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - - unsigned k_seq; - hc_sock_request_t *v_request; - kh_foreach(s->map, k_seq, v_request, - { hc_sock_light_request_free(v_request); }); - - kh_destroy_sock_map(s->map); - if (s->url) free(s->url); - close(s->fd); - free(s); -} - -static void _hcng_sock_increment_woff(hc_sock_t *socket, size_t bytes) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - s->woff += bytes; -} - -static int _hcng_sock_light_get_next_seq(hc_sock_t *socket) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - return s->seq++; -} - -static int _hcng_sock_light_set_nonblocking(hc_sock_t *socket) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - return (fcntl(s->fd, F_SETFL, fcntl(s->fd, F_GETFL) | O_NONBLOCK) < 0); -} - -static int _hcng_sock_light_get_fd(hc_sock_t *socket) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - return s->fd; -} - -static int _hcng_sock_light_connect(hc_sock_t *socket) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - struct sockaddr_storage ss; - memset(&ss, 0, sizeof(struct sockaddr_storage)); - - if (_hcng_sock_light_parse_url(s->url, (struct sockaddr *)&ss) < 0) - goto ERR_PARSE; - - size_t size = ss.ss_family == AF_INET ? sizeof(struct sockaddr_in) - : sizeof(struct sockaddr_in6); - if (connect(s->fd, (struct sockaddr *)&ss, (socklen_t)size) < 0) { - perror("connect error"); - goto ERR_CONNECT; - } - return 0; - -ERR_CONNECT: -ERR_PARSE: - return -1; -} - -static int _hcng_sock_light_send(hc_sock_t *socket, hc_msg_t *msg, - size_t msglen, uint32_t seq) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - int rc; - msg->hdr.seq_num = seq; - rc = (int)send(s->fd, msg, msglen, 0); - if (rc < 0) { - perror("hc_sock_light_send"); - return -1; - } - return 0; -} - -static int _hcng_sock_light_get_available(hc_sock_t *socket, u8 **buffer, - size_t *size) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - *buffer = s->buf + s->woff; - *size = RECV_BUFLEN - s->woff; - - return 0; -} - -static int _hcng_sock_light_recv(hc_sock_t *socket) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - int rc; - - /* - * This condition should be ensured to guarantee correct processing of - * messages. With TCP, we need at least a header as we will receive part of - * the stream. With UDP, we need the be able to receive the full datagram, - * otherwise the rest will be lost. - * - * Let's be sure to always be able to receive at least 1 JUMBO_MTU, which - * should be fine for al situations. - */ - assert(RECV_BUFLEN - s->woff > JUMBO_MTU); - - rc = (int)recv(s->fd, s->buf + s->woff, RECV_BUFLEN - s->woff, 0); - if (rc == 0) { - /* Connection has been closed */ - return 0; - } - if (rc < 0) { - /* - * Let's not return 0 which currently means the socket has been closed - */ - if (errno == EWOULDBLOCK) return -1; - if (errno == EINTR) { - WARN("recv has been stopped by signal"); - return -1; - } - perror("hc_sock_light_recv"); - return -1; - } - s->woff += rc; - return rc; -} - -static void _hcng_sock_light_mark_complete(hc_sock_light_t *s, - hc_data_t **pdata) { - hc_data_t *data = s->cur_request->data; - - khiter_t k = kh_get_sock_map(s->map, s->cur_request->seq); - if (k == kh_end(s->map)) { - ERROR("[hc_sock_light_mark_complete] Error removing request from map"); - } else { - kh_del_sock_map(s->map, k); - } - - hc_data_set_complete(data); - if (pdata) *pdata = data; - - /* Free current request */ - hc_sock_light_request_free(s->cur_request); - s->cur_request = NULL; -} - -static int _hcng_sock_light_process_notification(hc_sock_light_t *s, - hc_data_t **pdata) { - /* For now, notifications are not associated to requests */ - assert(!s->cur_request); - - /* - * Assumption: the whole notification data is returned in a single read and we - * immediately parse it. - * - * XXX This is only valid for UDP sockets. - */ - size_t notification_size = AVAILABLE(s); - - *pdata = hc_data_create(0, /* in_element_size, 0 = no parsing */ - notification_size, /* out_element_size */ - NULL); /* complete_cb */ - - /* Copy the packet payload as the single entry in hc_data_t */ - hc_data_push_many(*pdata, s->buf + s->roff, 1); - - return (int)notification_size; -} - -/* - * Notifications have no sequence number and are not linked to any request - */ -static hc_sock_request_t *_hcng_sock_light_get_request(hc_sock_light_t *s, - int seq) { - hc_sock_request_t *request; - /* Retrieve request from sock map */ - khiter_t k = kh_get_sock_map(s->map, seq); - if (k == kh_end(s->map)) { - ERROR( - "[_hcng_sock_light_get_request] Error searching for matching request"); - return NULL; - } - request = kh_val(s->map, k); - - if (!request) { - ERROR("[_hcng_sock_light_get_request] No request matching sequence number"); - return NULL; - } - return request; -} - -/* - * Return codes: - * 0 success, or not enough data yet to do something - * > 0 : notification type - * -99 invalid buffer data -> flush - */ -static int _hcng_sock_light_process_header(hc_sock_light_t *s, - hc_data_t **pdata) { - int rc; - - /* Check we have at least a header's worth of data, and consume it */ - if (AVAILABLE(s) < sizeof(hc_msg_header_t)) return 0; - - hc_msg_t *msg = (hc_msg_t *)(s->buf + s->roff); - - // INFO("Processing header header %s", command_type_str(msg->hdr.command_id)); - s->roff += sizeof(hc_msg_header_t); - - if (msg->hdr.message_type != NOTIFICATION_LIGHT) { - s->cur_request = _hcng_sock_light_get_request(s, msg->hdr.seq_num); - if (!s->cur_request) return -99; - } - - /* How many elements are we expecting in the reply ? */ - s->remaining = msg->hdr.length; - hc_data_t *request_data; - - switch (msg->hdr.message_type) { - case ACK_LIGHT: - assert(s->remaining == 1); // sic - assert(!pdata); - _hcng_sock_light_mark_complete(s, pdata); - break; - - case NACK_LIGHT: - assert(!pdata); - assert(s->remaining == 1); // sic - request_data = s->cur_request->data; - _hcng_sock_light_mark_complete(s, pdata); - hc_data_set_error(request_data); - break; - - case RESPONSE_LIGHT: - assert(pdata); - - if (s->remaining == 0) { - /* Empty response (i.e. containing 0 elements) */ - _hcng_sock_light_mark_complete(s, pdata); - return 0; - } - - /* Make room in hc_data_t... to avoid multiple calls */ - rc = hc_data_ensure_available(s->cur_request->data, s->remaining); - if (rc < 0) { - ERROR("[hc_sock_light_process] Error in hc_data_ensure_available"); - return -99; - } - break; - - case NOTIFICATION_LIGHT: { - assert(pdata); - assert(s->remaining == 0); - - /* This returns the notification size */ - size_t notification_size = - _hcng_sock_light_process_notification(s, pdata); - s->roff += notification_size; - return msg->hdr.command_id; - } - - default: - ERROR("[hc_sock_light_process] Invalid response received"); - return -99; - } - - return 0; -} - -static int _hcng_sock_light_process_payload(hc_sock_light_t *s, - hc_data_t **pdata) { - int err = 0; - int rc; - - hc_data_t *data = s->cur_request->data; - - /* We only process full elements (size is stored in data) */ - size_t num_chunks = AVAILABLE(s) / data->in_element_size; - - /* Check whether we have enough data to process */ - if (num_chunks == 0) return 0; - - /* Safeguard: assert(num_chunks < s->remaining); */ - if (num_chunks > s->remaining) { - WARN( - "[_hcng_sock_light_process_payload] Unexpected num_chunks > " - "s->remaining"); - num_chunks = s->remaining; - } - - if (!s->cur_request->parse) { - /* If we don't need to parse results, then we can directly push - * all of them into the result data structure */ - hc_data_push_many(data, s->buf + s->roff, num_chunks); - } else { - /* Iterate on chunks of data */ - for (int i = 0; i < num_chunks; i++) { - /* Get storage offset in hc_data_t */ - u8 *dst = hc_data_get_next(data); - if (!dst) { - ERROR("[hc_sock_light_process] Error in hc_data_get_next"); - err = -2; - break; - } - - /* Parse element #i */ - rc = s->cur_request->parse(s->buf + s->roff + i * data->in_element_size, - dst); - if (rc < 0) { - ERROR("[hc_sock_light_process] Error in parse"); - err = -1; - /* In this case we let the loop complete to collect other results */ - } - data->size++; - } - } - - s->roff += num_chunks * data->in_element_size; - - /* - * If we are not expecting any more data, mark the reply as complete - */ - s->remaining -= num_chunks; - if (s->remaining == 0) _hcng_sock_light_mark_complete(s, pdata); - - return err; -} - -/* - * Process messages as they are received in the ring buffer. There can be - * interleaved queries and replies (they are identified by sequence number), - * and the assumption is that a reply can arrive over mutiple packets (in - * other terms, it is possible that not all data from the reply is available - * in the buffer at a given time). However, we assume that a full query is - * received at once. - */ -static int _hcng_sock_light_process(hc_sock_t *socket, hc_data_t **data) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - int rc = 0; - - /* - * We loop consuming messages until there is no more data in the buffer, - * or that we can find an entire message. Messages are received - * sequentially, and we keep track of incomplete requests in s->cur_request. - */ - while (AVAILABLE(s) > 0) { - if (!s->cur_request) { - rc = _hcng_sock_light_process_header(s, data); - } else { - rc = _hcng_sock_light_process_payload(s, data); - } - if (rc < 0) break; - } - - if ((rc == -99) || (s->roff == s->woff)) { - /* Flush buffer */ - s->woff = 0; - } else { - /* Clean up read data from buffer */ - memmove(s->buf, s->buf + s->roff, AVAILABLE(s)); - s->woff -= s->roff; - } - s->roff = 0; - - return rc; -} - -static int _hcng_sock_light_callback(hc_sock_t *socket, hc_data_t **pdata) { - hc_data_t *data = NULL; - int rc = 0; - - for (;;) { - int n = _hcng_sock_light_recv(socket); - if (n == 0) goto ERR_EOF; - if (n < 0) { - switch (errno) { - case ECONNRESET: - case ENODEV: - /* Forwarder restarted */ - WARN("Forwarder likely restarted: not (yet) implemented"); - goto ERR; - case EWOULDBLOCK: - // DEBUG("Would block... stop reading from socket"); - goto END; - case EINTR: - WARN("callback has been stopped by signal"); - goto ERR; - default: - perror("hc_sock_light_callback"); - goto ERR; - } - } - rc = _hcng_sock_light_process(socket, &data); - if (rc < 0) goto ERR; - if (rc > 0) // i.e. rc = notification type - goto END; - } -END: - if (pdata) - *pdata = data; - else - hc_data_free(data); - return rc; - -ERR: - hc_data_free(data); -ERR_EOF: - return -1; -} - -/****************************************************************************** - * Command-specific structures and functions - ******************************************************************************/ - -typedef int (*HC_PARSE)(const u8 *, u8 *); - -typedef struct { - hc_action_t cmd; - command_type_t cmd_id; - size_t size_in; - size_t size_out; - HC_PARSE parse; -} hc_command_params_t; - -typedef struct hc_result_s { - hc_msg_t msg; - hc_command_params_t params; - bool async; - bool success; -} hc_result_t; - -int _hcng_sock_prepare_send(hc_sock_t *socket, hc_result_t *result, - data_callback_t complete_cb, - void *complete_cb_data) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - - // Prepare data - hc_data_t *data = - hc_data_create(result->params.size_in, result->params.size_out, NULL); - if (!data) { - ERROR("[_hcng_sock_prepare_send] Could not create data storage"); - goto ERR_DATA; - } - hc_data_set_callback(data, complete_cb, complete_cb_data); - - // Update the sequence number - int seq = _hcng_sock_light_get_next_seq(socket); - result->msg.hdr.seq_num = seq; // Like in _hcng_sock_light_send - - // Create state used to process the request - hc_sock_request_t *request = NULL; - request = hc_sock_request_create(seq, data, result->params.parse); - if (!request) { - ERROR("[_hcng_sock_prepare_send] Could not create request state"); - goto ERR_REQUEST; - } - - int rc; - khiter_t k = kh_put_sock_map(s->map, seq, &rc); - if (rc != KH_ADDED && rc != KH_RESET) { - ERROR("[_hcng_sock_prepare_send] Error adding request state to map"); - goto ERR_MAP; - } - kh_value(s->map, k) = request; - - return sizeof(result->msg); - -ERR_MAP: - hc_sock_light_request_free(request); -ERR_REQUEST: - hc_data_free(data); -ERR_DATA: - return -99; -} - -int _hcng_sock_set_recv_timeout_ms(hc_sock_t *socket, long timeout_ms) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = (int)(timeout_ms * 1000); // Convert ms into us - if (setsockopt(s->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { - perror("setsockopt"); - return -1; - } - - return 0; -} - -static int _hcng_execute_command(hc_sock_t *socket, hc_msg_t *msg, - size_t msg_len, hc_command_params_t *params, - hc_data_t **pdata, bool async) { - hc_sock_light_t *s = TO_HC_SOCK_LIGHT(socket); - int ret; - if (async) assert(!pdata); - - /* Sanity check */ - switch (params->cmd) { - case ACTION_CREATE: - assert(params->size_in != 0); /* payload repeated */ - assert(params->size_out == 0); - assert(params->parse == NULL); - break; - case ACTION_DELETE: - assert(params->size_in != 0); /* payload repeated */ - assert(params->size_out == 0); - assert(params->parse == NULL); - break; - case ACTION_GET: - case ACTION_LIST: - assert(params->size_in != 0); - assert(params->size_out != 0); - // TODO(eloparco): Parsing should not be necessary after - // (pending) refatoring - // assert(params->parse != NULL); - break; - case ACTION_SET: - case ACTION_SERVE: - case ACTION_STORE: - case ACTION_UPDATE: - assert(params->size_in != 0); - assert(params->size_out == 0); - assert(params->parse == NULL); - break; - case ACTION_CLEAR: - assert(params->size_in == 0); - assert(params->size_out == 0); - assert(params->parse == NULL); - break; - default: - return -1; - } - - // hc_sock_light_reset(s); - - /* XXX data will at least store the result (complete) */ - hc_data_t *data = hc_data_create(params->size_in, params->size_out, NULL); - if (!data) { - ERROR("[_hcng_execute_command] Could not create data storage"); - goto ERR_DATA; - } - - int seq = _hcng_sock_light_get_next_seq(socket); - - /* Create state used to process the request */ - hc_sock_request_t *request = NULL; - request = hc_sock_request_create(seq, data, params->parse); - if (!request) { - ERROR("[_hcng_execute_command] Could not create request state"); - goto ERR_REQUEST; - } - - /* Add state to map */ - int rc; - khiter_t k = kh_put_sock_map(s->map, seq, &rc); - if (rc != KH_ADDED && rc != KH_RESET) { - ERROR("[_hcng_execute_command] Error adding request state to map"); - goto ERR_MAP; - } - kh_value(s->map, k) = request; - - if (_hcng_sock_light_send(socket, msg, msg_len, seq) < 0) { - ERROR("[_hcng_execute_command] Error sending message"); - goto ERR_PROCESS; - } - - if (async) return 0; - - /* - * Dangerous zone, we might be doing blocking operations on a non-blocking - * UDP socket - */ - int retries = 0; - while (!data->complete) { - /* - * As the socket is non blocking it might happen that we need to read - * several times before success... - */ - int n = _hcng_sock_light_recv(socket); - if (n == 0) goto ERR_EOF; - if (n < 0) { - if ((errno == EWOULDBLOCK) && (retries < 10)) { /* Max 500ms */ - DEBUG("read = EWOULDBLOCK... sleeping for 50ms (max 500ms)"); - usleep(50000); /* 50ms */ - retries++; - continue; - } - break; - } - int rc = _hcng_sock_light_process(socket, pdata); - switch (rc) { - case 0: - case -1: - break; - case -99: - ERROR("[_hcng_execute_command] Error processing socket results"); - goto ERR; - default: - ERROR("[_hcng_execute_command] Unexpected return value"); - goto ERR; - } - } - -ERR_EOF: - ret = data->ret; - if (!data->complete) return -1; - if (!pdata) hc_data_free(data); - - return ret; - -ERR_PROCESS: -ERR_MAP: - hc_sock_light_request_free(request); -ERR: -ERR_REQUEST: - hc_data_free(data); -ERR_DATA: - return -99; -} - -/*----------------------------------------------------------------------------* - * Listeners - *----------------------------------------------------------------------------*/ - -/* LISTENER CREATE */ - -static hc_result_t *_listener_create_serialize(hc_sock_t *s, - hc_listener_t *listener, - bool async) { - hc_result_t *res = malloc(sizeof(*res)); - char listener_s[MAXSZ_HC_LISTENER]; - int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener); - if (rc >= MAXSZ_HC_LISTENER) - WARN("[_hcng_listener_create] Unexpected truncation of listener string"); - DEBUG("[_hcng_listener_create] listener=%s async=%s", listener_s, - BOOLSTR(async)); - - if (hc_listener_validate(listener) < 0) { - res->success = false; - return res; - } - - msg_listener_add_t msg = {.header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_LISTENER_ADD, - .length = 1, - .seq_num = 0, - }, - .payload = { - .address = listener->local_addr, - .port = htons(listener->local_port), - .family = listener->family, - .type = listener->type, - }}; - - rc = snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", listener->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_listener_create] Unexpected truncation of symbolic name " - "string"); - - rc = snprintf(msg.payload.interface_name, INTERFACE_LEN, "%s", - listener->interface_name); - if (rc >= INTERFACE_LEN) - WARN( - "[_hc_listener_create] Unexpected truncation of interface name " - "string"); - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = COMMAND_TYPE_LISTENER_ADD, - .size_in = sizeof(cmd_listener_add_t), - .size_out = 0, - .parse = NULL, - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.listener_add = msg.payload, - }, - .params = params, - .async = async, - .success = true, - }; - return res; -} - -static hc_result_t *_hcng_listener_create_conf(hc_sock_t *s, - hc_listener_t *listener) { - return _listener_create_serialize(s, listener, false); -} - -static int _hcng_listener_create_internal(hc_sock_t *socket, - hc_listener_t *listener, bool async) { - hc_result_t *result = _listener_create_serialize(socket, listener, async); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, NULL, - result->async); - } - - free(result); - DEBUG("[_hcng_listener_create] done or error"); - return ret; -} - -static int _hcng_listener_create(hc_sock_t *s, hc_listener_t *listener) { - DEBUG("[_hcng_listener_create]"); - return _hcng_listener_create_internal(s, listener, false); -} - -static int _hcng_listener_create_async(hc_sock_t *s, hc_listener_t *listener) { - DEBUG("[_hcng_listener_create_async]"); - return _hcng_listener_create_internal(s, listener, true); -} - -/* LISTENER PARSE */ - -static int hc_listener_parse(void *in, hc_listener_t *listener) { - int rc; - cmd_listener_list_item_t *item = (cmd_listener_list_item_t *)in; - - if (!IS_VALID_ID(item->id)) { - ERROR("[hc_listener_parse] Invalid id received"); - return -1; - } - - *listener = (hc_listener_t){ - .id = item->id, - .type = item->type, - .family = item->family, - .local_addr = UNION_CAST(item->address, ip_address_t), - .local_port = ntohs(item->port), - }; - rc = snprintf(listener->name, SYMBOLIC_NAME_LEN, "%s", item->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[hc_listener_parse] Unexpected truncation of symbolic name string"); - rc = snprintf(listener->interface_name, INTERFACE_LEN, "%s", - item->interface_name); - if (rc >= INTERFACE_LEN) - WARN("[hc_listener_parse] Unexpected truncation of interface name string"); - - if (hc_listener_validate(listener) < 0) return -1; - return 0; -} - -/* LISTENER LIST */ - -static hc_result_t *_hcng_listener_list_serialize(hc_sock_t *socket, - hc_data_t **pdata, - bool async) { - hc_result_t *res = malloc(sizeof(*res)); - DEBUG("[hc_listener_list] async=%s", BOOLSTR(async)); - - msg_listener_list_t msg = {.header = { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_LISTENER_LIST, - .length = 0, - .seq_num = 0, - }}; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = COMMAND_TYPE_LISTENER_LIST, - .size_in = sizeof(cmd_listener_list_item_t), - .size_out = sizeof(hc_listener_t), - .parse = (HC_PARSE)hc_listener_parse, - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.listener_list = msg.payload, - }, - .params = params, - .async = async, - .success = true, - }; - return res; -} - -static hc_result_t *_hcng_listener_list_conf(hc_sock_t *s, hc_data_t **pdata) { - return _hcng_listener_list_serialize(s, pdata, false); -} - -static int _hcng_listener_list_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - hc_result_t *result = _hcng_listener_list_serialize(socket, pdata, async); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, pdata, - result->async); - } - - hc_result_free(result); - DEBUG("[_hcng_listener_list] done or error"); - return ret; -} - -static int _hcng_listener_list(hc_sock_t *s, hc_data_t **pdata) { - DEBUG("[_hcng_listener_list]"); - return _hcng_listener_list_internal(s, pdata, false); -} - -static int _hcng_listener_list_async(hc_sock_t *s, hc_data_t **pdata) { - DEBUG("[_hcng_listener_list_as-nc]"); - return _hcng_listener_list_internal(s, pdata, true); -} - -/* LISTENER GET */ - -static int _hcng_listener_get(hc_sock_t *socket, hc_listener_t *listener, - hc_listener_t **listener_found) { - hc_data_t *listeners; - hc_listener_t *found; - - char listener_s[MAXSZ_HC_LISTENER]; - int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener); - if (rc >= MAXSZ_HC_LISTENER) - WARN("[hc_listener_get] Unexpected truncation of listener string"); - DEBUG("[hc_listener_get] listener=%s", listener_s); - - if (_hcng_listener_list(socket, &listeners) < 0) return -1; - - /* Test */ - if (hc_listener_find(listeners, listener, &found) < 0) { - hc_data_free(listeners); - return -1; - } - - if (found) { - *listener_found = malloc(sizeof(hc_listener_t)); - if (!*listener_found) return -1; - **listener_found = *found; - } else { - *listener_found = NULL; - } - - hc_data_free(listeners); - - return 0; -} - -/* LISTENER DELETE */ - -static int _hcng_listener_delete_internal(hc_sock_t *socket, - hc_listener_t *listener, bool async) { - char listener_s[MAXSZ_HC_LISTENER]; - int rc = hc_listener_snprintf(listener_s, MAXSZ_HC_LISTENER, listener); - if (rc >= MAXSZ_HC_LISTENER) - WARN("[_hcng_listener_delete] Unexpected truncation of listener string"); - DEBUG("[_hcng_listener_delete] listener=%s async=%s", listener_s, - BOOLSTR(async)); - - msg_listener_remove_t msg = {.header = { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_LISTENER_REMOVE, - .length = 1, - .seq_num = 0, - }}; - - if (listener->id) { - rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", - listener->id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_listener_delete] Unexpected truncation of symbolic name " - "string"); - } else if (*listener->name) { - rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%s", - listener->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_listener_delete] Unexpected truncation of symbolic name " - "string"); - } else { - hc_listener_t *listener_found; - if (_hcng_listener_get(socket, listener, &listener_found) < 0) return -1; - if (!listener_found) return -1; - rc = snprintf(msg.payload.symbolicOrListenerid, SYMBOLIC_NAME_LEN, "%d", - listener_found->id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_listener_delete] Unexpected truncation of symbolic name " - "string"); - free(listener_found); - } - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = COMMAND_TYPE_LISTENER_REMOVE, - .size_in = sizeof(cmd_listener_remove_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_listener_delete(hc_sock_t *s, hc_listener_t *listener) { - return _hcng_listener_delete_internal(s, listener, false); -} - -static int _hcng_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) { - return _hcng_listener_delete_internal(s, listener, true); -} - -/*----------------------------------------------------------------------------* - * CONNECTION - *----------------------------------------------------------------------------*/ - -/* CONNECTION CREATE */ - -static hc_result_t *_connection_create_serialize(hc_sock_t *socket, - hc_connection_t *connection, - bool async) { - hc_result_t *res = malloc(sizeof(*res)); - char connection_s[MAXSZ_HC_CONNECTION]; - int rc = - hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection); - if (rc >= MAXSZ_HC_CONNECTION) - WARN( - "[_hcng_connection_create] Unexpected truncation of connection " - "string"); - DEBUG("[_hcng_connection_create] connection=%s async=%s", connection_s, - BOOLSTR(async)); - - if (hc_connection_validate(connection) < 0) { - res->success = false; - return res; - } - - msg_connection_add_t msg = {.header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CONNECTION_ADD, - .length = 1, - .seq_num = 0, - }, - .payload = { - .remote_ip = connection->remote_addr, - .local_ip = connection->local_addr, - .remote_port = htons(connection->remote_port), - .local_port = htons(connection->local_port), - .family = connection->family, - .type = connection->type, - .admin_state = connection->admin_state, -#ifdef WITH_POLICY - .priority = connection->priority, - .tags = connection->tags, -#endif /* WITH_POLICY */ - }}; - rc = - snprintf(msg.payload.symbolic, SYMBOLIC_NAME_LEN, "%s", connection->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_connection_create] Unexpected truncation of symbolic name " - "string"); - // snprintf(msg.payload.interface_name, INTERFACE_NAME_LEN, "%s", - // connection->interface_name); - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = COMMAND_TYPE_CONNECTION_ADD, - .size_in = sizeof(cmd_connection_add_t), - .size_out = 0, - .parse = NULL, - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.connection_add = msg.payload, - }, - .params = params, - .async = async, - .success = true, - }; - return res; -} - -static hc_result_t *_hcng_connection_create_conf(hc_sock_t *s, - hc_connection_t *connection) { - return _connection_create_serialize(s, connection, false); -} - -static int _hcng_connection_create_internal(hc_sock_t *socket, - hc_connection_t *connection, - bool async) { - hc_result_t *result = _connection_create_serialize(socket, connection, async); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, NULL, - result->async); - } - - hc_result_free(result); - DEBUG("[_hcng_connection_create] done or error"); - return ret; -} - -static int _hcng_connection_create(hc_sock_t *s, hc_connection_t *connection) { - DEBUG("[_hcng_connection_create]"); - return _hcng_connection_create_internal(s, connection, false); -} - -static int _hcng_connection_create_async(hc_sock_t *s, - hc_connection_t *connection) { - DEBUG("[_hcng_connection_create_async]"); - return _hcng_connection_create_internal(s, connection, true); -} - -/* CONNECTION PARSE */ - -static int hc_connection_parse(void *in, hc_connection_t *connection) { - int rc; - cmd_connection_list_item_t *item = (cmd_connection_list_item_t *)in; - - if (!IS_VALID_ID(item->id)) { - ERROR("[hc_connection_parse] Invalid id received"); - return -1; - } - - *connection = (hc_connection_t){ - .id = item->id, - .type = item->type, - .family = item->family, - .local_addr = item->local_addr, - .local_port = ntohs(item->local_port), - .remote_addr = item->remote_addr, - .remote_port = ntohs(item->remote_port), - .admin_state = item->admin_state, -#ifdef WITH_POLICY - .priority = item->priority, - .tags = item->tags, -#endif /* WITH_POLICY */ - .state = item->state, - }; - rc = snprintf(connection->name, SYMBOLIC_NAME_LEN, "%s", item->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[hc_connection_parse] Unexpected truncation of symbolic name " - "string"); - rc = snprintf(connection->interface_name, INTERFACE_LEN, "%s", - item->interface_name); - if (rc >= INTERFACE_LEN) - WARN( - "[hc_connection_parse] Unexpected truncation of interface name " - "string"); - - if (hc_connection_validate(connection) < 0) return -1; - return 0; -} - -/* CONNECTION LIST */ - -static int _hcng_connection_list_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - DEBUG("[hc_connection_list] async=%s", BOOLSTR(async)); - - msg_connection_list_t msg = {.header = { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CONNECTION_LIST, - .length = 0, - .seq_num = 0, - }}; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = COMMAND_TYPE_CONNECTION_LIST, - .size_in = sizeof(cmd_connection_list_item_t), - .size_out = sizeof(hc_connection_t), - .parse = (HC_PARSE)hc_connection_parse, - }; - - int ret = _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), - ¶ms, pdata, async); - - DEBUG("[hc_connection_list] done or error"); - return ret; -} - -static int _hcng_connection_list(hc_sock_t *s, hc_data_t **pdata) { - DEBUG("[hc_connection_list]"); - return _hcng_connection_list_internal(s, pdata, false); -} - -static int _hcng_connection_list_async(hc_sock_t *s, hc_data_t **pdata) { - DEBUG("[hc_connection_list_async]"); - return _hcng_connection_list_internal(s, pdata, true); -} - -/* CONNECTION GET */ - -static int _hcng_connection_get(hc_sock_t *socket, hc_connection_t *connection, - hc_connection_t **connection_found) { - hc_data_t *connections; - hc_connection_t *found; - - char connection_s[MAXSZ_HC_CONNECTION]; - int rc = - hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection); - if (rc >= MAXSZ_HC_CONNECTION) - WARN("[hc_connection_get] Unexpected truncation of connection string"); - DEBUG("[hc_connection_get] connection=%s", connection_s); - - if (_hcng_connection_list(socket, &connections) < 0) return -1; - - /* Test */ - if (hc_connection_find(connections, connection, &found) < 0) { - hc_data_free(connections); - return -1; - } - - if (found) { - *connection_found = malloc(sizeof(hc_connection_t)); - if (!*connection_found) return -1; - **connection_found = *found; - } else { - *connection_found = NULL; - } - - hc_data_free(connections); - - return 0; -} - -/* CONNECTION DELETE */ - -static hc_result_t *_hcng_connection_delete_serialize( - hc_sock_t *socket, hc_connection_t *connection, bool async) { - hc_result_t *res = malloc(sizeof(*res)); - res->success = false; - - char connection_s[MAXSZ_HC_CONNECTION]; - int rc = - hc_connection_snprintf(connection_s, MAXSZ_HC_CONNECTION, connection); - if (rc >= MAXSZ_HC_CONNECTION) - WARN( - "[_hcng_connection_delete] Unexpected truncation of connection " - "string"); - DEBUG("[_hcng_connection_delete] connection=%s async=%s", connection_s, - BOOLSTR(async)); - - msg_connection_remove_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CONNECTION_REMOVE, - .length = 1, - .seq_num = 0, - }, - }; - - if (connection->id) { - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", - connection->id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_connection_delete] Unexpected truncation of symbolic name " - "string"); - } else if (*connection->name) { - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", - connection->name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_connection_delete] Unexpected truncation of symbolic name " - "string"); - } else { - hc_connection_t *connection_found; - if (hc_connection_get(socket, connection, &connection_found) < 0) - return res; - if (!connection_found) return res; - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", - connection_found->id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_connection_delete] Unexpected truncation of symbolic name " - "string"); - free(connection_found); - } - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = COMMAND_TYPE_CONNECTION_REMOVE, - .size_in = sizeof(cmd_connection_remove_t), - .size_out = 0, - .parse = NULL, - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.connection_remove = msg.payload, - }, - .params = params, - .async = async, - .success = true, - }; - return res; -} - -static hc_result_t *_hcng_connection_delete_conf(hc_sock_t *s, - hc_connection_t *connection) { - return _hcng_connection_delete_serialize(s, connection, false); -} - -static int _hcng_connection_delete_internal(hc_sock_t *socket, - hc_connection_t *connection, - bool async) { - hc_result_t *result = - _hcng_connection_delete_serialize(socket, connection, async); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, NULL, - result->async); - } - - hc_result_free(result); - return ret; -} - -static int _hcng_connection_delete(hc_sock_t *s, hc_connection_t *connection) { - return _hcng_connection_delete_internal(s, connection, false); -} - -static int _hcng_connection_delete_async(hc_sock_t *s, - hc_connection_t *connection) { - return _hcng_connection_delete_internal(s, connection, true); -} - -/* CONNECTION UPDATE */ - -static int _hcng_connection_update_by_id(hc_sock_t *s, int hc_connection_id, - hc_connection_t *connection) { - // Not implemented - return -1; -} - -static int _hcng_connection_update(hc_sock_t *s, - hc_connection_t *connection_current, - hc_connection_t *connection_updated) { - // Not implemented - return -1; -} - -/* CONNECTION SET ADMIN STATE */ - -static int _hcng_connection_set_admin_state_internal( - hc_sock_t *socket, const char *conn_id_or_name, face_state_t state, - bool async) { - int rc; - DEBUG( - "[hc_connection_set_admin_state] connection_id/name=%s admin_state=%s " - "async=%s", - conn_id_or_name, face_state_str(state), BOOLSTR(async)); - - struct { - cmd_header_t hdr; - cmd_connection_set_admin_state_t payload; - } msg = { - .hdr = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE, - .length = 1, - .seq_num = 0, - }, - .payload = - { - .admin_state = state, - }, - }; - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", - conn_id_or_name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_connection_set_admin_state] Unexpected truncation of symbolic " - "name string"); - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_CONNECTION_SET_ADMIN_STATE, - .size_in = sizeof(cmd_connection_set_admin_state_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_connection_set_admin_state(hc_sock_t *s, - const char *conn_id_or_name, - face_state_t state) { - return _hcng_connection_set_admin_state_internal(s, conn_id_or_name, state, - false); -} - -static int _hcng_connection_set_admin_state_async(hc_sock_t *s, - const char *conn_id_or_name, - face_state_t state) { - return _hcng_connection_set_admin_state_internal(s, conn_id_or_name, state, - true); -} - -#ifdef WITH_POLICY - -static int _hcng_connection_set_priority_internal(hc_sock_t *socket, - const char *conn_id_or_name, - uint32_t priority, - bool async) { - int rc; - DEBUG( - "[hc_connection_set_priority] connection_id/name=%s priority=%d " - "async=%s", - conn_id_or_name, priority, BOOLSTR(async)); - struct { - cmd_header_t hdr; - cmd_connection_set_priority_t payload; - } msg = { - .hdr = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY, - .length = 1, - .seq_num = 0, - }, - .payload = - { - .priority = priority, - }, - }; - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", - conn_id_or_name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_connection_set_priority] Unexpected truncation of symbolic " - "name " - "string"); - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_CONNECTION_SET_PRIORITY, - .size_in = sizeof(cmd_connection_set_priority_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_connection_set_priority(hc_sock_t *s, - const char *conn_id_or_name, - uint32_t priority) { - return _hcng_connection_set_priority_internal(s, conn_id_or_name, priority, - false); -} - -static int _hcng_connection_set_priority_async(hc_sock_t *s, - const char *conn_id_or_name, - uint32_t priority) { - return _hcng_connection_set_priority_internal(s, conn_id_or_name, priority, - true); -} - -#endif // WITH_POLICY - -static int _hcng_connection_set_tags_internal(hc_sock_t *s, - const char *conn_id_or_name, - policy_tags_t tags, bool async) { - int rc; - DEBUG("[hc_connection_set_tags] connection_id/name=%s tags=%d async=%s", - conn_id_or_name, tags, BOOLSTR(async)); - struct { - cmd_header_t hdr; - cmd_connection_set_tags_t payload; - } msg = { - .hdr = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CONNECTION_SET_TAGS, - .length = 1, - .seq_num = 0, - }, - .payload = - { - .tags = tags, - }, - }; - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", - conn_id_or_name); - if (rc >= SYMBOLIC_NAME_LEN) - WARN( - "[_hc_connection_set_tags] Unexpected truncation of symbolic name " - "string"); - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_CONNECTION_SET_TAGS, - .size_in = sizeof(cmd_connection_set_tags_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(s, (hc_msg_t *)&msg, sizeof(msg), ¶ms, NULL, - async); -} - -static int _hcng_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags) { - return _hcng_connection_set_tags_internal(s, conn_id_or_name, tags, false); -} - -static int _hcng_connection_set_tags_async(hc_sock_t *s, - const char *conn_id_or_name, - policy_tags_t tags) { - return _hcng_connection_set_tags_internal(s, conn_id_or_name, tags, true); -} - -/*----------------------------------------------------------------------------* - * Routes - *----------------------------------------------------------------------------*/ - -/* ROUTE CREATE */ - -static hc_result_t *_route_create_serialize(hc_sock_t *socket, - hc_route_t *route, bool async) { - hc_result_t *res = malloc(sizeof(*res)); - char route_s[MAXSZ_HC_ROUTE]; - int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route); - if (rc >= MAXSZ_HC_ROUTE) - WARN("[_hc_route_create] Unexpected truncation of route string"); - if (rc < 0) - WARN("[_hc_route_create] Error building route string"); - else - DEBUG("[hc_route_create] route=%s async=%s", route_s, BOOLSTR(async)); - - if (hc_route_validate(route) < 0) { - res->success = false; - return res; - } - - msg_route_add_t msg = {.header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_ROUTE_ADD, - .length = 1, - .seq_num = 0, - }, - .payload = { - .address = route->remote_addr, - .cost = route->cost, - .family = route->family, - .len = route->len, - }}; - - /* - * The route commands expects the ID or name as part of the - * symbolic_or_connid attribute. - */ - if (route->name[0] != '\0') { - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", - route->name); - } else { - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", - route->face_id); - } - - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_route_create] Unexpected truncation of symbolic name string"); - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = COMMAND_TYPE_ROUTE_ADD, - .size_in = sizeof(cmd_route_add_t), - .size_out = 0, - .parse = NULL, - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.route_add = msg.payload, - }, - .params = params, - .async = async, - .success = true, - }; - return res; -} - -static hc_result_t *_hcng_route_create_conf(hc_sock_t *s, hc_route_t *route) { - return _route_create_serialize(s, route, false); -} - -static int _hcng_route_create_internal(hc_sock_t *socket, hc_route_t *route, - bool async) { - hc_result_t *result = _route_create_serialize(socket, route, async); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, NULL, - result->async); - } - - hc_result_free(result); - return ret; -} - -static int _hcng_route_create(hc_sock_t *s, hc_route_t *route) { - return _hcng_route_create_internal(s, route, false); -} - -static int _hcng_route_create_async(hc_sock_t *s, hc_route_t *route) { - return _hcng_route_create_internal(s, route, true); -} - -/* ROUTE DELETE */ - -static int _hcng_route_delete_internal(hc_sock_t *socket, hc_route_t *route, - bool async) { - char route_s[MAXSZ_HC_ROUTE]; - int rc = hc_route_snprintf(route_s, MAXSZ_HC_ROUTE, route); - if (rc >= MAXSZ_HC_ROUTE) - WARN("[_hc_route_delete] Unexpected truncation of route string"); - DEBUG("[hc_route_delete] route=%s async=%s", route_s, BOOLSTR(async)); - - if (!IS_VALID_FAMILY(route->family)) return -1; - - struct { - cmd_header_t hdr; - cmd_route_remove_t payload; - } msg = {.hdr = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_ROUTE_REMOVE, - .length = 1, - .seq_num = 0, - }, - .payload = { - .address = route->remote_addr, - .family = route->family, - .len = route->len, - }}; - - /* - * The route commands expects the ID or name as part of the - * symbolic_or_connid attribute. - */ - if (route->name[0] != '\0') { - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%s", - route->name); - } else { - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", - route->face_id); - } - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = COMMAND_TYPE_ROUTE_REMOVE, - .size_in = sizeof(cmd_route_remove_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_route_delete(hc_sock_t *s, hc_route_t *route) { - return _hcng_route_delete_internal(s, route, false); -} - -static int _hcng_route_delete_async(hc_sock_t *s, hc_route_t *route) { - return _hcng_route_delete_internal(s, route, true); -} - -/* ROUTE PARSE */ - -static int hc_route_parse(void *in, hc_route_t *route) { - cmd_route_list_item_t *item = (cmd_route_list_item_t *)in; - - *route = (hc_route_t){ - .name = "", /* This is not reported back */ - .face_id = item->connection_id, - .family = item->family, - .remote_addr = item->address, - .len = item->len, - .cost = item->cost, - }; - - if (hc_route_validate(route) < 0) return -1; - return 0; -} - -/* ROUTE LIST */ - -static int _hcng_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - // DEBUG("[hc_route_list] async=%s", BOOLSTR(async)); - msg_route_list_t msg = {.header = { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_ROUTE_LIST, - .length = 0, - .seq_num = 0, - }}; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = COMMAND_TYPE_ROUTE_LIST, - .size_in = sizeof(cmd_route_list_item_t), - .size_out = sizeof(hc_route_t), - .parse = (HC_PARSE)hc_route_parse, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - pdata, async); -} - -static int _hcng_route_list(hc_sock_t *s, hc_data_t **pdata) { - return _hcng_route_list_internal(s, pdata, false); -} - -static int _hcng_route_list_async(hc_sock_t *s) { - return _hcng_route_list_internal(s, NULL, true); -} - -/*----------------------------------------------------------------------------* - * Face - * - * Face support is not directly available in hicn-light, but we can offer such - * an interface through a combination of listeners and connections. The code - * starts with some conversion functions between faces/listeners/connections. - * - * We also need to make sure that there always exist a (single) listener when - *a connection is created, and in the hICN face case, that there is a single - * connection attached to this listener. - * - *----------------------------------------------------------------------------*/ - -/* FACE CREATE */ - -static int _hcng_face_create(hc_sock_t *socket, hc_face_t *face) { - hc_listener_t listener; - hc_listener_t *listener_found; - - hc_connection_t connection; - hc_connection_t *connection_found; - - char face_s[MAXSZ_HC_FACE]; - int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); - if (rc >= MAXSZ_HC_FACE) - WARN("[hc_face_create] Unexpected truncation of face string"); - DEBUG("[hc_face_create] face=%s", face_s); - - switch (face->face.type) { - case FACE_TYPE_HICN: - case FACE_TYPE_TCP: - case FACE_TYPE_UDP: - if (hc_face_to_connection(face, &connection, false) < 0) { - ERROR("[hc_face_create] Could not convert face to connection."); - return -1; - } - - /* Ensure we have a corresponding local listener */ - if (hc_connection_to_local_listener(&connection, &listener) < 0) { - ERROR("[hc_face_create] Could not convert face to local listener."); - return -1; - } - - if (_hcng_listener_get(socket, &listener, &listener_found) < 0) { - ERROR("[hc_face_create] Could not retrieve listener"); - return -1; - } - - if (!listener_found) { - /* We need to create the listener if it does not exist */ - if (hc_listener_create(socket, &listener) < 0) { - ERROR("[hc_face_create] Could not create listener."); - free(listener_found); - return -1; - } - } else { - free(listener_found); - } - - /* Create corresponding connection */ - if (_hcng_connection_create(socket, &connection) < 0) { - ERROR("[hc_face_create] Could not create connection."); - return -1; - } - - /* - * Once the connection is created, we need to list all connections - * and compare with the current one to find the created face ID. - */ - if (_hcng_connection_get(socket, &connection, &connection_found) < 0) { - ERROR("[hc_face_create] Could not retrieve connection"); - return -1; - } - - if (!connection_found) { - ERROR("[hc_face_create] Could not find newly created connection."); - return -1; - } - - face->id = connection_found->id; - free(connection_found); - - break; - - case FACE_TYPE_HICN_LISTENER: - case FACE_TYPE_TCP_LISTENER: - case FACE_TYPE_UDP_LISTENER: - if (hc_face_to_listener(face, &listener) < 0) { - ERROR("Could not convert face to listener."); - return -1; - } - if (hc_listener_create(socket, &listener) < 0) { - ERROR("[hc_face_create] Could not create listener."); - return -1; - } - break; - default: - ERROR("[hc_face_create] Unknwon face type."); - - return -1; - }; - - return 0; -} - -static int _hcng_face_get(hc_sock_t *socket, hc_face_t *face, - hc_face_t **face_found) { - hc_listener_t listener; - hc_listener_t *listener_found; - - hc_connection_t connection; - hc_connection_t *connection_found; - - char face_s[MAXSZ_HC_FACE]; - int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); - if (rc >= MAXSZ_HC_FACE) - WARN("[hc_face_get] Unexpected truncation of face string"); - DEBUG("[hc_face_get] face=%s", face_s); - - switch (face->face.type) { - case FACE_TYPE_HICN: - case FACE_TYPE_TCP: - case FACE_TYPE_UDP: - if (hc_face_to_connection(face, &connection, false) < 0) return -1; - if (_hcng_connection_get(socket, &connection, &connection_found) < 0) - return -1; - if (!connection_found) { - *face_found = NULL; - return 0; - } - *face_found = malloc(sizeof(hc_face_t)); - hc_connection_to_face(connection_found, *face_found); - free(connection_found); - break; - - case FACE_TYPE_HICN_LISTENER: - case FACE_TYPE_TCP_LISTENER: - case FACE_TYPE_UDP_LISTENER: - if (hc_face_to_listener(face, &listener) < 0) return -1; - if (_hcng_listener_get(socket, &listener, &listener_found) < 0) return -1; - if (!listener_found) { - *face_found = NULL; - return 0; - } - *face_found = malloc(sizeof(hc_face_t)); - hc_listener_to_face(listener_found, *face_found); - free(listener_found); - break; - - default: - return -1; - } - - return 0; -} - -/* FACE DELETE */ - -static int _hcng_face_delete(hc_sock_t *socket, hc_face_t *face, - uint8_t delete_listener) { - char face_s[MAXSZ_HC_FACE]; - int rc = hc_face_snprintf(face_s, MAXSZ_HC_FACE, face); - if (rc >= MAXSZ_HC_FACE) - WARN("[hc_face_delete] Unexpected truncation of face string"); - DEBUG("[hc_face_delete] face=%s", face_s); - - hc_connection_t connection; - if (hc_face_to_connection(face, &connection, false) < 0) { - ERROR("[hc_face_delete] Could not convert face to connection."); - return -1; - } - - if (_hcng_connection_delete(socket, &connection) < 0) { - ERROR("[hc_face_delete] Error removing connection"); - return -1; - } - - if (!delete_listener) { - return 0; - } - - /* If this is the last connection attached to the listener, remove it */ - - hc_data_t *connections; - hc_listener_t listener = {{0}}; - - /* - * Ensure we have a corresponding local listener - * NOTE: hc_face_to_listener is not appropriate - */ - if (hc_connection_to_local_listener(&connection, &listener) < 0) { - ERROR("[hc_face_create] Could not convert face to local listener."); - return -1; - } -#if 1 - /* - * The name is generated to prepare listener creation, we need it to be - * empty for deletion. The id should not need to be reset though. - */ - listener.id = 0; - memset(listener.name, 0, sizeof(listener.name)); -#endif - if (_hcng_connection_list(socket, &connections) < 0) { - ERROR("[hc_face_delete] Error getting the list of listeners"); - return -1; - } - - bool delete = true; - foreach_connection(c, connections) { - if ((ip_address_cmp(&c->local_addr, &listener.local_addr, c->family) == - 0) && - (c->local_port == listener.local_port) && - (strcmp(c->interface_name, listener.interface_name) == 0)) { - delete = false; - } - } - - if (delete) { - if (_hcng_listener_delete(socket, &listener) < 0) { - ERROR("[hc_face_delete] Error removing listener"); - return -1; - } - } - - hc_data_free(connections); - - return 0; -} - -/* FACE LIST */ - -static int _hcng_face_list(hc_sock_t *socket, hc_data_t **pdata) { - hc_data_t *connection_data; - hc_face_t face; - - DEBUG("[hc_face_list]"); - - if (_hcng_connection_list(socket, &connection_data) < 0) { - ERROR("[hc_face_list] Could not list connections."); - return -1; - } - - hc_data_t *face_data = - hc_data_create(sizeof(hc_connection_t), sizeof(hc_face_t), NULL); - foreach_connection(c, connection_data) { - if (hc_connection_to_face(c, &face) < 0) { - ERROR("[hc_face_list] Could not convert connection to face."); - goto ERR; - } - hc_data_push(face_data, &face); - } - - *pdata = face_data; - hc_data_free(connection_data); - DEBUG("[hc_face_list] done"); - return 0; - -ERR: - hc_data_free(connection_data); - DEBUG("[hc_face_list] error"); - return -1; -} - -static int hc_connection_parse_to_face(void *in, hc_face_t *face) { - hc_connection_t connection; - - if (hc_connection_parse(in, &connection) < 0) { - ERROR("[hc_connection_parse_to_face] Could not parse connection"); - return -1; - } - - if (hc_connection_to_face(&connection, face) < 0) { - ERROR( - "[hc_connection_parse_to_face] Could not convert connection to " - "face."); - return -1; - } - - return 0; -} - -static int _hcng_face_list_async(hc_sock_t *socket) { - struct { - cmd_header_t hdr; - } msg = { - .hdr = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CONNECTION_LIST, - .length = 0, - .seq_num = 0, - }, - }; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = COMMAND_TYPE_CONNECTION_LIST, - .size_in = sizeof(cmd_connection_list_item_t), - .size_out = sizeof(hc_face_t), - .parse = (HC_PARSE)hc_connection_parse_to_face, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, true); -} - -static int _hcng_face_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, - face_state_t admin_state) { - return hc_connection_set_admin_state(s, conn_id_or_name, admin_state); -} - -#ifdef WITH_POLICY -static int _hcng_face_set_priority(hc_sock_t *s, const char *conn_id_or_name, - uint32_t priority) { - return hc_connection_set_priority(s, conn_id_or_name, priority); -} - -static int _hcng_face_set_tags(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags) { - return hc_connection_set_tags(s, conn_id_or_name, tags); -} -#endif // WITH_POLICY - -/*----------------------------------------------------------------------------* - * Punting - *----------------------------------------------------------------------------*/ - -static int _hcng_punting_create_internal(hc_sock_t *socket, - hc_punting_t *punting, bool async) { - int rc; - - if (hc_punting_validate(punting) < 0) return -1; - - struct { - cmd_header_t hdr; - cmd_punting_add_t payload; - } msg = {.hdr = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_PUNTING_ADD, - .length = 1, - .seq_num = 0, - }, - .payload = { - .address = punting->prefix, - .family = punting->family, - .len = punting->prefix_len, - }}; - rc = snprintf(msg.payload.symbolic_or_connid, SYMBOLIC_NAME_LEN, "%d", - punting->face_id); - if (rc >= SYMBOLIC_NAME_LEN) - WARN("[_hc_punting_create] Unexpected truncation of symbolic name string"); - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = COMMAND_TYPE_PUNTING_ADD, - .size_in = sizeof(cmd_punting_add_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_punting_create(hc_sock_t *s, hc_punting_t *punting) { - return _hcng_punting_create_internal(s, punting, false); -} - -static int _hcng_punting_create_async(hc_sock_t *s, hc_punting_t *punting) { - return _hcng_punting_create_internal(s, punting, true); -} - -static int _hcng_punting_get(hc_sock_t *s, hc_punting_t *punting, - hc_punting_t **punting_found) { - ERROR("hc_punting_get not (yet) implemented."); - return -1; -} - -static int _hcng_punting_delete(hc_sock_t *s, hc_punting_t *punting) { - ERROR("hc_punting_delete not (yet) implemented."); - return -1; -} - -#if 0 -static int hc_punting_parse(void * in, hc_punting_t * punting) -{ - ERROR("hc_punting_parse not (yet) implemented."); - return -1; -} -#endif - -static int _hcng_punting_list(hc_sock_t *s, hc_data_t **pdata) { - ERROR("hc_punting_list not (yet) implemented."); - return -1; -} - -/*----------------------------------------------------------------------------* - * Cache - *----------------------------------------------------------------------------*/ - -/* CACHE SET STORE */ - -static int _hcng_cache_set_store_internal(hc_sock_t *socket, hc_cache_t *cache, - bool async) { - msg_cache_set_store_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CACHE_SET_STORE, - .length = 1, - .seq_num = 0, - }, - .payload = { - .activate = cache->store, - }}; - - hc_command_params_t params = { - .cmd = ACTION_STORE, - .cmd_id = COMMAND_TYPE_CACHE_SET_STORE, - .size_in = sizeof(cmd_cache_set_store_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_cache_set_store(hc_sock_t *s, hc_cache_t *cache) { - return _hcng_cache_set_store_internal(s, cache, false); -} - -static int _hcng_cache_set_store_async(hc_sock_t *s, hc_cache_t *cache) { - return _hcng_cache_set_store_internal(s, cache, true); -} - -/* CACHE SET SERVE */ - -static int _hcng_cache_set_serve_internal(hc_sock_t *socket, hc_cache_t *cache, - bool async) { - msg_cache_set_serve_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CACHE_SET_SERVE, - .length = 1, - .seq_num = 0, - }, - .payload = { - .activate = cache->serve, - }}; - - hc_command_params_t params = { - .cmd = ACTION_SERVE, - .cmd_id = COMMAND_TYPE_CACHE_SET_SERVE, - .size_in = sizeof(cmd_cache_set_serve_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) { - return _hcng_cache_set_serve_internal(s, cache, false); -} - -static int _hcng_cache_set_serve_async(hc_sock_t *s, hc_cache_t *cache) { - return _hcng_cache_set_serve_internal(s, cache, true); -} - -/* CACHE CLEAR */ - -static int _hcng_cache_clear_internal(hc_sock_t *socket, hc_cache_t *cache, - bool async) { - msg_cache_clear_t msg = {.header = { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CACHE_CLEAR, - .length = 1, - .seq_num = 0, - }}; - - hc_command_params_t params = { - .cmd = ACTION_CLEAR, - .cmd_id = COMMAND_TYPE_CACHE_CLEAR, - .size_in = sizeof(cmd_cache_clear_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_cache_clear(hc_sock_t *s, hc_cache_t *cache) { - return _hcng_cache_clear_internal(s, cache, false); -} - -/* CACHE PARSE */ - -static int hc_cache_parse(void *in, hc_cache_info_t *cache_info) { - cmd_cache_list_reply_t *item = (cmd_cache_list_reply_t *)in; - *cache_info = (hc_cache_info_t){.store = item->store_in_cs, - .serve = item->serve_from_cs, - .cs_size = item->cs_size, - .num_stale_entries = item->num_stale_entries}; - - return 0; -} - -/* CACHE LIST */ - -static hc_result_t *_hcng_cache_list_serialize(hc_sock_t *socket, - hc_data_t **pdata, bool async) { - hc_result_t *res = malloc(sizeof(*res)); - DEBUG("[hc_cache_list] async=%s", BOOLSTR(async)); - - msg_cache_list_t msg = {.header = { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_CACHE_LIST, - .length = 0, - .seq_num = 0, - }}; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = COMMAND_TYPE_CACHE_LIST, - .size_in = sizeof(cmd_cache_list_reply_t), - .size_out = sizeof(hc_cache_info_t), - .parse = (HC_PARSE)hc_cache_parse, - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.cache_list = msg.payload, - }, - .params = params, - .async = async, - .success = true, - }; - return res; -} - -static int _hcng_cache_list_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - hc_result_t *result = _hcng_cache_list_serialize(socket, pdata, async); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, pdata, - result->async); - } - - hc_result_free(result); - return ret; -} - -static int _hcng_cache_list(hc_sock_t *s, hc_data_t **pdata) { - return _hcng_cache_list_internal(s, pdata, false); -} - -/*----------------------------------------------------------------------------* - * Strategy - *----------------------------------------------------------------------------*/ - -// per prefix -static hc_result_t *_strategy_set_serialize(hc_sock_t *socket, - hc_strategy_t *strategy) { - hc_result_t *res = malloc(sizeof(*res)); - - char strategy_s[MAXSZ_HC_STRATEGY]; - int rc = strcpy_s(strategy->name, MAXSZ_STRATEGY_NAME, - strategy_str(strategy->type)); - if (rc != EOK) goto ERR; - rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy); - if (rc >= MAXSZ_HC_STRATEGY) - WARN("[_hcng_strategy_create] Unexpected truncation of strategy string"); - DEBUG("[_hcng_strategy_create] strategy=%s", strategy_s); - - if (!IS_VALID_FAMILY(strategy->family) || - !IS_VALID_STRATEGY_TYPE(strategy->type)) { - goto ERR; - } - - msg_strategy_set_t msg = {.header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_STRATEGY_SET, - .length = 1, - .seq_num = 0, - }, - .payload = { - .address = strategy->address, - .family = strategy->family, - .len = strategy->len, - .type = strategy->type, - }}; - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_STRATEGY_SET, - .size_in = sizeof(cmd_strategy_set_t), - .size_out = 0, - .parse = NULL, - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.strategy_set = msg.payload, - }, - .params = params, - .async = false, - .success = true, - }; - return res; - -ERR: - res->success = false; - return res; -} - -static hc_result_t *_strategy_add_local_prefix_serialize( - hc_sock_t *socket, hc_strategy_t *strategy) { - hc_result_t *res = malloc(sizeof(*res)); - - char strategy_s[MAXSZ_HC_STRATEGY]; - int rc = strcpy_s(strategy->name, MAXSZ_STRATEGY_NAME, - strategy_str(strategy->type)); - if (rc != EOK) goto ERR; - rc = hc_strategy_snprintf(strategy_s, MAXSZ_HC_STRATEGY, strategy); - if (rc >= MAXSZ_HC_STRATEGY) - WARN("[_hcng_strategy_create] Unexpected truncation of strategy string"); - DEBUG("[_hcng_strategy_create] strategy=%s", strategy_s); - - if (!IS_VALID_FAMILY(strategy->family) || - !IS_VALID_STRATEGY_TYPE(strategy->type) || - !IS_VALID_FAMILY(strategy->local_family)) { - goto ERR; - } - - msg_strategy_add_local_prefix_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX, - .length = 1, - .seq_num = 0, - }, - .payload = { - .type = strategy->type, - .address = strategy->address, - .family = strategy->family, - .len = strategy->len, - .local_address = strategy->local_address, - .local_family = strategy->local_family, - .local_len = strategy->local_len, - }}; - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_STRATEGY_ADD_LOCAL_PREFIX, - .size_in = sizeof(cmd_strategy_add_local_prefix_t), - .size_out = 0, - .parse = NULL, - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.strategy_add_local_prefix = msg.payload, - }, - .params = params, - .async = false, - .success = true, - }; - return res; - -ERR: - res->success = false; - return res; -} - -static hc_result_t *_hcng_strategy_set_conf(hc_sock_t *s, - hc_strategy_t *strategy) { - return _strategy_set_serialize(s, strategy); -} - -static int _hcng_strategy_set(hc_sock_t *socket, hc_strategy_t *strategy) { - hc_result_t *result = _strategy_set_serialize(socket, strategy); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, NULL, - result->async); - } - - hc_result_free(result); - return ret; -} - -static hc_result_t *_hcng_strategy_add_local_prefix_conf( - hc_sock_t *s, hc_strategy_t *strategy) { - return _strategy_add_local_prefix_serialize(s, strategy); -} - -static int _hcng_strategy_add_local_prefix(hc_sock_t *socket, - hc_strategy_t *strategy) { - hc_result_t *result = _strategy_add_local_prefix_serialize(socket, strategy); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, NULL, - result->async); - } - - hc_result_free(result); - return ret; -} - -/* How to retrieve that from the forwarder ? */ -static const char *strategies[] = { - "random", - "load_balancer", -}; - -#define ARRAY_SIZE(array) (sizeof(array) / sizeof(*array)) - -static int _hcng_strategy_list(hc_sock_t *s, hc_data_t **data) { - int rc; - - *data = hc_data_create(0, sizeof(hc_strategy_t), NULL); - - for (unsigned i = 0; i < ARRAY_SIZE(strategies); i++) { - hc_strategy_t *strategy = (hc_strategy_t *)hc_data_get_next(*data); - if (!strategy) return -1; - rc = snprintf(strategy->name, MAXSZ_STRATEGY_NAME, "%s", strategies[i]); - if (rc >= MAXSZ_STRATEGY_NAME) - WARN("[hc_strategy_list] Unexpected truncation of strategy name string"); - (*data)->size++; - } - - return 0; -} - -/*----------------------------------------------------------------------------* - * WLDR - *----------------------------------------------------------------------------*/ - -// per connection -static int _hcng_wldr_set(hc_sock_t *s /* XXX */) { return 0; } - -/*----------------------------------------------------------------------------* - * MAP-Me - *----------------------------------------------------------------------------*/ - -static int _hcng_mapme_set(hc_sock_t *socket, int enabled) { - msg_mapme_enable_t msg = {.header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_MAPME_ENABLE, - .length = 1, - .seq_num = 0, - }, - .payload = { - .activate = enabled, - }}; - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_MAPME_ENABLE, - .size_in = sizeof(cmd_mapme_enable_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, false); -} - -static int _hcng_mapme_set_discovery(hc_sock_t *socket, int enabled) { - msg_mapme_enable_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_MAPME_SET_DISCOVERY, - .length = 1, - .seq_num = 0, - }, - .payload = { - .activate = enabled, - }}; - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_MAPME_SET_DISCOVERY, - .size_in = sizeof(cmd_mapme_set_discovery_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, false); -} - -static int _hcng_mapme_set_timescale(hc_sock_t *socket, uint32_t timescale) { - msg_mapme_set_timescale_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_MAPME_SET_TIMESCALE, - .length = 1, - .seq_num = 0, - }, - .payload = { - .timePeriod = timescale, - }}; - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_MAPME_SET_TIMESCALE, - .size_in = sizeof(cmd_mapme_set_timescale_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, false); -} - -static int _hcng_mapme_set_retx(hc_sock_t *socket, uint32_t timescale) { - msg_mapme_set_retx_t msg = {.header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_MAPME_SET_RETX, - .length = 1, - .seq_num = 0, - }, - .payload = { - .timePeriod = timescale, - }}; - - hc_command_params_t params = { - .cmd = ACTION_SET, - .cmd_id = COMMAND_TYPE_MAPME_SET_RETX, - .size_in = sizeof(msg_mapme_set_retx_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, false); -} - -static int _hcng_mapme_send_update(hc_sock_t *socket, hc_mapme_t *mapme) { - if (!IS_VALID_FAMILY(mapme->family)) return -1; - - msg_mapme_send_update_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_MAPME_SEND_UPDATE, - .length = 1, - .seq_num = 0, - }, - }; - - hc_command_params_t params = { - .cmd = ACTION_UPDATE, - .cmd_id = COMMAND_TYPE_MAPME_SEND_UPDATE, - .size_in = sizeof(msg_mapme_send_update_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, false); -} - -/*----------------------------------------------------------------------------* - * Policy - *----------------------------------------------------------------------------*/ - -#ifdef WITH_POLICY - -/* POLICY CREATE */ - -static int _hcng_policy_create_internal(hc_sock_t *socket, hc_policy_t *policy, - bool async) { - if (!IS_VALID_FAMILY(policy->family)) return -1; - - struct { - cmd_header_t hdr; - cmd_policy_add_t payload; - } msg = {.hdr = - { - .message_type = REQUEST_LIGHT, - COMMAND_TYPE_POLICY_ADD, - .length = 1, - .seq_num = 0, - }, - .payload = { - .address = policy->remote_addr, - .family = policy->family, - .len = policy->len, - .policy = policy->policy, - }}; - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = COMMAND_TYPE_POLICY_ADD, - .size_in = sizeof(cmd_policy_add_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_policy_create(hc_sock_t *s, hc_policy_t *policy) { - return _hcng_policy_create_internal(s, policy, false); -} - -static int _hcng_policy_create_async(hc_sock_t *s, hc_policy_t *policy) { - return _hcng_policy_create_internal(s, policy, true); -} - -/* POLICY DELETE */ - -static int _hcng_policy_delete_internal(hc_sock_t *socket, hc_policy_t *policy, - bool async) { - if (!IS_VALID_FAMILY(policy->family)) return -1; - - struct { - cmd_header_t hdr; - cmd_policy_remove_t payload; - } msg = {.hdr = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_POLICY_REMOVE, - .length = 1, - .seq_num = 0, - }, - .payload = { - .address = policy->remote_addr, - .family = policy->family, - .len = policy->len, - }}; - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = COMMAND_TYPE_POLICY_REMOVE, - .size_in = sizeof(cmd_policy_remove_t), - .size_out = 0, - .parse = NULL, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - NULL, async); -} - -static int _hcng_policy_delete(hc_sock_t *s, hc_policy_t *policy) { - return _hcng_policy_delete_internal(s, policy, false); -} - -static int _hcng_policy_delete_async(hc_sock_t *s, hc_policy_t *policy) { - return _hcng_policy_delete_internal(s, policy, true); -} - -/* POLICY PARSE */ - -static int hc_policy_parse(void *in, hc_policy_t *policy) { - cmd_policy_list_item_t *item = (cmd_policy_list_item_t *)in; - - if (!IS_VALID_ADDRESS(&item->address, item->family)) { - ERROR("[hc_policy_parse] Invalid address"); - return -1; - } - if (!IS_VALID_FAMILY(item->family)) { - ERROR("[hc_policy_parse] Invalid family"); - return -1; - } - if (!IS_VALID_PREFIX_LEN(item->len)) { - ERROR("[hc_policy_parse] Invalid len"); - return -1; - } - if (!IS_VALID_POLICY(item->policy)) { - ERROR("[hc_policy_parse] Invalid policy"); - return -1; - } - - *policy = (hc_policy_t){ - .family = item->family, - .remote_addr = item->address, - .len = item->len, - .policy = item->policy, - }; - return 0; -} - -/* POLICY LIST */ - -static int _hcng_policy_list_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - struct { - cmd_header_t hdr; - } msg = { - .hdr = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_POLICY_LIST, - .length = 0, - .seq_num = 0, - }, - }; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = COMMAND_TYPE_POLICY_LIST, - .size_in = sizeof(cmd_policy_list_item_t), - .size_out = sizeof(hc_policy_t), - .parse = (HC_PARSE)hc_policy_parse, - }; - - return _hcng_execute_command(socket, (hc_msg_t *)&msg, sizeof(msg), ¶ms, - pdata, async); -} - -static int _hcng_policy_list(hc_sock_t *s, hc_data_t **pdata) { - return _hcng_policy_list_internal(s, pdata, false); -} - -static int _hcng_policy_list_async(hc_sock_t *s, hc_data_t **pdata) { - return _hcng_policy_list_internal(s, pdata, true); -} - -#endif /* WITH_POLICY */ - -/*----------------------------------------------------------------------------* - * Subscriptioins - *----------------------------------------------------------------------------*/ - -/* SUBSCRIPTION CREATE */ - -static hc_result_t *_subscription_create_serialize( - hc_sock_t *s, hc_subscription_t *subscription) { - msg_subscription_add_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_SUBSCRIPTION_ADD, - .length = 1, - .seq_num = 0, - }, - .payload = {.topics = subscription->topics}}; - - hc_command_params_t params = { - .cmd = ACTION_CREATE, - .cmd_id = COMMAND_TYPE_SUBSCRIPTION_ADD, - .size_in = sizeof(cmd_subscription_add_t), - .size_out = 0, - .parse = NULL, - }; - - hc_result_t *res = malloc(sizeof(*res)); - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.subscription_add = msg.payload, - }, - .params = params, - .async = false, - .success = true, - }; - return res; -} - -static hc_result_t *_hcng_subscription_create_conf( - hc_sock_t *s, hc_subscription_t *subscription) { - return _subscription_create_serialize(s, subscription); -} - -static int _hcng_subscription_create(hc_sock_t *socket, - hc_subscription_t *subscriiption) { - hc_result_t *result = _subscription_create_serialize(socket, subscriiption); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, NULL, - result->async); - } - - hc_result_free(result); - return ret; -} - -/* SUBSCRIPTION DELETE */ - -static hc_result_t *_subscription_delete_serialize( - hc_sock_t *s, hc_subscription_t *subscription) { - msg_subscription_remove_t msg = { - .header = - { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_SUBSCRIPTION_REMOVE, - .length = 1, - .seq_num = 0, - }, - .payload = {.topics = subscription->topics}}; - - hc_command_params_t params = { - .cmd = ACTION_DELETE, - .cmd_id = COMMAND_TYPE_SUBSCRIPTION_REMOVE, - .size_in = sizeof(cmd_subscription_remove_t), - .size_out = 0, - .parse = NULL, - }; - - hc_result_t *res = malloc(sizeof(*res)); - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.subscription_remove = msg.payload, - }, - .params = params, - .async = false, - .success = true, - }; - return res; -} - -static hc_result_t *_hcng_subscription_delete_conf( - hc_sock_t *s, hc_subscription_t *subscription) { - return _subscription_delete_serialize(s, subscription); -} - -static int _hcng_subscription_delete(hc_sock_t *socket, - hc_subscription_t *subscriiption) { - hc_result_t *result = _subscription_delete_serialize(socket, subscriiption); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, NULL, - result->async); - } - - hc_result_free(result); - return ret; -} - -/*----------------------------------------------------------------------------* - * Statistics - *----------------------------------------------------------------------------*/ - -/* STATS GET */ - -static hc_result_t *_hcng_stats_get_serialize(hc_sock_t *socket, - hc_data_t **pdata, bool async) { - hc_result_t *res = malloc(sizeof(*res)); - DEBUG("[hc_stats_get] async=%s", BOOLSTR(async)); - - msg_stats_get_t msg = {.header = { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_STATS_GET, - .length = 0, - .seq_num = 0, - }}; - - hc_command_params_t params = { - .cmd = ACTION_GET, - .cmd_id = COMMAND_TYPE_STATS_GET, - .size_in = sizeof(hicn_light_stats_t), - .size_out = sizeof(hicn_light_stats_t), - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.stats_get = msg.payload, - }, - .params = params, - .async = async, - .success = true, - }; - return res; -} - -static int _hcng_stats_get_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - hc_result_t *result = _hcng_stats_get_serialize(socket, pdata, async); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, pdata, - result->async); - } - - hc_result_free(result); - DEBUG("[_hcng_stats_get] done or error"); - return ret; -} - -static int _hcng_stats_get(hc_sock_t *s, hc_data_t **pdata) { - DEBUG("[_hcng_stats_get]"); - return _hcng_stats_get_internal(s, pdata, false); -} - -/* STATS LIST */ - -static hc_result_t *_hcng_stats_list_serialize(hc_sock_t *socket, - hc_data_t **pdata, bool async) { - hc_result_t *res = malloc(sizeof(*res)); - DEBUG("[hc_stats_list] async=%s", BOOLSTR(async)); - - msg_stats_list_t msg = {.header = { - .message_type = REQUEST_LIGHT, - .command_id = COMMAND_TYPE_STATS_LIST, - .length = 0, - .seq_num = 0, - }}; - - hc_command_params_t params = { - .cmd = ACTION_LIST, - .cmd_id = COMMAND_TYPE_STATS_LIST, - .size_in = sizeof(cmd_stats_list_item_t), - .size_out = sizeof(cmd_stats_list_item_t), - }; - - *res = (hc_result_t){ - .msg = - (hc_msg_t){ - .hdr = msg.header, - .payload.stats_list = msg.payload, - }, - .params = params, - .async = async, - .success = true, - }; - return res; -} - -static int _hcng_stats_list_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - hc_result_t *result = _hcng_stats_list_serialize(socket, pdata, async); - - int ret = INPUT_ERROR; - if (result->success) { - ret = _hcng_execute_command(socket, (hc_msg_t *)&result->msg, - sizeof(result->msg), &result->params, pdata, - result->async); - } - - hc_result_free(result); - DEBUG("[_hcng_stats_list] done or error"); - return ret; -} - -static int _hcng_stats_list(hc_sock_t *s, hc_data_t **pdata) { - DEBUG("[_hcng_stats_list]"); - return _hcng_stats_list_internal(s, pdata, false); -} - -/* RESULT */ -hc_msg_t *_hcng_result_get_msg(hc_result_t *result) { return &result->msg; } -int _hcng_result_get_cmd_id(hc_result_t *result) { - return result->params.cmd_id; -} -bool _hcng_result_get_success(hc_result_t *result) { return result->success; } - -static hc_sock_t hc_sock_light_ng_interface = (hc_sock_t){ - .hc_sock_get_next_seq = _hcng_sock_light_get_next_seq, - .hc_sock_set_nonblocking = _hcng_sock_light_set_nonblocking, - .hc_sock_get_fd = _hcng_sock_light_get_fd, - .hc_sock_connect = _hcng_sock_light_connect, - .hc_sock_get_available = _hcng_sock_light_get_available, - .hc_sock_send = _hcng_sock_light_send, - .hc_sock_recv = _hcng_sock_light_recv, - .hc_sock_process = _hcng_sock_light_process, - .hc_sock_callback = _hcng_sock_light_callback, - .hc_sock_reset = _hcng_sock_light_reset, - .hc_sock_free = _hcng_sock_light_free, - .hc_sock_increment_woff = _hcng_sock_increment_woff, - .hc_sock_prepare_send = _hcng_sock_prepare_send, - .hc_sock_set_recv_timeout_ms = _hcng_sock_set_recv_timeout_ms, - .hc_listener_create = _hcng_listener_create, - .hc_listener_create_async = _hcng_listener_create_async, - .hc_listener_get = _hcng_listener_get, - .hc_listener_delete = _hcng_listener_delete, - .hc_listener_delete_async = _hcng_listener_delete_async, - .hc_listener_list = _hcng_listener_list, - .hc_listener_list_async = _hcng_listener_list_async, - .hc_connection_create = _hcng_connection_create, - .hc_connection_create_async = _hcng_connection_create_async, - .hc_connection_get = _hcng_connection_get, - .hc_connection_update_by_id = _hcng_connection_update_by_id, - .hc_connection_update = _hcng_connection_update, - .hc_connection_delete = _hcng_connection_delete, - .hc_connection_delete_async = _hcng_connection_delete_async, - .hc_connection_list = _hcng_connection_list, - .hc_connection_list_async = _hcng_connection_list_async, - .hc_connection_set_admin_state = _hcng_connection_set_admin_state, - .hc_connection_set_admin_state_async = - _hcng_connection_set_admin_state_async, - -#ifdef WITH_POLICY - .hc_connection_set_priority = _hcng_connection_set_priority, - .hc_connection_set_priority_async = _hcng_connection_set_priority_async, - .hc_connection_set_tags = _hcng_connection_set_tags, - .hc_connection_set_tags_async = _hcng_connection_set_tags_async, -#endif // WITH_POLICY - - .hc_face_create = _hcng_face_create, - .hc_face_get = _hcng_face_get, - .hc_face_delete = _hcng_face_delete, - .hc_face_list = _hcng_face_list, - .hc_face_list_async = _hcng_face_list_async, - .hc_face_set_admin_state = _hcng_face_set_admin_state, - -#ifdef WITH_POLICY - .hc_face_set_priority = _hcng_face_set_priority, - .hc_face_set_tags = _hcng_face_set_tags, -#endif // WITH_POLICY - .hc_subscription_create = _hcng_subscription_create, - .hc_subscription_delete = _hcng_subscription_delete, - - .hc_stats_get = _hcng_stats_get, - .hc_stats_list = _hcng_stats_list, - - .hc_route_create = _hcng_route_create, - .hc_route_create_async = _hcng_route_create_async, - .hc_route_delete = _hcng_route_delete, - .hc_route_delete_async = _hcng_route_delete_async, - .hc_route_list = _hcng_route_list, - .hc_route_list_async = _hcng_route_list_async, - - .hc_punting_create = _hcng_punting_create, - .hc_punting_create_async = _hcng_punting_create_async, - .hc_punting_get = _hcng_punting_get, - .hc_punting_delete = _hcng_punting_delete, - .hc_punting_list = _hcng_punting_list, - - .hc_cache_set_store = _hcng_cache_set_store, - .hc_cache_set_store_async = _hcng_cache_set_store_async, - .hc_cache_set_serve = _hcng_cache_set_serve, - .hc_cache_set_serve_async = _hcng_cache_set_serve_async, - .hc_cache_clear = _hcng_cache_clear, - .hc_cache_list = _hcng_cache_list, - - .hc_strategy_list = _hcng_strategy_list, - .hc_strategy_set = _hcng_strategy_set, - .hc_strategy_add_local_prefix = _hcng_strategy_add_local_prefix, - .hc_wldr_set = _hcng_wldr_set, - - .hc_mapme_set = _hcng_mapme_set, - .hc_mapme_set_discovery = _hcng_mapme_set_discovery, - .hc_mapme_set_timescale = _hcng_mapme_set_timescale, - .hc_mapme_set_retx = _hcng_mapme_set_retx, - .hc_mapme_send_update = _hcng_mapme_send_update, - -#ifdef WITH_POLICY - .hc_policy_create = _hcng_policy_create, - .hc_policy_create_async = _hcng_policy_create_async, - .hc_policy_delete = _hcng_policy_delete, - .hc_policy_delete_async = _hcng_policy_delete_async, - .hc_policy_list = _hcng_policy_list, - .hc_policy_list_async = _hcng_policy_list_async, -#endif // WITH_POLICY - - .hc_listener_create_conf = _hcng_listener_create_conf, - .hc_listener_list_conf = _hcng_listener_list_conf, - .hc_connection_create_conf = _hcng_connection_create_conf, - .hc_connection_delete_conf = _hcng_connection_delete_conf, - .hc_route_create_conf = _hcng_route_create_conf, - .hc_strategy_set_conf = _hcng_strategy_set_conf, - .hc_strategy_add_local_prefix_conf = _hcng_strategy_add_local_prefix_conf, - .hc_subscription_create_conf = _hcng_subscription_create_conf, - .hc_subscription_delete_conf = _hcng_subscription_delete_conf, - - .hc_result_get_msg = _hcng_result_get_msg, - .hc_result_get_cmd_id = _hcng_result_get_cmd_id, - .hc_result_get_success = _hcng_result_get_success, -}; - -// Public contructors - -hc_sock_t *_hc_sock_create_url(const char *url) { - hc_sock_light_t *s = malloc(sizeof(hc_sock_light_t)); - if (!s) goto ERR_MALLOC; - - s->vft = hc_sock_light_ng_interface; - s->url = url ? strdup(url) : NULL; - - s->fd = socket(AF_INET, SOCK_DGRAM, 0); - if (s->fd < 0) goto ERR_SOCKET; - - if (_hcng_sock_set_recv_timeout_ms((hc_sock_t *)s, - DEFAULT_SOCK_RECV_TIMEOUT_MS) < 0) - goto ERR_SOCKET; - - if (_hcng_sock_light_reset((hc_sock_t *)s) < 0) goto ERR_RESET; - - s->seq = 0; - s->cur_request = NULL; - - s->map = kh_init_sock_map(); - if (!s->map) goto ERR_MAP; - - return (hc_sock_t *)(s); - - // hc_sock_light_map_free(s->map); -ERR_MAP: -ERR_RESET: - if (s->url) free(s->url); - close(s->fd); -ERR_SOCKET: - free(s); -ERR_MALLOC: - return NULL; -} diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin.c b/ctrl/libhicnctrl/src/modules/hicn_plugin.c new file mode 100644 index 000000000..b3963b46c --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file api.c + * \brief Implementation of hICN control library API + */ + +#include <assert.h> // assert +#include <fcntl.h> // fcntl +#include <math.h> // log2 +#include <stdbool.h> +#include <stdio.h> // snprintf +#include <string.h> // memmove, strcasecmp +#include <sys/socket.h> // socket +#include <unistd.h> // close, fcntl + +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/socket.h> + +#include <vapi/vapi_safe.h> +#include <vppinfra/clib.h> +#include <vpp_plugins/hicn/error.h> + +#include "../socket_private.h" + +#include "hicn_plugin/base.h" // hc_sock_vpp_data_t +#include "hicn_plugin/listener.h" +#include "hicn_plugin/route.h" + +/****************************************************************************** + * Message helper types and aliases + ******************************************************************************/ + +#if 0 + +#define foreach_hc_command \ + _(hicn_api_node_params_set) \ + _(hicn_api_node_params_set_reply) \ + _(hicn_api_node_params_get_reply) \ + _(hicn_api_node_stats_get_reply) \ + _(hicn_api_face_get) \ + _(hicn_api_faces_details) \ + _(hicn_api_face_stats_details) \ + _(hicn_api_face_get_reply) \ + _(hicn_api_route_get) \ + _(hicn_api_route_get_reply) \ + _(hicn_api_routes_details) \ + _(hicn_api_strategies_get_reply) \ + _(hicn_api_strategy_get) \ + _(hicn_api_strategy_get_reply) + + +typedef vapi_type_msg_header2_t hc_msg_header_t; + +typedef union { +#define _(a) vapi_payload_##a a; + foreach_hc_command +#undef _ +} hc_msg_payload_t; + +typedef struct __attribute__((__packed__)) { + hc_msg_header_t hdr; + hc_msg_payload_t payload; +} hc_hicnp_t; + +typedef void (*NTOH)(void *msg); + +typedef struct __attribute__((__packed__)) { + hc_data_t *data; + uint32_t curr_msg; +} callback_ctx_t; + +typedef struct __attribute__((__packed__)) { + hc_hicnp_t *msg; + vapi_cb_t callback; + callback_ctx_t *callback_ctx; + NTOH ntoh; +} hc_msg_s; + +/****************************************************************************** + * Control socket + ******************************************************************************/ + +static void vpp_free(hc_sock_t *socket) { + hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); + if (s->url) free(s->url); + free(s); + + vapi_disconnect_safe(); +} + +static int vpp_get_next_seq(hc_sock_t *socket) { + hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); + return vapi_gen_req_context(s->g_vapi_ctx_instance); +} + +static int vpp_set_nonblocking(hc_sock_t *socket) { + hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); + return 0; +} + +static int vpp_callback(hc_sock_t *socket, hc_data_t **pdata) { + // NOT IMPLEMENTED + return -1; +} + +static int vpp_reset(hc_sock_t *socket) { + // NOT IMPLEMENTED + return -1; +} +#endif + +/*----------------------------------------------------------------------------* + * Listeners + *----------------------------------------------------------------------------*/ + +/****************************************************************************** + * Module functions + ******************************************************************************/ + +hc_sock_vpp_data_t *hc_sock_vpp_data_create(const char *url) { + hc_sock_vpp_data_t *s = malloc(sizeof(hc_sock_vpp_data_t)); + if (!s) goto ERR_MALLOC; + + s->roff = s->woff = 0; + s->url = url ? strdup(url) : NULL; + + return s; + +ERR_MALLOC: + return NULL; +} + +void hc_sock_vpp_data_free(hc_sock_vpp_data_t *s) { + vapi_disconnect_safe(); + + if (s->url) free(s->url); + free(s); +} + +static int vpp_connect(hc_sock_t *sock) { + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + vapi_error_e rv = + vapi_connect_safe(&s->g_vapi_ctx_instance, hc_sock_is_async(sock)); + if (rv != VAPI_OK) goto ERR_CONNECT; + + return 0; + +ERR_CONNECT: + ERROR("[hc_sock_connect] connection failed"); + return -1; +} + +static ssize_t vpp_prepare(hc_sock_t *sock, hc_request_t *request, + uint8_t **buffer) { + assert(!buffer); + + // XXX all the beginning is generic and could be shared across multiple + // modules + + /* Dispatch to subrequest if any */ + hc_request_t *current_request = hc_request_get_current(request); + + _ASSERT(!hc_request_get_data(current_request)); + + hc_action_t action = hc_request_get_action(current_request); + hc_object_type_t object_type = hc_request_get_object_type(current_request); + hc_object_t *object = hc_request_get_object(current_request); + + _ASSERT(hc_request_get_data(current_request) == NULL); + hc_data_t *data = hc_data_create(object_type); + if (!data) { + ERROR("[vpp_prepare] Could not create data storage"); + goto ERR; + } + hc_request_set_data(current_request, data); + + hc_module_object_ops_t *vft = &sock->ops.object_vft[object_type]; + if (!vft) goto ERR; + hc_execute_t execute = vft->execute[action]; + if (!execute) goto ERR; + int rc = execute(sock, object, data); + if (rc < 0) goto ERR; + + /* The result is fully contained in data */ + (void)rc; + + hc_request_set_complete(request); + return 0; + +ERR: + hc_data_set_error(data); + hc_request_set_complete(request); + return 0; +} + +static hc_sock_ops_t hc_sock_vpp = (hc_sock_ops_t){ + .create_data = (void *(*)(const char *))hc_sock_vpp_data_create, + .free_data = (void (*)(void *))hc_sock_vpp_data_free, + .get_fd = NULL, // not fd based + .get_recv_buffer = NULL, // no async support + .connect = vpp_connect, + .prepare = vpp_prepare, + .send = NULL, + .recv = NULL, + .process = NULL, +}; + +ssize_t vpp_command_serialize(hc_action_t action, hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg) { + return hc_sock_vpp.object_vft[object_type].serialize[action](object, msg); +} + +// Public constructor + +int hc_sock_initialize_module(hc_sock_t *s) { + s->ops = hc_sock_vpp; + // XXX shall we memset the VFT ? + /* LISTENER: CREATE, GET, DELETE not implemented, LIST ok */ + s->ops.object_vft[OBJECT_TYPE_LISTENER] = vpp_listener_module_ops; + /* CONNECTION : CREATE, GET, UPDATE, DELETE, LIST, SET_* not + implemented */ + s->ops.object_vft[OBJECT_TYPE_CONNECTION] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_FACE] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_PUNTING] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_CACHE] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_MAPME] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_WLDR] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_POLICY] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_ROUTE] = vpp_route_module_ops; + s->ops.object_vft[OBJECT_TYPE_STRATEGY] = HC_MODULE_OBJECT_OPS_EMPTY; + s->ops.object_vft[OBJECT_TYPE_SUBSCRIPTION] = HC_MODULE_OBJECT_OPS_EMPTY; + return 0; +} diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/base.h b/ctrl/libhicnctrl/src/modules/hicn_plugin/base.h new file mode 100644 index 000000000..05565e938 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/base.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file modules/hicn_plugin/base.h + * \brief Base structures for hICN plugin module + */ + +#include <vapi/vapi_safe.h> +#include "../../module.h" +#include "../../socket_private.h" + +typedef struct { + vapi_ctx_t g_vapi_ctx_instance; + char *url; + + size_t roff; /**< Read offset */ + size_t woff; /**< Write offset */ + u32 buffer[RECV_BUFLEN]; + /* Next sequence number to be used for requests */ + int seq; + + bool async; +} hc_sock_vpp_data_t; diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.c b/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.c new file mode 100644 index 000000000..f0aa4e884 --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file modules/hicn_plugin/listener.c + * \brief Implementation of listener object VFT for hicn_plugin. + */ + +#include <hicn/util/vector.h> + +#include "base.h" +#include "listener.h" + +struct listener_data_s { + hc_listener_t listener; + hc_data_t *data; +}; + +/** + * This is a callback used to append in callback_ctx which is a hc_data_t + * designed to hold hc_listener_t, a list of listener, each corresponding to an + * IP address (v4 then v6) of the interfaces, and thus build a list of hICN + * listeners. + */ +static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx, void *callback_ctx, + vapi_error_e rv, bool is_last, + vapi_payload_ip_address_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + if (reply && is_last) printf("COUCOU\n"); + if (is_last) return 0; + + struct listener_data_s *ld = (struct listener_data_s *)callback_ctx; + + if (reply->prefix.address.af == ADDRESS_IP4) { + memcpy(&(ld->listener.local_addr), reply->prefix.address.un.ip4, + IPV4_ADDR_LEN); + ld->listener.family = AF_INET; + } else { + memcpy(&(ld->listener.local_addr), reply->prefix.address.un.ip6, + IPV6_ADDR_LEN); + ld->listener.family = AF_INET6; + } + ld->listener.local_port = 0; + + ld->listener.id = reply->sw_if_index; + hc_data_t *data = ld->data; + hc_listener_t *listener = &ld->listener; + hc_data_push(data, listener); + + return rv; +} + +/* LISTENER LIST */ + +typedef struct { + u32 swif; + char interface_name[INTERFACE_LEN]; +} hc_vapi_interface_t; + +/* + * A pointer to hc_data_t is passed in the callback context + * Objective is to store a vector of hc_vapi_interface_t inside + */ +static vapi_error_e on_listener_list_complete_cb( + struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_sw_interface_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + if (is_last) return 0; + + hc_vapi_interface_t **vpp_interfaces_vec = + (hc_vapi_interface_t **)callback_ctx; + + hc_vapi_interface_t interface = {.swif = reply->sw_if_index}; + // XXX bug + memcpy(interface.interface_name, reply->interface_name, INTERFACE_LEN); + + vector_push(*vpp_interfaces_vec, interface); + + return rv; +} + +static int _vpp_listener_list(hc_sock_t *sock, hc_data_t *data) { + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + + int retval = -1; // VAPI_OK; + + hc_vapi_interface_t *vpp_interfaces_vec = NULL; + vector_init(vpp_interfaces_vec, 0, 0); + + vapi_lock(); + + vapi_msg_sw_interface_dump *msg = + vapi_alloc_sw_interface_dump(s->g_vapi_ctx_instance); + if (!msg) { + retval = VAPI_ENOMEM; + goto ERR_MSG; + } + msg->payload.sw_if_index = ~0; + msg->payload.name_filter_valid = 0; + + /* Retrieve the list of interfaces in vpp_interfaces_vec */ + int ret = + vapi_sw_interface_dump(s->g_vapi_ctx_instance, msg, + on_listener_list_complete_cb, &vpp_interfaces_vec); + + if (ret != VAPI_OK) goto ERR_LIST_INTERFACES; + + /* Query the forwarder for each interface */ + // stored in data->buffer == hc_vapi_interface_t* [] + // 2 calls for each interface + // + // This function is called twice for each interface, to get resp. the v4 and + // v6 IP addresses associated to it: + // ip_address_dump(sw_if_index, is_ipv6) + // + // Function call : + // vapi_msg_XXX *msg = vapi_alloc_XXX(s->g_vapi_ctx_instance); + // msg->payload.ATTR = VALUE; + // [...] + // int ret = vapi_XXX((s->g_vapi_ctx_instance, msg, CALLBACK, USER_DATA); + // + // CALLBACK = process_ip_info + // USER_DATA = data2 + // + // We can assume the callbacks are executed before the function returns, and + // that there is no async code. + // + int rc; + + hc_vapi_interface_t *interface; + vapi_msg_ip_address_dump *msg2; + + struct listener_data_s ld; + vector_foreach(vpp_interfaces_vec, interface, { + memset(&ld, 0, sizeof(struct listener_data_s)); + ld.listener.type = FACE_TYPE_HICN; + rc = snprintf(ld.listener.interface_name, INTERFACE_LEN, "%s", + interface->interface_name); + if (rc < 0 || rc >= INTERFACE_LEN) goto ERR_FOREACH; + + ld.data = data; + + for (unsigned i = 0; i < 2; i++) { + msg2 = vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance); + msg2->payload.sw_if_index = interface->swif; + msg2->payload.is_ipv6 = i; + retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, + process_ip_info, &ld); + if (ret != VAPI_OK) goto ERR_GET_IP; + } + }); + retval = 0; +ERR_GET_IP: +ERR_FOREACH: + vector_free(vpp_interfaces_vec); +ERR_LIST_INTERFACES: +ERR_MSG: + vapi_unlock(); + return retval; +} + +#define vpp_listener_create NULL +#define vpp_listener_delete NULL + +static int vpp_listener_list(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + assert(!object || hc_object_is_empty(object)); + return _vpp_listener_list(sock, data); +} + +DECLARE_VPP_MODULE_OBJECT_OPS(vpp, listener); diff --git a/ctrl/libhicnctrl/src/modules/hicn_light_common.c b/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.h index d1fb33993..f75c58db6 100644 --- a/ctrl/libhicnctrl/src/modules/hicn_light_common.c +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/listener.h @@ -13,18 +13,16 @@ * limitations under the License. */ -#include "hicn_light_common.h" +/** + * \file modules/hicn_plugin/listener.h + * \brief listener object VFT for hicn_plugin. + */ + +#ifndef HICNCTRL_MODULE_VPP_LISTENER_H +#define HICNCTRL_MODULE_VPP_LISTENER_H -hc_sock_request_t *hc_sock_request_create(int seq, hc_data_t *data, - HC_PARSE parse) { - assert(data); +#include "../../module.h" - hc_sock_request_t *request = malloc(sizeof(hc_sock_request_t)); - if (!request) return NULL; - request->seq = seq; - request->data = data; - request->parse = parse; - return request; -} +DECLARE_MODULE_OBJECT_OPS_H(vpp, listener); -void hc_sock_light_request_free(hc_sock_request_t *request) { free(request); } +#endif /* HICNCTRL_MODULE_VPP_LISTENER_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/route.c b/ctrl/libhicnctrl/src/modules/hicn_plugin/route.c new file mode 100644 index 000000000..45aced9cb --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/route.c @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file modules/hicn_plugin/route.c + * \brief Implementation of route object VFT for hicn_plugin. + */ + +#include "base.h" +#include "route.h" + +static vapi_error_e create_udp_tunnel_cb( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + if (reply->retval != VAPI_OK) return reply->retval; + + u32 *uei = (u32 *)callback_ctx; + *uei = reply->uei; + + return reply->retval; +} + +static vapi_error_e parse_route_create( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_ip_route_add_del_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + if (reply->retval != VAPI_OK) return reply->retval; + + return reply->retval; +} + +static vapi_error_e hicn_enable_cb( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_enable_disable_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + face_id_t *faceid = (face_id_t *)callback_ctx; + + if (reply->nfaces) { + *faceid = reply->faceids[0]; + } + + return reply->retval; +} + +static int _vpp_route_create(hc_sock_t *sock, hc_route_t *route) { + if (!IS_VALID_FAMILY(route->family)) return -1; + + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + int ret = -1; + vapi_lock(); + + vapi_msg_ip_route_add_del *msg = + vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1); + + msg->payload.is_add = 1; + if (route->family == AF_INET) { + memcpy(&msg->payload.route.prefix.address.un.ip4[0], &route->remote_addr.v4, + 4); + msg->payload.route.prefix.address.af = ADDRESS_IP4; + msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; + } else { + memcpy(&msg->payload.route.prefix.address.un.ip6[0], &route->remote_addr.v6, + 16); + msg->payload.route.prefix.address.af = ADDRESS_IP6; + msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; + } + + msg->payload.route.prefix.len = route->len; + + msg->payload.route.paths[0].sw_if_index = ~0; + msg->payload.route.paths[0].table_id = 0; + + hc_face_t *face = &(route->face); + + face->netdevice.index = ~0; + face->id = INVALID_FACE_ID; + + switch (face->type) { + case FACE_TYPE_HICN: { + if (hicn_ip_address_is_v4(&(face->remote_addr))) { + memcpy(&(msg->payload.route.paths[0].nh.address.ip4), + &face->remote_addr.v4, sizeof(ip4_address_t)); + msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; + } else { + memcpy(&(msg->payload.route.paths[0].nh.address.ip6), + &face->remote_addr.v6, sizeof(ip6_address_t)); + msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; + } + + msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL; + msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; + + break; + } + case FACE_TYPE_UDP: { + vapi_msg_hicn_api_udp_tunnel_add_del *msg2 = NULL; + u32 uei = ~0; + + if (hicn_ip_address_is_v4(&(face->remote_addr)) && + hicn_ip_address_is_v4(&(face->local_addr))) { + msg2 = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance); + memcpy(msg2->payload.src_addr.un.ip4, &face->local_addr.v4, + sizeof(ip4_address_t)); + msg2->payload.src_addr.af = ADDRESS_IP4; + + memcpy(msg2->payload.dst_addr.un.ip4, &face->remote_addr.v4, + sizeof(ip4_address_t)); + msg2->payload.dst_addr.af = ADDRESS_IP4; + + } else if (!hicn_ip_address_is_v4(&(route->face.remote_addr)) && + !hicn_ip_address_is_v4(&(route->face.local_addr))) { + msg2 = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance); + memcpy(msg2->payload.src_addr.un.ip6, &face->local_addr.v6, + sizeof(ip6_address_t)); + msg2->payload.src_addr.af = ADDRESS_IP6; + + memcpy(msg2->payload.dst_addr.un.ip6, &face->remote_addr.v6, + sizeof(ip6_address_t)); + msg2->payload.dst_addr.af = ADDRESS_IP6; + } else { + // NOT IMPLEMENTED + ret = -1; + goto done; + } + + msg2->payload.src_port = face->local_port; + msg2->payload.dst_port = face->remote_port; + msg2->payload.is_add = 1; + + int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg2, + create_udp_tunnel_cb, &uei); + + if (ret) { + ERROR("Error in vapi_hicn_api_udp_tunnel_add_del"); + vapi_msg_free(s->g_vapi_ctx_instance, msg); + goto done; + } + + msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP; + msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; + msg->payload.route.paths[0].nh.obj_id = uei; + + face->netdevice.index = uei; + + break; + } + default: + ret = -1; + goto done; + } + + ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, msg, parse_route_create, + NULL); + + if (ret) { + ERROR("Error in vapi_ip_route_add_del"); + goto done; + } + + vapi_msg_hicn_api_enable_disable *msg3 = + vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance); + + if (route->family == AF_INET) { + memcpy(&msg3->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); + msg3->payload.prefix.address.af = ADDRESS_IP4; + } else { + memcpy(&msg3->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); + msg3->payload.prefix.address.af = ADDRESS_IP6; + } + + msg3->payload.prefix.len = route->len; + msg3->payload.enable_disable = 1; + + ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg3, + hicn_enable_cb, &face->id); + + if (ret) { + ERROR("Error in vapi_hicn_api_enable_disable"); + } + +done: + vapi_unlock(); + return ret; +} + +static vapi_error_e hicn_disable_cb( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_enable_disable_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + return reply->retval; +} + +static vapi_error_e parse_route_delete( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_ip_route_add_del_reply *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + return reply->retval; +} + +static int _vpp_route_delete(hc_sock_t *sock, hc_route_t *route) { + if (!IS_VALID_FAMILY(route->family)) return -1; + + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + + vapi_lock(); + + vapi_msg_hicn_api_enable_disable *msg = + vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance); + + if (route->family == AF_INET) { + memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); + msg->payload.prefix.address.af = ADDRESS_IP4; + } else { + memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); + msg->payload.prefix.address.af = ADDRESS_IP6; + } + + msg->payload.prefix.len = route->len; + msg->payload.enable_disable = 0; + + vapi_error_e ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg, + hicn_disable_cb, NULL); + + if (ret) { + ERROR("Error in vapi_hicn_api_enable_disable in route delete"); + goto done; + } + + vapi_msg_ip_route_add_del *msg2 = + vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1); + + msg2->payload.is_add = 0; + if (route->family == AF_INET) { + memcpy(&msg2->payload.route.prefix.address.un.ip4[0], + &route->remote_addr.v4, 4); + msg2->payload.route.prefix.address.af = ADDRESS_IP4; + } else { + memcpy(&msg2->payload.route.prefix.address.un.ip6[0], + &route->remote_addr.v6, 16); + msg2->payload.route.prefix.address.af = ADDRESS_IP6; + } + + msg2->payload.route.prefix.len = route->len; + + msg2->payload.route.paths[0].sw_if_index = ~0; + msg2->payload.route.paths[0].table_id = 0; + + hc_face_t *face = &(route->face); + switch (face->type) { + case FACE_TYPE_HICN: { + if (hicn_ip_address_is_v4(&(face->remote_addr))) { + memcpy(&(msg2->payload.route.paths[0].nh.address.ip4), + &face->remote_addr.v4, sizeof(ip4_address_t)); + msg2->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; + } else { + memcpy(&(msg2->payload.route.paths[0].nh.address.ip6), + &face->remote_addr.v6, sizeof(ip6_address_t)); + msg2->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; + } + + msg2->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL; + msg2->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; + + break; + } + case FACE_TYPE_UDP: { + msg2->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP; + msg2->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; + msg2->payload.route.paths[0].nh.obj_id = face->netdevice.index; + break; + } + default: + return -1; + } + + ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, msg2, parse_route_delete, + NULL); + + if (ret) { + ERROR("Error in vapi_ip_route_add_del in route delete"); + goto done; + } + +done: + + vapi_unlock(); + return ret; +} + +/* ROUTE LIST */ + +static vapi_error_e parse_udp_encap_list( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_udp_encap_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + hc_face_t *face = (hc_face_t *)callback_ctx; + + if (face->netdevice.index == reply->udp_encap.id) { + switch (reply->udp_encap.src_ip.af) { + case ADDRESS_IP4: { + memcpy(&face->local_addr.v4, &(reply->udp_encap.src_ip.un.ip4), + sizeof(ip4_address_t)); + memcpy(&face->remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4), + sizeof(ip4_address_t)); + break; + } + case ADDRESS_IP6: { + memcpy(&face->local_addr.v6, &(reply->udp_encap.src_ip.un.ip6), + sizeof(ip6_address_t)); + memcpy(&face->remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6), + sizeof(ip6_address_t)); + break; + } + default: + break; + } + + face->local_port = reply->udp_encap.src_port; + face->remote_port = reply->udp_encap.dst_port; + } + return rv; +} + +static int _fill_face_with_info(hc_face_t *face, vapi_type_fib_path *path) { + switch (path->type) { + case FIB_API_PATH_FLAG_NONE: { + face->type = FACE_TYPE_HICN; + switch (path->proto) { + case FIB_API_PATH_NH_PROTO_IP4: + memcpy(&face->remote_addr.v4, &(path->nh.address.ip4), + sizeof(ipv4_address_t)); + break; + case FIB_API_PATH_NH_PROTO_IP6: + memcpy(&face->remote_addr.v6, &(path->nh.address.ip6), + sizeof(ipv6_address_t)); + break; + default: + break; + } + face->netdevice.index = path->sw_if_index; + } break; + case FIB_API_PATH_TYPE_UDP_ENCAP: { + face->type = FACE_TYPE_UDP; + face->netdevice.index = clib_net_to_host_u32(path->nh.obj_id); + // Let's make the compiler happy + (void)parse_udp_encap_list; + // vapi_msg_udp_encap_dump *msg; + // msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance); + // vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list, + // face); + } break; + default: + return -1; + } + return 0; +} + +static vapi_error_e parse_route_list(vapi_ctx_t ctx, void *callback_ctx, + vapi_error_e rv, bool is_last, + vapi_payload_ip_route_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + // XXX DEBUG XXX + if (reply && is_last) printf("COUCOU\n"); + + if (is_last) return 0; + + hc_data_t *data = (hc_data_t *)callback_ctx; + + /* + * Implementation: + * A route has n paths... we iterate for each path and search for a + * corresponding face in the hc_data_t result struct... and we fill the face + * info with the route path. + * + * TODO + * - comment on paths + * - explain the jump to END, this was previously implemented with a + * boolean flags skipping all remaining tests in the function... + */ + for (int j = 0; j < reply->route.n_paths; j++) { + hc_data_foreach(data, obj, { + hc_route_t *route = &obj->route; + + if (hicn_ip_address_is_v4(&(route->remote_addr)) && + memcmp(route->remote_addr.v4.as_u8, + reply->route.prefix.address.un.ip4, + sizeof(ipv4_address_t)) == 0 && + route->len == reply->route.prefix.len && route->face_id == ~0) { + _fill_face_with_info(&(route->face), &reply->route.paths[j]); + goto END; + + } else if (memcmp(route->remote_addr.v6.as_u8, + reply->route.prefix.address.un.ip6, + sizeof(ipv6_address_t)) == 0 && + route->len == reply->route.prefix.len && + route->face_id == ~0) { + _fill_face_with_info(&(route->face), &reply->route.paths[j]); + goto END; + } + }); + } + +END: + return rv; +} + +/** + * Populates the hc_data_t structure passed as the context with... + */ +static vapi_error_e parse_hicn_route_list( + vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, + vapi_payload_hicn_api_routes_details *reply) { + if (reply == NULL || rv != VAPI_OK) return rv; + + if (reply && is_last) printf("COUCOU\n"); + if (is_last) return 0; + + hc_data_t *data = (hc_data_t *)callback_ctx; + + for (int i = 0; i < reply->nfaces; i++) { + hc_route_t route; + memset(&route, 0, sizeof(hc_route_t)); + + /* + * We set the face_id to ~0 to act as a marker in parse_route_list that + * the route is missing face information. + */ + route.face_id = ~0; + route.cost = 1; + route.len = reply->prefix.len; + if (reply->prefix.address.af == ADDRESS_IP6) { + memcpy(route.remote_addr.v6.as_u8, reply->prefix.address.un.ip6, 16); + route.family = AF_INET6; + } else { + memcpy(route.remote_addr.v4.as_u8, reply->prefix.address.un.ip4, 4); + route.family = AF_INET; + } + + hc_data_push(data, &route); + } + + return rv; +} + +/* + * hicn_api_routes_dump + * ip_route_dump + * + * @returns hc_data_t<hc_route_t> + */ +static int _vpp_route_list(hc_sock_t *sock, hc_data_t *data) { + int ret; + hc_sock_vpp_data_t *s = (hc_sock_vpp_data_t *)sock->data; + + vapi_lock(); + + /* Start by retrieving hicn routes (we have no face information at this + * stage)... */ + vapi_msg_hicn_api_routes_dump *msg; + msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance); + if (!msg) goto ERR_MSG; + + ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg, + parse_hicn_route_list, data); + if (ret != VAPI_OK) goto ERR_API; + + /* + * ... an complement them using IP (v4 and v6 routes). Similar routes will + * be aggregated, based on IP prefix, in parse_*_route_list. + */ + vapi_msg_ip_route_dump *msg2; + for (unsigned i = 0; i < 2; i++) { + msg2 = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance); + if (!msg2) goto ERR_MSG; + + msg2->payload.table.table_id = 0; + msg2->payload.table.is_ip6 = i; + + ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, msg2, parse_route_list, + data); + if (ret != VAPI_OK) goto ERR_API; + } + + goto END; + +ERR_MSG: + ret = VAPI_ENOMEM; + goto END; + +ERR_API: +END: + vapi_unlock(); + return ret; +} + +static int vpp_route_create(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + int rc = _vpp_route_create(sock, &object->route); + if (rc < 0) + hc_data_set_complete(data); + else + hc_data_set_error(data); + return rc; +} + +static int vpp_route_delete(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + int rc = _vpp_route_delete(sock, &object->route); + if (rc < 0) + hc_data_set_complete(data); + else + hc_data_set_error(data); + return rc; +} + +static int vpp_route_list(hc_sock_t *sock, hc_object_t *object, + hc_data_t *data) { + assert(!object || hc_object_is_empty(object)); + return _vpp_route_list(sock, data); +} + +DECLARE_VPP_MODULE_OBJECT_OPS(vpp, route); diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin/route.h b/ctrl/libhicnctrl/src/modules/hicn_plugin/route.h new file mode 100644 index 000000000..652d3e89a --- /dev/null +++ b/ctrl/libhicnctrl/src/modules/hicn_plugin/route.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file modules/hicn_plugin/route.h + * \brief route object VFT for hicn_plugin. + */ + +#ifndef HICNCTRL_MODULE_VPP_ROUTE_H +#define HICNCTRL_MODULE_VPP_ROUTE_H + +#include "../../module.h" + +DECLARE_MODULE_OBJECT_OPS_H(vpp, route); + +#endif /* HICNCTRL_MODULE_VPP_ROUTE_H */ diff --git a/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c b/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c deleted file mode 100644 index 6d1baa786..000000000 --- a/ctrl/libhicnctrl/src/modules/hicn_plugin_api.c +++ /dev/null @@ -1,1402 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * \file api.c - * \brief Implementation of hICN control library API - */ - -#include <assert.h> // assert -#include <fcntl.h> // fcntl -#include <math.h> // log2 -#include <stdbool.h> -#include <stdio.h> // snprintf -#include <string.h> // memmove, strcasecmp -#include <sys/socket.h> // socket -#include <unistd.h> // close, fcntl -#include <vapi/vapi_safe.h> -#include <vppinfra/clib.h> -#include <vpp_plugins/hicn/error.h> - -#include "api_private.h" - -/** - * Messages to the forwarder might be multiplexed thanks to the seqNum fields in - * the header_control_message structure. The forwarder simply answers back the - * original sequence number. We maintain a map of such sequence number to - * outgoing queries so that replied can be demultiplexed and treated - * appropriately. - */ -/* TYPEDEF_MAP_H(hc_sock_map, int, hc_sock_request_t *); */ -/* TYPEDEF_MAP(hc_sock_map, int, hc_sock_request_t *, int_cmp, int_snprintf, */ -/* generic_snprintf); */ - -struct hc_sock_vpp_s { - /* This must be the first element of the struct */ - hc_sock_t vft; - - vapi_ctx_t g_vapi_ctx_instance; - char *url; - - size_t roff; /**< Read offset */ - size_t woff; /**< Write offset */ - u32 buffer[RECV_BUFLEN]; - /* Next sequence number to be used for requests */ - int seq; - - bool async; -}; - -typedef struct hc_sock_vpp_s hc_sock_vpp_t; - -#define TO_HC_SOCK_VPP(s) (hc_sock_vpp_t *)(s) - -/****************************************************************************** - * Message helper types and aliases - ******************************************************************************/ - -#define foreach_hc_command \ - _(hicn_api_node_params_set) \ - _(hicn_api_node_params_set_reply) \ - _(hicn_api_node_params_get_reply) \ - _(hicn_api_node_stats_get_reply) \ - _(hicn_api_face_get) \ - _(hicn_api_faces_details) \ - _(hicn_api_face_stats_details) \ - _(hicn_api_face_get_reply) \ - _(hicn_api_route_get) \ - _(hicn_api_route_get_reply) \ - _(hicn_api_routes_details) \ - _(hicn_api_strategies_get_reply) \ - _(hicn_api_strategy_get) \ - _(hicn_api_strategy_get_reply) - -typedef vapi_type_msg_header2_t hc_msg_header_t; - -typedef union { -#define _(a) vapi_payload_##a a; - foreach_hc_command -#undef _ -} hc_msg_payload_t; - -typedef struct __attribute__((__packed__)) { - hc_msg_header_t hdr; - hc_msg_payload_t payload; -} hc_hicnp_t; - -typedef void (*NTOH)(void *msg); - -typedef struct __attribute__((__packed__)) { - hc_data_t *data; - uint32_t curr_msg; -} callback_ctx_t; - -typedef struct __attribute__((__packed__)) { - hc_hicnp_t *hicnp_msg; - vapi_cb_t callback; - callback_ctx_t *callback_ctx; - NTOH ntoh; -} hc_msg_s; - -/****************************************************************************** - * Control socket - ******************************************************************************/ - -static void _hc_sock_vpp_free(hc_sock_t *socket) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - if (s->url) free(s->url); - free(s); - - vapi_disconnect_safe(); -} - -static int _hc_sock_vpp_get_next_seq(hc_sock_t *socket) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - return vapi_gen_req_context(s->g_vapi_ctx_instance); -} - -static int _hc_sock_vpp_set_nonblocking(hc_sock_t *socket) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - s->async = 1; - return 0; -} - -static int _hc_sock_vpp_get_fd(hc_sock_t *s) { return 1; } - -static int _hc_sock_vpp_connect(hc_sock_t *socket) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - vapi_error_e rv = vapi_connect_safe(&s->g_vapi_ctx_instance, s->async); - if (rv != VAPI_OK) goto ERR_CONNECT; - - return 0; - -ERR_CONNECT: - ERROR("[hc_sock_connect] connection failed"); - return -1; -} - -static int _hc_sock_vpp_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, - uint32_t seq) { - return -1; -} - -static int _hc_sock_vpp_get_available(hc_sock_t *s, u8 **buffer, size_t *size) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_sock_vpp_recv(hc_sock_t *s) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_sock_vpp_process(hc_sock_t *s, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_sock_vpp_callback(hc_sock_t *socket, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_sock_vpp_reset(hc_sock_t *socket) { - // NOT IMPLEMENTED - return -1; -} - -/****************************************************************************** - * Command-specific structures and functions - ******************************************************************************/ - -/*----------------------------------------------------------------------------* - * Listeners - *----------------------------------------------------------------------------*/ - -/* LISTENER CREATE */ - -static int _hc_listener_create(hc_sock_t *s, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_listener_create_async(hc_sock_t *s, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; -} - -/* LISTENER GET */ -static int _hc_listener_get(hc_sock_t *s, hc_listener_t *listener, - hc_listener_t **listener_found) { - // NOT IMPLEMENTED - return -1; -} - -/* LISTENER DELETE */ - -static int _hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_listener_delete_async(hc_sock_t *s, hc_listener_t *listener) { - // NOT IMPLEMENTED - return -1; -} - -static vapi_error_e process_ip_info(struct vapi_ctx_s *ctx, void *callback_ctx, - vapi_error_e rv, bool is_last, - vapi_payload_ip_address_details *reply) { - if (is_last) return 0; - hc_data_t *data = (hc_data_t *)callback_ctx; - - if (data->size == data->current) { - data->buffer = - realloc(data->buffer, sizeof(hc_listener_t) * data->size * 2); - - if (!data->buffer) return VAPI_ENOMEM; - - data->size *= 2; - } - - hc_listener_t *listener = - (hc_listener_t *)(data->buffer + data->current * sizeof(hc_listener_t)); - memset(listener, 0, sizeof(hc_listener_t)); - - if (reply->prefix.address.af == ADDRESS_IP4) { - memcpy(listener->local_addr.v4.as_u8, reply->prefix.address.un.ip4, - IPV4_ADDR_LEN); - listener->family = AF_INET; - } else { - memcpy(listener->local_addr.v6.as_u8, reply->prefix.address.un.ip6, - IPV6_ADDR_LEN); - listener->family = AF_INET6; - } - - listener->id = reply->sw_if_index; - data->current++; - return rv; -} - -typedef struct { - u32 swif; - char interface_name[INTERFACE_LEN]; -} hc_vapi_interface_t; - -static vapi_error_e listener_list_complete_cb( - struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_sw_interface_details *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - - if (is_last) return 0; - - hc_data_t *data = (hc_data_t *)callback_ctx; - - if (data->size == data->current) { - data->buffer = - realloc(data->buffer, sizeof(hc_vapi_interface_t) * data->size * 2); - - if (!data->buffer) return VAPI_ENOMEM; - - data->size *= 2; - } - - hc_vapi_interface_t *swif = - &((hc_vapi_interface_t *)data->buffer)[data->current]; - - swif[0].swif = reply->sw_if_index; - memcpy(swif[0].interface_name, reply->interface_name, INTERFACE_LEN); - - data->current++; - - return rv; -} - -/* LISTENER LIST */ -static int _hc_listener_list(hc_sock_t *socket, hc_data_t **pdata) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - int retval = VAPI_OK; - vapi_lock(); - vapi_msg_sw_interface_dump *hicnp_msg; - hicnp_msg = vapi_alloc_sw_interface_dump(s->g_vapi_ctx_instance); - - if (!hicnp_msg) { - retval = VAPI_ENOMEM; - goto END; - } - - hicnp_msg->payload.sw_if_index = ~0; - hicnp_msg->payload.name_filter_valid = 0; - - hc_data_t *data = hc_data_create(0, sizeof(hc_vapi_interface_t), NULL); - - if (!data) { - retval = -1; - goto END; - } - - hc_data_t *data2 = hc_data_create(0, 1, NULL); - - if (!data2) { - retval = -1; - goto END; - } - - data->buffer = malloc(sizeof(hc_vapi_interface_t)); - data->size = 1; - - if (!data->buffer) { - free(data); - retval = -1; - goto FREE_DATA; - } - - int ret = vapi_sw_interface_dump(s->g_vapi_ctx_instance, hicnp_msg, - listener_list_complete_cb, data); - - if (ret != VAPI_OK) { - free(data->buffer); - free(data); - retval = -1; - goto FREE_DATA_BUFFER; - } - - data2->buffer = malloc(sizeof(hc_listener_t)); - data2->size = 1; - data2->out_element_size = 1; - - if (!data2->buffer) { - free(data2->buffer); - retval = -1; - goto CLEAN; - } - - /* Query the forwarder for each interface */ - for (int i = 0; i < data->current; i++) { - int index = data2->current; - vapi_msg_ip_address_dump *msg = - vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance); - msg->payload.sw_if_index = ((hc_vapi_interface_t *)data->buffer)[i].swif; - msg->payload.is_ipv6 = 0; - retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg, process_ip_info, - data2); - vapi_msg_ip_address_dump *msg2 = - vapi_alloc_ip_address_dump(s->g_vapi_ctx_instance); - - if (retval) goto CLEAN; - - msg2->payload.sw_if_index = ((hc_vapi_interface_t *)data->buffer)[i].swif; - msg2->payload.is_ipv6 = 1; - retval = vapi_ip_address_dump(s->g_vapi_ctx_instance, msg2, process_ip_info, - data2); - for (size_t j = index; j < data2->current; j++) { - memcpy(((hc_listener_t *)(data2->buffer))[j].interface_name, - ((hc_vapi_interface_t *)(data->buffer))[i].interface_name, - INTERFACE_LEN); - ((hc_listener_t *)(data2->buffer))[j].type = FACE_TYPE_HICN; - } - - if (retval) goto CLEAN; - } - -CLEAN: -FREE_DATA_BUFFER: - free(data->buffer); -FREE_DATA: - free(data); - - data2->size = data2->current; - data2->out_element_size = sizeof(hc_listener_t); - *pdata = data2; -END: - vapi_unlock(); - return retval; -} - -static int _hc_listener_list_async(hc_sock_t *s, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; -} - -/*----------------------------------------------------------------------------* - * CONNECTION - *----------------------------------------------------------------------------*/ - -/* CONNECTION CREATE */ - -static int _hc_connection_create(hc_sock_t *s, hc_connection_t *connection) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_create_async(hc_sock_t *s, - hc_connection_t *connection) { - // NOT IMPLEMENTED - return -1; -} - -/* CONNECTION GET */ - -static int _hc_connection_get(hc_sock_t *s, hc_connection_t *connection, - hc_connection_t **connection_found) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_update_by_id(hc_sock_t *s, int hc_connection_id, - hc_connection_t *connection) { - // Not implemented - return -1; -} - -static int _hc_connection_update(hc_sock_t *s, - hc_connection_t *connection_current, - hc_connection_t *connection_updated) { - // Not implemented - return -1; -} - -/* CONNECTION DELETE */ - -static int _hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_delete_async(hc_sock_t *s, - hc_connection_t *connection) { - // NOT IMPLEMENTED - return -1; -} - -/* CONNECTION LIST */ - -static int _hc_connection_list(hc_sock_t *s, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_list_async(hc_sock_t *s, hc_data_t **pdata) { - // NOT IMPLEMENTED - return -1; -} - -/* CONNECTION SET ADMIN STATE */ - -static int _hc_connection_set_admin_state(hc_sock_t *s, - const char *conn_id_or_name, - face_state_t state) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_set_admin_state_async(hc_sock_t *s, - const char *conn_id_or_name, - face_state_t state) { - // NOT IMPLEMENTED - return -1; -} - -#ifdef WITH_POLICY - -static int _hc_connection_set_priority(hc_sock_t *s, - const char *conn_id_or_name, - uint32_t priority) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_set_priority_async(hc_sock_t *s, - const char *conn_id_or_name, - uint32_t priority) { - // NOT IMPLEMENTED - return -1; -} - -#endif // WITH_POLICY - -static int _hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags) { - // NOT IMPLEMENTED - return -1; -} - -static int _hc_connection_set_tags_async(hc_sock_t *s, - const char *conn_id_or_name, - policy_tags_t tags) { - // NOT IMPLEMENTED - return -1; -} - -/*----------------------------------------------------------------------------* - * Routes - *----------------------------------------------------------------------------*/ - -static vapi_error_e create_udp_tunnel_cb( - vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_udp_tunnel_add_del_reply *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - - if (reply->retval != VAPI_OK) return reply->retval; - - u32 *uei = (u32 *)callback_ctx; - *uei = reply->uei; - - return reply->retval; -} - -/* ROUTE CREATE */ -static vapi_error_e parse_route_create( - vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_ip_route_add_del_reply *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - - if (reply->retval != VAPI_OK) return reply->retval; - - return reply->retval; -} - -static vapi_error_e hicn_enable_cb( - vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_enable_disable_reply *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - face_id_t *faceid = (face_id_t *)callback_ctx; - - if (reply->nfaces) { - *faceid = reply->faceids[0]; - } - - return reply->retval; -} - -static int _hc_route_create_internal(hc_sock_t *socket, hc_route_t *route, - bool async) { - if (!IS_VALID_FAMILY(route->family)) return -1; - - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - int ret = -1; - vapi_lock(); - - vapi_msg_ip_route_add_del *hicnp_msg = - vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1); - - hicnp_msg->payload.is_add = 1; - if (route->family == AF_INET) { - memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], - &route->remote_addr.v4, 4); - hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4; - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; - } else { - memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], - &route->remote_addr.v6, 16); - hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6; - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; - } - - hicnp_msg->payload.route.prefix.len = route->len; - - hicnp_msg->payload.route.paths[0].sw_if_index = ~0; - hicnp_msg->payload.route.paths[0].table_id = 0; - - hc_face_t *face = &(route->face); - - face->face.netdevice.index = ~0; - face->id = INVALID_FACE_ID; - - switch (face->face.type) { - case FACE_TYPE_HICN: { - if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr)))) { - memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), - &face->face.remote_addr.v4, sizeof(ip4_address_t)); - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; - } else { - memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), - &face->face.remote_addr.v6, sizeof(ip6_address_t)); - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; - } - - hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL; - hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; - - break; - } - case FACE_TYPE_UDP: { - vapi_msg_hicn_api_udp_tunnel_add_del *msg = NULL; - u32 uei = ~0; - - if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr))) && - ip_address_is_v4((ip_address_t *)(&(face->face.local_addr)))) { - msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance); - memcpy(msg->payload.src_addr.un.ip4, &face->face.local_addr.v4, - sizeof(ip4_address_t)); - msg->payload.src_addr.af = ADDRESS_IP4; - - memcpy(msg->payload.dst_addr.un.ip4, &face->face.remote_addr.v4, - sizeof(ip4_address_t)); - msg->payload.dst_addr.af = ADDRESS_IP4; - - } else if (!ip_address_is_v4( - (ip_address_t *)(&(route->face.face.remote_addr))) && - !ip_address_is_v4( - (ip_address_t *)(&(route->face.face.local_addr)))) { - msg = vapi_alloc_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance); - memcpy(msg->payload.src_addr.un.ip6, &face->face.local_addr.v6, - sizeof(ip6_address_t)); - msg->payload.src_addr.af = ADDRESS_IP6; - - memcpy(msg->payload.dst_addr.un.ip6, &face->face.remote_addr.v6, - sizeof(ip6_address_t)); - msg->payload.dst_addr.af = ADDRESS_IP6; - } else { - // NOT IMPLEMENTED - ret = -1; - goto done; - } - - msg->payload.src_port = face->face.local_port; - msg->payload.dst_port = face->face.remote_port; - msg->payload.is_add = 1; - - int ret = vapi_hicn_api_udp_tunnel_add_del(s->g_vapi_ctx_instance, msg, - create_udp_tunnel_cb, &uei); - - if (ret) { - ERROR("Error in vapi_hicn_api_udp_tunnel_add_del"); - vapi_msg_free(s->g_vapi_ctx_instance, hicnp_msg); - goto done; - } - - hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP; - hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; - hicnp_msg->payload.route.paths[0].nh.obj_id = uei; - - face->face.netdevice.index = uei; - - break; - } - default: - ret = -1; - goto done; - } - - ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, - parse_route_create, NULL); - - if (ret) { - ERROR("Error in vapi_ip_route_add_del"); - goto done; - } - - vapi_msg_hicn_api_enable_disable *msg = - vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance); - - if (route->family == AF_INET) { - memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); - msg->payload.prefix.address.af = ADDRESS_IP4; - } else { - memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); - msg->payload.prefix.address.af = ADDRESS_IP6; - } - - msg->payload.prefix.len = route->len; - msg->payload.enable_disable = 1; - - ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg, - hicn_enable_cb, &face->id); - - if (ret) { - ERROR("Error in vapi_hicn_api_enable_disable"); - } - -done: - vapi_unlock(); - return ret; -} - -static int _hc_route_create(hc_sock_t *s, hc_route_t *route) { - return _hc_route_create_internal(s, route, false); -} - -static int _hc_route_create_async(hc_sock_t *s, hc_route_t *route) { - return _hc_route_create_internal(s, route, true); -} - -/* ROUTE DELETE */ -static vapi_error_e parse_route_delete( - vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_ip_route_add_del_reply *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - - return reply->retval; -} - -static vapi_error_e hicn_disable_cb( - vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_enable_disable_reply *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - - return reply->retval; -} - -static int _hc_route_delete_internal(hc_sock_t *socket, hc_route_t *route, - bool async) { - if (!IS_VALID_FAMILY(route->family)) return -1; - - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - - vapi_lock(); - - vapi_msg_hicn_api_enable_disable *msg = - vapi_alloc_hicn_api_enable_disable(s->g_vapi_ctx_instance); - - if (route->family == AF_INET) { - memcpy(&msg->payload.prefix.address.un.ip4[0], &route->remote_addr.v4, 4); - msg->payload.prefix.address.af = ADDRESS_IP4; - } else { - memcpy(&msg->payload.prefix.address.un.ip6[0], &route->remote_addr.v6, 16); - msg->payload.prefix.address.af = ADDRESS_IP6; - } - - msg->payload.prefix.len = route->len; - msg->payload.enable_disable = 0; - - vapi_error_e ret = vapi_hicn_api_enable_disable(s->g_vapi_ctx_instance, msg, - hicn_disable_cb, NULL); - - if (ret) { - ERROR("Error in vapi_hicn_api_enable_disable in route delete"); - goto done; - } - - vapi_msg_ip_route_add_del *hicnp_msg = - vapi_alloc_ip_route_add_del(s->g_vapi_ctx_instance, 1); - - hicnp_msg->payload.is_add = 0; - if (route->family == AF_INET) { - memcpy(&hicnp_msg->payload.route.prefix.address.un.ip4[0], - &route->remote_addr.v4, 4); - hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP4; - } else { - memcpy(&hicnp_msg->payload.route.prefix.address.un.ip6[0], - &route->remote_addr.v6, 16); - hicnp_msg->payload.route.prefix.address.af = ADDRESS_IP6; - } - - hicnp_msg->payload.route.prefix.len = route->len; - - hicnp_msg->payload.route.paths[0].sw_if_index = ~0; - hicnp_msg->payload.route.paths[0].table_id = 0; - - hc_face_t *face = &(route->face); - switch (face->face.type) { - case FACE_TYPE_HICN: { - if (ip_address_is_v4((ip_address_t *)(&(face->face.remote_addr)))) { - memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip4), - &face->face.remote_addr.v4, sizeof(ip4_address_t)); - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; - } else { - memcpy(&(hicnp_msg->payload.route.paths[0].nh.address.ip6), - &face->face.remote_addr.v6, sizeof(ip6_address_t)); - hicnp_msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; - } - - hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_NORMAL; - hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; - - break; - } - case FACE_TYPE_UDP: { - hicnp_msg->payload.route.paths[0].type = FIB_API_PATH_TYPE_UDP_ENCAP; - hicnp_msg->payload.route.paths[0].flags = FIB_API_PATH_FLAG_NONE; - hicnp_msg->payload.route.paths[0].nh.obj_id = face->face.netdevice.index; - break; - } - default: - return -1; - } - - ret = vapi_ip_route_add_del(s->g_vapi_ctx_instance, hicnp_msg, - parse_route_delete, NULL); - - if (ret) { - ERROR("Error in vapi_ip_route_add_del in route delete"); - goto done; - } - -done: - - vapi_unlock(); - return ret; -} - -static int _hc_route_delete(hc_sock_t *s, hc_route_t *route) { - return _hc_route_delete_internal(s, route, false); -} - -static int _hc_route_delete_async(hc_sock_t *s, hc_route_t *route) { - return _hc_route_delete_internal(s, route, true); -} - -static vapi_error_e parse_udp_encap_list( - vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_udp_encap_details *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - - hc_face_t *face = (hc_face_t *)callback_ctx; - - if (face->face.netdevice.index == reply->udp_encap.id) { - switch (reply->udp_encap.src_ip.af) { - case ADDRESS_IP4: { - memcpy(&face->face.local_addr.v4, &(reply->udp_encap.src_ip.un.ip4), - sizeof(ip4_address_t)); - memcpy(&face->face.remote_addr.v4, &(reply->udp_encap.dst_ip.un.ip4), - sizeof(ip4_address_t)); - break; - } - case ADDRESS_IP6: { - memcpy(&face->face.local_addr.v6, &(reply->udp_encap.src_ip.un.ip6), - sizeof(ip6_address_t)); - memcpy(&face->face.remote_addr.v6, &(reply->udp_encap.dst_ip.un.ip6), - sizeof(ip6_address_t)); - break; - } - default: - break; - } - - face->face.local_port = reply->udp_encap.src_port; - face->face.remote_port = reply->udp_encap.dst_port; - } - return rv; -} - -static int _fill_face_with_info(hc_face_t *face, vapi_type_fib_path *path, - hc_sock_t *s) { - switch (path->type) { - case FIB_API_PATH_FLAG_NONE: { - face->face.type = FACE_TYPE_HICN; - switch (path->proto) { - case FIB_API_PATH_NH_PROTO_IP4: - memcpy(&face->face.remote_addr.v4, &(path->nh.address.ip4), - sizeof(ip4_address_t)); - break; - case FIB_API_PATH_NH_PROTO_IP6: - memcpy(&face->face.remote_addr.v6, &(path->nh.address.ip6), - sizeof(ip6_address_t)); - break; - default: - break; - } - face->face.netdevice.index = path->sw_if_index; - } break; - case FIB_API_PATH_TYPE_UDP_ENCAP: { - face->face.type = FACE_TYPE_UDP; - face->face.netdevice.index = clib_net_to_host_u32(path->nh.obj_id); - // Let's make the compiler happy - (void)parse_udp_encap_list; - // vapi_msg_udp_encap_dump *msg; - // msg = vapi_alloc_udp_encap_dump(s->g_vapi_ctx_instance); - // vapi_udp_encap_dump(s->g_vapi_ctx_instance, msg, parse_udp_encap_list, - // face); - } break; - default: - return -1; - } - return 0; -} - -/* ROUTE LIST */ -typedef struct hicn_route_socket_s { - hc_data_t *data; - hc_sock_t *s; -} hicn_route_socket_t; - -static vapi_error_e parse_route_list(vapi_ctx_t ctx, void *callback_ctx, - vapi_error_e rv, bool is_last, - vapi_payload_ip_route_details *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - - hicn_route_socket_t *rs = (hicn_route_socket_t *)callback_ctx; - hc_data_t *data = rs->data; - - u8 found = false; - for (int j = 0; j < reply->route.n_paths; j++) { - for (int i = 0; i < data->size && !found; i++) { - hc_route_t *route = &((hc_route_t *)(data->buffer))[i]; - - if (ip_address_is_v4((ip_address_t *)&(route->remote_addr)) && - memcmp(route->remote_addr.v4.as_u8, - reply->route.prefix.address.un.ip4, - sizeof(ip4_address_t)) == 0 && - route->len == reply->route.prefix.len && route->face_id == ~0) { - _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s); - found = true; - } else if (memcmp(route->remote_addr.v6.as_u8, - reply->route.prefix.address.un.ip6, - sizeof(ip6_address_t)) == 0 && - route->len == reply->route.prefix.len && - route->face_id == ~0) { - _fill_face_with_info(&(route->face), &reply->route.paths[j], rs->s); - found = true; - } - } - } - - return rv; -} - -static vapi_error_e parse_hicn_route_list( - vapi_ctx_t ctx, void *callback_ctx, vapi_error_e rv, bool is_last, - vapi_payload_hicn_api_routes_details *reply) { - if (reply == NULL || rv != VAPI_OK) return rv; - - hc_data_t *data = (hc_data_t *)callback_ctx; - - int empty_spots = data->size - data->current; - if (empty_spots < reply->nfaces) { - int new_size = data->size + (reply->nfaces - empty_spots); - data->buffer = realloc(data->buffer, sizeof(hc_route_t) * (new_size)); - if (!data->buffer) return VAPI_ENOMEM; - - data->size = new_size; - } - - for (int i = 0; i < reply->nfaces; i++) { - hc_route_t *route = &((hc_route_t *)(data->buffer))[data->current]; - route->face_id = ~0; - route->cost = 1; - route->len = reply->prefix.len; - if (reply->prefix.address.af == ADDRESS_IP6) { - memcpy(route->remote_addr.v6.as_u8, reply->prefix.address.un.ip6, 16); - } else { - memcpy(route->remote_addr.v4.as_u8, reply->prefix.address.un.ip4, 4); - } - route->family = - reply->prefix.address.af == ADDRESS_IP6 ? AF_INET6 : AF_INET; - data->current++; - } - - return rv; -} - -static int _hc_route_list_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - hc_sock_vpp_t *s = TO_HC_SOCK_VPP(socket); - vapi_lock(); - - vapi_msg_hicn_api_routes_dump *msg; - msg = vapi_alloc_hicn_api_routes_dump(s->g_vapi_ctx_instance); - - hc_data_t *data = hc_data_create(0, sizeof(hc_route_t), NULL); - int ret = VAPI_OK; - - if (!data) { - ret = -1; - goto err; - } - - data->buffer = malloc(sizeof(hc_route_t)); - data->size = 1; - - if (!data->buffer) { - ret = -1; - goto err_free; - } - - ret = vapi_hicn_api_routes_dump(s->g_vapi_ctx_instance, msg, - parse_hicn_route_list, data); - - if (ret != VAPI_OK) goto err_free; - - vapi_msg_ip_route_dump *hicnp_msg; - hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance); - hicnp_msg->payload.table.table_id = 0; - hicnp_msg->payload.table.is_ip6 = 1; - - hicn_route_socket_t ctx = { - .data = data, - .s = socket, - }; - - ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, - &ctx); - - hicnp_msg = vapi_alloc_ip_route_dump(s->g_vapi_ctx_instance); - hicnp_msg->payload.table.table_id = 0; - hicnp_msg->payload.table.is_ip6 = 0; - - ret = vapi_ip_route_dump(s->g_vapi_ctx_instance, hicnp_msg, parse_route_list, - &ctx); - - if (ret != VAPI_OK) goto err_free; - - *pdata = data; - - vapi_unlock(); - return ret; - -err_free: - free(data); -err: - vapi_unlock(); - return ret; -} - -static int _hc_route_list(hc_sock_t *s, hc_data_t **pdata) { - return _hc_route_list_internal(s, pdata, false); -} - -static int _hc_route_list_async(hc_sock_t *s) { - return _hc_route_list_internal(s, NULL, true); -} - -/*----------------------------------------------------------------------------* - * Face - * - * Face support is not directly available in hicn-light, but we can offer such - * an interface through a combination of listeners and connections. The code - * starts with some conversion functions between faces/listeners/connections. - * - * We also need to make sure that there always exist a (single) listener when a - * connection is created, and in the hICN face case, that there is a single - * connection attached to this listener. - * - *----------------------------------------------------------------------------*/ - -static int _hc_face_create(hc_sock_t *socket, hc_face_t *face) { - ERROR("Face creation not implemented."); - return -1; -} - -static int _hc_face_get(hc_sock_t *socket, hc_face_t *face, - hc_face_t **face_found) { - ERROR("Face deletion not implemented."); - return -1; -} - -static int _hc_face_delete(hc_sock_t *s, hc_face_t *face, - uint8_t delete_listener) { - ERROR("Face deletion not implemented."); - return -1; -} - -/* FACE LIST */ - -static int _hc_face_list(hc_sock_t *s, hc_data_t **pdata) { - ERROR("Face list not implemented."); - return -1; -} - -static int _hc_face_list_async(hc_sock_t *s) { return 0; } - -static int _hc_face_set_admin_state( - hc_sock_t *s, const char *conn_id_or_name, // XXX wrong identifier - face_state_t admin_state) { - return 0; -} - -#ifdef WITH_POLICY -static int _hc_face_set_priority(hc_sock_t *s, const char *conn_id_or_name, - uint32_t priority) { - ERROR("Face set priority not implemented."); - return -1; -} - -static int _hc_face_set_tags(hc_sock_t *s, const char *conn_id_or_name, - policy_tags_t tags) { - ERROR("Face set tags not implemented."); - return -1; -} -#endif // WITH_POLICY - -/*----------------------------------------------------------------------------* - * Punting - *----------------------------------------------------------------------------*/ - -static int _hc_punting_create_internal(hc_sock_t *s, hc_punting_t *punting, - bool async) { - return -1; -} - -static int _hc_punting_create(hc_sock_t *s, hc_punting_t *punting) { - return _hc_punting_create_internal(s, punting, false); -} - -static int _hc_punting_create_async(hc_sock_t *s, hc_punting_t *punting) { - return _hc_punting_create_internal(s, punting, true); -} - -static int _hc_punting_get(hc_sock_t *s, hc_punting_t *punting, - hc_punting_t **punting_found) { - ERROR("hc_punting_get not (yet) implemented."); - return -1; -} - -static int _hc_punting_delete(hc_sock_t *s, hc_punting_t *punting) { - ERROR("hc_punting_delete not (yet) implemented."); - return -1; -} - -static int _hc_punting_list(hc_sock_t *s, hc_data_t **pdata) { - ERROR("hc_punting_list not (yet) implemented."); - return -1; -} - -/*----------------------------------------------------------------------------* - * Cache - *----------------------------------------------------------------------------*/ - -static int _hc_cache_set_store_internal(hc_sock_t *s, hc_cache_t *cache, - bool async) { - return 0; -} - -static int _hc_cache_set_store(hc_sock_t *s, hc_cache_t *cache) { - return _hc_cache_set_store_internal(s, cache, false); -} - -static int _hc_cache_set_store_async(hc_sock_t *s, hc_cache_t *cache) { - return _hc_cache_set_store_internal(s, cache, true); -} - -static int _hc_cache_set_serve_internal(hc_sock_t *s, hc_cache_t *cache, - bool async) { - return 0; -} - -static int _hc_cache_set_serve(hc_sock_t *s, hc_cache_t *cache) { - return _hc_cache_set_serve_internal(s, cache, false); -} - -static int _hc_cache_set_serve_async(hc_sock_t *s, hc_cache_t *cache) { - return _hc_cache_set_serve_internal(s, cache, true); -} - -/*----------------------------------------------------------------------------* - * Strategy - *----------------------------------------------------------------------------*/ - -// per prefix -static int _hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) { return 0; } - -static int _hc_strategy_add_local_prefix(hc_sock_t *s, - hc_strategy_t *strategy) { - return 0; -} - -static int _hc_strategy_list(hc_sock_t *s, hc_data_t **data) { return 0; } - -/*----------------------------------------------------------------------------* - * WLDR - *----------------------------------------------------------------------------*/ - -// per connection -static int _hc_wldr_set(hc_sock_t *s /* XXX */) { return 0; } - -/*----------------------------------------------------------------------------* - * MAP-Me - *----------------------------------------------------------------------------*/ - -static int _hc_mapme_set(hc_sock_t *s, int enabled) { return 0; } - -static int _hc_mapme_set_discovery(hc_sock_t *s, int enabled) { return 0; } - -static int _hc_mapme_set_timescale(hc_sock_t *s, uint32_t timescale) { - return 0; -} - -static int _hc_mapme_set_retx(hc_sock_t *s, uint32_t timescale) { return 0; } - -/*----------------------------------------------------------------------------* - * Policy - *----------------------------------------------------------------------------*/ - -#ifdef WITH_POLICY - -/* POLICY CREATE */ - -static int _hc_policy_create_internal(hc_sock_t *socket, hc_policy_t *policy, - bool async) { - return -1; -} - -static int _hc_policy_create(hc_sock_t *s, hc_policy_t *policy) { - return _hc_policy_create_internal(s, policy, false); -} - -static int _hc_policy_create_async(hc_sock_t *s, hc_policy_t *policy) { - return _hc_policy_create_internal(s, policy, true); -} - -/* POLICY DELETE */ - -static int _hc_policy_delete_internal(hc_sock_t *socket, hc_policy_t *policy, - bool async) { - return -1; -} - -static int _hc_policy_delete(hc_sock_t *s, hc_policy_t *policy) { - return _hc_policy_delete_internal(s, policy, false); -} - -static int _hc_policy_delete_async(hc_sock_t *s, hc_policy_t *policy) { - return _hc_policy_delete_internal(s, policy, true); -} - -/* POLICY LIST */ - -static int _hc_policy_list_internal(hc_sock_t *socket, hc_data_t **pdata, - bool async) { - return -1; -} - -static int _hc_policy_list(hc_sock_t *s, hc_data_t **pdata) { - return _hc_policy_list_internal(s, pdata, false); -} - -static int _hc_policy_list_async(hc_sock_t *s, hc_data_t **pdata) { - return _hc_policy_list_internal(s, pdata, true); -} - -#endif /* WITH_POLICY */ - -/*----------------------------------------------------------------------------* - * Configuration - *----------------------------------------------------------------------------*/ - -typedef struct hc_result_s { - void *_; -} hc_result_t; - -static hc_result_t *_hc_listener_create_conf(hc_sock_t *s, - hc_listener_t *listener) { - ERROR("Not implemented."); - return NULL; -} -static hc_result_t *_hc_connection_create_conf(hc_sock_t *s, - hc_connection_t *connection) { - ERROR("Not implemented."); - return NULL; -} -static hc_result_t *_hc_route_create_conf(hc_sock_t *s, hc_route_t *route) { - ERROR("Not implemented."); - return NULL; -} -static hc_result_t *_hc_strategy_set_conf(hc_sock_t *s, - hc_strategy_t *strategy) { - ERROR("Not implemented."); - return NULL; -} -static hc_result_t *_hc_strategy_add_local_prefix_conf( - hc_sock_t *s, hc_strategy_t *strategy) { - ERROR("Not implemented."); - return NULL; -} - -hc_msg_t *_hc_result_get_msg(hc_result_t *result) { - ERROR("Not implemented."); - return NULL; -} -int _hc_result_get_cmd_id(hc_result_t *result) { - ERROR("Not implemented."); - return -1; -} -bool _hc_result_get_success(hc_result_t *result) { - ERROR("Not implemented."); - return false; -} -void _hc_result_free(hc_result_t *result) { free(result); } - -static hc_sock_t hc_sock_vpp_interface = (hc_sock_t){ - .hc_sock_get_next_seq = _hc_sock_vpp_get_next_seq, - .hc_sock_set_nonblocking = _hc_sock_vpp_set_nonblocking, - .hc_sock_get_fd = _hc_sock_vpp_get_fd, - .hc_sock_connect = _hc_sock_vpp_connect, - .hc_sock_get_available = _hc_sock_vpp_get_available, - .hc_sock_send = _hc_sock_vpp_send, - .hc_sock_recv = _hc_sock_vpp_recv, - .hc_sock_process = _hc_sock_vpp_process, - .hc_sock_callback = _hc_sock_vpp_callback, - .hc_sock_reset = _hc_sock_vpp_reset, - .hc_sock_free = _hc_sock_vpp_free, - .hc_listener_create = _hc_listener_create, - .hc_listener_create_async = _hc_listener_create_async, - .hc_listener_get = _hc_listener_get, - .hc_listener_delete = _hc_listener_delete, - .hc_listener_delete_async = _hc_listener_delete_async, - .hc_listener_list = _hc_listener_list, - .hc_listener_list_async = _hc_listener_list_async, - .hc_connection_create = _hc_connection_create, - .hc_connection_create_async = _hc_connection_create_async, - .hc_connection_get = _hc_connection_get, - .hc_connection_update_by_id = _hc_connection_update_by_id, - .hc_connection_update = _hc_connection_update, - .hc_connection_delete = _hc_connection_delete, - .hc_connection_delete_async = _hc_connection_delete_async, - .hc_connection_list = _hc_connection_list, - .hc_connection_list_async = _hc_connection_list_async, - .hc_connection_set_admin_state = _hc_connection_set_admin_state, - .hc_connection_set_admin_state_async = _hc_connection_set_admin_state_async, - -#ifdef WITH_POLICY - .hc_connection_set_priority = _hc_connection_set_priority, - .hc_connection_set_priority_async = _hc_connection_set_priority_async, - .hc_connection_set_tags = _hc_connection_set_tags, - .hc_connection_set_tags_async = _hc_connection_set_tags_async, -#endif // WITH_POLICY - - .hc_face_create = _hc_face_create, - .hc_face_get = _hc_face_get, - .hc_face_delete = _hc_face_delete, - .hc_face_list = _hc_face_list, - .hc_face_list_async = _hc_face_list_async, - .hc_face_set_admin_state = _hc_face_set_admin_state, - -#ifdef WITH_POLICY - .hc_face_set_priority = _hc_face_set_priority, - .hc_face_set_tags = _hc_face_set_tags, -#endif // WITH_POLICY - - .hc_route_create = _hc_route_create, - .hc_route_create_async = _hc_route_create_async, - .hc_route_delete = _hc_route_delete, - .hc_route_delete_async = _hc_route_delete_async, - .hc_route_list = _hc_route_list, - .hc_route_list_async = _hc_route_list_async, - - .hc_punting_create = _hc_punting_create, - .hc_punting_create_async = _hc_punting_create_async, - .hc_punting_get = _hc_punting_get, - .hc_punting_delete = _hc_punting_delete, - .hc_punting_list = _hc_punting_list, - - .hc_cache_set_store = _hc_cache_set_store, - .hc_cache_set_store_async = _hc_cache_set_store_async, - .hc_cache_set_serve = _hc_cache_set_serve, - .hc_cache_set_serve_async = _hc_cache_set_serve_async, - - .hc_strategy_list = _hc_strategy_list, - .hc_strategy_set = _hc_strategy_set, - .hc_strategy_add_local_prefix = _hc_strategy_add_local_prefix, - .hc_wldr_set = _hc_wldr_set, - - .hc_mapme_set = _hc_mapme_set, - .hc_mapme_set_discovery = _hc_mapme_set_discovery, - .hc_mapme_set_timescale = _hc_mapme_set_timescale, - .hc_mapme_set_retx = _hc_mapme_set_retx, - -#ifdef WITH_POLICY - .hc_policy_create = _hc_policy_create, - .hc_policy_create_async = _hc_policy_create_async, - .hc_policy_delete = _hc_policy_delete, - .hc_policy_delete_async = _hc_policy_delete_async, - .hc_policy_list = _hc_policy_list, - .hc_policy_list_async = _hc_policy_list_async, -#endif // WITH_POLICY - - .hc_listener_create_conf = _hc_listener_create_conf, - .hc_connection_create_conf = _hc_connection_create_conf, - .hc_route_create_conf = _hc_route_create_conf, - .hc_strategy_set_conf = _hc_strategy_set_conf, - .hc_strategy_add_local_prefix_conf = _hc_strategy_add_local_prefix_conf, - - .hc_result_get_msg = _hc_result_get_msg, - .hc_result_get_cmd_id = _hc_result_get_cmd_id, - .hc_result_get_success = _hc_result_get_success, - .hc_result_free = _hc_result_free, -}; - -hc_sock_t *_hc_sock_create_url(const char *url) { - if (url) { - // NOT IMPLEMENTED - return NULL; - } - - hc_sock_vpp_t *s = malloc(sizeof(hc_sock_vpp_t)); - - if (!s) goto ERR_SOCK; - - memset(s, 0, sizeof(hc_sock_vpp_t)); - - s->vft = hc_sock_vpp_interface; - - // By default the socket is blocking -- not async - s->async = 0; - - return (hc_sock_t *)(s); - -ERR_SOCK: - return NULL; -} diff --git a/ctrl/libhicnctrl/src/object.c b/ctrl/libhicnctrl/src/object.c new file mode 100644 index 000000000..34f21509a --- /dev/null +++ b/ctrl/libhicnctrl/src/object.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file object.c + * \brief Implementation of API object representation. + */ + +#include <hicn/ctrl/action.h> +#include <hicn/ctrl/object.h> + +#include "objects/base.h" // iszero +#include "object_vft.h" + +bool hc_object_is_empty(const hc_object_t *object) { + return iszero(object, sizeof(hc_object_t)); +} + +int hc_object_validate(hc_object_type_t object_type, hc_object_t *object, + bool allow_partial) { + const hc_object_ops_t *vft = object_vft[object_type]; + if (!vft) return -1; + return vft->validate(object, allow_partial); +} + +int hc_object_cmp(hc_object_type_t object_type, hc_object_t *object1, + hc_object_t *object2) { + const hc_object_ops_t *vft = object_vft[object_type]; + if (!vft) return -1; + return vft->cmp(object1, object2); +} + +int hc_object_snprintf(char *s, size_t size, hc_object_type_t object_type, + hc_object_t *object) { + const hc_object_ops_t *vft = object_vft[object_type]; + if (!vft) return -1; + return vft->obj_snprintf(s, size, object); +} + +size_t hc_object_size(hc_object_type_t object_type) { + const hc_object_ops_t *vft = object_vft[object_type]; + if (!vft) return -1; + return vft->size; +} diff --git a/ctrl/libhicnctrl/src/object_private.h b/ctrl/libhicnctrl/src/object_private.h new file mode 100644 index 000000000..2be12fd5e --- /dev/null +++ b/ctrl/libhicnctrl/src/object_private.h @@ -0,0 +1,35 @@ +#ifndef HICNCTRL_OBJECT_PRIVATE_H +#define HICNCTRL_OBJECT_PRIVATE_H + +#define INT_CMP(x, y) ((x > y) ? 1 : (x < y) ? -1 : 0) + +// XXX Those are always true +#define IS_VALID_ADDRESS(x) (1) +#define IS_VALID_CONNECTION_ID(x) (1) // XXX ID +#define IS_VALID_ROUTE_COST(x) (1) +#define IS_VALID_PREFIX_LEN(x) (1) +#define IS_VALID_POLICY(x) (1) +#define IS_VALID_ID(x) (1) +#define IS_VALID_INTERFACE_NAME(x) (1) +#define IS_VALID_NAME(x) (1) +#define IS_VALID_TYPE(x) IS_VALID_ENUM_TYPE(FACE_TYPE, x) +#define IS_VALID_FACE_STATE(x) (1) + +#define IS_VALID_ADDR_TYPE(x) ((x >= ADDR_INET) && (x <= ADDR_UNIX)) + +#define IS_VALID_CONNECTION_TYPE(x) IS_VALID_ENUM_TYPE(CONNECTION_TYPE, x) + +#define GENERATE_FIND(TYPE) \ + int hc_##TYPE##_find(hc_data_t *data, const hc_##TYPE##_t *element, \ + hc_##TYPE##_t **found) { \ + foreach_type(hc_##TYPE##_t, x, data) { \ + if (hc_##TYPE##_cmp(x, element) == 0) { \ + *found = x; \ + return 0; \ + } \ + }; \ + *found = NULL; /* this is optional */ \ + return 0; \ + } + +#endif /* HICNCTRL_OBJECT_PRIVATE_H */ diff --git a/ctrl/libhicnctrl/src/object_type.c b/ctrl/libhicnctrl/src/object_type.c new file mode 100644 index 000000000..0303fce75 --- /dev/null +++ b/ctrl/libhicnctrl/src/object_type.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file object_type.c + * \brief Implementation of object type. + */ + +#include <strings.h> + +#include <hicn/ctrl/object_type.h> + +const char *object_type_str[] = { +#define _(x) [OBJECT_TYPE_##x] = #x, + foreach_object_type +#undef _ +}; + +hc_object_type_t object_type_from_str(const char *object_str) { +#define _(x) \ + if (strcasecmp(object_str, #x) == 0) \ + return OBJECT_TYPE_##x; \ + else + foreach_object_type +#undef _ + return OBJECT_TYPE_UNDEFINED; +} diff --git a/ctrl/libhicnctrl/src/object_vft.c b/ctrl/libhicnctrl/src/object_vft.c new file mode 100644 index 000000000..808c0f913 --- /dev/null +++ b/ctrl/libhicnctrl/src/object_vft.c @@ -0,0 +1,19 @@ +#include "object_vft.h" + +#include "objects/listener.h" +#include "objects/connection.h" +#include "objects/route.h" +#include "objects/face.h" +#include "objects/strategy.h" +#include "objects/subscription.h" +#include "objects/active_interface.h" + +const hc_object_ops_t *object_vft[] = { + [OBJECT_TYPE_LISTENER] = &hc_listener_ops, + [OBJECT_TYPE_CONNECTION] = &hc_connection_ops, + [OBJECT_TYPE_ROUTE] = &hc_route_ops, + [OBJECT_TYPE_FACE] = &hc_face_ops, + [OBJECT_TYPE_STRATEGY] = &hc_strategy_ops, + [OBJECT_TYPE_SUBSCRIPTION] = &hc_subscription_ops, + [OBJECT_TYPE_ACTIVE_INTERFACE] = &hc_active_interface_ops, +}; diff --git a/ctrl/libhicnctrl/src/object_vft.h b/ctrl/libhicnctrl/src/object_vft.h new file mode 100644 index 000000000..e27fe5d36 --- /dev/null +++ b/ctrl/libhicnctrl/src/object_vft.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file object_vft.h + * \brief Object VFT. + */ + +#ifndef HICNCTRL_OBJECT_VFT +#define HICNCTRL_OBJECT_VFT + +#include <stddef.h> // size_t +#include <hicn/ctrl/object_type.h> +#include <hicn/ctrl/object.h> + +typedef struct { + hc_object_type_t object_type; + const char *object_name; + size_t size; + int (*validate)(const hc_object_t *object, bool allow_partial); + int (*cmp)(const hc_object_t *object1, const hc_object_t *object2); + /* cannot be named snprintf as it collides with a macro in clang/iOS */ + int (*obj_snprintf)(char *s, size_t size, const hc_object_t *object); +} hc_object_ops_t; + +#define DECLARE_OBJECT_OPS_H(TYPE, NAME) \ + extern const hc_object_ops_t hc_##NAME##_ops; + +#define DECLARE_OBJECT_OPS(TYPE, NAME) \ + const hc_object_ops_t hc_##NAME##_ops = { \ + .object_type = TYPE, \ + .object_name = #NAME, \ + .size = sizeof(hc_##NAME##_t), \ + .validate = _hc_##NAME##_validate, \ + .cmp = _hc_##NAME##_cmp, \ + .obj_snprintf = _hc_##NAME##_snprintf, \ + }; + +extern const hc_object_ops_t *object_vft[]; + +#endif /* HICNCTRL_OBJECT_VFT */ diff --git a/ctrl/libhicnctrl/src/objects/active_interface.c b/ctrl/libhicnctrl/src/objects/active_interface.c new file mode 100644 index 000000000..796123963 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/active_interface.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file active_interface.c + * \brief Implementation of active_interface object. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/active_interface.h> +#include <hicn/util/log.h> +#include <hicn/util/ip_address.h> + +#include "../object_private.h" +#include "../object_vft.h" + +/* ACTIVE_INTERFACE VALIDATE */ + +int hc_active_interface_validate(const hc_active_interface_t *active_interface, + bool allow_partial) { + return 0; // XXX TODO +} + +int _hc_active_interface_validate(const hc_object_t *object, + bool allow_partial) { + return hc_active_interface_validate(&object->active_interface, allow_partial); +} + +/* ACTIVE_INTERFACE CMP */ + +// XXX TODO +int hc_active_interface_cmp(const hc_active_interface_t *active_interface1, + const hc_active_interface_t *active_interface2) { + return -1; +} + +int _hc_active_interface_cmp(const hc_object_t *object1, + const hc_object_t *object2) { + return hc_active_interface_cmp(&object1->active_interface, + &object2->active_interface); +} + +/* ACTIVE_INTERFACE SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_active_interface_snprintf( + char *s, size_t size, const hc_active_interface_t *active_interface) { + int rc; + char *pos = s; + + rc = hicn_ip_prefix_snprintf(pos, size, &active_interface->prefix); + if ((rc < 0) || (rc >= size)) return rc; + pos += rc; + size -= rc; + + for (netdevice_type_t type = NETDEVICE_TYPE_UNDEFINED + 1; + type < NETDEVICE_TYPE_N; type++) { + if (!netdevice_flags_has(active_interface->interface_types, type)) continue; + rc = snprintf(pos, size, " %s", netdevice_type_str(type)); + if ((rc < 0) || (rc >= size)) return (int)(pos - s + rc); + + pos += rc; + size -= rc; + } + return (int)(pos - s); +} + +int _hc_active_interface_snprintf(char *s, size_t size, + const hc_object_t *object) { + return hc_active_interface_snprintf(s, size, &object->active_interface); +} + +DECLARE_OBJECT_OPS(OBJECT_TYPE_ACTIVE_INTERFACE, active_interface); diff --git a/ctrl/libhicnctrl/src/objects/active_interface.h b/ctrl/libhicnctrl/src/objects/active_interface.h new file mode 100644 index 000000000..973b08e40 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/active_interface.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file active_interface.h + * \brief Route. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H +#define HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H + +#include "../object_vft.h" + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_ACTIVE_INTERFACE, active_interface); + +#endif /* HICNCTRL_IMPL_OBJECTS_ACTIVE_INTERFACE_H */ diff --git a/ctrl/libhicnctrl/src/objects/base.c b/ctrl/libhicnctrl/src/objects/base.c new file mode 100644 index 000000000..86e4bfb72 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/base.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file base.c + * \brief Implementation of base functions for object APIs. + */ + +#include <stdbool.h> + +#include "base.h" + +#include <hicn/util/log.h> + +bool iszero(const void *ptr, int bytes) { + char *bptr = (char *)ptr; + while (bytes--) + if (*bptr++) return false; + return true; +} + +bool isempty(const char *str) { return str[0] == '\0'; } diff --git a/ctrl/libhicnctrl/src/objects/base.h b/ctrl/libhicnctrl/src/objects/base.h new file mode 100644 index 000000000..eb85483e9 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/base.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file base.h + * \brief Base functions for object APIs. + */ + +#ifndef HICNCTRL_OBJECTS_BASE_H +#define HICNCTRL_OBJECTS_BASE_H + +bool iszero(const void *ptr, int bytes); +bool isempty(const char *str); + +#endif /* HICNCTRL_OBJECTS_BASE_H */ diff --git a/ctrl/libhicnctrl/src/objects/connection.c b/ctrl/libhicnctrl/src/objects/connection.c new file mode 100644 index 000000000..14e763396 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/connection.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file connection.c + * \brief Implementation of connection object. + */ + +#include <assert.h> + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/connection.h> +#include <hicn/util/log.h> + +#include "../object_private.h" +#include "../object_vft.h" +#include "base.h" + +bool hc_connection_is_local(const hc_connection_t *connection) { + return (strncmp(connection->interface_name, "lo", INTERFACE_LEN) == 0); +} + +bool hc_connection_has_local(const hc_connection_t *connection) { + assert(connection); + return IS_VALID_PORT(connection->local_port) && + IS_VALID_ADDRESS(connection->local_addr); +} + +/* CONNECTION VALIDATE */ + +int hc_connection_validate(const hc_connection_t *connection, + bool allow_partial) { + int has_id = 0; + int has_name = 0; + int has_interface_name = 0; + int has_netdevice_type = 0; + int has_type = 0; + int has_family = 0; + int has_local_addr = 0; + int has_local_port = 0; + int has_remote_addr = 0; + int has_remote_port = 0; + int has_admin_state = 0; + int has_priority = 0; + int has_tags = 0; + int has_state = 0; + + if (connection->id == ~0) { + ERROR("[hc_listener_validate] Invalid id specified"); + return -1; + } + has_id = 1; + + if (!isempty(connection->name)) { + if (!IS_VALID_NAME(connection->name)) { + ERROR("[hc_connection_validate] Invalid name specified"); + return -1; + } + has_name = 1; + } + + if (!isempty(connection->interface_name)) { + if (!IS_VALID_INTERFACE_NAME(connection->interface_name)) { + ERROR("[hc_connection_validate] Invalid interface_name specified"); + return -1; + } + has_interface_name = 1; + } + + if (connection->type != FACE_TYPE_UNDEFINED) { + if (!IS_VALID_TYPE(connection->type)) { + ERROR("[hc_connection_validate] Invalid type specified"); + return -1; + } + has_type = 1; + } + + if (connection->family != AF_UNSPEC) { + if (!IS_VALID_FAMILY(connection->family)) { + ERROR("[hc_connection_validate] Invalid family specified"); + return -1; + } + has_family = 1; + } + + if (!hicn_ip_address_empty(&connection->local_addr)) { + if (!IS_VALID_ADDRESS(connection->local_addr)) { + ERROR("[hc_connection_validate] Invalid local_addr specified"); + return -1; + } + has_local_addr = 1; + } + + if (connection->local_port != 0) { + if (!IS_VALID_PORT(connection->local_port)) { + ERROR("[hc_connection_validate] Invalid local_port specified"); + return -1; + } + has_local_port = 1; + } + + if (!hicn_ip_address_empty(&connection->remote_addr)) { + if (!IS_VALID_ADDRESS(connection->remote_addr)) { + ERROR("[hc_connection_validate] Invalid remote_addr specified"); + return -1; + } + has_remote_addr = 1; + } + + if (connection->remote_port != 0) { + if (!IS_VALID_PORT(connection->remote_port)) { + ERROR("[hc_connection_validate] Invalid remote_port specified"); + return -1; + } + has_remote_port = 1; + } + + int has_key = has_id || has_name; + int has_mandatory_attributes = has_interface_name && has_type && has_family && + has_local_addr && has_local_port && + has_remote_addr && has_remote_port; + int has_optional_attributes = + has_netdevice_type && has_admin_state && has_state; + has_optional_attributes = has_optional_attributes && has_priority && has_tags; + + if (allow_partial) { + if (has_key && !has_mandatory_attributes && !has_optional_attributes) + return 0; + else if (has_mandatory_attributes) + return 0; + else + return -1; + } else { + if (has_key && has_mandatory_attributes) return 0; + return -1; + } +} + +int _hc_connection_validate(const hc_object_t *object, bool allow_partial) { + return hc_connection_validate(&object->connection, allow_partial); +} + +/* CONNECTION CMP */ + +/* + * hICN light uses ports even for hICN connections, but their value is + * ignored. As connections are specific to hicn-light, we can safely use IP + * and ports for comparison independently of the face type. + */ +int hc_connection_cmp(const hc_connection_t *c1, const hc_connection_t *c2) { + int rc; + + rc = INT_CMP(c1->type, c2->type); + if (rc != 0) return rc; + + rc = INT_CMP(c1->family, c2->family); + if (rc != 0) return rc; + + rc = strncmp(c1->interface_name, c2->interface_name, INTERFACE_LEN); + if (rc != 0) return rc; + + rc = hicn_ip_address_cmp(&c1->local_addr, &c2->local_addr); + if (rc != 0) return rc; + + rc = INT_CMP(c1->local_port, c2->local_port); + if (rc != 0) return rc; + + rc = hicn_ip_address_cmp(&c1->remote_addr, &c2->remote_addr); + if (rc != 0) return rc; + + rc = INT_CMP(c1->remote_port, c2->remote_port); + if (rc != 0) return rc; + + return rc; +} + +int _hc_connection_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_connection_cmp(&object1->connection, &object2->connection); +} + +/* CONNECTION SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_connection_snprintf(char *s, size_t size, + const hc_connection_t *connection) { + char local[MAXSZ_URL]; + char remote[MAXSZ_URL]; + int rc; + + // assert(connection->connection_state) + if (strcmp(connection->name, "SELF") == 0) { + return snprintf(s, size, "%s", connection->name); + } + + rc = url_snprintf(local, MAXSZ_URL, &connection->local_addr, + connection->local_port); + if (rc >= MAXSZ_URL) + WARN("[hc_connection_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + rc = url_snprintf(remote, MAXSZ_URL, &connection->remote_addr, + connection->remote_port); + if (rc >= MAXSZ_URL) + WARN("[hc_connection_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + + return snprintf(s, size, "%s %s %s %s", connection->name, local, remote, + face_type_str(connection->type)); +} + +int _hc_connection_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_connection_snprintf(s, size, &object->connection); +} + +int hc_connection_create(hc_sock_t *s, hc_connection_t *connection) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.connection = *connection; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +int hc_connection_get(hc_sock_t *s, hc_connection_t *connection, + hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.connection = *connection; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_CONNECTION, &object, pdata); +} + +int hc_connection_delete(hc_sock_t *s, hc_connection_t *connection) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.connection = *connection; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +int hc_connection_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_CONNECTION, NULL, pdata); +} + +int hc_connection_set_admin_state(hc_sock_t *s, const char *conn_id_or_name, + face_state_t state) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1; + object.connection.admin_state = state; + return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +int hc_connection_set_priority(hc_sock_t *s, const char *conn_id_or_name, + uint32_t priority) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1; + object.connection.priority = priority; + return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +int hc_connection_set_tags(hc_sock_t *s, const char *conn_id_or_name, + + policy_tags_t tags) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + int rc = snprintf(object.connection.name, SYMBOLIC_NAME_LEN, "%s", + conn_id_or_name); + if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) return -1; + object.connection.tags = tags; + return hc_execute(s, ACTION_UPDATE, OBJECT_TYPE_CONNECTION, &object, NULL); +} + +GENERATE_FIND(connection); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_CONNECTION, connection); diff --git a/ctrl/libhicnctrl/src/objects/connection.h b/ctrl/libhicnctrl/src/objects/connection.h new file mode 100644 index 000000000..4a4c78f09 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/connection.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file connection.h + * \brief Connection. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_CONNECTION_H +#define HICNCTRL_IMPL_OBJECTS_CONNECTION_H + +#include "../object_vft.h" + +bool hc_connection_is_local(const hc_connection_t *connection); +bool hc_connection_has_local(const hc_connection_t *connection); + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_CONNECTION, connection); + +#endif /* HICNCTRL_IMPL_OBJECTS_CONNECTION_H */ diff --git a/ctrl/libhicnctrl/src/objects/face.c b/ctrl/libhicnctrl/src/objects/face.c new file mode 100644 index 000000000..c535ff4c5 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/face.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file face.c + * \brief Implementation of face object. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/face.h> +#include <hicn/util/log.h> + +#include "../object_private.h" +#include "../object_vft.h" + +bool hc_face_has_netdevice(const hc_face_t *face) { + return netdevice_is_empty(&face->netdevice); +} + +/* FACE VALIDATE */ + +int hc_face_validate(const hc_face_t *face, bool allow_partial) { + if ((!allow_partial || !hc_face_has_netdevice(face)) && + !IS_VALID_INTERFACE_NAME(face->interface_name)) { + ERROR("[hc_face_validate] Invalid interface_name specified"); + return -1; + } + if (!IS_VALID_TYPE(face->type)) { + ERROR("[hc_face_validate] Invalid type specified"); + return -1; + } + if ((!allow_partial || face->family != AF_UNSPEC) && + !IS_VALID_FAMILY(face->family)) { + ERROR("[hc_face_validate] Invalid family specified"); + return -1; + } + if ((!allow_partial || !hicn_ip_address_empty(&face->local_addr)) && + !IS_VALID_ADDRESS(face->local_addr)) { + ERROR("[hc_face_validate] Invalid local_addr specified"); + return -1; + } + if ((!allow_partial || !(face->local_port == 0)) && + !IS_VALID_PORT(face->local_port)) { + ERROR("[hc_face_validate] Invalid local_port specified"); + return -1; + } + if (!IS_VALID_ADDRESS(face->remote_addr)) { + ERROR("[hc_face_validate] Invalid remote_addr specified"); + return -1; + } + if (!IS_VALID_PORT(face->remote_port)) { + ERROR("[hc_face_validate] Invalid remote_port specified"); + return -1; + } + return 0; +} + +int _hc_face_validate(const hc_object_t *object, bool allow_partial) { + return hc_face_validate(&object->face, allow_partial); +} + +/* FACE CMP */ + +int hc_face_cmp(const hc_face_t *c1, const hc_face_t *c2) { + return -99; // Not implemented +} + +int _hc_face_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_face_cmp(&object1->face, &object2->face); +} + +/* FACE SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_face_snprintf(char *s, size_t size, const hc_face_t *face) { + /* URLs are also big enough to contain IP addresses in the hICN case */ + char local[MAXSZ_URL]; + char remote[MAXSZ_URL]; + char tags[MAXSZ_POLICY_TAGS]; + int rc; + + switch (face->type) { + case FACE_TYPE_HICN: + case FACE_TYPE_HICN_LISTENER: + rc = hicn_ip_address_snprintf(local, MAXSZ_URL, &face->local_addr); + if (rc >= MAXSZ_URL) + WARN("[hc_face_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + rc = hicn_ip_address_snprintf(remote, MAXSZ_URL, &face->remote_addr); + if (rc >= MAXSZ_URL) + WARN("[hc_face_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + break; + case FACE_TYPE_TCP: + case FACE_TYPE_UDP: + case FACE_TYPE_TCP_LISTENER: + case FACE_TYPE_UDP_LISTENER: + rc = url_snprintf(local, MAXSZ_URL, &face->local_addr, face->local_port); + if (rc >= MAXSZ_URL) + WARN("[hc_face_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + rc = url_snprintf(remote, MAXSZ_URL, &face->remote_addr, + face->remote_port); + if (rc >= MAXSZ_URL) + WARN("[hc_face_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + break; + default: + return -1; + } + + // [#ID NAME] TYPE LOCAL_URL REMOTE_URL STATE/ADMIN_STATE (TAGS) + rc = policy_tags_snprintf(tags, MAXSZ_POLICY_TAGS, face->tags); + if (rc >= MAXSZ_POLICY_TAGS) + WARN("[hc_face_snprintf] Unexpected truncation of policy tags string"); + if (rc < 0) return rc; + + return snprintf( + s, size, "[#%d %s] %s %s %s %s %s/%s [%d] (%s)", face->id, face->name, + face->netdevice.index != NETDEVICE_UNDEFINED_INDEX ? face->netdevice.name + : "*", + face_type_str(face->type), local, remote, face_state_str(face->state), + face_state_str(face->admin_state), face->priority, tags); +} + +int _hc_face_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_face_snprintf(s, size, &object->face); +} + +int hc_face_create(hc_sock_t *s, hc_face_t *face) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.face = *face; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_FACE, &object, NULL); +} + +int hc_face_get(hc_sock_t *s, hc_face_t *face, hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.face = *face; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_FACE, &object, pdata); +} + +int hc_face_delete(hc_sock_t *s, hc_face_t *face) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.face = *face; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_FACE, &object, NULL); +} + +int hc_face_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_FACE, NULL, pdata); +} + +int hc_face_list_async(hc_sock_t *s) { + return hc_execute_async(s, ACTION_LIST, OBJECT_TYPE_FACE, NULL, NULL, NULL); +} + +GENERATE_FIND(face); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_FACE, face); diff --git a/ctrl/libhicnctrl/src/objects/face.h b/ctrl/libhicnctrl/src/objects/face.h new file mode 100644 index 000000000..08f90f195 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/face.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file face.h + * \brief Face. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_FACE_H +#define HICNCTRL_IMPL_OBJECTS_FACE_H + +#include "../object_vft.h" + +int hc_face_validate(const hc_face_t *face, bool allow_partial); + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_FACE, face); + +#endif /* HICNCTRL_IMPL_OBJECTS_FACE_H */ diff --git a/ctrl/libhicnctrl/src/objects/listener.c b/ctrl/libhicnctrl/src/objects/listener.c new file mode 100644 index 000000000..660a4931d --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/listener.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file listener.c + * \brief Implementation of listener. + */ + +#include <string.h> + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/listener.h> +#include <hicn/util/log.h> + +#include "../object_vft.h" +#include "../object_private.h" +#include "base.h" + +bool hc_listener_is_local(const hc_listener_t *listener) { + return (strncmp(listener->interface_name, "lo", INTERFACE_LEN) == 0); +} + +/* LISTENER VALIDATE */ + +int hc_listener_validate(const hc_listener_t *listener, bool allow_partial) { + // if a field is specified it should be valid + // then we allow different specification, by key or by attributes, if + // allow_partial + + int has_id = 0; + int has_name = 0; + int has_interface_name = 0; + int has_type = 0; + int has_family = 0; + int has_local_addr = 0; + int has_local_port = 0; + + if (listener->id == ~0) { + ERROR("[hc_listener_validate] Invalid id specified"); + return -1; + } + has_id = 1; + + if (!isempty(listener->name)) { + if (!IS_VALID_NAME(listener->name)) { + ERROR("[hc_listener_validate] Invalid name specified"); + return -1; + } + has_name = 1; + } + + if (!isempty(listener->interface_name)) { + if (!IS_VALID_INTERFACE_NAME(listener->interface_name)) { + ERROR("[hc_listener_validate] Invalid interface_name specified"); + return -1; + } + has_interface_name = 1; + } + + if (listener->type != FACE_TYPE_UNDEFINED) { + if (!IS_VALID_TYPE(listener->type)) { + ERROR("[hc_listener_validate] Invalid type specified"); + return -1; + } + has_type = 1; + } + + if (listener->family != AF_UNSPEC) { + if (!IS_VALID_FAMILY(listener->family)) { + ERROR("[hc_listener_validat] Invalid family specified"); + return -1; + } + has_family = 1; + } + + if (!hicn_ip_address_empty(&listener->local_addr)) { + if (!IS_VALID_ADDRESS(listener->local_addr)) { + ERROR("[hc_listener_validate] Invalid local_addr specified"); + return -1; + } + has_local_addr = 1; + } + + if (listener->local_port != 0) { + if (!IS_VALID_PORT(listener->local_port)) { + ERROR("[hc_listener_validate] Invalid local_port specified"); + return -1; + } + has_local_port = 1; + } + + if (allow_partial) { + if ((has_id || has_name) && !has_type && !has_family && !has_local_port && + !has_local_port) + return 0; + else if (has_name && has_type && has_family && has_local_addr && + has_local_port) + return 0; + else + return -1; + } else { + /* name is optional */ + if (has_id && has_interface_name && has_type && has_family && + has_local_addr && has_local_port) + return 0; + return -1; + } +} + +int _hc_listener_validate(const hc_object_t *object, bool allow_partial) { + return hc_listener_validate(&object->listener, allow_partial); +} + +/* LISTENER CMP */ + +int hc_listener_cmp(const hc_listener_t *l1, const hc_listener_t *l2) { + int rc; + + rc = INT_CMP(l1->type, l2->type); + if (rc != 0) return rc; + + rc = INT_CMP(l1->family, l2->family); + if (rc != 0) return rc; + + rc = strncmp(l1->interface_name, l2->interface_name, INTERFACE_LEN); + if (rc != 0) return rc; + + rc = hicn_ip_address_cmp(&l1->local_addr, &l2->local_addr); + if (rc != 0) return rc; + + rc = INT_CMP(l1->local_port, l2->local_port); + if (rc != 0) return rc; + + return rc; +} + +int _hc_listener_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_listener_cmp(&object1->listener, &object2->listener); +} + +/* LISTENER SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_listener_snprintf(char *s, size_t size, const hc_listener_t *listener) { + char local[MAXSZ_URL]; + int rc; + rc = url_snprintf(local, MAXSZ_URL, &listener->local_addr, + listener->local_port); + if (rc >= MAXSZ_URL) + WARN("[hc_listener_snprintf] Unexpected truncation of URL string"); + if (rc < 0) return rc; + + return snprintf(s, size, "%s %s %s interface=%s", listener->name, local, + face_type_str(listener->type), listener->interface_name); +} + +int _hc_listener_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_listener_snprintf(s, size, &object->listener); +} + +/* OPERATIONS */ + +int hc_listener_create(hc_sock_t *s, hc_listener_t *listener) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.listener = *listener; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_LISTENER, &object, NULL); +} + +int hc_listener_get(hc_sock_t *s, hc_listener_t *listener, hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.listener = *listener; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_LISTENER, &object, pdata); +} + +int hc_listener_delete(hc_sock_t *s, hc_listener_t *listener) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.listener = *listener; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_LISTENER, &object, NULL); +} + +int hc_listener_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_LISTENER, NULL, pdata); +} + +GENERATE_FIND(listener); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_LISTENER, listener); diff --git a/ctrl/libhicnctrl/src/objects/listener.h b/ctrl/libhicnctrl/src/objects/listener.h new file mode 100644 index 000000000..515c8f0ad --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/listener.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file listener.h + * \brief Listener. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_LISTENER_H +#define HICNCTRL_IMPL_OBJECTS_LISTENER_H + +#include "../object_vft.h" + +bool hc_listener_is_local(const hc_listener_t *listener); + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_LISTENER, listener); + +#endif /* HICNCTRL_IMPL_OBJECTS_LISTENER_H */ diff --git a/ctrl/libhicnctrl/src/objects/route.c b/ctrl/libhicnctrl/src/objects/route.c new file mode 100644 index 000000000..44f39bcd7 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/route.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file route.c + * \brief Implementation of route object. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/route.h> +#include <hicn/util/log.h> + +#include "../object_private.h" +#include "../object_vft.h" +#include "face.h" +#include "base.h" + +bool hc_route_has_face(const hc_route_t *route) { + return !iszero(&route->face, sizeof(hc_face_t)); +} + +/* ROUTE VALIDATE */ + +int hc_route_validate(const hc_route_t *route, bool allow_partial) { + int has_id = 0; + int has_name = 0; + int has_face = 0; + + int has_family = 0; + int has_remote_addr = 0; + + if (!IS_VALID_CONNECTION_ID(route->face_id)) { + ERROR("[hc_route_validate] Invalid face id"); + return -1; + } + has_id = 1; + + if (!isempty(route->face_name)) { + if (!IS_VALID_NAME(route->face_name)) { + ERROR("[hc_route_validate] Invalid name specified"); + return -1; + } + has_name = 1; + } + + if (route->family != AF_UNSPEC) { + if (!IS_VALID_FAMILY(route->family)) { + ERROR("[hc_route_validate] Invalid family specified"); + return -1; + } + has_family = 1; + } + + if (!hicn_ip_address_empty(&route->remote_addr)) { + if (!IS_VALID_ADDRESS(route->remote_addr)) { + ERROR("[hc_route_validate] Invalid remote_addr specified"); + return -1; + } + has_remote_addr = 1; + } + + if (!IS_VALID_ROUTE_COST(route->cost)) { + ERROR("[hc_route_validate] Invalid cost"); + return -1; + } + + if (!IS_VALID_PREFIX_LEN(route->len)) { + ERROR("[hc_route_validate] Invalid len"); + return -1; + } + + if (hc_route_has_face(route)) { + if (!hc_face_validate(&route->face, allow_partial)) { + ERROR("[hc_route_validate] Invalid face"); + return -1; + } + has_face = 1; + } + + int has_face_info = has_id || has_name || has_face; + + if (!has_face_info) return -1; + if (allow_partial && (has_name + has_face != 1)) return -1; + + if (has_face_info && has_family && has_remote_addr) return 0; + + return -1; +} + +int _hc_route_validate(const hc_object_t *object, bool allow_partial) { + return hc_route_validate(&object->route, allow_partial); +} + +/* ROUTE CMP */ + +// XXX TODO +int hc_route_cmp(const hc_route_t *route1, const hc_route_t *route2) { + return -1; +} + +int _hc_route_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_route_cmp(&object1->route, &object2->route); +} + +/* ROUTE SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_route_snprintf(char *s, size_t size, const hc_route_t *route) { + /* interface cost prefix length */ + + char prefix[MAXSZ_IP_ADDRESS]; + int rc; + + rc = hicn_ip_address_snprintf(prefix, MAXSZ_IP_ADDRESS, &route->remote_addr); + if (rc >= MAXSZ_IP_ADDRESS) + ; + if (rc < 0) return rc; + + return snprintf(s, size, "%d (%s) %*d %s %*d", route->face_id, + route->face_name, MAXSZ_COST, route->cost, prefix, MAXSZ_LEN, + route->len); +} + +int _hc_route_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_route_snprintf(s, size, &object->route); +} + +int hc_route_create(hc_sock_t *s, hc_route_t *route) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.route = *route; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_ROUTE, &object, NULL); +} + +int hc_route_get(hc_sock_t *s, hc_route_t *route, hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.route = *route; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_ROUTE, &object, pdata); +} + +int hc_route_delete(hc_sock_t *s, hc_route_t *route) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.route = *route; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_ROUTE, &object, NULL); +} + +int hc_route_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_ROUTE, NULL, pdata); +} + +int hc_route_list_async(hc_sock_t *s) { + return hc_execute_async(s, ACTION_LIST, OBJECT_TYPE_ROUTE, NULL, NULL, NULL); +} + +// XXX difference between GET and FIND +GENERATE_FIND(route); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_ROUTE, route); diff --git a/ctrl/libhicnctrl/src/objects/route.h b/ctrl/libhicnctrl/src/objects/route.h new file mode 100644 index 000000000..854bd70a6 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/route.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file route.h + * \brief Route. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_ROUTE_H +#define HICNCTRL_IMPL_OBJECTS_ROUTE_H + +#include "../object_vft.h" + +bool hc_route_has_face(const hc_route_t* route); + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_ROUTE, route); + +#endif /* HICNCTRL_IMPL_OBJECTS_ROUTE_H */ diff --git a/ctrl/libhicnctrl/src/objects/stats.c b/ctrl/libhicnctrl/src/objects/stats.c new file mode 100644 index 000000000..2c3135d3c --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/stats.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file stats.c + * \brief Implementation of stats. + */ + +#include <string.h> + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/stats.h> +#include <hicn/util/log.h> + +#include "../object_vft.h" +#include "../object_private.h" + +int hc_stats_snprintf(char *s, size_t size, const hc_stats_t *stats) { +#if 0 + INFO("Connection #%d:", conn_stats->id); + INFO("\tinterests received: %d pkts (%d bytes)", + conn_stats->stats.interests.rx_pkts, + conn_stats->stats.interests.rx_bytes); + INFO("\tinterests transmitted: %d pkts (%d bytes)", + conn_stats->stats.interests.tx_pkts, + conn_stats->stats.interests.tx_bytes); + INFO("\tdata received: %d pkts (%d bytes)", + conn_stats->stats.data.rx_pkts, + conn_stats->stats.data.rx_bytes); + INFO("\tdata transmitted: %d pkts (%d bytes)", + conn_stats->stats.data.tx_pkts, + conn_stats->stats.data.tx_bytes); +#endif + return 0; +} + +int hc_stats_get(hc_sock_t *s, hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.listener = *listener; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_STATS, &object, pdata); +} + +int hc_stats_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_STATS, NULL, pdata); +} diff --git a/ctrl/libhicnctrl/src/objects/strategy.c b/ctrl/libhicnctrl/src/objects/strategy.c new file mode 100644 index 000000000..0e7a5787e --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/strategy.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file strategy.c + * \brief Implementation of strategy. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/strategy.h> +#include <hicn/util/log.h> + +#include "../object_vft.h" +#include "../object_private.h" + +/* STREATEGY VALIDATE */ + +int hc_strategy_validate(const hc_strategy_t *strategy, bool allow_partial) { + // TODO verify name + return 0; +} + +int _hc_strategy_validate(const hc_object_t *object, bool allow_partial) { + return hc_strategy_validate(&object->strategy, allow_partial); +} + +/* STRATEGY CMP */ + +int hc_strategy_cmp(const hc_strategy_t *s1, const hc_strategy_t *s2) { + return strcmp(s1->name, s2->name); +} + +int _hc_strategy_cmp(const hc_object_t *object1, const hc_object_t *object2) { + return hc_strategy_cmp(&object1->strategy, &object2->strategy); +} + +/* STRATEGY SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_strategy_snprintf(char *s, size_t size, const hc_strategy_t *strategy) { + return snprintf(s, size, "%s", strategy->name); +} + +int _hc_strategy_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_strategy_snprintf(s, size, &object->strategy); +} + +/* OPERATIONS */ + +int hc_strategy_create(hc_sock_t *s, hc_strategy_t *strategy) { return -1; } + +int hc_strategy_get(hc_sock_t *s, hc_strategy_t *strategy, hc_data_t **pdata) { + return -1; +} + +int hc_strategy_delete(hc_sock_t *s, hc_strategy_t *strategy) { return -1; } + +int hc_strategy_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_STRATEGY, NULL, pdata); +} + +/* new api */ + +int hc_strategy_set(hc_sock_t *s, hc_strategy_t *strategy) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.strategy = *strategy; + return hc_execute(s, ACTION_SET, OBJECT_TYPE_STRATEGY, &object, NULL); +} + +#if 0 +int hc_strategy_add_local_prefix(hc_sock_t *s, hc_strategy_t *strategy) { + return s->hc_strategy_add_local_prefix(s, strategy); +} +#endif + +GENERATE_FIND(strategy); + +DECLARE_OBJECT_OPS(OBJECT_TYPE_STRATEGY, strategy); diff --git a/ctrl/libhicnctrl/src/objects/strategy.h b/ctrl/libhicnctrl/src/objects/strategy.h new file mode 100644 index 000000000..0cc4f525d --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/strategy.h @@ -0,0 +1,29 @@ + +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file listener.h + * \brief Listener. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_STRATEGY_H +#define HICNCTRL_IMPL_OBJECTS_STRATEGY_H + +#include "../object_vft.h" + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_STRATEGY, strategy); + +#endif /* HICNCTRL_IMPL_OBJECTS_STRATEGY_H */ diff --git a/ctrl/libhicnctrl/src/objects/subscription.c b/ctrl/libhicnctrl/src/objects/subscription.c new file mode 100644 index 000000000..087e42ffb --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/subscription.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file subscription.c + * \brief Implementation of subscription. + */ + +#include <hicn/ctrl/api.h> +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/subscription.h> +#include <hicn/util/log.h> + +#include "../object_vft.h" +#include "../object_private.h" + +/* SUBSCRIPTION VALIDATE */ + +int hc_subscription_validate(const hc_subscription_t *subscription, + bool allow_partial) { + /* Any topic is considered valid */ + return 0; +} + +int _hc_subscription_validate(const hc_object_t *object, bool allow_partial) { + return hc_subscription_validate(&object->subscription, allow_partial); +} + +/* LISTENER CMP */ + +int hc_subscription_cmp(const hc_subscription_t *l1, + const hc_subscription_t *l2) { + return -1; +} + +int _hc_subscription_cmp(const hc_object_t *object1, + const hc_object_t *object2) { + return hc_subscription_cmp(&object1->subscription, &object2->subscription); +} + +/* SUBSCRIPTION SNPRINTF */ + +/* /!\ Please update constants in header file upon changes */ +int hc_subscription_snprintf(char *s, size_t size, + const hc_subscription_t *subscription) { + return -1; +} + +int _hc_subscription_snprintf(char *s, size_t size, const hc_object_t *object) { + return hc_subscription_snprintf(s, size, &object->subscription); +} + +/* OPERATIONS */ + +int hc_subscription_create(hc_sock_t *s, hc_subscription_t *subscription) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.subscription = *subscription; + return hc_execute(s, ACTION_CREATE, OBJECT_TYPE_SUBSCRIPTION, &object, NULL); +} + +int hc_subscription_get(hc_sock_t *s, hc_subscription_t *subscription, + hc_data_t **pdata) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.subscription = *subscription; + return hc_execute(s, ACTION_GET, OBJECT_TYPE_SUBSCRIPTION, &object, pdata); +} + +int hc_subscription_delete(hc_sock_t *s, hc_subscription_t *subscription) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + object.subscription = *subscription; + return hc_execute(s, ACTION_DELETE, OBJECT_TYPE_SUBSCRIPTION, &object, NULL); +} + +int hc_subscription_list(hc_sock_t *s, hc_data_t **pdata) { + return hc_execute(s, ACTION_LIST, OBJECT_TYPE_SUBSCRIPTION, NULL, pdata); +} + +GENERATE_FIND(subscription); +DECLARE_OBJECT_OPS(OBJECT_TYPE_SUBSCRIPTION, subscription); diff --git a/ctrl/libhicnctrl/src/objects/subscription.h b/ctrl/libhicnctrl/src/objects/subscription.h new file mode 100644 index 000000000..6eb7583c6 --- /dev/null +++ b/ctrl/libhicnctrl/src/objects/subscription.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file subscription.h + * \brief Listener. + */ + +#ifndef HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H +#define HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H + +#include "../object_vft.h" + +DECLARE_OBJECT_OPS_H(OBJECT_TYPE_SUBSCRIPTION, subscription); + +#endif /* HICNCTRL_IMPL_OBJECTS_SUBSCRIPTION_H */ diff --git a/hicn-light/src/hicn/config/parse.c b/ctrl/libhicnctrl/src/parse.c index ba9c0b348..ca19d8280 100644 --- a/hicn-light/src/hicn/config/parse.c +++ b/ctrl/libhicnctrl/src/parse.c @@ -1,12 +1,29 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <limits.h> //#include <hicn/ctrl/cli.h> +#include <hicn/ctrl/action.h> #include <hicn/util/log.h> #include <hicn/util/sstrncpy.h> -#include "parse.h" +#include <hicn/ctrl/parse.h> /* * As there is no portable way to generate a va_list to use with sscanf to @@ -16,45 +33,7 @@ * NOTE: update sscanf accordingly */ -#include "command.h" - -const char *action_str[] = { -#define _(x) [ACTION_##x] = #x, - foreach_action -#undef _ -}; - -#define action_str(x) action_str[x] - -hc_action_t action_from_str(const char *action_str) { -#define _(x) \ - if (strcasecmp(action_str, #x) == 0) \ - return ACTION_##x; \ - else - foreach_action -#undef _ - if (strcasecmp(action_str, "add") == 0) return ACTION_CREATE; - else if (strcasecmp(action_str, "remove") == 0) return ACTION_DELETE; - else return ACTION_UNDEFINED; -} - -const char *object_str[] = { -#define _(x) [OBJECT_##x] = #x, - foreach_object -#undef _ -}; - -#define object_str(x) object_str[x] - -hc_object_type_t object_from_str(const char *object_str) { -#define _(x) \ - if (strcasecmp(object_str, #x) == 0) \ - return OBJECT_##x; \ - else - foreach_object -#undef _ - return OBJECT_UNDEFINED; -} +//#include "command.h" const char *action_to_cmd_action(hc_action_t action) { switch (action) { @@ -79,59 +58,71 @@ const char *action_to_cmd_action(hc_action_t action) { } } -const char *parser_type_fmt(const parser_type_t *type) { - switch (type->name) { - case TYPENAME_INT: - return TYPE_FMT_INT; - case TYPENAME_UINT: - return TYPE_FMT_UINT; - case TYPENAME_STR: - return TYPE_FMT_STRN(type->str.max_size); - case TYPENAME_SYMBOLIC_OR_ID: - return TYPE_FMT_SYMBOLIC_OR_ID; - case TYPENAME_INTERFACE_NAME: - return TYPE_FMT_INTERFACE_NAME; - case TYPENAME_IP_ADDRESS: - return TYPE_FMT_IP_ADDRESS; - case TYPENAME_IP_PREFIX: - return TYPE_FMT_IP_PREFIX; - case TYPENAME_ON_OFF: - return TYPE_FMT_ON_OFF; - case TYPENAME_ENUM: - return TYPE_FMT_ENUM; - case TYPENAME_POLICY_STATE: - return TYPE_FMT_POLICY_STATE; - case TYPENAME_UNDEFINED: - default: - return NULL; - } -} - -int parser_type_func(const parser_type_t *type, void *src, void *dst, +/* + * This function now assumes all parameteres in src are received as string + */ +int parser_type_func(const parser_type_t *type, const char *src, void *dst, void *dst2, void *dst3) { - ip_address_t addr; + hicn_ip_address_t addr; char *addr_str; char *len_str; - int len, tmp, rc; + int len, rc; + long tmp; switch (type->name) { case TYPENAME_INT: - tmp = *(int *)src; - if (tmp < type->sint.min || tmp > type->sint.max) { + tmp = strtol(src, NULL, 10); + if ((tmp < INT32_MIN) || (tmp > INT32_MAX)) { + ERROR("Input number (%d) not matching type 'signed integer'", tmp); + return -1; + } + if ((tmp < type->integer.min) || (tmp > type->integer.max)) { ERROR("Input number (%d) not inside range [%d, %d]", tmp, - type->sint.min, type->sint.max); + type->integer.min, type->integer.max); return -1; } - *(int *)dst = *(int *)src; + if (tmp > INT_MAX) return -1; + *(int *)dst = (int)tmp; break; case TYPENAME_UINT: - tmp = *(int *)src; - if (tmp < type->uint.min || tmp > type->uint.max) { + tmp = strtol(src, NULL, 10); + if ((tmp < 0) || (tmp > UINT32_MAX)) { + ERROR("Input number (%d) not matching type 'signed integer'", tmp); + return -1; + } + if ((tmp < type->integer.min) || (tmp > type->integer.max)) { ERROR("Input number (%d) not inside range [%d, %d]", tmp, - type->uint.min, type->uint.max); + type->integer.min, type->integer.max); return -1; } - *(unsigned *)dst = *(unsigned *)src; + if (tmp > UINT_MAX) return -1; + *(unsigned *)dst = (unsigned)tmp; + break; + case TYPENAME_INT16: + tmp = strtol(src, NULL, 10); + if ((tmp < INT16_MIN) || (tmp > INT16_MAX)) { + ERROR("Input number (%d) not matching type 'signed integer'", tmp); + return -1; + } + if ((tmp < type->integer.min) || (tmp > type->integer.max)) { + ERROR("Input number (%d) not inside range [%d, %d]", tmp, + type->integer.min, type->integer.max); + return -1; + } + *(int16_t *)dst = tmp; + break; + case TYPENAME_UINT16: + tmp = strtol(src, NULL, 10); + if ((tmp < 0) || (tmp > UINT16_MAX)) { + ERROR("Input number (%d) not matching type 'signed integer'", tmp); + return -1; + } + if ((tmp < type->integer.min) || (tmp > type->integer.max)) { + ERROR("Input number (%d) not inside range [%d, %d]", tmp, + type->integer.min, type->integer.max); + return -1; + } + *(uint16_t *)dst = tmp; break; case TYPENAME_STR: rc = strcpy_s(dst, type->str.max_size, src); @@ -141,14 +132,14 @@ int parser_type_func(const parser_type_t *type, void *src, void *dst, } break; case TYPENAME_IP_ADDRESS: - rc = ip_address_pton((char *)src, &addr); + rc = hicn_ip_address_pton((char *)src, &addr); if (rc < 0) { ERROR("Wrong IP address format"); return -1; } - *(ip_address_t *)dst = addr; - *(int *)dst2 = ip_address_get_family((char *)src); + *(hicn_ip_address_t *)dst = addr; + *(int *)dst2 = hicn_ip_address_str_get_family((char *)src); break; case TYPENAME_ON_OFF: if (strcmp((char *)src, "off") == 0) { @@ -163,16 +154,16 @@ int parser_type_func(const parser_type_t *type, void *src, void *dst, case TYPENAME_IP_PREFIX: addr_str = strtok((char *)src, "/"); len_str = strtok(NULL, " "); - rc = ip_address_pton((char *)src, &addr); + rc = hicn_ip_address_pton((char *)src, &addr); if (rc < 0) { ERROR("Wrong IP address format"); return -1; } len = atoi(len_str); - *(ip_address_t *)dst = addr; + *(hicn_ip_address_t *)dst = addr; *(int *)dst2 = len; - *(int *)dst3 = ip_address_get_family(addr_str); + *(int *)dst3 = hicn_ip_address_str_get_family(addr_str); break; case TYPENAME_ENUM: /* Enum index from string */ @@ -197,6 +188,29 @@ int parser_type_func(const parser_type_t *type, void *src, void *dst, return 0; } +// NEW FUNCTION +int parse_getopt_args(const command_parser_t *parser, int argc, char *argv[], + hc_command_t *command) { + /* Loop over remaining commandline positional arguments */ + for (unsigned i = 0; i < argc; i++) { + const command_parameter_t *p = &parser->parameters[i]; + + if (parser_type_func(&p->type, argv[i], + &command->object.as_uint8 + p->offset, + &command->object.as_uint8 + p->offset2, + &command->object.as_uint8 + p->offset3) < 0) { + ERROR("Error during parsing of parameter '%s' value", p->name); + goto ERR; + } + } + if (parser->post_hook) parser->post_hook(&command->object.as_uint8); + return 0; + +ERR: + return -1; +} + +/* Build a format string to parse all params as a string */ int parse_params(const command_parser_t *parser, const char *params_s, hc_command_t *command) { char fmt[1024]; @@ -208,13 +222,7 @@ int parse_params(const command_parser_t *parser, const char *params_s, unsigned count = 0; for (unsigned i = 0; i < parser->nparams; i++) { - const command_parameter_t *p = &parser->parameters[i]; - const char *_fmt = parser_type_fmt(&p->type); - // printf(" _fmt=%s\n", _fmt); - if (!_fmt) { - WARN("Ignored parameter %s with unknown type formatter", p->name); - continue; - } + const char *_fmt = "%s"; n = snprintf(pos, 1024 - size, "%s", _fmt); pos += n; @@ -269,7 +277,7 @@ int parse(const char *cmd, hc_command_t *command) { } command->action = action_from_str(action_s); - command->object.type = object_from_str(object_s); + command->object_type = object_type_from_str(object_s); if (strnlen_s(params_s, MAX_SCANF_PARAM_LEN) > 0) { for (char *ptr = params_s; (ptr = strchr(ptr, ' ')) != NULL; ptr++) @@ -281,7 +289,7 @@ int parse(const char *cmd, hc_command_t *command) { * command exists. */ const command_parser_t *parser = - command_search(command->action, command->object.type, nparams); + command_search(command->action, command->object_type, nparams); if (!parser) { ERROR("Could not find parser for command '%s %s'", action_s, object_s); return -1; @@ -300,7 +308,7 @@ int help(const char *cmd) { char action_s[MAX_SCANF_PARAM_LEN]; char object_s[MAX_SCANF_PARAM_LEN]; char params_s[MAX_SCANF_PARAM_LEN]; - hc_object_type_t object = OBJECT_UNDEFINED; + hc_object_type_t object_type = OBJECT_TYPE_UNDEFINED; hc_action_t action = ACTION_UNDEFINED; int n = sscanf(cmd, "help %[^\n]s", params_s); @@ -317,9 +325,9 @@ int help(const char *cmd) { // Object specified: list actions available for that object if (nparams == 1) { - object = object_from_str(params_s); - if (object == OBJECT_UNDEFINED) { - fprintf(stderr, "Error: undefined object.\n"); + object_type = object_type_from_str(params_s); + if (object_type == OBJECT_TYPE_UNDEFINED) { + fprintf(stderr, "Error: undefined object type.\n"); return -1; } @@ -329,16 +337,17 @@ int help(const char *cmd) { // Object and action specified: list detailed commands n = sscanf(params_s, "%s %[^\n]s", object_s, action_s); assert(n == 2); - object = object_from_str(object_s); - action = action_from_str(action_s); - if (object == OBJECT_UNDEFINED || action == ACTION_UNDEFINED) { - fprintf(stderr, "Error: undefined object and/or action.\n"); + object_type = object_type_from_str(object_s); + if (object_type == OBJECT_TYPE_UNDEFINED) { + fprintf(stderr, "Error: undefined object type.\n"); return -1; } + action = action_from_str(action_s); + assert(action != ACTION_UNDEFINED); CMD_LIST: printf("Available commands:\n"); - command_list(object, action); + command_list(object_type, action); return 0; } diff --git a/ctrl/libhicnctrl/src/request.c b/ctrl/libhicnctrl/src/request.c new file mode 100644 index 000000000..0e1d07b04 --- /dev/null +++ b/ctrl/libhicnctrl/src/request.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file request.c + * \brief Implementation of pending requests. + */ + +#include <assert.h> +#include <stdlib.h> + +#include <hicn/util/log.h> + +#include "request.h" + +const char *hc_request_state_str[] = { +#define _(x) [REQUEST_STATE_##x] = #x, + foreach_request_state +#undef _ +}; + +struct hc_request_s { + int seq; + hc_action_t action; + hc_object_type_t object_type; + hc_object_t *object; + +#if 0 + int (*parse)(const uint8_t *src, uint8_t *dst); +#endif + + /* Callbacks */ + hc_result_callback_t callback; + void *callback_data; + + /* Temp data used for the execution of the request */ + hc_data_t *data; + + /* Nested requests support + * + * In order to answer complex requests, involving a combination of requests to + * the forwarder, we will allow maintaining a Finite State Machine in the + * requests (and a tree of requests) + * + * The entry point for the modules will always remain the initial request, + * however, we will chain nested requests in their parent fields, and point to + * the one currently under execution in current. + * */ + hc_request_state_t state; + unsigned state_count; /* Usefor for iterative requests */ + hc_request_t *parent; + hc_request_t *current; +}; + +hc_request_t *hc_request_create(int seq, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data) { + hc_request_t *request = malloc(sizeof(hc_request_t)); + if (!request) return NULL; + request->seq = seq; + + request->action = action; + request->object_type = object_type; + request->object = object; + + request->callback = callback; + request->callback_data = callback_data; + + request->data = NULL; + + request->state = REQUEST_STATE_INIT; + request->state_count = 0; + request->parent = NULL; + request->current = NULL; + + return request; +} + +void hc_request_free(hc_request_t *request) { free(request); } + +void hc_request_set(hc_request_t *request, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object) { + request->action = action; + request->object_type = object_type; + request->object = object; +} + +int hc_request_get_seq(const hc_request_t *request) { return request->seq; } + +hc_request_t *hc_request_get_current(hc_request_t *request) { + return request->current ? request->current : request; +} + +hc_request_t *hc_request_pop(hc_request_t *request) { + hc_request_t *current_request = hc_request_get_current(request); + hc_request_t *parent = current_request->parent; + request->current = parent; + if (parent) { + parent->data = current_request->data; + /* We only free the current_request if it was not the root */ + hc_request_free(current_request); + } + return parent; +} + +hc_request_state_t hc_request_get_state(const hc_request_t *request) { + return request->state; +} + +void hc_request_set_state(hc_request_t *request, hc_request_state_t state) { + request->state = state; +} + +int hc_request_get_state_count(const hc_request_t *request) { + return request->state_count; +} + +void hc_request_set_state_count(hc_request_t *request, unsigned count) { + request->state_count = count; +} + +hc_action_t hc_request_get_action(const hc_request_t *request) { + return request->action; +} + +hc_object_type_t hc_request_get_object_type(const hc_request_t *request) { + return request->object_type; +} + +hc_object_t *hc_request_get_object(const hc_request_t *request) { + return request->object; +} + +hc_data_t *hc_request_get_data(const hc_request_t *request) { + return request->data; +} + +void hc_request_set_data(hc_request_t *request, hc_data_t *data) { + assert(!request->data); + request->data = data; +} + +void hc_request_reset_data(hc_request_t *request) { + if (!request->data) return; + hc_data_free(request->data); + request->data = NULL; +} + +bool hc_request_is_subscription(const hc_request_t *request) { + hc_action_t action = hc_request_get_action(request); + hc_object_type_t object_type = hc_request_get_object_type(request); + return (action == ACTION_SUBSCRIBE) || + (action == ACTION_CREATE && object_type == OBJECT_TYPE_SUBSCRIPTION); +} + +bool hc_request_requires_object(const hc_request_t *request) { + hc_action_t action = hc_request_get_action(request); + return (action != ACTION_LIST) && (action != ACTION_SUBSCRIBE); +} + +void hc_request_clear_data(hc_request_t *request) { request->data = NULL; } + +void hc_request_set_complete(hc_request_t *request) { + request->state = REQUEST_STATE_COMPLETE; +} + +bool hc_request_is_complete(const hc_request_t *request) { + return request->state == REQUEST_STATE_COMPLETE; +} + +void hc_request_on_complete(hc_request_t *request) { + // request->state = REQUEST_STATE_COMPLETE; + if (!request->callback) return; + request->callback(request->data, request->callback_data); +} + +void hc_request_on_notification(hc_request_t *request) { + if (!request->callback) return; + request->callback(request->data, request->callback_data); +} + +hc_request_t *hc_request_make_subrequest(hc_request_t *request, + hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object) { + hc_request_t *sr = + hc_request_create(request->seq, action, object_type, object, + request->callback, request->callback_data); + + /* The parent is either the current one, or the request itself if NULL */ + hc_request_t *current_request = hc_request_get_current(request); + hc_request_reset_data(current_request); + sr->parent = current_request; + request->current = sr; + return sr; +} diff --git a/ctrl/libhicnctrl/src/request.h b/ctrl/libhicnctrl/src/request.h new file mode 100644 index 000000000..32f9f72b9 --- /dev/null +++ b/ctrl/libhicnctrl/src/request.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file request.h + * \brief Pending requests. + */ + +#ifndef HC_REQUEST_H +#define HC_REQUEST_H + +#include <stdbool.h> + +#include <hicn/ctrl/action.h> +#include <hicn/ctrl/callback.h> +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> + +#if 0 +typedef int (*HC_PARSE)(const uint8_t *, uint8_t *); +#endif + +#define foreach_request_state \ + _(UNDEFINED) \ + _(INIT) \ + _(CONNECTION_CREATE_LISTENER_LIST) \ + _(CONNECTION_CREATE_LISTENER_ITERATE) \ + _(CONNECTION_CREATE_LISTENER_GET) \ + _(CONNECTION_CREATE_LISTENER_VERIFY) \ + _(CONNECTION_CREATE_LISTENER_CREATE) \ + _(CONNECTION_CREATE_LISTENER_CHECK) \ + _(CONNECTION_CREATE) \ + _(CONNECTION_CREATE_N) \ + _(FACE_CREATE_CONNECTION_CREATE) \ + _(FACE_CREATE_CONNECTION_CHECK) \ + _(FACE_CREATE_CONNECTION_GET) \ + _(FACE_CREATE_CONNECTION_VERIFY) \ + _(FACE_CREATE_LISTENER_CREATE) \ + _(FACE_CREATE_LISTENER_CHECK) \ + _(FACE_LIST_CONNECTION_LIST) \ + _(ROUTE_CREATE_FACE_CREATE) \ + _(ROUTE_CREATE_FACE_CHECK) \ + _(ROUTE_CREATE) \ + _(GET_LIST) \ + _(COMPLETE) \ + _(N) + +typedef enum { +#define _(x) REQUEST_STATE_##x, + foreach_request_state +#undef _ +} hc_request_state_t; + +extern const char *hc_request_state_str[]; + +#define hc_request_state_str(x) hc_request_state_str[x] + +/* + * Internal state associated to a pending request + */ +typedef struct hc_request_s hc_request_t; + +hc_request_t *hc_request_create(int seq, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data); + +void hc_request_free(hc_request_t *request); + +void hc_request_set(hc_request_t *request, hc_action_t action, + hc_object_type_t object_type, hc_object_t *object); + +int hc_request_get_seq(const hc_request_t *request); +hc_request_t *hc_request_get_current(hc_request_t *request); +hc_request_t *hc_request_pop(hc_request_t *request); + +hc_request_state_t hc_request_get_state(const hc_request_t *request); +void hc_request_set_state(hc_request_t *request, hc_request_state_t state); + +int hc_request_get_state_count(const hc_request_t *request); +void hc_request_set_state_count(hc_request_t *request, unsigned count); + +hc_action_t hc_request_get_action(const hc_request_t *request); +hc_object_type_t hc_request_get_object_type(const hc_request_t *request); +hc_object_t *hc_request_get_object(const hc_request_t *request); +hc_data_t *hc_request_get_data(const hc_request_t *request); +void hc_request_set_data(hc_request_t *request, hc_data_t *data); +void hc_request_reset_data(hc_request_t *request); + +bool hc_request_is_subscription(const hc_request_t *request); +bool hc_request_requires_object(const hc_request_t *request); + +// do not free data which might be invalid +// XXX to be removed if we replace "ensure_data_size_and_free" functions and the +// like, with equivalent functions acting on request +void hc_request_clear_data(hc_request_t *request); + +void hc_request_set_complete(hc_request_t *request); +bool hc_request_is_complete(const hc_request_t *request); + +void hc_request_on_complete(hc_request_t *request); +void hc_request_on_notification(hc_request_t *request); + +/* + * Same seq & callbacks + */ +hc_request_t *hc_request_make_subrequest(hc_request_t *request, + hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object); + +#endif /* HC_REQUEST_H */ diff --git a/ctrl/libhicnctrl/src/route.c b/ctrl/libhicnctrl/src/route.c index f59dbce7c..71e39d7ad 100644 --- a/ctrl/libhicnctrl/src/route.c +++ b/ctrl/libhicnctrl/src/route.c @@ -25,12 +25,12 @@ #define DEFAULT_HICN_ROUTE_COST 1 struct hicn_route_s { - ip_prefix_t prefix; + hicn_ip_prefix_t prefix; face_id_t face_id; route_cost_t cost; /* Optional, 0 means no value, defaults to 1 */ }; -hicn_route_t* hicn_route_create(ip_prefix_t* prefix, face_id_t face_id, +hicn_route_t* hicn_route_create(hicn_ip_prefix_t* prefix, face_id_t face_id, route_cost_t cost) { hicn_route_t* route = malloc(sizeof(hicn_route_t)); if (!route) return NULL; @@ -52,7 +52,7 @@ void hicn_route_free(hicn_route_t* route) { free(route); } int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2) { int rc; - rc = ip_prefix_cmp(&route1->prefix, &route2->prefix); + rc = hicn_ip_prefix_cmp(&route1->prefix, &route2->prefix); if (rc != 0) return rc; return (route1->face_id > route2->face_id) ? 1 @@ -60,12 +60,12 @@ int hicn_route_cmp(const hicn_route_t* route1, const hicn_route_t* route2) { : 0; } -int hicn_route_get_prefix(const hicn_route_t* route, ip_prefix_t* prefix) { +int hicn_route_get_prefix(const hicn_route_t* route, hicn_ip_prefix_t* prefix) { *prefix = route->prefix; return 0; } -int hicn_route_set_prefix(hicn_route_t* route, const ip_prefix_t prefix) { +int hicn_route_set_prefix(hicn_route_t* route, const hicn_ip_prefix_t prefix) { route->prefix = prefix; return 0; } @@ -83,6 +83,6 @@ int hicn_route_set_cost(hicn_route_t* route, const int cost) { /* /!\ Please update constants in header file upon changes */ size_t hicn_route_snprintf(char* s, size_t size, const hicn_route_t* route) { char prefix_s[MAXSZ_IP_PREFIX]; - ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_IP_PREFIX); + hicn_ip_prefix_ntop(&route->prefix, prefix_s, MAXSZ_IP_PREFIX); return snprintf(s, size, "%s [%d]", prefix_s, route->cost); } diff --git a/ctrl/libhicnctrl/src/socket.c b/ctrl/libhicnctrl/src/socket.c new file mode 100644 index 000000000..c3636075d --- /dev/null +++ b/ctrl/libhicnctrl/src/socket.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file socket.c + * \brief Implementation of control socket. + */ + +#include <dlfcn.h> +#include <stdio.h> + +#include <hicn/ctrl/socket.h> +#include <hicn/util/log.h> + +#ifdef ANDROID +/* + * In android we do not load a module at runtime but we link the hicnlight + * implementation directly to the main library. + */ +#include "modules/hicn_light.h" +#endif /* ANDROID */ + +#include "socket_private.h" + +TYPEDEF_MAP(hc_sock_map, int, hc_request_t *, int_cmp, int_snprintf, + generic_snprintf); + +const char *forwarder_type_str[] = { +#define _(x) [FORWARDER_TYPE_##x] = #x, + foreach_forwarder_type +#undef _ +}; + +forwarder_type_t forwarder_type_from_str(const char *str) { + for (forwarder_type_t i = FORWARDER_TYPE_UNDEFINED + 1; i < FORWARDER_TYPE_N; + i++) { + if (strcasecmp(str, forwarder_type_str[i]) == 0) return i; + } + return FORWARDER_TYPE_UNDEFINED; +} + +#ifndef ANDROID +static int hc_sock_set_ops(hc_sock_t *s, const char *name, const char *url) { + char complete_name[128]; +#ifdef __APPLE__ + sprintf(complete_name, "%s.dylib", name); +#elif defined(__linux__) + snprintf(complete_name, 128, "%s.so", name); +#else +#error "System not supported for dynamic lynking" +#endif + + void *handle = 0; + const char *error = 0; + int (*initialize_module)(hc_sock_t *) = 0; + int rc = 0; + + // open module + handle = dlopen(complete_name, RTLD_LAZY); + if (!handle) { + if ((error = dlerror()) != 0) { + ERROR("%s", error); + } + goto ERR_DL; + return -1; + } + s->handle = handle; + + // get factory method + initialize_module = + (int (*)(hc_sock_t *))dlsym(handle, "hc_sock_initialize_module"); + if (!initialize_module) { + if ((error = dlerror()) != 0) { + ERROR("%s", error); + } + goto ERR_INIT; + } + initialize_module(s); + + return rc; +ERR_INIT: + dlclose(s->handle); + s->handle = NULL; +ERR_DL: + return -1; +} +#endif /* ! ANDROID */ + +int hc_sock_is_async(hc_sock_t *s) { return s->async; } + +int hc_sock_set_async(hc_sock_t *s) { + s->async = true; + return 0; +} + +hc_sock_t *hc_sock_create(forwarder_type_t forwarder, const char *url) { +#ifndef ANDROID + int rc; +#endif + + hc_sock_t *s = malloc(sizeof(hc_sock_t)); + if (!s) goto ERR_MALLOC; + +#ifdef ANDROID + assert(forwarder == HICNLIGHT); + s->data = hc_sock_light_data_create(url); + s->handle = NULL; +#else + switch (forwarder) { + case FORWARDER_TYPE_HICNLIGHT: + rc = hc_sock_set_ops(s, "hicnlightctrl_module", url); + break; + case FORWARDER_TYPE_VPP: + rc = hc_sock_set_ops(s, "vppctrl_module", url); + break; + default: + goto ERR_INIT; + } + + if (rc < 0) goto ERR_INIT; + + s->data = s->ops.create_data(url); +#endif + + if (!s->data) goto ERR_DATA; + + s->map = hc_sock_map_create(); + if (!s->map) goto ERR_MAP; + + s->async = false; + + s->seq_request = 0; + s->current_request = NULL; + + return s; + +ERR_MAP: +#ifdef ANDROID + hc_sock_light_data_free(s->data); +#else + ; // XXX VFT() free +#endif +ERR_DATA: +#ifndef ANDROID +ERR_INIT: +#endif + free(s); +ERR_MALLOC: + return NULL; +} + +void hc_sock_free(hc_sock_t *s) { + if (s->ops.disconnect) s->ops.disconnect(s); +#ifdef ANDROID + hc_sock_light_data_free(s->data); +#else + if (s->ops.free_data) s->ops.free_data(s->data); + if (s->handle) { + dlclose(s->handle); + } +#endif /* ANDROID */ + + hc_request_t **request_array = NULL; + int n = hc_sock_map_get_value_array(s->map, &request_array); + if (n < 0) { + ERROR("Could not retrieve pending request array for freeing up resources"); + } else { + for (unsigned i = 0; i < n; i++) { + hc_request_t *request = request_array[i]; + if (hc_sock_map_remove(s->map, hc_request_get_seq(request), NULL) < 0) + ERROR("[hc_sock_light_process] Error removing request from map"); + hc_request_free(request); + } + free(request_array); + } + + hc_sock_map_free(s->map); + + free(s); +} + +#if 0 +int hc_sock_get_next_seq(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); } + +int hc_sock_set_nonblocking(hc_sock_t *s) { return s->hc_sock_get_next_seq(s); } + +#endif + +int hc_sock_get_fd(hc_sock_t *s) { return s->ops.get_fd(s); } + +int hc_sock_connect(hc_sock_t *s) { return s->ops.connect(s); } + +int hc_sock_get_recv_buffer(hc_sock_t *s, u8 **buffer, size_t *size) { + return s->ops.get_recv_buffer(s, buffer, size); +} +#if 0 + +int hc_sock_send(hc_sock_t *s, hc_msg_t *msg, size_t msglen, uint32_t seq) { + return s->hc_sock_send(s, msg, msglen, seq); +} + +int hc_sock_recv(hc_sock_t *s) { return s->ops.recv(s); } +#endif + +#if 0 +int hc_sock_process(hc_sock_t *s, hc_data_t **data) { + return s->hc_sock_process(s, data); +} + +int hc_sock_callback(hc_sock_t *s, hc_data_t **data) { + return s->hc_sock_callback(s, data); +} + +int hc_sock_reset(hc_sock_t *s) { return s->hc_sock_reset(s); } + +void hc_sock_increment_woff(hc_sock_t *s, size_t bytes) { + s->hc_sock_increment_woff(s, bytes); +} + +int hc_sock_prepare_send(hc_sock_t *s, hc_result_t *result, + data_callback_t complete_cb, void *complete_cb_data) { + return s->hc_sock_prepare_send(s, result, complete_cb, complete_cb_data); +} + +int hc_sock_set_recv_timeout_ms(hc_sock_t *s, long timeout_ms) { + return s->hc_sock_set_recv_timeout_ms(s, timeout_ms); +} +#endif + +hc_request_t *hc_sock_create_request(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data) { + /* Create request state */ + int seq = s->seq_request++; + hc_request_t *request = hc_request_create(seq, action, object_type, object, + callback, callback_data); + if (!request) goto ERR_MALLOC; + + hc_request_set_state(request, REQUEST_STATE_INIT); + + // Add state to map + if (hc_sock_map_add(s->map, seq, request) < 0) { + ERROR("[hc_sock_create_request] Error adding request state to map"); + goto ERR_MAP; + } + + return request; + +ERR_MAP: + free(request); +ERR_MALLOC: + return NULL; +} + +hc_request_t *hc_sock_get_request(hc_sock_t *s) { return s->current_request; } + +void hc_sock_free_request(hc_sock_t *s, hc_request_t *request, bool recursive) { + if (hc_sock_map_remove(s->map, hc_request_get_seq(request), NULL) < 0) { + ERROR("[hc_sock_free_request] Error removing request from map"); + } + if (recursive) { + hc_request_t *r = NULL; + do { + r = hc_request_pop(request); + } while (r); + } + hc_request_free(request); + s->current_request = NULL; +} + +/** + * TODO: return code: + * -1 object not found + * -2 action not found + * -3 error during serialization + * + * @return the size of the created message + */ +ssize_t hc_sock_serialize_object(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg) { + hc_serialize_t fn = (s->ops.object_vft[object_type]).serialize[action]; + if (!fn) return -1; + return fn(object, msg); +} + +int hc_sock_parse_object(hc_sock_t *s, hc_object_type_t object_type, + uint8_t *buffer, size_t size, hc_object_t *object) { + return s->ops.object_vft[object_type].parse(buffer, size, object); +} diff --git a/ctrl/libhicnctrl/src/socket_private.h b/ctrl/libhicnctrl/src/socket_private.h new file mode 100644 index 000000000..30f3bcb6e --- /dev/null +++ b/ctrl/libhicnctrl/src/socket_private.h @@ -0,0 +1,47 @@ +#ifndef HICNCTRL_SOCKET_PRIVATE_H +#define HICNCTRL_SOCKET_PRIVATE_H + +#include <hicn/util/map.h> +#include <hicn/ctrl/socket.h> + +#include "module.h" + +TYPEDEF_MAP_H(hc_sock_map, int, hc_request_t *); + +struct hc_sock_s { + int request_seq; + hc_sock_map_t *map; + + bool async; + int seq_request; + + /* + * Stores the current request being parsed in case of fragmented reception or + * analysis (as it is the case now) between header and payload + */ + hc_request_t *current_request; + + hc_sock_ops_t ops; + + void *data; + void *handle; +}; + +hc_request_t *hc_sock_create_request(hc_sock_t *s, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, + hc_result_callback_t callback, + void *callback_data); + +hc_request_t *hc_sock_get_request(hc_sock_t *s); + +void hc_sock_free_request(hc_sock_t *s, hc_request_t *request, bool recursive); + +ssize_t hc_sock_serialize_object(hc_sock_t *sock, hc_action_t action, + hc_object_type_t object_type, + hc_object_t *object, uint8_t *msg); + +int hc_sock_parse_object(hc_sock_t *sock, hc_object_type_t object_type, + uint8_t *buffer, size_t size, hc_object_t *object); + +#endif /* HICNCTRL_SOCKET_PRIVATE_H */ diff --git a/ctrl/libhicnctrl/src/test/CMakeLists.txt b/ctrl/libhicnctrl/src/test/CMakeLists.txt new file mode 100644 index 000000000..7fdff476d --- /dev/null +++ b/ctrl/libhicnctrl/src/test/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright (c) 2021-2022 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################################## +# Test sources +############################################################## +list(APPEND TESTS_SRC + main.cc + common.cc + test_data.cc + test_hicnlight_listener.cc + test_hicnlight_connection.cc + test_hicnlight_route.cc + ../modules/hicn_light/connection.c + ../modules/hicn_light/face.c + ../modules/hicn_light/listener.c + ../modules/hicn_light/route.c +) + +############################################################## +# Build single unit test executable and add it to test list +############################################################## +build_executable(libhicnctrl_tests + NO_INSTALL + SOURCES ${TESTS_SRC} + LINK_LIBRARIES + ${LIBRARIES} + ${LIBHICNCTRL_SHARED} + ${GTEST_LIBRARIES} + pthread + INCLUDE_DIRS + $<TARGET_PROPERTY:${LIBHICNCTRL_SHARED},INCLUDE_DIRECTORIES> + ${GTEST_INCLUDE_DIRS} + DEPENDS gtest ${LIBHICNCTRL_SHARED} + COMPONENT ${LIBHICNCTRL_COMPONENT} + DEFINITIONS ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} + LINK_FLAGS ${LINK_FLAGS} +) + +add_test_internal(libhicnctrl_tests) diff --git a/ctrl/libhicnctrl/src/test/common.cc b/ctrl/libhicnctrl/src/test/common.cc new file mode 100644 index 000000000..075281d2e --- /dev/null +++ b/ctrl/libhicnctrl/src/test/common.cc @@ -0,0 +1,13 @@ +#include "common.h" + +std::string dump_buffer(const char *name, uint8_t *buffer, size_t size) { + std::ostringstream oss; + oss << "const std::vector<uint8_t> " << name << " = {"; + for (size_t i = 0; i < size; i++) { + if (i > 0) oss << ", "; + oss << "0x" << std::setw(2) << std::setfill('0') << std::hex + << static_cast<int>(buffer[i]); + } + oss << "};" << std::endl; + return oss.str(); +} diff --git a/ctrl/libhicnctrl/src/test/common.h b/ctrl/libhicnctrl/src/test/common.h new file mode 100644 index 000000000..8927c86ec --- /dev/null +++ b/ctrl/libhicnctrl/src/test/common.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HICNCTRL_TEST_COMMON +#define HICNCTRL_TEST_COMMON + +#define BUFSIZE 8192 + +#include <gtest/gtest.h> + +class TestHicnLight : public ::testing::Test { + protected: + TestHicnLight() {} + virtual ~TestHicnLight() {} + virtual void SetUp() {} + virtual void TearDown() {} +}; + +class TestHicnLightSerialize : public TestHicnLight { + // TestHicnLightSerialize() {} + // virtual ~TestHicnLightSerialize() {} +}; + +class TestHicnLightParse : public TestHicnLight { + // TestHicnLightParse() {} + // virtual ~TestHicnLightParse() {} +}; + +std::string dump_buffer(const char *name, uint8_t *buffer, size_t size); + +#define EXPECT_PAYLOAD_EQ(BUFFER, SIZE, PAYLOAD) \ + EXPECT_EQ(memcmp((BUFFER), &(PAYLOAD)[0], PAYLOAD.size()), 0) \ + << dump_buffer(#PAYLOAD, (BUFFER), SIZE); + +#define EXPECT_PAYLOAD_EQ_STRUCT(BUFFER, SIZE, PAYLOAD) \ + EXPECT_EQ(memcmp((BUFFER), (PAYLOAD), SIZE), 0) \ + << dump_buffer("expected:", (uint8_t *)(BUFFER), SIZE); + +#endif /* HICNCTRL_TEST_COMMON */ diff --git a/ctrl/libhicnctrl/src/test/main.cc b/ctrl/libhicnctrl/src/test/main.cc new file mode 100644 index 000000000..49cc28f66 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/main.cc @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/ctrl/libhicnctrl/src/test/test_data.cc b/ctrl/libhicnctrl/src/test/test_data.cc new file mode 100644 index 000000000..46debb0e7 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/test_data.cc @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> +#include <sstream> + +extern "C" { +#include <hicn/ctrl/objects.h> +#include <hicn/ctrl/data.h> +#include <hicn/ctrl/object.h> +} + +#include "common.h" + +namespace { + +TEST_F(TestHicnLight, TestHicnLightData) { + hc_object_t object; + memset(&object, 0, sizeof(hc_object_t)); + + int rc; + hc_data_t* data = hc_data_create(OBJECT_TYPE_FACE); + hc_data_set_max_size(data, 2); + + ASSERT_EQ(hc_data_get_size(data), 0) << "Initial data size should be zero"; + + /* Try to allocate more than max */ + rc = hc_data_allocate(data, 5); + ASSERT_EQ(rc, -1) << "Allocating above max_size should fail"; + + /* Allocate room for two objects */ + rc = hc_data_allocate(data, 2); + ASSERT_EQ(rc, 0) << "Allocating data the first time should succeed"; + + ASSERT_EQ(hc_data_get_size(data), 0) + << "Initial size should be 0 after allocation"; + + /* Try to allocate twice */ + rc = hc_data_allocate(data, 2); + ASSERT_EQ(rc, -1) << "Allocating data multiple times should fail"; + + ASSERT_EQ(hc_data_get_size(data), 0) + << "Size after failed push should remain unchanged"; + + /* Push a first object */ + rc = hc_data_push(data, &object); + ASSERT_EQ(rc, 0) << "First push should succeed"; + + ASSERT_EQ(hc_data_get_size(data), 1) + << "Data size first successful push should be 1"; + + /* Push a second object */ + rc = hc_data_push(data, &object); + ASSERT_EQ(rc, 0) << "Second push should succeed"; + + ASSERT_EQ(hc_data_get_size(data), 2) + << "Data size after second successful push should be 2"; + + /* Push a third object, exceeding the allocated size */ + rc = hc_data_push(data, &object); + ASSERT_EQ(rc, -1) << "Third push on full data of size 2 should fail"; + + /* Clear */ + rc = hc_data_clear(data); + ASSERT_EQ(rc, 0) << "Clear should always succeed"; + + rc = hc_data_push(data, &object); + ASSERT_EQ(rc, 0) << "Pushing element after reallocation should succeed"; + + ASSERT_EQ(hc_data_get_size(data), 1) << "Size after first push should be one"; + // XXX + + /* Try to push an invalid object */ + // XXX so far NULL + rc = hc_data_push(data, NULL); + ASSERT_EQ(rc, -1) << "Pushing invalid element should fail"; + + ASSERT_EQ(hc_data_get_size(data), 1) + << "Size after push failure should remain unchanged"; + // XXX + + hc_data_free(data); +} + +} // namespace diff --git a/ctrl/libhicnctrl/src/test/test_hicnlight_connection.cc b/ctrl/libhicnctrl/src/test/test_hicnlight_connection.cc new file mode 100644 index 000000000..53dd88ac3 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/test_hicnlight_connection.cc @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> +#include <sstream> + +#include <hicn/ctrl/object.h> + +#include "../modules/hicn_light/connection.h" +#include "common.h" + +namespace { + +const hc_object_t valid_connection = { + .connection = {.id = 0, + .name = {'l', 's', 't', 0}, + .interface_name = {'l', 'o', 0}, + .netdevice_type = NETDEVICE_TYPE_WIRED, + .type = FACE_TYPE_UDP, + .family = AF_INET, + .local_addr = IPV4_LOOPBACK, + .local_port = 9695, + .remote_addr = IPV4_LOOPBACK, + .remote_port = 9695, + .admin_state = FACE_STATE_UP, + .priority = 0, + .tags = POLICY_TAGS_EMPTY, + .state = FACE_STATE_UP}}; + +const std::vector<uint8_t> valid_connection_create_payload = { + /* header */ + 0xc0, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* char name[SYMBOLIC_NAME_LEN] = "lst"; */ + 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* ip_address_t local_addr = [padding] 127.0.0.1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* ip_address_t remote_addr = [padding] 127.0.0.1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* uint16_t local_port = 9695; */ + 0x25, 0xdf, + /* uint16_t remote_port = 9695; */ + 0x25, 0xdf, + /* int family = AF_INET; */ + 0x02, + /* face_type_t type = FACE_TYPE_UDP_LISTENER; */ + 0x05, + /* uint8_t admin_state = FACE_STATE_UP; */ + 0x02, + /* Padding ? */ + 0x00, + /* uint32_t priority = 0; */ + 0x00, 0x00, 0x00, 0x00, + /* policy_tags_t tags; */ + 0x00, 0x00, 0x00, 0x00}; + +const std::vector<uint8_t> valid_connection_delete_payload = { + 0xc0, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x73, 0x74, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const std::vector<uint8_t> valid_connection_list_payload = { + 0xc0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeConnectionCreate) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.connection, &valid_connection, sizeof(hc_connection_t)); + + hc_serialize_t fn = hicnlight_connection_module_ops.serialize[ACTION_CREATE]; + size_t n = fn(&obj, buf); + + // XXX debug + // THIS HAS UNINIT VALUES + std::cout << "n=" << n << std::endl; + EXPECT_EQ(memcmp(buf, buf, 60), 0); + EXPECT_EQ(memcmp(buf, buf, 62), 0); + EXPECT_EQ(memcmp(buf, buf, 64), 0); // XXX we start having issues + EXPECT_EQ(memcmp(buf, buf, 66), 0); + EXPECT_EQ(memcmp(buf, buf, 68), 0); + EXPECT_EQ(memcmp(buf, buf, 70), 0); + EXPECT_EQ(memcmp(buf, buf, 72), 0); + // XXX debug + + EXPECT_EQ(n, valid_connection_create_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_connection_create_payload); +} + +// TODO +// - create with id != 0 +// - create with invalid fields, non zero-terminated strings, etc. + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeConnectionDelete) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.connection, &valid_connection, sizeof(hc_connection_t)); + + hc_serialize_t fn = hicnlight_connection_module_ops.serialize[ACTION_DELETE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_connection_delete_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_connection_delete_payload); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeConnectionList) { + uint8_t buf[BUFSIZE]; + + hc_serialize_t fn = hicnlight_connection_module_ops.serialize[ACTION_LIST]; + size_t n = fn(NULL, buf); + + EXPECT_EQ(n, valid_connection_list_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_connection_list_payload); +} + +} // namespace diff --git a/ctrl/libhicnctrl/src/test/test_hicnlight_listener.cc b/ctrl/libhicnctrl/src/test/test_hicnlight_listener.cc new file mode 100644 index 000000000..fb3df39a8 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/test_hicnlight_listener.cc @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sstream> + +extern "C" { +#include <hicn/ctrl/object.h> +#include <hicn/ctrl/objects/listener.h> +#include "../modules/hicn_light/listener.h" +} + +#include "common.h" + +namespace { + +static const hc_object_t valid_listener = { + .listener = {.name = {'l', 's', 't', 0}, + .interface_name = {'l', 'o', 0}, + .id = 0, + .type = FACE_TYPE_UDP_LISTENER, + .family = AF_INET, + .local_addr = IPV4_LOOPBACK, + .local_port = 9695}}; + +const std::vector<uint8_t> valid_listener_create_payload = { + /* header */ + 0xc0, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* char name[SYMBOLIC_NAME_LEN] = "lst"; */ + 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* char interface_name[INTERFACE_LEN] = "lo"; */ + 0x6c, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* ip_address_t local_addr = [padding] 127.0.0.1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* uint16_t local_port = 9695; */ + 0x25, 0xdf, + /* int family = AF_INET; */ + 0x02, + /* face_type_t type = FACE_TYPE_UDP_LISTENER; */ + 0x06}; + +const std::vector<uint8_t> valid_listener_delete_payload = { + /* header */ + 0xc0, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + /* char symbolicOrListenerid[SYMBOLIC_NAME_LEN] = "lst"; */ + 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +const std::vector<uint8_t> valid_listener_list_payload = { + /* header */ + 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* @see <hicn/ctrl/objects/listener.h> */ +const std::vector<uint8_t> valid_listener_payload = { + /* char name[SYMBOLIC_NAME_LEN] = "lst"; */ + 0x6c, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* char interface_name[INTERFACE_LEN] = "lo"; */ + 0x6c, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* ip_address_t local_addr = [padding] 127.0.0.1 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* uint32_t id = 0; */ + 0x00, 0x00, 0x00, 0x00, + /* uint16_t local_port = 9695; */ + 0x25, 0xdf, + /* face_type_t type = FACE_TYPE_UDP */ + 0x06, + /* int family = AF_INET; */ + 0x02}; + +TEST_F(TestHicnLightParse, TestHicnLightParseListener) { + /* Parse payload into an object */ + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + int rc = hicnlight_listener_module_ops.parse( + &valid_listener_payload[0], valid_listener_payload.size(), &obj); + EXPECT_EQ(rc, 0); + EXPECT_EQ(hc_listener_cmp(&obj.listener, &valid_listener.listener), 0); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeListenerCreate) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.listener, &valid_listener, sizeof(hc_listener_t)); + + hc_serialize_t fn = hicnlight_listener_module_ops.serialize[ACTION_CREATE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_listener_create_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_listener_create_payload); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeListenerDelete) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.listener, &valid_listener, sizeof(hc_listener_t)); + + hc_serialize_t fn = hicnlight_listener_module_ops.serialize[ACTION_DELETE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_listener_delete_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_listener_delete_payload); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeListenerList) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.listener, &valid_listener, sizeof(hc_listener_t)); + + hc_serialize_t fn = hicnlight_listener_module_ops.serialize[ACTION_LIST]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_listener_list_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_listener_list_payload); +} +} // namespace diff --git a/ctrl/libhicnctrl/src/test/test_hicnlight_route.cc b/ctrl/libhicnctrl/src/test/test_hicnlight_route.cc new file mode 100644 index 000000000..d48066ba2 --- /dev/null +++ b/ctrl/libhicnctrl/src/test/test_hicnlight_route.cc @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> +#include <sstream> + +extern "C" { +#include <hicn/ctrl/object.h> +#include "../modules/hicn_light/route.h" +} + +#include "common.h" + +namespace { + +const hc_object_t valid_route = { + .route = {.face_id = 1, + .face_name = {0}, // NULL, use face_id instead + .family = AF_INET, + .remote_addr = IPV4_LOOPBACK, + .len = 16, + .cost = 1, + .face = {0}}}; + +const std::vector<uint8_t> valid_route_create_payload = { + /* uint8_t message_type = REQUEST_LIGHT */ + 0xc0, + /* uint8_t command_id = COMMAND_TYPE_ROUTE_ADD */ + 0x08, + /* uint16_t length = 1 */ + 0x01, 0x00, + /* uint32_t seq_num = 0 */ + 0x00, 0x00, 0x00, 0x00, + /* char symbolic_or_connid[16] = "1\0" */ + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* hicn_ip_address_t address = {0, 0, 0, 127.0.0.1} */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* */ + 0x01, + /* */ + 0x00, + /* */ + 0x02, + /* */ + 0x10}; + +const std::vector<uint8_t> valid_route_delete_payload = { + /* uint8_t message_type = REQUEST_LIGHT */ + 0xc0, + /* uint8_t command_id = COMMAND_TYPE_ROUTE_REMOVE */ + 0x09, + /* uint16_t length = 1 */ + 0x01, 0x00, + /* uint32_t seq_num = 0 */ + 0x00, 0x00, 0x00, 0x00, + + /* char symbolic_or_connid[16] = "1\0" */ + 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + /* hicn_ip_address_t address = {0, 0, 0, 127.0.0.1} */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x00, 0x00, 0x01, + /* uint8_t family = AF_INET (2) */ + 0x02, + /* uint8_t len = 16 */ + 0x10, + /* 2-byte padding */ + 0x00, 0x00}; + +const std::vector<uint8_t> valid_route_list_payload = {0xc0, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeRouteCreate) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.route, &valid_route, sizeof(hc_route_t)); + + hc_serialize_t fn = hicnlight_route_module_ops.serialize[ACTION_CREATE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_route_create_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_route_create_payload); +} + +// TODO +// - create with id != 0 +// - create with invalid fields, non zero-terminated strings, etc. + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeRouteDelete) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.route, &valid_route, sizeof(hc_route_t)); + + hc_serialize_t fn = hicnlight_route_module_ops.serialize[ACTION_DELETE]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_route_delete_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_route_delete_payload); +} + +TEST_F(TestHicnLightSerialize, TestHicnLightSerializeRouteList) { + uint8_t buf[BUFSIZE]; + + hc_object_t obj; + memset(&obj, 0, sizeof(hc_object_t)); + memcpy(&obj.route, &valid_route, sizeof(hc_route_t)); + + hc_serialize_t fn = hicnlight_route_module_ops.serialize[ACTION_LIST]; + size_t n = fn(&obj, buf); + + EXPECT_EQ(n, valid_route_list_payload.size()); + EXPECT_PAYLOAD_EQ(buf, n, valid_route_list_payload); +} + +} // namespace diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt index 241cae7f2..337e22b7f 100644 --- a/hicn-light/CMakeLists.txt +++ b/hicn-light/CMakeLists.txt @@ -93,7 +93,6 @@ else() ${LIBHICNCTRL_STATIC} ) else () - message("qui2!!!") set(HICN_LIBRARIES ${LIBHICN_SHARED} ${LIBHICNCTRL_SHARED} diff --git a/hicn-light/src/hicn/CMakeLists.txt b/hicn-light/src/hicn/CMakeLists.txt index 401ae84eb..feaac5c39 100644 --- a/hicn-light/src/hicn/CMakeLists.txt +++ b/hicn-light/src/hicn/CMakeLists.txt @@ -61,7 +61,8 @@ endif() # Compiler options ############################################################## set(COMPILER_OPTIONS - ${DEFAULT_COMPILER_OPTIONS} + PRIVATE ${DEFAULT_COMPILER_OPTIONS} + #PRIVATE "-Wno-address-of-packed-member" ) ############################################################## diff --git a/hicn-light/src/hicn/cli/hicnc.c b/hicn-light/src/hicn/cli/hicnc.c index 3074016c5..b4a6e8191 100644 --- a/hicn-light/src/hicn/cli/hicnc.c +++ b/hicn-light/src/hicn/cli/hicnc.c @@ -22,13 +22,23 @@ #endif #include "color.h" -#include "../config/parse.h" +#include <hicn/ctrl/parse.h> +#include <hicn/ctrl/hicn-light.h> #include <hicn/util/log.h> #include <hicn/util/sstrncpy.h> -#include <hicn/ctrl/hicn-light-ng.h> #define PORT 9695 +/* + * Duplicated from hicn_light_ng_api.c while is only available as a module in + * libhicnctrl + */ +const char *command_type_str[] = { +#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u), + foreach_command_type +#undef _ +}; + static struct option longFormOptions[] = {{"help", no_argument, 0, 'h'}, {"server", required_argument, 0, 'S'}, {"port", required_argument, 0, 'P'}, @@ -50,6 +60,55 @@ void signal_handler(int sig) { stop = true; } +#if 0 +int hc_active_interface_snprintf(char *buf, size_t size, + hc_event_active_interface_update_t *event) { + int rc; + char *pos = buf; + + rc = ip_prefix_snprintf(pos, size, &event->prefix); + if ((rc < 0) || (rc >= size)) return rc; + pos += rc; + size -= rc; + + for (netdevice_type_t type = NETDEVICE_TYPE_UNDEFINED + 1; + type < NETDEVICE_TYPE_N; type++) { + if (!netdevice_flags_has(event->interface_type, type)) continue; + rc = snprintf(pos, size, " %s", netdevice_type_str(type)); + if ((rc < 0) || (rc >= size)) return pos - buf + rc; + + pos += rc; + size -= rc; + } + return pos - buf; +} + +// XXX hc_object_snprintf +void hc_subscription_display(command_type_t command_type, + const uint8_t *buffer) { + char buf[65535]; + + switch (command_type) { + case COMMAND_TYPE_CONNECTION_ADD: + case COMMAND_TYPE_CONNECTION_REMOVE: + case COMMAND_TYPE_CONNECTION_UPDATE: + hc_connection_snprintf(buf, sizeof(buf), (hc_connection_t *)buffer); + break; + case COMMAND_TYPE_ACTIVE_INTERFACE_UPDATE: + hc_active_interface_snprintf( + buf, sizeof(buf), (hc_event_active_interface_update_t *)buffer); + break; + case COMMAND_TYPE_ROUTE_LIST: + hc_route_snprintf(buf, sizeof(buf), (hc_route_t *)buffer); + break; + default: + INFO("Unknown event received"); + return; + } + INFO("%s %s", command_type_str(command_type), buf); +} +#endif + int main(int argc, char *const *argv) { log_conf.log_level = LOG_INFO; @@ -149,13 +208,13 @@ int main(int argc, char *const *argv) { #define BUFSIZE 255 char url[BUFSIZE]; snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port); - s = hc_sock_create_forwarder_url(HICNLIGHT_NG, url); + s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, url); } else { - s = hc_sock_create_forwarder(HICNLIGHT_NG); + s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); } if (!s) { fprintf(stderr, "Could not create socket.\n"); - goto ERR_SOCK; + goto ERR_SOCKET; } if (hc_sock_connect(s) < 0) { @@ -163,7 +222,7 @@ int main(int argc, char *const *argv) { goto ERR_CONNECT; } - if (!IS_VALID_OBJECT_TYPE(command.object.type) || + if (!IS_VALID_OBJECT_TYPE(command.object_type) || !IS_VALID_ACTION(command.action)) { fprintf(stderr, "Unsupported command"); goto ERR_PARAM; @@ -171,285 +230,54 @@ int main(int argc, char *const *argv) { int rc = UNSUPPORTED_CMD_ERROR; hc_data_t *data = NULL; - char buf_listener[MAXSZ_HC_LISTENER]; - char buf_connection[MAXSZ_HC_CONNECTION]; - char buf_route[MAXSZ_HC_ROUTE]; - char buf[MAX_LEN]; - switch (command.object.type) { - case OBJECT_ROUTE: - switch (command.action) { - case ACTION_CREATE: - rc = hc_route_create(s, &command.object.route); - break; - - case ACTION_DELETE: - rc = hc_route_delete(s, &command.object.route); - break; - - case ACTION_LIST: - rc = hc_route_list(s, &data); - if (rc < 0) break; - - INFO("Routes:"); - foreach_route(r, data) { - if (hc_route_snprintf(buf_route, MAXSZ_HC_ROUTE, r) >= - MAXSZ_HC_ROUTE) - ERROR("Display error"); - INFO("%s", buf_route); - } - break; - - default: - break; - } - break; - - case OBJECT_LISTENER: - switch (command.action) { - case ACTION_CREATE: - rc = hc_listener_create(s, &command.object.listener); - break; - - case ACTION_DELETE: - rc = hc_listener_delete(s, &command.object.listener); - break; - - case ACTION_LIST: - rc = hc_listener_list(s, &data); - if (rc < 0) break; - - INFO("Listeners:"); - foreach_listener(l, data) { - if (hc_listener_snprintf(buf_listener, MAXSZ_HC_LISTENER + 17, l) >= - MAXSZ_HC_LISTENER) - ERROR("Display error"); - INFO("[%d] %s", l->id, buf_listener); - } - break; - - default: - break; - } - break; - - case OBJECT_CONNECTION: - switch (command.action) { - case ACTION_CREATE: - rc = hc_connection_create(s, &command.object.connection); - break; - - case ACTION_DELETE: - rc = hc_connection_delete(s, &command.object.connection); - break; - - case ACTION_LIST: - rc = hc_connection_list(s, &data); - if (rc < 0) break; - - INFO("Connections:"); - foreach_connection(c, data) { - if (hc_connection_snprintf(buf_connection, MAXSZ_HC_CONNECTION, - c) >= MAXSZ_HC_CONNECTION) - ERROR("Display error"); - INFO("[%d] %s", c->id, buf_connection); - } - break; - - default: - break; - } - break; - - case OBJECT_CACHE: - switch (command.action) { - case ACTION_SERVE: - rc = hc_cache_set_serve(s, &command.object.cache); - break; - - case ACTION_STORE: - rc = hc_cache_set_store(s, &command.object.cache); - break; - - case ACTION_CLEAR: - rc = hc_cache_clear(s, &command.object.cache); - break; - - case ACTION_LIST: - rc = hc_cache_list(s, &data); - if (rc < 0) break; - - hc_cache_snprintf(buf, MAX_LEN, (hc_cache_info_t *)data->buffer); - printf("%s\n", buf); - break; - - default: - break; - } - break; - - case OBJECT_STRATEGY: - switch (command.action) { - case ACTION_SET: - rc = hc_strategy_set(s, &command.object.strategy); - break; - - default: - break; - } - break; - case OBJECT_MAPME: - switch (command.action) { - case ACTION_UPDATE: - rc = hc_mapme_send_update(s, &command.object.mapme); - break; - case ACTION_SET: - if (command.object.mapme.target == MAPME_TARGET_ENABLE) { - rc = hc_mapme_set(s, &command.object.mapme); - } else if (command.object.mapme.target == MAPME_TARGET_DISCOVERY) { - rc = hc_mapme_set_discovery(s, &command.object.mapme); - } else if (command.object.mapme.target == MAPME_TARGET_TIMESCALE) { - rc = hc_mapme_set_timescale(s, &command.object.mapme); - } else if (command.object.mapme.target == MAPME_TARGET_RETX) { - rc = hc_mapme_set_retx(s, &command.object.mapme); - } - break; - - default: - break; - } - break; - - case OBJECT_LOCAL_PREFIX: - switch (command.action) { - case ACTION_CREATE: - rc = hc_strategy_add_local_prefix(s, &command.object.strategy); - break; - - default: - break; - } - break; - - case OBJECT_SUBSCRIPTION: - // Disable socket recv timeout - hc_sock_set_recv_timeout_ms(s, 0); - - rc = hc_subscription_create(s, &command.object.subscription); - if (rc < 0) break; - INFO("Subscription sent"); - - while (!stop) { - int rc = hc_sock_callback(s, &data); - if (rc < 0 && !stop) ERROR("Notification error"); - - if (!stop) { - event_type_t event_type = rc; - INFO("Notification recevied %s [%d]", event_str(event_type), - event_type); - - if (event_type == EVENT_INTERFACE_UPDATE) { - hc_event_interface_update_t *event = - (hc_event_interface_update_t *)(data->buffer); - INFO("Interface update event received: %u", event->interface_type); - } - } - } - - INFO("Unsubscribing..."); - rc = hc_subscription_delete(s, &command.object.subscription); - break; - - case OBJECT_STATS: - switch (command.action) { - case ACTION_GET: - rc = hc_stats_get(s, &data); - if (rc < 0) break; - - hc_stats_snprintf(buf, MAX_LEN, (hicn_light_stats_t *)data->buffer); - INFO("\n%s", buf); - break; - - case ACTION_LIST: - rc = hc_stats_list(s, &data); - if (rc < 0) break; - - cmd_stats_list_item_t *conn_stats = - (cmd_stats_list_item_t *)data->buffer; - cmd_stats_list_item_t *end = - (cmd_stats_list_item_t *)(data->buffer + - data->size * data->out_element_size); - while (conn_stats < end) { - INFO("Connection #%d:", conn_stats->id); - INFO("\tinterests received: %d pkts (%d bytes)", - conn_stats->stats.interests.rx_pkts, - conn_stats->stats.interests.rx_bytes); - INFO("\tinterests transmitted: %d pkts (%d bytes)", - conn_stats->stats.interests.tx_pkts, - conn_stats->stats.interests.tx_bytes); - INFO("\tdata received: %d pkts (%d bytes)", - conn_stats->stats.data.rx_pkts, - conn_stats->stats.data.rx_bytes); - INFO("\tdata transmitted: %d pkts (%d bytes)", - conn_stats->stats.data.tx_pkts, - conn_stats->stats.data.tx_bytes); - - conn_stats++; - } - break; - - default: - break; - } - break; + rc = hc_execute(s, command.action, command.object_type, &command.object, + &data); -#ifdef TEST_FACE_CREATION - case OBJECT_FACE: - switch (command.action) { - case ACTION_CREATE: { - hc_face_t face = {0}; - face.face.type = FACE_TYPE_UDP; - face.face.family = AF_INET; - face.face.local_addr = IPV4_LOOPBACK; - face.face.remote_addr = IPV4_LOOPBACK; - face.face.local_port = 9696; - face.face.remote_port = 9696; - - rc = hc_face_create(s, &face); - break; - } - default: - break; - } - break; -#endif - - default: - break; + if (rc < 0) { + switch (rc) { + case INPUT_ERROR: + ERROR("Wrong input parameters"); + break; + case UNSUPPORTED_CMD_ERROR: + ERROR("Unsupported command"); + break; + default: + ERROR("Error executing command"); + break; + } + goto ERR_COMMAND; } - hc_data_free(data); - if (rc < -1) { - if (rc == INPUT_ERROR) ERROR("Wrong input parameters"); - if (rc == UNSUPPORTED_CMD_ERROR) ERROR("Unsupported command"); - goto ERR_CMD; + if (!data) goto ERR_QUERY; + if (!hc_data_get_result(data)) goto ERR_DATA; + + if (command.action == ACTION_LIST) { + char buf[MAXSZ_HC_OBJECT]; + hc_data_foreach(data, obj, { + rc = hc_object_snprintf(buf, MAXSZ_HC_OBJECT, command.object_type, obj); + if (rc < 0) + WARN("Display error"); + else if (rc >= MAXSZ_HC_OBJECT) + WARN("Output truncated"); + else + printf("%s\n", buf); + }); } - if (rc < 0) ERROR("Error executing command"); - // Remove the connection created to send the command - command.object.connection.id = 0; - rc = strcpy_s(command.object.connection.name, - sizeof(command.object.connection.name), "SELF"); - if (rc != EOK || hc_connection_delete(s, &command.object.connection) < 0) - fprintf(stderr, "Error removing local connection to forwarder\n"); - - exit(EXIT_SUCCESS); + hc_data_free(data); + hc_sock_free(s); + return EXIT_SUCCESS; -ERR_CMD: +ERR_DATA: + hc_data_free(data); +ERR_QUERY: +ERR_COMMAND: ERR_CONNECT: hc_sock_free(s); -ERR_SOCK: +ERR_SOCKET: ERR_PARSE: ERR_PARAM: - exit(EXIT_FAILURE); + ERROR("Error"); + return EXIT_FAILURE; } diff --git a/hicn-light/src/hicn/cli/hicns.c b/hicn-light/src/hicn/cli/hicns.c index 2f7a360f8..fa668062d 100644 --- a/hicn-light/src/hicn/cli/hicns.c +++ b/hicn-light/src/hicn/cli/hicns.c @@ -21,7 +21,7 @@ #endif #include "logo.h" -#include "../config/parse.h" +#include <hicn/ctrl/parse.h> #include <hicn/util/sstrncpy.h> #define PORT 9695 @@ -181,9 +181,9 @@ int main(int argc, char *const *argv) { #define BUFSIZE 255 char url[BUFSIZE]; snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port); - s = hc_sock_create_forwarder_url(HICNLIGHT_NG, url); + s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, url); } else { - s = hc_sock_create_forwarder(HICNLIGHT_NG); + s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); } if (!s) { fprintf(stderr, "Could not create socket.\n"); diff --git a/hicn-light/src/hicn/config/CMakeLists.txt b/hicn-light/src/hicn/config/CMakeLists.txt index 90d0a2229..b1b04d679 100644 --- a/hicn-light/src/hicn/config/CMakeLists.txt +++ b/hicn-light/src/hicn/config/CMakeLists.txt @@ -13,28 +13,32 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/configuration.h - ${CMAKE_CURRENT_SOURCE_DIR}/command.h ${CMAKE_CURRENT_SOURCE_DIR}/commands.h - ${CMAKE_CURRENT_SOURCE_DIR}/parse.h ) list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/module_object.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/connection.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/face.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/route.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/strategy.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/modules/hicn_light/subscription.c ${CMAKE_CURRENT_SOURCE_DIR}/configuration.c ${CMAKE_CURRENT_SOURCE_DIR}/configuration_file.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_cache.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_connection.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_face.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_listener.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_mapme.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_policy.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_punting.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_route.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_stats.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_strategy.c - ${CMAKE_CURRENT_SOURCE_DIR}/command_subscription.c - ${CMAKE_CURRENT_SOURCE_DIR}/command.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_cache.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_connection.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_face.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_listener.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_mapme.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_policy.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_punting.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_route.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_stats.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_strategy.c + #${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_subscription.c ${CMAKE_CURRENT_SOURCE_DIR}/commands.c - ${CMAKE_CURRENT_SOURCE_DIR}/parse.c ) set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) diff --git a/hicn-light/src/hicn/config/command_face.c b/hicn-light/src/hicn/config/command_face.c deleted file mode 100644 index 95ec404f0..000000000 --- a/hicn-light/src/hicn/config/command_face.c +++ /dev/null @@ -1,16 +0,0 @@ -#if 0 -#include "command.h" - -/* Parameters */ - -/* Commands */ - -// XXX missing add - -static const command_parser_t command_face_list = { - .action = ACTION_LIST, - .object = OBJECT_FACE, - .nparams = 0, -}; -COMMAND_REGISTER(command_face_list); -#endif
\ No newline at end of file diff --git a/hicn-light/src/hicn/config/commands.c b/hicn-light/src/hicn/config/commands.c index be00575d7..08c43ba24 100644 --- a/hicn-light/src/hicn/config/commands.c +++ b/hicn-light/src/hicn/config/commands.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -42,7 +42,8 @@ #include <hicn/core/listener.h> //the listener list #include <hicn/core/listener_table.h> #include <hicn/core/subscription.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> +//#include <hicn/utils/utils.h> #include <hicn/utils/punting.h> #include <hicn/util/log.h> #include <hicn/validation.h> @@ -55,8 +56,17 @@ #define DEFAULT_COST 1 #define DEFAULT_PORT 1234 -#define make_ack(msg) ((msg_header_t *)msg)->header.message_type = ACK_LIGHT -#define make_nack(msg) ((msg_header_t *)msg)->header.message_type = NACK_LIGHT +#define make_ack(msg) \ + do { \ + ((msg_header_t *)msg)->header.message_type = ACK_LIGHT; \ + ((msg_header_t *)msg)->header.length = 0; \ + } while (0) + +#define make_nack(msg) \ + do { \ + ((msg_header_t *)msg)->header.message_type = NACK_LIGHT; \ + ((msg_header_t *)msg)->header.length = 0; \ + } while (0) #define msg_malloc_list(msg, COMMAND_ID, N, seq_number) \ do { \ @@ -138,6 +148,7 @@ uint8_t *configuration_on_listener_add(forwarder_t *forwarder, uint8_t *packet, case FACE_TYPE_HICN_LISTENER: break; default: + ERROR("Wrong listener type"); goto NACK; } @@ -266,8 +277,11 @@ uint8_t *configuration_on_listener_remove(forwarder_t *forwarder, continue; unsigned conn_id = - (unsigned int)connection_table_get_connection_id(table, connection); + (unsigned)connection_table_get_connection_id(table, connection); + /* Remove connection from the FIB */ + // XXX TODO get entries, raise notifications... + // XXX isn't it possible to implement this in the forwarder ????? forwarder_remove_connection_id_from_routes(forwarder, conn_id); /* Remove connection */ @@ -288,10 +302,8 @@ NACK: } // TODO(eloparco): Unused forwarder param -static inline void fill_listener_command(forwarder_t *forwarder, - listener_t *listener, +static inline void fill_listener_command(const listener_t *listener, cmd_listener_list_item_t *cmd) { - assert(forwarder); assert(listener); assert(cmd); @@ -306,15 +318,15 @@ static inline void fill_listener_command(forwarder_t *forwarder, switch (addr->as_ss.ss_family) { case AF_INET: sin = (struct sockaddr_in *)addr; - cmd->family = AF_INET; - cmd->address.v4.as_inaddr = sin->sin_addr; - cmd->port = sin->sin_port; + cmd->family = (uint8_t)AF_INET; + cmd->local_addr.v4.as_inaddr = sin->sin_addr; + cmd->local_port = sin->sin_port; break; case AF_INET6: sin6 = (struct sockaddr_in6 *)addr; - cmd->family = AF_INET6; - cmd->address.v6.as_in6addr = sin6->sin6_addr; - cmd->port = sin6->sin6_port; + cmd->family = (uint8_t)AF_INET6; + cmd->local_addr.v6.as_in6addr = sin6->sin6_addr; + cmd->local_port = sin6->sin6_port; break; default: break; @@ -344,9 +356,8 @@ uint8_t *configuration_on_listener_list(forwarder_t *forwarder, uint8_t *packet, if (!msg) goto NACK; cmd_listener_list_item_t *payload = &msg->payload; - listener_t *listener; listener_table_foreach(table, listener, { - fill_listener_command(forwarder, listener, payload); + fill_listener_command(listener, payload); payload++; }); @@ -406,41 +417,10 @@ uint8_t *configuration_on_connection_add(forwarder_t *forwarder, control->remote_port) < 0) goto NACK; - connection_t *connection = connection_table_get_by_pair(table, &pair); -#ifdef WITH_MAPME - connection_event_t event; -#endif /* WITH_MAPME */ - - if (!connection) { - connection = - connection_create(control->type, symbolic_name, &pair, forwarder); - if (!connection) { - ERROR("Failed to create %s connection", face_type_str(control->type)); - goto NACK; - } - -#ifdef WITH_MAPME - event = CONNECTION_EVENT_CREATE; -#endif /* WITH_MAPME */ - } else { - WARN("Connection already exists"); - -#ifdef WITH_MAPME - event = CONNECTION_EVENT_UPDATE; -#endif /* WITH_MAPME */ - } - -#ifdef WITH_POLICY - connection_set_tags(connection, control->tags); - connection_set_priority(connection, control->priority); -#endif /* WITH_POLICY */ - - connection_set_admin_state(connection, control->admin_state); - -#ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_on_connection_event(forwarder, connection, event); -#endif /* WITH_MAPME */ + if (forwarder_add_connection(forwarder, symbolic_name, control->type, &pair, + control->tags, control->priority, + control->admin_state) < 0) + goto NACK; make_ack(msg); return (uint8_t *)msg; @@ -486,24 +466,20 @@ uint8_t *configuration_on_connection_remove(forwarder_t *forwarder, goto NACK; } - /* Remove connection from the FIB */ - forwarder_remove_connection_id_from_routes(forwarder, conn_id); - - /* Remove connection */ - connection_table_t *table = forwarder_get_connection_table(forwarder); - connection_t *connection = connection_table_get_by_id(table, conn_id); - connection_table_remove_by_id(table, conn_id); + /* + * + * Don't close the fd for SELF otherwise it won't be possible + * to send the reply back. The connection is finalized later in + * _forwarder_finalize_connection_if_self + */ + bool finalize = (strcmp(control->symbolic_or_connid, "SELF") != 0); - // Don't close the fd for SELF otherwise it won't be possible - // to send the reply back - if (strcmp(control->symbolic_or_connid, "SELF") != 0) - connection_finalize(connection); - WITH_DEBUG(connection_table_print_by_pair(table);) + if (forwarder_remove_connection(forwarder, conn_id, finalize) < 0) goto NACK; -#ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_on_connection_event(forwarder, NULL, CONNECTION_EVENT_DELETE); -#endif /* WITH_MAPME */ + WITH_DEBUG({ + connection_table_t *table = forwarder_get_connection_table(forwarder); + connection_table_print_by_pair(table); + }) make_ack(msg); return (uint8_t *)msg; @@ -519,10 +495,8 @@ static inline void tolower_str(char *str) { } // TODO(eloparco): Forwarder param not used -static inline void fill_connections_command(forwarder_t *forwarder, - connection_t *connection, +static inline void fill_connections_command(const connection_t *connection, cmd_connection_list_item_t *cmd) { - assert(forwarder); assert(connection); assert(cmd); @@ -531,12 +505,12 @@ static inline void fill_connections_command(forwarder_t *forwarder, const address_pair_t *pair = connection_get_pair(connection); cmd->id = connection_get_id(connection), - cmd->state = connection_get_state(connection), - cmd->admin_state = connection_get_admin_state(connection), - cmd->type = connection_get_type(connection), + cmd->state = (uint8_t)connection_get_state(connection), + cmd->admin_state = (uint8_t)connection_get_admin_state(connection), + cmd->type = (uint8_t)connection_get_type(connection), #ifdef WITH_POLICY cmd->priority = connection_get_priority(connection), - cmd->tags = connection_get_tags(connection), + cmd->tags = (uint8_t)connection_get_tags(connection), #endif /* WITH_POLICY */ snprintf(cmd->name, SYMBOLIC_NAME_LEN, "%s", connection_get_name(connection)); @@ -547,7 +521,7 @@ static inline void fill_connections_command(forwarder_t *forwarder, switch (pair->local.as_ss.ss_family) { case AF_INET: - cmd->family = AF_INET; + cmd->family = (uint8_t)AF_INET; sin = (struct sockaddr_in *)(&pair->local); cmd->local_port = sin->sin_port; @@ -559,7 +533,7 @@ static inline void fill_connections_command(forwarder_t *forwarder, break; case AF_INET6: - cmd->family = AF_INET6; + cmd->family = (uint8_t)AF_INET6; sin6 = (struct sockaddr_in6 *)(&pair->local); cmd->local_port = sin6->sin6_port; @@ -594,6 +568,7 @@ uint8_t *configuration_on_connection_list(forwarder_t *forwarder, // -1 since current connection (i.e. the one used to send // the command) is not considered size_t n = connection_table_len(table) - 1; + msg_connection_list_t *msg_received = (msg_connection_list_t *)packet; uint8_t command_id = msg_received->header.command_id; uint32_t seq_num = msg_received->header.seq_num; @@ -603,10 +578,9 @@ uint8_t *configuration_on_connection_list(forwarder_t *forwarder, if (!msg) goto NACK; cmd_connection_list_item_t *payload = &msg->payload; - connection_t *connection; - connection_table_foreach(table, connection, { + connection_table_foreach_new(table, connection, { if (connection->id == ingress_id) continue; - fill_connections_command(forwarder, connection, payload); + fill_connections_command(connection, payload); payload++; }); @@ -619,6 +593,7 @@ NACK: return (uint8_t *)msg; } +#if 0 uint8_t *configuration_on_connection_set_admin_state(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, @@ -640,13 +615,11 @@ uint8_t *configuration_on_connection_set_admin_state(forwarder_t *forwarder, connection_set_admin_state(conn, control->admin_state); -#ifdef WITH_MAPME /* Hook: connection event */ forwarder_on_connection_event(forwarder, conn, control->admin_state == FACE_STATE_UP ? CONNECTION_EVENT_SET_UP : CONNECTION_EVENT_SET_DOWN); -#endif /* WITH_MAPME */ make_ack(msg); return (uint8_t *)msg; @@ -656,6 +629,7 @@ NACK: return (uint8_t *)msg; } +#endif uint8_t *configuration_on_connection_update(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, @@ -684,6 +658,8 @@ NACK: return (uint8_t *)msg; } +#if 0 + uint8_t *configuration_on_connection_set_priority(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, @@ -701,11 +677,9 @@ uint8_t *configuration_on_connection_set_priority(forwarder_t *forwarder, connection_set_priority(conn, control->priority); -#ifdef WITH_MAPME /* Hook: connection event */ forwarder_on_connection_event(forwarder, conn, CONNECTION_EVENT_PRIORITY_CHANGED); -#endif /* WITH_MAPME */ make_ack(msg); return (uint8_t *)msg; @@ -733,10 +707,8 @@ uint8_t *configuration_on_connection_set_tags(forwarder_t *forwarder, connection_set_tags(conn, control->tags); -#ifdef WITH_MAPME /* Hook: connection event */ forwarder_on_connection_event(forwarder, conn, CONNECTION_EVENT_TAGS_CHANGED); -#endif /* WITH_MAPME */ make_ack(msg); return (uint8_t *)msg; @@ -747,6 +719,8 @@ NACK: return (uint8_t *)msg; } +#endif + /* Route */ uint8_t *configuration_on_route_add(forwarder_t *forwarder, uint8_t *packet, @@ -763,9 +737,9 @@ uint8_t *configuration_on_route_add(forwarder_t *forwarder, uint8_t *packet, forwarder, control->symbolic_or_connid, ingress_id); if (!connection_id_is_valid(conn_id)) goto NACK; - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; if (!forwarder_add_or_update_route(forwarder, &prefix, conn_id)) goto NACK; @@ -792,9 +766,9 @@ uint8_t *configuration_on_route_remove(forwarder_t *forwarder, uint8_t *packet, symbolic_to_conn_id(forwarder, control->symbolic_or_connid); if (!connection_id_is_valid(conn_id)) goto NACK; - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; if (!forwarder_remove_route(forwarder, &prefix, conn_id)) goto NACK; @@ -806,6 +780,29 @@ NACK: return (uint8_t *)msg; } +static inline void fill_route_command(const fib_entry_t *entry, + cmd_route_list_item_t *cmd) { + const nexthops_t *nexthops = fib_entry_get_nexthops(entry); + assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops)); + size_t num_nexthops = nexthops_get_len(nexthops); + + if (num_nexthops == 0) return; + + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + const hicn_ip_address_t *address = hicn_prefix_get_ip_address(prefix); + int family = hicn_ip_address_get_family(address); + + nexthops_foreach(nexthops, nexthop, { + cmd->family = family; + cmd->remote_addr = *address; + cmd->face_id = nexthop; + cmd->len = hicn_prefix_get_len(prefix); + cmd->cost = DEFAULT_COST; + + cmd++; + }); +} + uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, size_t *reply_size) { INFO("CMD: route list (ingress=%d)", ingress_id); @@ -816,7 +813,6 @@ uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet, uint8_t command_id = msg_received->header.command_id; uint32_t seq_num = msg_received->header.seq_num; const fib_t *fib = forwarder_get_fib(forwarder); - fib_entry_t *entry; /* * Two step approach to precompute the number of entries to allocate @@ -835,38 +831,7 @@ uint8_t *configuration_on_route_list(forwarder_t *forwarder, uint8_t *packet, if (!msg) goto NACK; cmd_route_list_item_t *payload = &msg->payload; - fib_foreach_entry(fib, entry, { - const nexthops_t *nexthops = fib_entry_get_nexthops(entry); - assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops)); - size_t num_nexthops = nexthops_get_len(nexthops); - - if (num_nexthops == 0) continue; - - NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry)); - - unsigned nexthop; - nexthops_foreach(nexthops, nexthop, { - address_t address; - nameBitvector_ToAddress(prefix, &address); - switch (address_family(&address)) { - case AF_INET: - payload->family = AF_INET; - payload->address.v4.as_inaddr = address4_ip(&address); - break; - case AF_INET6: - payload->family = AF_INET6; - payload->address.v6.as_in6addr = address6_ip(&address); - break; - default: - break; - } - payload->connection_id = nexthop; - payload->len = nameBitvector_GetLength(prefix); - payload->cost = DEFAULT_COST; - - payload++; - }); - }); + fib_foreach_entry(fib, entry, { fill_route_command(entry, payload); }); *reply_size = sizeof(msg->header) + n * sizeof(msg->payload); return (uint8_t *)msg; @@ -983,12 +948,12 @@ uint8_t *configuration_on_strategy_set(forwarder_t *forwarder, uint8_t *packet, cmd_strategy_set_t *control = &msg->payload; char prefix_s[MAXSZ_IP_PREFIX]; - ip_prefix_t prefix = { + hicn_ip_prefix_t prefix = { .family = control->family, .address = control->address, .len = control->len, }; - int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); + int rc = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) goto NACK; @@ -998,9 +963,10 @@ uint8_t *configuration_on_strategy_set(forwarder_t *forwarder, uint8_t *packet, configuration_get_strategy(config, prefix_s); strategy_options_t *options = NULL; - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, control->family, control->address, - control->len); + // XXX check control->family + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&control->address, control->len, + &name_prefix); // The strategy is not present in the hash table // or has to be updated or to be restarted @@ -1012,9 +978,9 @@ uint8_t *configuration_on_strategy_set(forwarder_t *forwarder, uint8_t *packet, forwarder_set_strategy(forwarder, &name_prefix, strategy, options); } else { WITH_WARN({ - char *nameString = name_ToString(&name_prefix); - WARN("Strategy for prefix %s not updated", nameString); - free(nameString); + char buf[MAXSZ_HICN_PREFIX]; + hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, &name_prefix); + WARN("Strategy for prefix %s not updated", buf); }) } @@ -1040,12 +1006,12 @@ uint8_t *configuration_on_strategy_add_local_prefix(forwarder_t *forwarder, cmd_strategy_add_local_prefix_t *control = &msg->payload; char prefix_s[MAXSZ_IP_PREFIX]; - ip_prefix_t prefix = { + hicn_ip_prefix_t prefix = { .family = control->family, .address = control->address, .len = control->len, }; - int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); + int rc = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) goto NACK; @@ -1060,17 +1026,17 @@ uint8_t *configuration_on_strategy_add_local_prefix(forwarder_t *forwarder, strategy != STRATEGY_TYPE_REPLICATION) goto NACK; - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, control->family, control->address, - control->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&control->address, control->len, + &name_prefix); strategy_options_t options; - Name local_prefix = EMPTY_NAME; - name_CreateFromAddress(&local_prefix, control->local_family, - control->local_address, control->local_len); + hicn_prefix_t local_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&control->address, control->len, + &local_prefix); - // for the moment bestpath and replication are the same but we distinguish the - // two in case they will diverge in the future + // for the moment bestpath and replication are the same but we distinguish + // the two in case they will diverge in the future if (strategy == STRATEGY_TYPE_BESTPATH) { options.bestpath.local_prefixes = create_local_prefixes(); local_prefixes_add_prefix(options.bestpath.local_prefixes, &local_prefix); @@ -1212,11 +1178,11 @@ uint8_t *configuration_on_punting_add(forwarder_t *forwarder, uint8_t *packet, goto NACK; } - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; char prefix_s[MAXSZ_IP_PREFIX]; - int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); + int rc = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) goto NACK; @@ -1359,12 +1325,11 @@ uint8_t *configuration_on_mapme_send_update(forwarder_t *forwarder, mapme_t *mapme = forwarder_get_mapme(forwarder); /* - * The command triggers a mapme update for all prefixes produced on this face + * The command triggers a mapme update for all prefixes produced on this + * face * */ - fib_entry_t *entry; fib_foreach_entry(fib, entry, { const nexthops_t *nexthops = fib_entry_get_nexthops(entry); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { if (nexthop != ingress_id) continue; /* This entry points to the producer face */ @@ -1393,9 +1358,9 @@ uint8_t *configuration_on_policy_add(forwarder_t *forwarder, uint8_t *packet, msg_policy_add_t *msg = (msg_policy_add_t *)packet; cmd_policy_add_t *control = &msg->payload; - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; if (!forwarder_add_or_update_policy(forwarder, &prefix, &control->policy)) goto NACK; @@ -1419,9 +1384,9 @@ uint8_t *configuration_on_policy_remove(forwarder_t *forwarder, uint8_t *packet, msg_policy_remove_t *msg = (msg_policy_remove_t *)packet; cmd_policy_remove_t *control = &msg->payload; - ip_prefix_t prefix = {.family = control->family, - .address = control->address, - .len = control->len}; + hicn_ip_prefix_t prefix = {.family = control->family, + .address = control->address, + .len = control->len}; if (!forwarder_remove_policy(forwarder, &prefix)) goto NACK; @@ -1434,6 +1399,39 @@ NACK: return (uint8_t *)msg; } +static inline void fill_policy_command(const fib_entry_t *entry, + cmd_policy_list_item_t *cmd) { + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + const hicn_ip_address_t *ip_address = hicn_prefix_get_ip_address(prefix); + cmd->remote_addr = *ip_address; + cmd->family = hicn_ip_address_get_family(ip_address); + cmd->len = hicn_prefix_get_len(prefix); + + hicn_policy_t policy = fib_entry_get_policy(entry); + _hicn_policy_t _policy = { + .stats = { + .wired = {.throughput = htonf(policy.stats.wired.throughput), + .latency = htonf(policy.stats.wired.latency), + .loss_rate = htonf(policy.stats.wired.loss_rate)}, + .wifi = {.throughput = htonf(policy.stats.wifi.throughput), + .latency = htonf(policy.stats.wifi.latency), + .loss_rate = htonf(policy.stats.wifi.loss_rate)}, + .cellular = {.throughput = htonf(policy.stats.cellular.throughput), + .latency = htonf(policy.stats.cellular.latency), + .loss_rate = htonf(policy.stats.cellular.loss_rate)}, + .all = {.throughput = htonf(policy.stats.all.throughput), + .latency = htonf(policy.stats.all.latency), + .loss_rate = htonf(policy.stats.all.loss_rate)}}}; + for (unsigned i = 0; i < POLICY_TAG_N; i++) { + _policy.tags[i] = (_policy_tag_state_t){ + .state = policy.tags[i].state, + .disabled = policy.tags[i].disabled, + }; + } + memcpy(_policy.app_name, policy.app_name, APP_NAME_LEN); + memcpy(cmd->policy, &_policy, sizeof(_policy)); +} + uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, size_t *reply_size) { assert(forwarder); @@ -1454,30 +1452,8 @@ uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet, cmd_policy_list_item_t *payload = &msg->payload; - fib_entry_t *entry; - fib_foreach_entry(fib, entry, { - NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry)); - address_t address; - nameBitvector_ToAddress(prefix, &address); - - switch (address_family(&address)) { - case AF_INET: - payload->family = AF_INET; - payload->address.v4.as_inaddr = address4_ip(&address); - break; - - case AF_INET6: - payload->family = AF_INET6; - payload->address.v6.as_in6addr = address6_ip(&address); - break; - - default: - break; - } - payload->len = nameBitvector_GetLength(prefix); - payload->policy = fib_entry_get_policy(entry); - + fill_policy_command(entry, payload); payload++; }); @@ -1544,9 +1520,17 @@ uint8_t *configuration_on_subscription_remove(forwarder_t *forwarder, return (uint8_t *)msg; } +uint8_t *configuration_on_active_interface_update(forwarder_t *forwarder, + uint8_t *packet, + unsigned ingress_id, + size_t *reply_size) { + msg_active_interface_update_t *msg = (msg_active_interface_update_t *)packet; + make_nack(msg); + return (uint8_t *)msg; +} + uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet, - command_type_t command_type, unsigned ingress_id, - size_t *reply_size) { + unsigned ingress_id, size_t *reply_size) { uint8_t *reply = NULL; /* @@ -1557,6 +1541,7 @@ uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet, * * XXX rework this part. */ + command_type_t command_type = ((msg_header_t *)packet)->header.command_id; switch (command_type) { #define _(l, u) \ case COMMAND_TYPE_##u: \ @@ -1586,28 +1571,100 @@ ssize_t command_process_msgbuf(forwarder_t *forwarder, msgbuf_t *msgbuf) { uint8_t *reply = NULL; size_t reply_size = 0; - command_type_t command_type = msgbuf_get_command_type(msgbuf); - - reply = - command_process(forwarder, packet, command_type, ingress_id, &reply_size); + reply = command_process(forwarder, packet, ingress_id, &reply_size); if (connection_id_is_valid(msgbuf->connection_id)) { connection_table_t *table = forwarder_get_connection_table(forwarder); const connection_t *connection = connection_table_at(table, ingress_id); connection_send_packet(connection, reply, reply_size); } - switch (msgbuf->command.type) { - case COMMAND_TYPE_LISTENER_LIST: - case COMMAND_TYPE_CONNECTION_LIST: - case COMMAND_TYPE_ROUTE_LIST: - case COMMAND_TYPE_POLICY_LIST: - /* Free replies that have been allocated (not NACK's) */ - if (((msg_header_t *)reply)->header.message_type != NACK_LIGHT) - free(reply); + /* Free allocated replies */ + if (reply != packet) free(reply); + return msgbuf_get_len(msgbuf); +} + +void commands_notify(const forwarder_t *forwarder, hc_topic_t topic, + uint8_t *msg, size_t size) { + // Retrieve subscribed connections + subscription_table_t *subscriptions = forwarder_get_subscriptions(forwarder); + unsigned *subscribed_conn_ids = + subscription_table_get_connections_for_topic(subscriptions, topic); + + // Send notification to subscribed connections + const connection_table_t *table = forwarder_get_connection_table(forwarder); + for (int i = 0; i < vector_len(subscribed_conn_ids); i++) { + const connection_t *conn = + connection_table_at(table, subscribed_conn_ids[i]); + connection_send_packet(conn, msg, size); + } +} + +void commands_notify_connection(const forwarder_t *forwarder, + connection_event_t event, + const connection_t *connection) { +#if 0 + uint8_t command_id; + switch (event) { + case CONNECTION_EVENT_CREATE: + command_id = COMMAND_TYPE_CONNECTION_ADD; break; - default: + case CONNECTION_EVENT_DELETE: + command_id = COMMAND_TYPE_CONNECTION_REMOVE; + break; + case CONNECTION_EVENT_UPDATE: + case CONNECTION_EVENT_SET_UP: + case CONNECTION_EVENT_SET_DOWN: + case CONNECTION_EVENT_PRIORITY_CHANGED: + case CONNECTION_EVENT_TAGS_CHANGED: + command_id = COMMAND_TYPE_CONNECTION_UPDATE; break; + case CONNECTION_EVENT_UNDEFINED: + case CONNECTION_EVENT_N: + default: + return; } +#endif - return msgbuf_get_len(msgbuf); + msg_connection_notify_t msg = {.header = { + .message_type = NOTIFICATION_LIGHT, + .command_id = OBJECT_TYPE_CONNECTION, + .length = 1, + .seq_num = 0, + }}; + fill_connections_command(connection, &msg.payload); + + commands_notify(forwarder, TOPIC_CONNECTION, (uint8_t *)&msg, sizeof(msg)); +} + +void commands_notify_route(const forwarder_t *forwarder, + const fib_entry_t *entry) { + const nexthops_t *nexthops = fib_entry_get_nexthops(entry); + size_t n = nexthops_get_len(nexthops); + msg_route_notify_t *msg = NULL; + msg_malloc_list(msg, OBJECT_TYPE_ROUTE, n, 0); + if (!msg) return; + + fill_route_command(entry, &msg->payload); + + commands_notify(forwarder, TOPIC_ROUTE, (uint8_t *)&msg, sizeof(msg)); +} + +void commands_notify_active_interface_update(const forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, + netdevice_flags_t flags) { + struct { + cmd_header_t header; + hc_active_interface_t payload; + } msg = {.header = + { + .message_type = NOTIFICATION_LIGHT, + .command_id = OBJECT_TYPE_ACTIVE_INTERFACE, + .length = 1, + .seq_num = 0, + }, + .payload = {.prefix = *prefix, .interface_types = flags}}; + + INFO("Notify active interface"); + commands_notify(forwarder, TOPIC_ACTIVE_INTERFACE, (uint8_t *)&msg, + sizeof(msg)); } diff --git a/hicn-light/src/hicn/config/commands.h b/hicn-light/src/hicn/config/commands.h index 3852a76ac..f212c1b0b 100644 --- a/hicn-light/src/hicn/config/commands.h +++ b/hicn-light/src/hicn/config/commands.h @@ -29,11 +29,10 @@ #include "../core/msgbuf.h" #include "../core/strategy.h" #include <hicn/ctrl/api.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> uint8_t *command_process(forwarder_t *forwarder, uint8_t *packet, - command_type_t command_type, unsigned ingress_id, - size_t *reply_size); + unsigned ingress_id, size_t *reply_size); ssize_t command_process_msgbuf(forwarder_t *forwarder, msgbuf_t *msgbuf); @@ -152,4 +151,15 @@ uint8_t *configuration_on_policy_list(forwarder_t *forwarder, uint8_t *packet, uint8_t *configuration_on_stats_list(forwarder_t *forwarder, uint8_t *packet, unsigned ingress_id, size_t *reply_size); +void commands_notify_connection(const forwarder_t *forwarder, + connection_event_t event, + const connection_t *connection); + +void commands_notify_route(const forwarder_t *forwarder, + const fib_entry_t *entry); + +void commands_notify_active_interface_update(const forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, + netdevice_flags_t flags); + #endif // HICNLIGHT_COMMANDS_H diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c index 9123ceebf..f38c4f22f 100644 --- a/hicn-light/src/hicn/config/configuration.c +++ b/hicn-light/src/hicn/config/configuration.c @@ -41,7 +41,8 @@ #include <hicn/core/listener.h> //the listener list #include <hicn/core/listener_table.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> +//#include <hicn/utils/utils.h> #include <hicn/utils/punting.h> #include <hicn/util/log.h> #include <hicn/face.h> @@ -72,6 +73,8 @@ struct configuration_s { int logfile_fd; bool daemon; kh_strategy_map_t *strategy_map; + size_t n_suffixes_per_split; + int_manifest_split_strategy_t split_strategy; }; configuration_t *configuration_create() { @@ -92,6 +95,8 @@ configuration_t *configuration_create() { #endif configuration_set_loglevel(config, loglevel_from_str(DEFAULT_LOGLEVEL)); config->strategy_map = kh_init_strategy_map(); + config->n_suffixes_per_split = DEFAULT_N_SUFFIXES_PER_SPLIT; + config->split_strategy = DEFAULT_DISAGGREGATION_STRATEGY; return config; } @@ -127,6 +132,25 @@ void configuration_set_fn_config(configuration_t *config, config->fn_config = fn_config; } +void configuration_set_suffixes_per_split(configuration_t *config, + size_t n_suffixes_per_split) { + config->n_suffixes_per_split = n_suffixes_per_split; +} + +size_t configuration_get_suffixes_per_split(const configuration_t *config) { + return config->n_suffixes_per_split; +} + +void configuration_set_split_strategy( + configuration_t *config, int_manifest_split_strategy_t split_strategy) { + config->split_strategy = split_strategy; +} + +int_manifest_split_strategy_t configuration_get_split_strategy( + const configuration_t *config) { + return config->split_strategy; +} + void configuration_set_port(configuration_t *config, uint16_t port) { config->port = port; } diff --git a/hicn-light/src/hicn/config/configuration.h b/hicn-light/src/hicn/config/configuration.h index 93b4cf7c3..0d1a2b8e7 100644 --- a/hicn-light/src/hicn/config/configuration.h +++ b/hicn-light/src/hicn/config/configuration.h @@ -30,7 +30,8 @@ #include "../core/msgbuf.h" #include "../core/strategy.h" #include <hicn/ctrl/api.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> +#include <hicn/interest_manifest.h> KHASH_MAP_INIT_STR(strategy_map, unsigned); @@ -103,6 +104,18 @@ const char *configuration_get_fn_config(const configuration_t *config); void configuration_set_fn_config(configuration_t *config, const char *fn_config); +void configuration_set_suffixes_per_split(configuration_t *config, + size_t n_suffixes_per_split); + +size_t configuration_get_suffixes_per_split(const configuration_t *config); + +void configuration_set_split_strategy( + configuration_t *config, + int_manifest_split_strategy_t n_suffixes_per_split); + +int_manifest_split_strategy_t configuration_get_split_strategy( + const configuration_t *config); + void configuration_set_port(configuration_t *config, uint16_t port); uint16_t configuration_get_port(const configuration_t *config); diff --git a/hicn-light/src/hicn/config/configuration_file.c b/hicn-light/src/hicn/config/configuration_file.c index 2e8e7a6ac..8649e0143 100644 --- a/hicn-light/src/hicn/config/configuration_file.c +++ b/hicn-light/src/hicn/config/configuration_file.c @@ -20,11 +20,13 @@ #include <errno.h> #include <stdio.h> #include <string.h> + +#include <hicn/ctrl/hicn-light.h> #include <hicn/config/configuration_file.h> #include <hicn/util/sstrncpy.h> #include "commands.h" -#include "parse.h" +#include <hicn/ctrl/parse.h> #define BUFFERLEN 2048 @@ -62,12 +64,17 @@ bool configuration_file_process(forwarder_t *forwarder, const char *filename) { char buffer[BUFFERLEN]; bool success = true; + +#if 0 // TODO(eloparco): We could use a fake socket since we only need the vft - hc_sock_t *s = hc_sock_create_forwarder(HICNLIGHT_NG); + hc_sock_t *s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL); if (!s) { ERROR("Could not create socket"); goto ERR_SOCK; } +#else + hc_sock_initialize_module(NULL); +#endif while (success && fgets(buffer, BUFFERLEN, f) != NULL) { linesRead++; @@ -83,42 +90,31 @@ bool configuration_file_process(forwarder_t *forwarder, const char *filename) { continue; } - // TODO(eloparco): Handle all commands - hc_result_t *result = NULL; - if (command.action == ACTION_CREATE) { - if (command.object.type == OBJECT_LISTENER) { - result = hc_listener_create_conf(s, &command.object.listener); - } else if (command.object.type == OBJECT_CONNECTION) { - result = hc_connection_create_conf(s, &command.object.connection); - } else if (command.object.type == OBJECT_ROUTE) { - result = hc_route_create_conf(s, &command.object.route); - } else if (command.object.type == OBJECT_LOCAL_PREFIX) { - result = hc_strategy_add_local_prefix_conf(s, &command.object.strategy); - } - } else if (command.action == ACTION_SET) { - if (command.object.type == OBJECT_STRATEGY) { - result = hc_strategy_set_conf(s, &command.object.strategy); - } - } - if (result == NULL) { - ERROR("Command '%s' not supported", cmd); - continue; + /* Serialize request into message */ + // hc_msg_t msg; + uint8_t msg[1024]; + ssize_t msg_len = hc_light_command_serialize( + command.action, command.object_type, &command.object, msg); + switch (msg_len) { + case -1: + case -2: + ERROR("Command '%s' not supported", cmd); + continue; + case -3: + ERROR("Error during command serialization '%s'", cmd); + continue; + default: + break; } size_t _unused; - hc_msg_t *msg = hc_result_get_msg(s, result); - command_type_t cmd_id = hc_result_get_cmd_id(s, result); - bool success = hc_result_get_success(s, result); - if (success == false) { - ERROR("Error serializing command : '%s'", cmd); - continue; - } - - command_process(forwarder, (uint8_t *)msg, cmd_id, CONNECTION_ID_UNDEFINED, + command_process(forwarder, (uint8_t *)msg, CONNECTION_ID_UNDEFINED, &_unused); - hc_result_free(result); } + +#if 0 hc_sock_free(s); +#endif if (ferror(f)) { ERROR("Error on input file %s line %d: (%d) %s", filename, linesRead, errno, @@ -128,8 +124,10 @@ bool configuration_file_process(forwarder_t *forwarder, const char *filename) { fclose(f); return true; +#if 0 ERR_SOCK: hc_sock_free(s); +#endif ERR_READ: fclose(f); ERR_OPEN: diff --git a/hicn-light/src/hicn/config/configuration_file.h b/hicn-light/src/hicn/config/configuration_file.h index 4d9535ab7..03599d4f4 100644 --- a/hicn-light/src/hicn/config/configuration_file.h +++ b/hicn-light/src/hicn/config/configuration_file.h @@ -28,6 +28,7 @@ #define configuration_file_h #include <hicn/core/forwarder.h> +#include <hicn/ctrl/hicn-light.h> /** * Configure hicn-light by reading a configuration file line-by-line and diff --git a/hicn-light/src/hicn/config/parse.h b/hicn-light/src/hicn/config/parse.h deleted file mode 100644 index 06269208a..000000000 --- a/hicn-light/src/hicn/config/parse.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef HICNLIGHT_PARSE_CMD -#define HICNLIGHT_PARSE_CMD - -#include <hicn/ctrl/api.h> - -int parse(const char* cmd, hc_command_t* command); -int help(const char* cmd); - -/** - * @brief Convert the action enum to the action name used in the commands (e.g. - * from ACTION_CREATE to "add"). - */ -const char* action_to_cmd_action(hc_action_t action); - -#endif /* HICNLIGHT_PARSE_CMD */ diff --git a/hicn-light/src/hicn/core/CMakeLists.txt b/hicn-light/src/hicn/core/CMakeLists.txt index 9516a6a72..94295bdf1 100644 --- a/hicn-light/src/hicn/core/CMakeLists.txt +++ b/hicn-light/src/hicn/core/CMakeLists.txt @@ -3,7 +3,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -21,7 +21,6 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.h ${CMAKE_CURRENT_SOURCE_DIR}/fib.h ${CMAKE_CURRENT_SOURCE_DIR}/forwarder.h - ${CMAKE_CURRENT_SOURCE_DIR}/interest_manifest.h ${CMAKE_CURRENT_SOURCE_DIR}/listener.h ${CMAKE_CURRENT_SOURCE_DIR}/listener_table.h ${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.h @@ -34,13 +33,11 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/strategy_vft.h ${CMAKE_CURRENT_SOURCE_DIR}/subscription.h ${CMAKE_CURRENT_SOURCE_DIR}/ticks.h -# ${CMAKE_CURRENT_SOURCE_DIR}/system.h + + # ${CMAKE_CURRENT_SOURCE_DIR}/system.h ${CMAKE_CURRENT_SOURCE_DIR}/mapme.h ${CMAKE_CURRENT_SOURCE_DIR}/wldr.h - ${CMAKE_CURRENT_SOURCE_DIR}/messageHandler.h - ${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.h ${CMAKE_CURRENT_SOURCE_DIR}/nexthops.h - ${CMAKE_CURRENT_SOURCE_DIR}/name.h ) list(APPEND SOURCE_FILES @@ -53,15 +50,12 @@ list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/fib.c ${CMAKE_CURRENT_SOURCE_DIR}/fib_entry.c ${CMAKE_CURRENT_SOURCE_DIR}/forwarder.c - ${CMAKE_CURRENT_SOURCE_DIR}/interest_manifest.c ${CMAKE_CURRENT_SOURCE_DIR}/listener.c ${CMAKE_CURRENT_SOURCE_DIR}/listener_table.c ${CMAKE_CURRENT_SOURCE_DIR}/listener_vft.c ${CMAKE_CURRENT_SOURCE_DIR}/mapme.c ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf.c ${CMAKE_CURRENT_SOURCE_DIR}/msgbuf_pool.c - ${CMAKE_CURRENT_SOURCE_DIR}/nameBitvector.c - ${CMAKE_CURRENT_SOURCE_DIR}/name.c ${CMAKE_CURRENT_SOURCE_DIR}/nexthops.c ${CMAKE_CURRENT_SOURCE_DIR}/packet_cache.c ${CMAKE_CURRENT_SOURCE_DIR}/pit.c diff --git a/hicn-light/src/hicn/core/address.c b/hicn-light/src/hicn/core/address.c index a4b41c8b5..65664fa17 100644 --- a/hicn-light/src/hicn/core/address.c +++ b/hicn-light/src/hicn/core/address.c @@ -21,8 +21,8 @@ #include <hicn/core/address.h> #include <hicn/util/sstrncpy.h> -int address_from_ip_port(address_t *address, int family, ip_address_t *addr, - uint16_t port) { +int address_from_ip_port(address_t *address, int family, + hicn_ip_address_t *addr, uint16_t port) { switch (family) { case AF_INET: *address = ADDRESS4(ntohl(addr->v4.as_inaddr.s_addr), ntohs(port)); diff --git a/hicn-light/src/hicn/core/address.h b/hicn-light/src/hicn/core/address.h index 7958bd063..38cd1e87c 100644 --- a/hicn-light/src/hicn/core/address.h +++ b/hicn-light/src/hicn/core/address.h @@ -63,8 +63,8 @@ static inline bool _address6_is_local(struct sockaddr_in6 *sin6) { ((address)->as_ss.ss_family == AF_INET) ? address4_is_local(address) \ : address6_is_local(address) -int address_from_ip_port(address_t *address, int family, ip_address_t *addr, - uint16_t port); +int address_from_ip_port(address_t *address, int family, + hicn_ip_address_t *addr, uint16_t port); static inline address_t ADDRESS4(in_addr_t in_addr, int port) { address_t address = { diff --git a/hicn-light/src/hicn/core/address_pair.c b/hicn-light/src/hicn/core/address_pair.c index facbb8dc4..c4f8b397b 100644 --- a/hicn-light/src/hicn/core/address_pair.c +++ b/hicn-light/src/hicn/core/address_pair.c @@ -30,8 +30,10 @@ address_pair_t address_pair_factory(address_t local, address_t remote) { } int address_pair_from_ip_port(address_pair_t* pair, int family, - ip_address_t* local_addr, uint16_t local_port, - ip_address_t* remote_addr, uint16_t remote_port) { + hicn_ip_address_t* local_addr, + uint16_t local_port, + hicn_ip_address_t* remote_addr, + uint16_t remote_port) { memset(pair, 0, sizeof(*pair)); if (address_from_ip_port(&pair->local, family, local_addr, local_port) < 0) return -1; diff --git a/hicn-light/src/hicn/core/address_pair.h b/hicn-light/src/hicn/core/address_pair.h index 2fd207d34..b2872ad35 100644 --- a/hicn-light/src/hicn/core/address_pair.h +++ b/hicn-light/src/hicn/core/address_pair.h @@ -40,8 +40,10 @@ typedef struct { address_pair_t address_pair_factory(address_t local, address_t remote); int address_pair_from_ip_port(address_pair_t* pair, int family, - ip_address_t* local_addr, uint16_t local_port, - ip_address_t* remote_addr, uint16_t remote_port); + hicn_ip_address_t* local_addr, + uint16_t local_port, + hicn_ip_address_t* remote_addr, + uint16_t remote_port); static inline int address_pair_equals(const address_pair_t* pair1, const address_pair_t* pair2) { diff --git a/hicn-light/src/hicn/core/connection.c b/hicn-light/src/hicn/core/connection.c index 2108d30af..ff73a9ae8 100644 --- a/hicn-light/src/hicn/core/connection.c +++ b/hicn-light/src/hicn/core/connection.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -22,8 +22,9 @@ #include <hicn/core/forwarder.h> #include <hicn/core/listener.h> -#include <hicn/util/log.h> #include <hicn/core/wldr.h> +#include <hicn/policy.h> +#include <hicn/util/log.h> #include "connection.h" #include "connection_vft.h" @@ -31,7 +32,7 @@ // This is called by configuration connection_t *connection_create(face_type_t type, const char *name, const address_pair_t *pair, - forwarder_t *forwarder) { + const forwarder_t *forwarder) { assert(face_type_is_valid(type)); assert(pair); assert(forwarder); @@ -70,6 +71,38 @@ connection_t *connection_create(face_type_t type, const char *name, return connection_table_at(table, connection_id); } +netdevice_type_t connection_get_netdevice_type(const char *interface_name) { + if (strncmp(interface_name, "lo", 2) == 0) { + return NETDEVICE_TYPE_LOOPBACK; + } + if ((strncmp(interface_name, "eth", 3) == 0) || + (strncmp(interface_name, "en", 2) == 0)) { + /* eth* en* enx* */ + return NETDEVICE_TYPE_WIRED; + } + if (strncmp(interface_name, "wl", 2) == 0) { + /* wlan* wlp* wlx* */ + return NETDEVICE_TYPE_WIFI; + } + if (strncmp(interface_name, "rmnet_ipa", 9) == 0) { + /* Qualcomm IPA driver */ + return NETDEVICE_TYPE_UNDEFINED; + } + if ((strncmp(interface_name, "rmnet", 5) == 0) || + (strncmp(interface_name, "rev_rmnet", 9) == 0) || + (strncmp(interface_name, "ccmni", 5) == 0)) { + /* + * rmnet* (Qualcomm) ccmni* (MediaTek) + */ + return NETDEVICE_TYPE_CELLULAR; + } + /* usb0 might be cellular (eg Zenfone2) */ + /* what about tethering */ + /* tun* dummy* ... */ + /* bnet* pan* hci* for bluetooth */ + return NETDEVICE_TYPE_UNDEFINED; +} + /** * @brief Initializes a connection * @@ -122,6 +155,30 @@ int connection_initialize(connection_t *connection, face_type_t type, .wldr_autostart = true, }; + connection->interface_type = + connection_get_netdevice_type(connection->interface_name); + +#ifdef WITH_POLICY + connection_clear_tags(connection); + switch (connection->interface_type) { +#if 0 + case NETDEVICE_TYPE_LOOPBACK: + connection_add_tag(connection, POLICY_TAG_LOOPBACK); + break; +#endif + case NETDEVICE_TYPE_WIRED: + connection_add_tag(connection, POLICY_TAG_WIRED); + break; + case NETDEVICE_TYPE_WIFI: + connection_add_tag(connection, POLICY_TAG_WIFI); + break; + case NETDEVICE_TYPE_CELLULAR: + connection_add_tag(connection, POLICY_TAG_CELLULAR); + default: + break; + } +#endif + connection->data = malloc(connection_vft[get_protocol(connection->type)]->data_size); if (!connection->data) goto ERR_DATA; @@ -200,8 +257,8 @@ int connection_finalize(connection_t *connection) { return 0; } -int connection_send_packet(const connection_t *connection, - const uint8_t *packet, size_t size) { +bool connection_send_packet(const connection_t *connection, + const uint8_t *packet, size_t size) { assert(connection); assert(face_type_is_valid(connection->type)); assert(packet); @@ -231,10 +288,12 @@ bool connection_send(connection_t *connection, off_t msgbuf_id, bool queue) { const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder); msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); +#if 0 if (connection->wldr) wldr_set_label(connection->wldr, msgbuf); else msgbuf_reset_wldr_label(msgbuf); +#endif return _connection_send(connection, msgbuf, queue); } diff --git a/hicn-light/src/hicn/core/connection.h b/hicn-light/src/hicn/core/connection.h index ac75428dd..b459a6d81 100644 --- a/hicn-light/src/hicn/core/connection.h +++ b/hicn-light/src/hicn/core/connection.h @@ -33,25 +33,30 @@ #define CONNECTION_ID_UNDEFINED ~0 -#ifdef WITH_MAPME +#define foreach_connection_event \ + _(UNDEFINED) \ + _(CREATE) \ + _(DELETE) \ + _(UPDATE) \ + _(SET_UP) \ + _(SET_DOWN) \ + _(PRIORITY_CHANGED) \ + _(TAGS_CHANGED) \ + _(N) + typedef enum { - CONNECTION_EVENT_CREATE, - CONNECTION_EVENT_DELETE, - CONNECTION_EVENT_UPDATE, - CONNECTION_EVENT_SET_UP, - CONNECTION_EVENT_SET_DOWN, - CONNECTION_EVENT_PRIORITY_CHANGED, - CONNECTION_EVENT_TAGS_CHANGED, +#define _(x) CONNECTION_EVENT_##x, + foreach_connection_event +#undef _ } connection_event_t; -#endif /* WITH_MAPME */ - struct wldr_s; typedef struct { unsigned id; char* name; char* interface_name; + netdevice_type_t interface_type; face_type_t type; address_pair_t pair; // bool up; @@ -111,6 +116,7 @@ typedef struct { #define connection_get_admin_state(C) ((C)->admin_state) #define connection_set_admin_state(C, STATE) (C)->admin_state = STATE #define connection_get_interface_name(C) ((C)->interface_name) +#define connection_get_interface_type(C) ((C)->interface_type) #ifdef WITH_POLICY #define connection_get_priority(C) ((C)->priority) @@ -118,7 +124,7 @@ typedef struct { #define connection_get_tags(C) ((C)->tags) #define connection_set_tags(C, TAGS) (C)->tags = TAGS #define connection_has_tag(C, TAG) policy_tags_has(connection_get_tags(C), TAG) -#define connection_add_tag(C, TAG) policy_tags_add(connection_get_tags(X), TAG) +#define connection_add_tag(C, TAG) policy_tags_add(&connection_get_tags(C), TAG) #define connection_remove_tag(C, TAG) \ do { \ policy_tags_t _conn_var(tags); \ @@ -198,7 +204,7 @@ static inline void connection_set_tags(connection_t* connection, connection_t* connection_create(face_type_t type, const char* name, const address_pair_t* pair, - struct forwarder_s* forwarder); + const struct forwarder_s* forwarder); int connection_initialize(connection_t* connection, face_type_t type, const char* name, const char* interface_name, int fd, @@ -207,8 +213,8 @@ int connection_initialize(connection_t* connection, face_type_t type, int connection_finalize(connection_t* connection); -int connection_send_packet(const connection_t* connection, - const uint8_t* packet, size_t size); +bool connection_send_packet(const connection_t* connection, + const uint8_t* packet, size_t size); bool connection_flush(connection_t* connection); diff --git a/hicn-light/src/hicn/core/connection_table.c b/hicn-light/src/hicn/core/connection_table.c index c723073a1..7bc0e2f4c 100644 --- a/hicn-light/src/hicn/core/connection_table.c +++ b/hicn-light/src/hicn/core/connection_table.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -81,6 +81,14 @@ connection_t *connection_table_allocate(const connection_table_t *table, pool_get(table->connections, conn); if (!conn) return NULL; +#ifdef __APPLE__ + // set __uint8_t sin_len to 0 + uint8_t *ptr = (uint8_t *)address_pair_get_local(pair); + *ptr = 0x0; + ptr = (uint8_t *)address_pair_get_remote(pair); + *ptr = 0x0; +#endif /* __APPLE__ */ + off_t id = conn - table->connections; int rc; @@ -106,6 +114,14 @@ void connection_table_deallocate(const connection_table_t *table, const char *name = connection_get_name(conn); const address_pair_t *pair = connection_get_pair(conn); +#ifdef __APPLE__ + // set __uint8_t sin_len to 0 + uint8_t *ptr = (uint8_t *)address_pair_get_local(pair); + *ptr = 0x0; + ptr = (uint8_t *)address_pair_get_remote(pair); + *ptr = 0x0; +#endif /* __APPLE__ */ + // Remove from name hash table khiter_t k = kh_get_ct_name(table->id_by_name, name); assert(k != kh_end(table->id_by_name)); @@ -124,6 +140,14 @@ void connection_table_deallocate(const connection_table_t *table, connection_t *connection_table_get_by_pair(const connection_table_t *table, const address_pair_t *pair) { +#ifdef __APPLE__ + // set __uint8_t sin_len to 0 + uint8_t *ptr = (uint8_t *)address_pair_get_local(pair); + *ptr = 0x0; + ptr = (uint8_t *)address_pair_get_remote(pair); + *ptr = 0x0; +#endif /* __APPLE__ */ + khiter_t k = kh_get_ct_pair(table->id_by_pair, pair); if (k == kh_end(table->id_by_pair)) return NULL; return table->connections + kh_val(table->id_by_pair, k); @@ -196,7 +220,7 @@ int connection_table_get_random_name(const connection_table_t *table, int i, n_attempts = 2 * USHRT_MAX; for (i = 0; i < n_attempts; i++) { int rc = snprintf(name, SYMBOLIC_NAME_LEN, "conn%u", RAND16()); - if (rc >= SYMBOLIC_NAME_LEN) continue; + if (rc < 0 || rc >= SYMBOLIC_NAME_LEN) continue; // Check if generated connection name is a duplicate khiter_t k = kh_get_ct_name(table->id_by_name, name); @@ -209,4 +233,4 @@ int connection_table_get_random_name(const connection_table_t *table, } return 0; -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/core/connection_table.h b/hicn-light/src/hicn/core/connection_table.h index 7d4bad761..566443d93 100644 --- a/hicn-light/src/hicn/core/connection_table.h +++ b/hicn-light/src/hicn/core/connection_table.h @@ -160,11 +160,14 @@ connection_t *_connection_table_get_by_id(connection_table_t *table, off_t id); * @return off_t The index of the specified connection in the connection table. */ #define connection_table_get_connection_id(table, conn) \ - (conn - table->connections) + (unsigned)(conn - table->connections) #define connection_table_foreach(table, conn, BODY) \ pool_foreach(table->connections, (conn), BODY) +#define connection_table_foreach_new(table, CONN, BODY) \ + pool_foreach_typed(table->connections, connection_t *, CONN, BODY) + #define connection_table_enumerate(table, i, conn, BODY) \ pool_enumerate(table->connections, (i), (conn), BODY) diff --git a/hicn-light/src/hicn/core/connection_vft.h b/hicn-light/src/hicn/core/connection_vft.h index 1a6ecbb78..cc736905c 100644 --- a/hicn-light/src/hicn/core/connection_vft.h +++ b/hicn-light/src/hicn/core/connection_vft.h @@ -30,8 +30,8 @@ typedef struct { const address_t* remote, const char* interface_name); bool (*flush)(connection_t* connection); bool (*send)(connection_t* connection, msgbuf_t* msgbuf, bool queue); - int (*send_packet)(const connection_t* connection, const uint8_t* packet, - size_t size); + bool (*send_packet)(const connection_t* connection, const uint8_t* packet, + size_t size); // void (*read_callback)(connection_t * connection, int fd, void * data); size_t data_size; } connection_ops_t; diff --git a/hicn-light/src/hicn/core/fib.c b/hicn-light/src/hicn/core/fib.c index d8d3c7cfa..64dd3fe7d 100644 --- a/hicn-light/src/hicn/core/fib.c +++ b/hicn-light/src/hicn/core/fib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,20 +19,21 @@ #include <hicn/core/fib.h> typedef struct fib_node_s { - struct fib_node_s *left; - struct fib_node_s *right; + struct fib_node_s *child[2]; /* 0: left, 1: right */ fib_entry_t *entry; bool is_used; } fib_node_t; +#define ZERO 0 +#define ONE 1 + static fib_node_t *fib_node_create(fib_node_t *left, fib_node_t *right, fib_entry_t *entry, bool is_used) { fib_node_t *node = malloc(sizeof(fib_node_t)); if (!node) return NULL; *node = (fib_node_t){ - .left = left, - .right = right, + .child = {left, right}, .entry = entry, .is_used = is_used, }; @@ -43,8 +44,8 @@ static fib_node_t *fib_node_create(fib_node_t *left, fib_node_t *right, static void fib_node_free(fib_node_t *node) { if (!node) return; - fib_node_free(node->right); - fib_node_free(node->left); + fib_node_free(node->child[ZERO]); + fib_node_free(node->child[ONE]); fib_entry_free(node->entry); free(node); @@ -82,293 +83,387 @@ size_t fib_get_size(const fib_t *fib) { return fib->size; } -#define FIB_SET(CURR, NEW_PREFIX, CURR_PREFIX_LEN) \ - do { \ - bool bit; \ - int res = nameBitvector_testBit(NEW_PREFIX, CURR_PREFIX_LEN, &bit); \ - assert(res >= 0); \ - (void)res; /* unused */ \ - CURR = bit ? CURR->right : CURR->left; \ - } while (0) - -#define FIB_INSERT(DST, SRC, PREFIX, PREFIX_LEN) \ - do { \ - bool bit; \ - int res = nameBitvector_testBit(PREFIX, PREFIX_LEN, &bit); \ - assert(res >= 0); \ - (void)res; /* unused */ \ - if (bit) \ - DST->right = SRC; \ - else \ - DST->left = SRC; \ - } while (0) - -void fib_add(fib_t *fib, fib_entry_t *entry) { - assert(fib); - assert(entry); +/* + * This struct will hold various information related to the returned node such + * as its parent and grandparent if any, as well as some already computed + * information about the prefix. + */ +typedef struct { + /* Result node ancestors (NULL if not applicable) */ + fib_node_t *parent; + fib_node_t *gparent; + /* Information related to the result node */ + hicn_prefix_t *prefix; + uint32_t prefix_len; + uint32_t match_len; +} fib_search_t; +/* + * @brief Search for longest subprefix (helper function) + * @param [in] fib - Pointer to the FIB to search + * @param [in] prefix - The prefix used for search + * @param [out] search - A pointer to a structure that will hold related search + * information, that can be NULL if this is not needed. + * + * @returns The node whose entry corresponds to the longest subprefix of the + * prefix passed in parameter, or NULL if not found. The longest prefix match is + * thus the resulting node if curr_len == prefix_len, and its parent + * otherwise. + * + * Implementation details: + * + * This function performs a descent in the tree, following branches + * corresponding to the value of the next bit, until reaching past a leaf, or + * either the current node prefix: + * when one of the two following conditions is met: + * - is not a prefix of the searched one (match_len < curr_len), or + * - is longer or equal than the inserted one (curr_len >= prefix_len) + */ +fib_node_t *fib_search(const fib_t *fib, const hicn_prefix_t *prefix, + fib_search_t *search) { + uint32_t prefix_len = hicn_prefix_get_len(prefix); + uint32_t curr_len; + uint32_t match_len; - NameBitvector *new_prefix = name_GetContentName(fib_entry_get_prefix(entry)); - uint32_t new_prefix_len = nameBitvector_GetLength(new_prefix); + fib_node_t *parent = NULL; + fib_node_t *gparent = NULL; fib_node_t *curr = fib->root; - fib_node_t *last = NULL; + while (curr) { + const hicn_prefix_t *curr_prefix = fib_entry_get_prefix(curr->entry); + curr_len = hicn_prefix_get_len(curr_prefix); + match_len = hicn_prefix_lpm(prefix, curr_prefix); + + // XXX >= vs == for the second stop condition + // curr_len >= prefix_len l >= L + // L is a prefix of l + // > means we did not find + // = means we could have found + // leverage this info for contains! + // XXX remove this comment when done + if (match_len < curr_len || curr_len >= prefix_len) break; + + gparent = parent; + parent = curr; - NameBitvector *curr_name; - uint32_t curr_prefix_len; - uint32_t match_len; + /* The following lookup won't fail since curr_len < prefix_len */ + uint8_t next_bit = hicn_prefix_get_bit(prefix, curr_len); + curr = curr->child[next_bit]; + } - while (curr) { - curr_name = name_GetContentName(fib_entry_get_prefix(curr->entry)); + if (search) { + search->parent = parent; + search->gparent = gparent; + if (curr) { + search->prefix_len = curr_len; + search->match_len = match_len; + } + } + return curr; +} - match_len = nameBitvector_lpm(new_prefix, curr_name); - curr_prefix_len = nameBitvector_GetLength(curr_name); +/* + * Helper: insert a new node between parent and child. + * + * parent == NULL means we set the root of the FIB + * child == NULL means our node has no child + */ +fib_node_t *_fib_insert(fib_t *fib, fib_entry_t *entry, fib_node_t *parent, + fib_node_t *child, bool is_used) { + fib_node_t *new_node = fib_node_create(NULL, NULL, entry, is_used); + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); - if (curr_prefix_len != - match_len || // the new entry does not match the curr - curr_prefix_len >= - new_prefix_len) // in this case we cannot procede anymore - break; + if (!parent) { + fib->root = new_node; + } else { + const hicn_prefix_t *parent_prefix = fib_entry_get_prefix(parent->entry); + uint32_t parent_prefix_len = hicn_prefix_get_len(parent_prefix); + uint8_t next_bit = hicn_prefix_get_bit(prefix, parent_prefix_len); + parent->child[next_bit] = new_node; + } - last = curr; - FIB_SET(curr, new_prefix, curr_prefix_len); + if (child) { + const hicn_prefix_t *curr_prefix = fib_entry_get_prefix(entry); + uint32_t match_len = hicn_prefix_lpm(prefix, curr_prefix); + uint8_t next_bit = hicn_prefix_get_bit(curr_prefix, match_len); + new_node->child[next_bit] = child; } - // this is the root (empty trie) or an empty child - if (!curr) { - fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true); - if (!last) { - fib->root = new_node; - } else { - uint32_t last_prefix_len = nameBitvector_GetLength( - name_GetContentName(fib_entry_get_prefix(last->entry))); + if (is_used) fib->size++; + return new_node; +} - FIB_INSERT(last, new_node, new_prefix, last_prefix_len); - } - fib->size++; - return; +/* + * Helper: remove a node from parent + */ +void _fib_remove(fib_t *fib, fib_node_t *curr, fib_node_t *parent) { + /* + * If we remove the node, curr has either 0 or 1 child. In the latter case, + * we attach it to parent + */ + fib_node_t *child = curr->child[ZERO] ? curr->child[ZERO] : curr->child[ONE]; + if (!parent) { + fib->root = child; + } else { + if (parent->child[ZERO] == curr) + parent->child[ZERO] = child; + else + parent->child[ONE] = child; } + if (curr->is_used) fib->size--; + fib_node_free(curr); +} + +/* + * - Stop condition: curr == NULL. This corresponds to: + * + * (CASE 1) Our parent is a strict prefix and we simply have to create a new + * leaf child in the correct branch based on the next bit following the parent + * prefix. + * + * Otherwise, our parent node exist. Based on the stop condition, we + * either have: + * + * - Stop condition 1 : curr_len == match_len AND curr_len >= + * prefix_len l == m && l >= L + * + * 2 sub-cases: + * - l = m > L : IMPOSSIBLE L < m since m = LPM(l, L) means L >= m + * - l = m = L : insert the current node, either it exists or not + * + * We thus have: + * + * (CASE 2) The node already exist. If is not in use we turn it on and we set + * the right fib entry. + * + * The case when it is used should never occur because of the way we add + * entries in the FIB... but let's add the nexthops we wish to insert into + * the existing FIB entry. + * + * - Stop condition 2: curr_len != match_len + * l != m => l > m + * + * We have two possibilities: + * - Only one is bigger than m (case 3) + * - They are both bigger than m (case 4) + * + * (CASE 3) Only one is bigger than m + * L == m => L < l (since l != m and l >= m) + * l > L = m + * + * This means L is a prefix of l. + * l' + * / + * L + * / + * l + * + * (CASE 4) They are both bigger than m + * - l > L > m + * - L > l > m + * - L = l > m + * + * Both share L and l share l' as a common prefix, and this is not l' since + * they share the name next bit. + * + * So this case is impossible and we would have taken the other branch during + * the descent: + * + * l' + * / \ + * l L + * + * We are in a situation where e need to insert an internal node: + * + * l' + * | + * X <------ internal node + * / \ + * l L + */ +void fib_add(fib_t *fib, fib_entry_t *entry) { + assert(fib); + assert(entry); + + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + uint32_t prefix_len = hicn_prefix_get_len(prefix); + + fib_search_t search; + fib_node_t *curr = fib_search(fib, prefix, &search); - // curr is not null + /* Case 1 */ + if (!curr) { + _fib_insert(fib, entry, search.parent, NULL, true); + return; + } - // the node already exist - // if is not in use we turn it on and we set the rigth fib entry - if (curr_prefix_len == match_len && new_prefix_len == match_len) { + /* Case 2 */ + if (search.prefix_len == search.match_len && prefix_len == search.match_len) { if (!curr->is_used) { curr->is_used = true; + if (curr->entry) fib_entry_free(curr->entry); curr->entry = entry; fib->size++; - return; } else { - // this case should never happen beacuse of the way we add - // entries in the fib const nexthops_t *nexthops = fib_entry_get_nexthops(entry); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { fib_entry_nexthops_add(curr->entry, nexthop); }); + fib_entry_free(entry); } + return; } - // key is prefix of the curr node (so new_prefix_len < curr_prefix_len) - if (new_prefix_len == match_len) { - fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true); - if (!last) { - fib->root = new_node; - } else { - uint32_t last_prefix_len = nameBitvector_GetLength( - name_GetContentName(fib_entry_get_prefix(last->entry))); - FIB_INSERT(last, new_node, new_prefix, last_prefix_len); - } - FIB_INSERT(new_node, curr, curr_name, match_len); - fib->size++; + /* Case 3 */ + if (prefix_len == search.match_len) { + _fib_insert(fib, entry, search.parent, curr, true); return; } - // in the last case we need to add an inner node - Name inner_prefix = EMPTY_NAME; - name_Copy(fib_entry_get_prefix(entry), &inner_prefix); - nameBitvector_clear(name_GetContentName(&inner_prefix), match_len); - name_setLen(&inner_prefix, match_len); - - // this is an inner node, we don't want an acctive strategy - // like low_latency that sends probes in this node + /* Case 4 */ + hicn_prefix_t inner_prefix; /* dup'ed in fib_entry_create */ + hicn_prefix_copy(&inner_prefix, prefix); + hicn_prefix_truncate(&inner_prefix, search.match_len); fib_entry_t *inner_entry = fib_entry_create( &inner_prefix, STRATEGY_TYPE_UNDEFINED, NULL, fib->forwarder); - - fib_node_t *inner_node = fib_node_create(NULL, NULL, inner_entry, false); - fib_node_t *new_node = fib_node_create(NULL, NULL, entry, true); - - if (!last) { - // we need to place the inner_node at the root - fib->root = inner_node; - } else { - uint32_t last_prefix_len = nameBitvector_GetLength( - name_GetContentName(fib_entry_get_prefix(last->entry))); - NameBitvector *inner_name = name_GetContentName(&inner_prefix); - FIB_INSERT(last, inner_node, inner_name, last_prefix_len); - } - - bool bit; - int res = nameBitvector_testBit(new_prefix, match_len, &bit); - assert(res >= 0); - (void)res; /* unused */ - inner_node->left = bit ? curr : new_node; - inner_node->right = bit ? new_node : curr; - fib->size++; + fib_node_t *new_node = + _fib_insert(fib, inner_entry, search.parent, curr, false); + _fib_insert(fib, entry, new_node, NULL, true); } -fib_entry_t *fib_contains(const fib_t *fib, const Name *prefix) { +/* + * Implementation details: + * + * To find whether the fib contains a prefix, we issue a search, and based on + * the stopping conditions, we return the entry if and only if curr + * is not NULL, and prefix_len == curr_len (== match_len) + */ +fib_entry_t *fib_contains(const fib_t *fib, const hicn_prefix_t *prefix) { assert(fib); assert(prefix); - NameBitvector *key_name = name_GetContentName(prefix); - uint32_t key_prefix_len = nameBitvector_GetLength(key_name); + uint32_t prefix_len = hicn_prefix_get_len(prefix); - fib_node_t *curr = fib->root; + fib_search_t search; + fib_node_t *curr = fib_search(fib, prefix, &search); - while (curr) { - NameBitvector *curr_name = - name_GetContentName(fib_entry_get_prefix(curr->entry)); - uint32_t match_len = nameBitvector_lpm(key_name, curr_name); - uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name); - - if (match_len < curr_prefix_len) { - // the current node does not match completelly the key, so - // the key is not in the trie - // this implies curr_prefix_len > key_prefix_len - return NULL; - } - - if (curr_prefix_len == key_prefix_len) { //== match_len - // this is an exact match - if (!curr->is_used) { - // the key does not exists - return NULL; - } - // we found the key - return curr->entry; - } - - FIB_SET(curr, key_name, curr_prefix_len); - } - - return NULL; + if (!curr) return NULL; + if (search.prefix_len != prefix_len) return NULL; + return curr->is_used ? curr->entry : NULL; } -static void fib_node_remove(fib_t *fib, const Name *prefix) { +/* + * @brief Remove a prefix (and the associated node) from FIB + * + * We search for + * + * Actions depend on N, the number of children of the node to remove + * Examples are build using 'left' children only, but the cases with 'right' + * children are symmetrical. + * + * Legend: + * (empty) : no children + * * : 0 or more children + * + : at least one children + * + * N == 2 - Mark the node as unused + * + * parent parent + * / \ / \ + * curr ... ==> (curr) ... + * / \ / \ + * L R L R + * + * N == 1 - Attach the child to the parent node (whether parent is used or not) + * + * a) curr has no parent (curr is the root) + * + * curr + + * / ==> + * + + * + * b) curr has a parent + * parent parent + * / \ / \ + * curr * ==> L * + * / \ + * L + * + * (parent) (parent) + * / \ / \ + * curr + ==> L + + * / \ + * L + * + * N == 0 + * + * a) curr has no parent (curr is the root) + * + * curr + * / \ ==> + * + * b) parent is unused. + * + * Assuming curr is the left child, then parent must have a + * right child, and the grand-parent must be used. + * + * gp gp gp + * / / / + * (parent) ==> (parent) ==> + + * / \ / \ + * curr + + + * / \ + * + * c) parent is used. + * + * Assuming curr is the left child, we simply remove it from + * parent, leaving parent unchanged whether it has a right child or not. + * + * parent parent + * / \ / \ + * curr * ==> * + * / \ + * + * + */ +static void fib_node_remove(fib_t *fib, const hicn_prefix_t *prefix) { assert(fib); assert(prefix); - NameBitvector *key_name = name_GetContentName(prefix); - uint32_t key_prefix_len = nameBitvector_GetLength(key_name); + uint32_t prefix_len = hicn_prefix_get_len(prefix); - fib_node_t *curr = fib->root; - fib_node_t *parent = NULL; - fib_node_t *grandpa = NULL; + fib_search_t search; + fib_node_t *curr = fib_search(fib, prefix, &search); - uint32_t match_len; - uint32_t curr_prefix_len; + /* + * If we reach a NULL, unused node, or a node not matching, that means the + * node does not exist + */ + if (!curr || !curr->is_used || (search.prefix_len != prefix_len)) return; - while (curr) { - NameBitvector *curr_name = - name_GetContentName(fib_entry_get_prefix(curr->entry)); - match_len = nameBitvector_lpm(key_name, curr_name); - curr_prefix_len = nameBitvector_GetLength(curr_name); + uint8_t N = 0; + if (curr->child[ZERO]) N++; + if (curr->child[ONE]) N++; - if (match_len < curr_prefix_len || curr_prefix_len == key_prefix_len) { + switch (N) { + case 2: + curr->is_used = false; break; - } - - grandpa = parent; - parent = curr; - FIB_SET(curr, key_name, curr_prefix_len); - } - - if (!curr || !curr->is_used || (curr_prefix_len != key_prefix_len)) { - // the node does not exists - return; - } - - // curr has 2 children, leave it there and mark it as inner - if (curr->right && curr->left) { - curr->is_used = false; - fib->size--; - return; - } - - // curr has no children - if (!curr->right && !curr->left) { - if (!parent) { - // curr is the root and is the only node in the fib - fib->root = NULL; - fib->size--; - fib_node_free(curr); - return; - } - if (!grandpa) { - // parent is the root - if (fib->root->left == curr) - fib->root->left = NULL; - else - fib->root->right = NULL; - fib->size--; - fib_node_free(curr); - return; - } - if (!parent->is_used) { - // parent is an inner node - // remove curr and inner_node (parent), connect the other child - // of the parent to the grandpa - fib_node_t *tmp = (parent->right == curr) ? parent->left : parent->right; - - if (grandpa->right == parent) - grandpa->right = tmp; - else - grandpa->left = tmp; - - fib->size--; - fib_node_free(curr); - fib_node_free(parent); - return; - } - // parent is node not an inner_node - // just remove curr the node - if (parent->right == curr) - parent->right = NULL; - else - parent->left = NULL; - fib->size--; - fib_node_free(curr); - return; - } - - // curr has one child - if (curr->right || curr->left) { - if (!parent) { - // curr is the root - fib->root = fib->root->right ? fib->root->right : fib->root->left; - fib->size--; - fib_node_free(curr); - return; - } - // attach the child of curr to parent - fib_node_t *tmp = curr->right ? curr->right : curr->left; - - if (parent->right == curr) - parent->right = tmp; - else - parent->left = tmp; + case 1: + _fib_remove(fib, curr, search.parent); + break; - fib->size--; - fib_node_free(curr); - return; + case 0: + _fib_remove(fib, curr, search.parent); + if (!search.parent->is_used) + _fib_remove(fib, search.parent, search.gparent); + break; } } -void fib_remove(fib_t *fib, const Name *name, unsigned conn_id) { +void fib_remove(fib_t *fib, const hicn_prefix_t *prefix, unsigned conn_id) { assert(fib); - assert(name); + assert(prefix); - fib_entry_t *entry = fib_contains(fib, name); + fib_entry_t *entry = fib_contains(fib, prefix); if (!entry) return; fib_entry_nexthops_remove(entry, conn_id); @@ -382,16 +477,24 @@ static size_t fib_node_remove_connection_id(fib_node_t *node, unsigned conn_id, if (!node) return pos; if (node->is_used) { fib_entry_nexthops_remove(node->entry, conn_id); + + /* When using MAP-Me, we keep empty FIB entries */ #ifndef WITH_MAPME if (fib_entry_nexthops_len(node->entry) == 0) array[pos++] = node->entry; #endif /* WITH_MAPME */ } - pos = fib_node_remove_connection_id(node->right, conn_id, array, pos); - pos = fib_node_remove_connection_id(node->left, conn_id, array, pos); + pos = fib_node_remove_connection_id(node->child[ONE], conn_id, array, pos); + pos = fib_node_remove_connection_id(node->child[ZERO], conn_id, array, pos); return pos; } -void fib_remove_connection_id(fib_t *fib, unsigned conn_id) { +void fib_remove_entry(fib_t *fib, fib_entry_t *entry) { + fib_node_remove(fib, fib_entry_get_prefix(entry)); +} + +void fib_remove_connection(fib_t *fib, unsigned conn_id, + fib_entry_t ***removed_entries, + size_t *num_removed_entries) { assert(fib); fib_entry_t **array = malloc(sizeof(fib_entry_t *) * fib->size); @@ -399,61 +502,64 @@ void fib_remove_connection_id(fib_t *fib, unsigned conn_id) { size_t pos = 0; pos = fib_node_remove_connection_id(fib->root, conn_id, array, pos); - for (int i = 0; i < pos; i++) - fib_node_remove(fib, fib_entry_get_prefix(array[i])); - free(array); -} + if (removed_entries) { + /* + * The caller is taking charge of releasing entries (as well as the returned + * array + */ + assert(num_removed_entries); -fib_entry_t *fib_match_message(const fib_t *fib, - const msgbuf_t *interest_msgbuf) { - assert(fib); - assert(interest_msgbuf); + *removed_entries = array; + *num_removed_entries = pos; - return fib_match_bitvector( - fib, name_GetContentName(msgbuf_get_name(interest_msgbuf))); + } else { + for (int i = 0; i < pos; i++) + fib_node_remove(fib, fib_entry_get_prefix(array[i])); + } + free(array); } -fib_entry_t *fib_match_name(const fib_t *fib, const Name *name) { +fib_entry_t *fib_match_msgbuf(const fib_t *fib, const msgbuf_t *msgbuf) { assert(fib); - assert(name); + assert(msgbuf); - return fib_match_bitvector(fib, name_GetContentName(name)); + return fib_match_name(fib, msgbuf_get_name(msgbuf)); } -fib_entry_t *fib_match_bitvector(const fib_t *fib, const NameBitvector *name) { +/* + * Implementation details: + * + * fib_search returns the longest non-strict subprefix. + * - curr == NULL means no such prefix exist and we can return the parent. + * - if we have an exact match (curr_len == key_prefix_len), then we + * return curr unless is_used is false, in which case we return the parent. + * - otherwise, the parent is the longest prefix match + */ +fib_entry_t *fib_match_prefix(const fib_t *fib, const hicn_prefix_t *prefix) { assert(fib); - assert(name); - - uint32_t key_prefix_len = nameBitvector_GetLength(name); + assert(prefix); - fib_node_t *curr = fib->root; - fib_node_t *candidate = NULL; + uint32_t prefix_len = hicn_prefix_get_len(prefix); - while (curr) { - NameBitvector *curr_name = - name_GetContentName(fib_entry_get_prefix(curr->entry)); - uint32_t match_len = nameBitvector_lpm(name, curr_name); - uint32_t curr_prefix_len = nameBitvector_GetLength(curr_name); - - if (match_len < curr_prefix_len) { - // the current node does not match completelly the key, so - // return the parent of this node (saved in candidate) - break; - } - - if (curr->is_used) candidate = curr; + fib_search_t search; + fib_node_t *curr = fib_search(fib, prefix, &search); - // if we are here match_len == curr_prefix_len (can't be larger) - // so this node is actually a good candidate for a match - if (curr_prefix_len == key_prefix_len) { - // this an exact match, do not continue - break; - } - - FIB_SET(curr, name, curr_prefix_len); + if (!curr) { + /* This can happen with an empty FIB for instance */ + if (!search.parent) return NULL; + return search.parent->entry; } + if ((search.prefix_len <= prefix_len) && curr->is_used) return curr->entry; + if (search.parent) return search.parent->entry; + return NULL; +} - return candidate ? candidate->entry : NULL; +fib_entry_t *fib_match_name(const fib_t *fib, const hicn_name_t *name) { + hicn_prefix_t prefix; + const hicn_name_prefix_t *name_prefix = hicn_name_get_prefix(name); + prefix.name = *name_prefix; + prefix.len = hicn_name_prefix_get_len_bits(name_prefix); + return fib_match_prefix(fib, &prefix); } static size_t fib_node_collect_entries(fib_node_t *node, fib_entry_t **array, @@ -464,8 +570,8 @@ static size_t fib_node_collect_entries(fib_node_t *node, fib_entry_t **array, if (node->is_used) array[pos++] = node->entry; - pos = fib_node_collect_entries(node->right, array, pos); - pos = fib_node_collect_entries(node->left, array, pos); + pos = fib_node_collect_entries(node->child[ONE], array, pos); + pos = fib_node_collect_entries(node->child[ZERO], array, pos); return pos; } @@ -476,3 +582,123 @@ size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p) { pos = fib_node_collect_entries(fib->root, *array_p, pos); return pos; } + +bool _fib_is_valid(const fib_node_t *node) { + if (!node) return true; + + const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry); + uint32_t prefix_len = hicn_prefix_get_len(prefix); + + for (unsigned i = 0; i < 2; i++) { + const fib_node_t *child = node->child[i]; + if (!child) continue; + const hicn_prefix_t *child_prefix = fib_entry_get_prefix(child->entry); + + uint32_t match_len = hicn_prefix_lpm(prefix, child_prefix); + if (match_len != prefix_len) return false; + if (!node->is_used && !child->is_used) return false; + if (hicn_prefix_get_bit(child_prefix, match_len) != i) return false; + if (!_fib_is_valid(child)) return false; + } + return true; +} + +/* + * @brief Check that the structure of the FIB is correct : prefixes are + * correctly nested, 0 are on the left, 1 on the right, and that we have no + * more than 1 unused prefix as parents. + */ +bool fib_is_valid(const fib_t *fib) { return _fib_is_valid(fib->root); } + +/* + * Checks whether the preorder traversal of the sub-tree corresponds to the + * prefix and used arrays, starting from pos (helper) + */ +bool __fib_check_preorder(const fib_node_t *node, + const hicn_prefix_t **prefix_array, bool *used_array, + size_t size, size_t *pos) { + /* Check left subtree... */ + fib_node_t *left = node->child[ZERO]; + if (left && !__fib_check_preorder(left, prefix_array, used_array, size, pos)) + return false; + + /* ... then current node ... */ + if (*pos > size) { + ERROR("size error"); + return false; + } + + const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry); + + if (!hicn_prefix_equals(prefix, prefix_array[*pos])) { + char buf[MAXSZ_HICN_PREFIX]; + int rc; + + ERROR("Prefix mismatch in position %d %s != %s", pos); + rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)"); + ERROR("Expected: %s", buf); + + rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix_array[*pos]); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)"); + ERROR("Expected: %s", buf); + return false; + } + + (*pos)++; + + /* ... then right subtree */ + fib_node_t *right = node->child[ONE]; + if (right && + !__fib_check_preorder(right, prefix_array, used_array, size, pos)) + return false; + + return true; +} + +/* + * Checks whether the preorder traversal of the trie + * corresponds to the prefix and used arrays. + */ +bool _fib_check_preorder(const fib_t *fib, const hicn_prefix_t **prefix_array, + bool *used_array, size_t size) { + if (!fib->root) return true; + size_t pos = 0; + if (!__fib_check_preorder(fib->root, prefix_array, used_array, size, &pos)) + return false; + /* We need to check that we don't miss elements */ + return pos == size; +} + +// XXX print empty node but not recurse +void _fib_dump(const fib_node_t *node, int start, int indent) { + char buf[MAXSZ_HICN_PREFIX]; + + if (node) { + const hicn_prefix_t *prefix = fib_entry_get_prefix(node->entry); + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "%s %d", "(error)", rc); + } else { + snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(null)"); + } + + // Left + if (indent > 0) { + for (int i = 0; i < start - 1; i++) printf(" "); + for (int i = start + 1; i < indent; i++) printf("| "); + printf("|"); + printf("_ %s\n", buf); + } else { + printf("%s\n", buf); + } + + if (!node) return; + + _fib_dump(node->child[ZERO], start, indent + 1); + _fib_dump(node->child[ONE], start + 1, indent + 1); +} + +void fib_dump(const fib_t *fib) { _fib_dump(fib->root, 0, 0); } diff --git a/hicn-light/src/hicn/core/fib.h b/hicn-light/src/hicn/core/fib.h index c0fda960b..501935b0b 100644 --- a/hicn-light/src/hicn/core/fib.h +++ b/hicn-light/src/hicn/core/fib.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,7 +18,7 @@ #include "fib_entry.h" #include "msgbuf.h" -#include "name.h" +#include <hicn/name.h> #define _fib_var(x) _fib_##x @@ -32,24 +32,39 @@ size_t fib_get_size(const fib_t *fib); void fib_add(fib_t *fib, fib_entry_t *node); -fib_entry_t *fib_contains(const fib_t *fib, const Name *prefix); +fib_entry_t *fib_contains(const fib_t *fib, const hicn_prefix_t *prefix); -void fib_remove(fib_t *fib, const Name *prefix, unsigned conn_id); +void fib_remove(fib_t *fib, const hicn_prefix_t *prefix, unsigned conn_id); -void fib_remove_connection_id(fib_t *fib, unsigned conn_id); +void fib_remove_entry_connection(fib_t *fib, fib_entry_t *entry, + unsigned conn_id, fib_entry_t **removed_entry); -fib_entry_t *fib_match_message(const fib_t *fib, - const msgbuf_t *interest_msgbuf); -fib_entry_t *fib_match_name(const fib_t *fib, const Name *name); -fib_entry_t *fib_match_bitvector(const fib_t *fib, const NameBitvector *name); +void fib_remove_name_connection(fib_t *fib, const hicn_prefix_t *prefix, + unsigned conn_id); + +void fib_remove_entry(fib_t *fib, fib_entry_t *entry); + +void fib_remove_connection(fib_t *fib, unsigned conn_id, + fib_entry_t ***removed_entries, + size_t *num_removed_entries); + +fib_entry_t *fib_match_msgbuf(const fib_t *fib, const msgbuf_t *msgbuf); + +fib_entry_t *fib_match_prefix(const fib_t *fib, const hicn_prefix_t *prefix); + +fib_entry_t *fib_match_name(const fib_t *fib, const hicn_name_t *name); size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p); +/* + * NOTE : do not use return on the loop body to avoid leaking memory + */ #define fib_foreach_entry(FIB, ENTRY, BODY) \ do { \ fib_entry_t **_fib_var(array); \ size_t _fib_var(n) = fib_get_entry_array((FIB), &_fib_var(array)); \ size_t _fib_var(i); \ + fib_entry_t *ENTRY; \ for (_fib_var(i) = 0; _fib_var(i) < _fib_var(n); _fib_var(i)++) { \ ENTRY = _fib_var(array)[_fib_var(i)]; \ do { \ @@ -59,4 +74,13 @@ size_t fib_get_entry_array(const fib_t *fib, fib_entry_t ***array_p); free(_fib_var(array)); \ } while (0) +bool fib_is_valid(const fib_t *fib); +bool _fib_check_preorder(const fib_t *fib, const hicn_prefix_t **prefix_array, + bool *used_array, size_t size); + +#define fib_check_preorder(F, PA, UA) \ + _fib_check_preorder(F, PA, UA, sizeof(PA) / sizeof(hicn_prefix_t *)) + +void fib_dump(const fib_t *fib); + #endif /* HICNLIGHT_FIB_H */ diff --git a/hicn-light/src/hicn/core/fib_entry.c b/hicn-light/src/hicn/core/fib_entry.c index 80d337884..b588e3638 100644 --- a/hicn-light/src/hicn/core/fib_entry.c +++ b/hicn-light/src/hicn/core/fib_entry.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,7 +18,6 @@ #include <hicn/hicn-light/config.h> #include <hicn/core/fib_entry.h> #include <hicn/core/strategy.h> -#include <hicn/core/nameBitvector.h> #ifdef WITH_MAPME #include <hicn/core/ticks.h> @@ -38,17 +37,22 @@ #include <hicn/core/policy_stats.h> #endif /* WITH_POLICY_STATS */ -fib_entry_t *fib_entry_create(Name *name, strategy_type_t strategy_type, +fib_entry_t *fib_entry_create(const hicn_prefix_t *prefix, + strategy_type_t strategy_type, strategy_options_t *strategy_options, const forwarder_t *forwarder) { - assert(name); - assert(forwarder); + assert(prefix); + /* + * For tests, we allow forwarder to be NULL, some + * functions cannot be called but otherwise we need a main loop, etc. + */ + // assert(forwarder); fib_entry_t *entry = malloc(sizeof(fib_entry_t)); if (!entry) goto ERR_MALLOC; memset(entry, 0, sizeof(*entry)); - name_Copy(name, &entry->name); + hicn_prefix_copy(&entry->prefix, prefix); entry->nexthops = NEXTHOPS_EMPTY; fib_entry_add_strategy_options(entry, STRATEGY_TYPE_BESTPATH, NULL); @@ -148,8 +152,10 @@ void fib_entry_set_strategy(fib_entry_t *entry, strategy_type_t strategy_type, strategy_initialize(&entry->strategy, entry->forwarder); } -#ifdef WITH_POLICY - +/* + * Filters the set of nexthops passed as parameters (and not the one stored in + * the FIB entry + */ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, unsigned ingress_id, bool prefer_local) { assert(entry); @@ -165,7 +171,6 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, const connection_table_t *table = forwarder_get_connection_table(entry->forwarder); connection_t *conn; - unsigned nexthop, i; uint_fast32_t flags; hicn_policy_t policy = fib_entry_get_policy(entry); @@ -205,6 +210,7 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, conn = connection_table_at(table, nexthop); nexthops_disable_if(nexthops, i, (connection_is_local(conn))); +#ifdef WITH_POLICY /* Policy filtering : next hops */ nexthops_disable_if( nexthops, i, @@ -238,6 +244,7 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, nexthops, i, (policy.tags[POLICY_TAG_TRUSTED].state == POLICY_STATE_PROHIBIT) && (connection_has_tag(conn, POLICY_TAG_TRUSTED))); +#endif /* WITH_POLICY */ }); if (nexthops_get_curlen(nexthops) == 0) { @@ -248,6 +255,7 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, /* We have at least one matching next hop, implement heuristic */ +#ifdef WITH_POLICY /* * As VPN connections might trigger duplicate uses of one interface, we start * by filtering out interfaces based on trust status. @@ -329,6 +337,8 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, }); if (nexthops_get_curlen(nexthops) == 0) nexthops->flags = flags; } +// XXX backup curlen ??? +#endif /* WITH_POLICY */ DEBUG("[fib_entry_filter_nexthops] before face priority num=%d/%d", nexthops_get_curlen(nexthops), nexthops_get_len(nexthops)); @@ -349,10 +359,63 @@ nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, DEBUG("[fib_entry_filter_nexthops] result num=%d/%d", nexthops_get_curlen(nexthops), nexthops_get_len(nexthops)); + /* Nexthop priority */ + + /* + * Filter out nexthops with lowest strategy priority. + * Initializing at 0 allows to disable nexthops with a negative priority + */ + max_priority = 0; + nexthops_enumerate(nexthops, i, nexthop, { + (void)nexthop; + int priority = nexthops->state[i].priority; + if (priority > max_priority) max_priority = priority; + }); + nexthops_enumerate(nexthops, i, nexthop, { + int priority = nexthops->state[i].priority; + nexthops_disable_if(nexthops, i, (priority < max_priority)); + }); + + /* + * If multipath is disabled, we don't offer much choice to the forwarding + * strategy, but still go through it for accounting purposes. + */ + if ((policy.tags[POLICY_TAG_MULTIPATH].state == POLICY_STATE_PROHIBIT) || + (policy.tags[POLICY_TAG_MULTIPATH].state == POLICY_STATE_AVOID)) { + DEBUG( + "[fib_entry_get_nexthops_from_strategy] select single nexthops due to " + "multipath policy"); + nexthops_select_first(nexthops); + } + return nexthops; } /* + * Retrieve all candidate nexthops for sending mapme updates == all non local + * connections. We don't apply the policy at this stage. + */ +nexthops_t *fib_entry_get_mapme_nexthops(fib_entry_t *entry, + nexthops_t *new_nexthops) { + assert(new_nexthops); + + const connection_table_t *table = + forwarder_get_connection_table(entry->forwarder); + + /* We create a nexthop structure based on connections */ + // XXX This should be done close to where it is needed + connection_t *connection; + connection_table_foreach(table, connection, { + if (connection_is_local(connection)) continue; + new_nexthops->elts[nexthops_get_len(new_nexthops)] = + connection_table_get_connection_id(table, connection); + nexthops_inc(new_nexthops); + }); + + return new_nexthops; +} + +/* * Update available next hops following policy update. * * The last nexthop parameter is only used if needed, otherwise the pointer to @@ -397,13 +460,20 @@ nexthops_t *fib_entry_get_available_nexthops(fib_entry_t *entry, #endif } +#ifdef WITH_POLICY + hicn_policy_t fib_entry_get_policy(const fib_entry_t *entry) { return entry->policy; } void fib_entry_set_policy(fib_entry_t *entry, hicn_policy_t policy) { + INFO("fib_entry_set_policy"); entry->policy = policy; + forwarder_on_route_event(entry->forwarder, entry); + + // XXX generic mechanism to perform a mapme update +#if 0 #ifdef WITH_MAPME /* * Skip entries that do not correspond to a producer ( / have a locally @@ -411,8 +481,8 @@ void fib_entry_set_policy(fib_entry_t *entry, hicn_policy_t policy) { */ if (!fib_entry_has_local_nexthop(entry)) return; mapme_t *mapme = forwarder_get_mapme(entry->forwarder); - mapme_set_all_adjacencies(mapme, entry); #endif /* WITH_MAPME */ +#endif } #endif /* WITH_POLICY */ @@ -475,10 +545,7 @@ nexthops_t *fib_entry_get_nexthops_from_strategy(fib_entry_t *entry, * Initializing at 0 allows to disable nexthops with a negative priority */ unsigned max_priority = 0; - unsigned i; - nexthop_t nexthop; nexthops_enumerate(nexthops, i, nexthop, { - (void)nexthop; int priority = nexthops->state[i].priority; if (priority > max_priority) max_priority = priority; }); @@ -546,9 +613,9 @@ void fib_entry_on_timeout(fib_entry_t *entry, strategy_on_timeout(&entry->strategy, &entry->nexthops, timeout_nexthops); } -const Name *fib_entry_get_prefix(const fib_entry_t *entry) { +const hicn_prefix_t *fib_entry_get_prefix(const fib_entry_t *entry) { assert(entry); - return &(entry->name); + return &(entry->prefix); } /* @@ -557,7 +624,6 @@ const Name *fib_entry_get_prefix(const fib_entry_t *entry) { bool fib_entry_has_local_nexthop(const fib_entry_t *entry) { connection_table_t *table = forwarder_get_connection_table(entry->forwarder); - unsigned nexthop; nexthops_foreach(fib_entry_get_nexthops(entry), nexthop, { const connection_t *conn = connection_table_at(table, nexthop); /* Ignore non-local connections */ diff --git a/hicn-light/src/hicn/core/fib_entry.h b/hicn-light/src/hicn/core/fib_entry.h index 628c4cd4f..b625a33ef 100644 --- a/hicn-light/src/hicn/core/fib_entry.h +++ b/hicn-light/src/hicn/core/fib_entry.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -37,16 +37,20 @@ #ifndef fib_entry_h #define fib_entry_h -#include "name.h" +#include <hicn/name.h> #include "strategy.h" #include "msgbuf.h" #include "nexthops.h" #include "policy_stats.h" typedef struct { - Name name; + hicn_prefix_t prefix; unsigned refcount; nexthops_t nexthops; + + /* This is used for producer prefixes only */ + uint32_t nexthops_hash; + strategy_entry_t strategy; const void *forwarder; @@ -59,10 +63,12 @@ typedef struct { policy_stats_t policy_stats; #ifdef WITH_MAPME +#if 0 /* In case of no multipath, this stores the previous decision taken by policy. * As the list of nexthops is not expected to change, we can simply store the * flags */ uint_fast32_t prev_nexthops_flags; +#endif void *user_data; void (*user_data_release)(void **user_data); #endif /* WITH_MAPME */ @@ -73,6 +79,7 @@ typedef struct { #define fib_entry_strategy_type(fib_entry) ((fib_entry)->strategy.type) #define fib_entry_get_nexthops(fib_entry) (&(fib_entry)->nexthops) + #define fib_entry_nexthops_len(fib_entry) \ (nexthops_get_len(&(fib_entry)->nexthops)) #define fib_entry_nexthops_curlen(fib_entry) \ @@ -81,14 +88,36 @@ typedef struct { #define fib_entry_foreach_nexthop(fib_entry, nexthop, BODY) \ nexthops_foreach(fib_entry->nexthops, BODY) -#define fib_entry_nexthops_changed(fib_entry) \ - ((fib_entry)->prev_nexthops_flags == fib_entry_get_nexthops(fib_entry)->flags) - -#define fib_entry_set_prev_nexthops(fib_entry) \ - ((fib_entry)->prev_nexthops_flags = fib_entry_get_nexthops(fib_entry)->flags) +#define fib_entry_get_nexthops_hash(E) ((E)->nexthops_hash) +#define fib_entry_set_nexthops_hash(E, H) (E)->nexthops_hash = (H) + +static inline void fib_entry_set_nexthops(fib_entry_t *entry, + nexthops_t *nexthops) { + entry->nexthops = *nexthops; +} + +static inline void fib_entry_initialize_nexthops(fib_entry_t *entry) { + entry->nexthops = NEXTHOPS_EMPTY; +} + +static inline bool fib_entry_nexthops_changed(fib_entry_t *entry, + nexthops_t *nexthops) { + uint32_t old_hash = fib_entry_get_nexthops_hash(entry); + uint32_t hash = nexthops_get_hash(nexthops); + if (hash != old_hash) { + fib_entry_set_nexthops_hash(entry, hash); + return true; + } + return false; +}; struct forwarder_s; -fib_entry_t *fib_entry_create(Name *name, strategy_type_t strategy_type, + +/* + * This does a copy of the name passed as parameter + */ +fib_entry_t *fib_entry_create(const hicn_prefix_t *prefix, + strategy_type_t strategy_type, strategy_options_t *strategy_options, const struct forwarder_s *table); @@ -106,8 +135,6 @@ void fib_entry_nexthops_add(fib_entry_t *fib_entry, unsigned nexthop); void fib_entry_nexthops_remove(fib_entry_t *fib_entry, unsigned nexthop); -size_t fib_entry_NexthopCount(const fib_entry_t *fib_entry); - /** * @function fib_entry_nexthops_get * @abstract Returns the nexthop set of the FIB entry. You must Acquire if it @@ -132,6 +159,12 @@ void fib_entry_set_policy(fib_entry_t *fib_entry, hicn_policy_t policy); void fib_entry_update_stats(fib_entry_t *fib_entry, uint64_t now); #endif /* WITH_POLICY */ +nexthops_t *fib_entry_filter_nexthops(fib_entry_t *entry, nexthops_t *nexthops, + unsigned ingress_id, bool prefer_local); + +nexthops_t *fib_entry_get_mapme_nexthops(fib_entry_t *entry, + nexthops_t *new_nexthops); + nexthops_t *fib_entry_get_available_nexthops(fib_entry_t *fib_entry, unsigned in_connection, nexthops_t *new_nexthops); @@ -145,7 +178,7 @@ nexthops_t *fib_entry_get_nexthops_from_strategy( * @abstract Returns a copy of the prefix. * @return A reference counted copy that you must destroy */ -const Name *fib_entry_get_prefix(const fib_entry_t *fib_entry); +const hicn_prefix_t *fib_entry_get_prefix(const fib_entry_t *fib_entry); bool fib_entry_has_local_nexthop(const fib_entry_t *entry); diff --git a/hicn-light/src/hicn/core/forwarder.c b/hicn-light/src/hicn/core/forwarder.c index 74be6431a..14f1649fa 100644 --- a/hicn-light/src/hicn/core/forwarder.c +++ b/hicn-light/src/hicn/core/forwarder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -69,7 +69,7 @@ #endif /* WITH_POLICY_STATS */ #include <hicn/core/wldr.h> -#include <hicn/core/interest_manifest.h> +#include <hicn/interest_manifest.h> #include <hicn/util/log.h> struct forwarder_s { @@ -189,9 +189,10 @@ forwarder_t *forwarder_create(configuration_t *configuration) { vector_init(forwarder->pending_conn, MAX_MSG, 0); vector_init(forwarder->acquired_msgbuf_ids, MAX_MSG, 0); - char *n_suffixes_per_split_str = getenv("N_SUFFIXES_PER_SPIT"); + char *n_suffixes_per_split_str = getenv("N_SUFFIXES_PER_SPLIT"); if (n_suffixes_per_split_str) - N_SUFFIXES_PER_SPIT = atoi(n_suffixes_per_split_str); + configuration_set_suffixes_per_split(forwarder_get_configuration(forwarder), + atoi(n_suffixes_per_split_str)); return forwarder; @@ -239,6 +240,162 @@ void forwarder_free(forwarder_t *forwarder) { free(forwarder); } +/* + * An event occurred that might trigger an update of the FIB cache. It is + * possible that the flags have been reset following a connection add or remote. + * The objective of this function is to prepare the cache entry, and to alert of + * any change for both consumer and producer prefixes. + */ +void forwarder_on_route_event(const forwarder_t *forwarder, + fib_entry_t *entry) { + commands_notify_route(forwarder, entry); + + nexthops_t new_nexthops = NEXTHOPS_EMPTY; + nexthops_t *nexthops; + + char *prefix_type_s; + + const connection_table_t *table = + forwarder_get_connection_table(entry->forwarder); + + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); + + WITH_INFO({ + char buf[MAXSZ_HICN_PREFIX]; + hicn_prefix_snprintf(buf, MAXSZ_HICN_NAME, prefix); + INFO("fib_entry_on_event: %s", buf); + )}; + + if (!fib_entry_has_local_nexthop(entry)) { + /* Recompute FIB cache, then check whether it has changed based on hash */ + prefix_type_s = "consumer"; + nexthops = fib_entry_get_nexthops(entry); + nexthops_reset(nexthops); + fib_entry_filter_nexthops(entry, nexthops, ~0, false); + } else { + /* Check available non-local connections (on which we would send MAP-Me + * updates */ + prefix_type_s = "producer"; + + nexthops = fib_entry_get_mapme_nexthops(entry, &new_nexthops); + fib_entry_filter_nexthops(entry, nexthops, ~0, true); + +#ifdef WITH_MAPME + mapme_set_adjacencies(forwarder->mapme, entry, nexthops); +#endif /* WITH_MAPME */ + } + + if (!fib_entry_nexthops_changed(entry, nexthops)) return; + + /* Send notification */ + WITH_INFO({ + char buf[MAXSZ_HICN_PREFIX]; + hicn_prefix_snprintf(buf, MAXSZ_HICN_NAME, prefix); + INFO("Active interfaces changed for %s prefix %s", prefix_type_s, buf); + }); + + netdevice_flags_t flags = NETDEVICE_FLAGS_EMPTY; + nexthops_foreach(nexthops, nh, { + connection_t *connection = connection_table_get_by_id(table, nh); + netdevice_flags_add(flags, connection_get_interface_type(connection)); + }); + + hicn_ip_prefix_t ip_prefix; + hicn_prefix_get_ip_prefix(prefix, &ip_prefix); + commands_notify_active_interface_update(forwarder, &ip_prefix, flags); +} + +int forwarder_add_connection(const forwarder_t *forwarder, + const char *symbolic_name, face_type_t type, + address_pair_t *pair, policy_tags_t tags, + int priority, face_state_t admin_state) { + connection_table_t *table = forwarder_get_connection_table(forwarder); + connection_t *connection = connection_table_get_by_pair(table, pair); + + if (!connection) { + connection = connection_create(type, symbolic_name, pair, forwarder); + if (!connection) { + ERROR("Failed to create %s connection", face_type_str(type)); + return -1; + } + + } else { + WARN("Connection already exists"); + } + +#ifdef WITH_POLICY + connection_set_tags(connection, tags); + connection_set_priority(connection, priority); +#endif /* WITH_POLICY */ + + connection_set_admin_state(connection, admin_state); + return 0; +} + +int forwarder_remove_connection(const forwarder_t *forwarder, + unsigned connection_id, bool finalize) { + /* Remove connection from the FIB */ + forwarder_remove_connection_id_from_routes(forwarder, connection_id); + + /* Remove connection */ + connection_table_t *table = forwarder_get_connection_table(forwarder); + + /* Hook: connection deleted through the control protocol */ + connection_t *connection = connection_table_at(table, connection_id); + forwarder_on_connection_event(forwarder, connection, CONNECTION_EVENT_DELETE); + + connection_table_remove_by_id(table, connection_id); + if (finalize) connection_finalize(connection); + + return 0; +} + +/* + * This is currently called from commands.c for every command sent to update + * a connection. + */ +void forwarder_on_connection_event(const forwarder_t *forwarder, + const connection_t *connection, + connection_event_t event) { + assert(connection); + + commands_notify_connection(forwarder, event, connection); + + unsigned conn_id = connection_get_id(connection); + + /* We need to send a MapMe update on the newly selected connections for + * each concerned fib_entry : connection is involved, or no more involved */ + fib_t *fib = forwarder_get_fib(forwarder); + fib_foreach_entry(fib, entry, { + const nexthops_t *nexthops = fib_entry_get_nexthops(entry); + + if (!fib_entry_has_local_nexthop(entry)) { + /* Consumer prefix */ + /* + * A new connection has no impact until it is added to FIB, which will + * be handled in a route event + */ + if (event == CONNECTION_EVENT_CREATE) break; + + /* + * For each FIB entry, trigger an event only if the connection is part + * of nexthops */ + // XXX Replace this by a function + nexthops_foreach(nexthops, nexthop, { + if (nexthop != conn_id) continue; + forwarder_on_route_event(forwarder, entry); + break; + }); + } else { + /* Producer prefix */ + if (connection_is_local(connection)) break; + + // XXX we could optimize event more + forwarder_on_route_event(forwarder, entry); + } + }); +} + void forwarder_setup_local_listeners(forwarder_t *forwarder, uint16_t port) { assert(forwarder); listener_setup_local(forwarder, port); @@ -249,7 +406,8 @@ configuration_t *forwarder_get_configuration(forwarder_t *forwarder) { return forwarder->config; } -subscription_table_t *forwarder_get_subscriptions(forwarder_t *forwarder) { +subscription_table_t *forwarder_get_subscriptions( + const forwarder_t *forwarder) { return forwarder->subscriptions; } @@ -259,7 +417,7 @@ connection_table_t *forwarder_get_connection_table( return forwarder->connection_table; } -listener_table_t *forwarder_get_listener_table(forwarder_t *forwarder) { +listener_table_t *forwarder_get_listener_table(const forwarder_t *forwarder) { assert(forwarder); return forwarder->listener_table; } @@ -295,7 +453,8 @@ void forwarder_cs_set_size(forwarder_t *forwarder, size_t size) { if (pkt_cache_set_cs_size(forwarder->pkt_cache, size) < 0) { ERROR( "Unable to resize the CS: provided maximum size (%u) is smaller than " - "the number of elements currently stored in the CS (%u). Clear the CS " + "the number of elements currently stored in the CS (%u). Clear the " + "CS " "and retry.", size, pkt_cache_get_cs_size(forwarder->pkt_cache)); } @@ -335,11 +494,11 @@ static ssize_t forwarder_drop(forwarder_t *forwarder, off_t msgbuf_id) { const msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); switch (msgbuf_get_type(msgbuf)) { - case MSGBUF_TYPE_INTEREST: + case HICN_PACKET_TYPE_INTEREST: forwarder->stats.countInterestsDropped++; break; - case MSGBUF_TYPE_DATA: + case HICN_PACKET_TYPE_DATA: forwarder->stats.countObjectsDropped++; break; @@ -384,7 +543,7 @@ static ssize_t forwarder_forward_via_connection(forwarder_t *forwarder, // Here we need to update the path label of a data packet before send // it. The path label update can be done here because the packet is sent // directly to the socket - if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) + if (msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA) msgbuf_update_pathlabel(msgbuf, connection_get_id(conn)); bool success = connection_send_packet(conn, msgbuf_get_packet(msgbuf), @@ -415,11 +574,11 @@ static ssize_t forwarder_forward_via_connection(forwarder_t *forwarder, } switch (msgbuf_get_type(msgbuf)) { - case MSGBUF_TYPE_INTEREST: + case HICN_PACKET_TYPE_INTEREST: forwarder->stats.countInterestForwarded++; break; - case MSGBUF_TYPE_DATA: + case HICN_PACKET_TYPE_DATA: forwarder->stats.countObjectsForwarded++; break; @@ -451,7 +610,6 @@ static unsigned forwarder_forward_to_nexthops(forwarder_t *forwarder, msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); unsigned ingressId = msgbuf_get_connection_id(msgbuf); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { // DEBUG("[forwarder_forward_to_nexthops] - nexthop = %d"); if (nexthop == ingressId) continue; @@ -469,43 +627,57 @@ static bool forwarder_forward_via_fib(forwarder_t *forwarder, off_t msgbuf_id, pkt_cache_entry_t *entry) { assert(forwarder && entry && msgbuf_id_is_valid(msgbuf_id)); + bool ret = true; + const msgbuf_pool_t *msgbuf_pool = forwarder_get_msgbuf_pool(forwarder); msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); - assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST); + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); - fib_entry_t *fib_entry = fib_match_message(forwarder->fib, msgbuf); + fib_entry_t *fib_entry = fib_match_msgbuf(forwarder->fib, msgbuf); if (!fib_entry) return false; - // DEBUG("[forwarder] Getting nexthops from strategy"); - nexthops_t *nexthops = fib_entry_get_nexthops_from_strategy( - fib_entry, msgbuf, verdict == PKT_CACHE_VERDICT_RETRANSMIT_INTEREST); + nexthops_t *nexthops = fib_entry_get_nexthops(fib_entry); + + /* Backup flags and cur_len*/ + uint_fast32_t flags = nexthops->flags; + size_t cur_len = nexthops_get_curlen(nexthops); + + /* This affects the nexthops */ + nexthops = strategy_lookup_nexthops(&fib_entry->strategy, nexthops, msgbuf); if (nexthops_get_curlen(nexthops) == 0) { ERROR("Message %p returned an empty next hop set", msgbuf); - return false; + ret = false; + goto END; } pit_entry_t *pit_entry = &entry->u.pit_entry; - if (!pit_entry) return false; + if (!pit_entry) { + ret = false; + goto END; + } pit_entry_set_fib_entry(pit_entry, fib_entry); // this requires some additional checks. It may happen that some of the output // faces selected by the forwarding strategy are not usable. So far all the // forwarding strategy return only valid faces (or an empty list) - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { // DEBUG("Adding egress to PIT for nexthop %d", nexthop); pit_entry_egress_add(pit_entry, nexthop); }); if (forwarder_forward_to_nexthops(forwarder, msgbuf_id, nexthops) <= 0) { - // this should never happen - ERROR("Message %p returned an empty next hop set", msgbuf); - return false; + ERROR("Error forwarding mMessage %p to next hops", msgbuf); + ret = false; } - return true; +END: + /* Restore flags & curlen */ + nexthops->flags = flags; + nexthops->cur_elts = cur_len; + + return ret; } #endif /* ! BYPASS_FIB */ @@ -519,7 +691,7 @@ int _forwarder_forward_upon_interest( // - Aggregation can be perfomed, do not forward if (verdict == PKT_CACHE_VERDICT_AGGREGATE_INTEREST) { forwarder_drop(forwarder, interest_msgbuf_id); - return msgbuf_get_len(msgbuf); + return (int)msgbuf_get_len(msgbuf); } // - Data packet matching the interest was found, forward reply @@ -532,12 +704,12 @@ int _forwarder_forward_upon_interest( msgbuf_reset_pathlabel(data_msgbuf); forwarder_forward_via_connection(forwarder, data_msgbuf_id, msgbuf_get_connection_id(interest_msgbuf)); - return msgbuf_get_len(msgbuf); + return (int)msgbuf_get_len(msgbuf); } // - For aggregated interest, the interest forwarding is done in // `_forwarder_forward_aggregated_interest()` - if (is_aggregated) return msgbuf_get_len(msgbuf); + if (is_aggregated) return (int)msgbuf_get_len(msgbuf); // - Try to forward the interest int rc = @@ -552,7 +724,7 @@ int _forwarder_forward_upon_interest( return -1; } - return msgbuf_get_len(msgbuf); + return (int)msgbuf_get_len(msgbuf); } static void _forwarder_update_interest_stats(forwarder_t *forwarder, @@ -601,31 +773,32 @@ static void _forwarder_update_interest_stats(forwarder_t *forwarder, } } +/** + * Return the interest manifest from the interest payload + */ static interest_manifest_header_t *_forwarder_get_interest_manifest( msgbuf_t *msgbuf) { - uint8_t *packet = msgbuf_get_packet(msgbuf); - hicn_header_t *header = (hicn_header_t *)packet; - hicn_type_t type = hicn_header_to_type(header); + uint8_t *payload; + size_t payload_size; - hicn_payload_type_t payload_type; - int rc = hicn_ops_vft[type.l1]->get_payload_type(type, &header->protocol, - &payload_type); - _ASSERT(rc == HICN_LIB_ERROR_NONE); - if (payload_type != HPT_MANIFEST) return NULL; + hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf); - size_t header_length, payload_length; - rc = hicn_ops_vft[type.l1]->get_header_length(type, &header->protocol, - &header_length); + hicn_payload_type_t payload_type; + HICN_UNUSED(int rc) = hicn_packet_get_payload_type(pkbuf, &payload_type); assert(rc == HICN_LIB_ERROR_NONE); - rc = hicn_ops_vft[type.l1]->get_payload_length(type, &header->protocol, - &payload_length); + if (payload_type != HPT_MANIFEST) return NULL; + + rc = hicn_packet_get_payload(pkbuf, &payload, &payload_size, false); assert(rc == HICN_LIB_ERROR_NONE); - u8 *payload = (u8 *)header + header_length; interest_manifest_header_t *int_manifest_header = (interest_manifest_header_t *)payload; - if (!interest_manifest_is_valid(int_manifest_header, payload_length)) + + // Deserialize intrest mmanifest + interest_manifest_deserialize(int_manifest_header); + + if (!interest_manifest_is_valid(int_manifest_header, payload_size)) return NULL; return int_manifest_header; @@ -635,20 +808,34 @@ static interest_manifest_header_t *_forwarder_get_interest_manifest( // sub-manifest is sent using the forwarding strategy defined for the prefix int _forwarder_forward_aggregated_interest( forwarder_t *forwarder, interest_manifest_header_t *int_manifest_header, - int n_suffixes_to_fwd, msgbuf_t *msgbuf, off_t msgbuf_id, - pkt_cache_entry_t **entries) { + msgbuf_t *msgbuf, off_t msgbuf_id, pkt_cache_entry_t **entries) { assert(msgbuf_id_is_valid(msgbuf_id) && - msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST); + msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); + + bool ret = -1; + + fib_entry_t *fib_entry = fib_match_msgbuf(forwarder->fib, msgbuf); + if (!fib_entry) goto END; + + nexthops_t *nexthops = fib_entry_get_nexthops(fib_entry); + if (nexthops_get_curlen(nexthops) == 0) { + ret = 0; + goto END; + } - fib_entry_t *fib_entry = fib_match_message(forwarder->fib, msgbuf); - if (!fib_entry) return -1; + /* Backup flags and cur_len*/ + uint_fast32_t flags = nexthops->flags; + size_t cur_len = nexthops_get_curlen(nexthops); - int n_suffixes_per_split = N_SUFFIXES_PER_SPIT; + size_t n_suffixes_per_split = configuration_get_suffixes_per_split( + forwarder_get_configuration(forwarder)); + int_manifest_split_strategy_t disaggregation_strategy = + configuration_get_split_strategy(forwarder_get_configuration(forwarder)); switch (disaggregation_strategy) { - case INT_MANIFEST_SPLIT_NONE: + case INT_MANIFEST_SPLIT_STRATEGY_NONE: n_suffixes_per_split = int_manifest_header->n_suffixes + 1; - case INT_MANIFEST_SPLIT_MAX_N_SUFFIXES: { + case INT_MANIFEST_SPLIT_STRATEGY_MAX_N_SUFFIXES: { // Generate sub-manifests: same as original manifest, // but different suffix in the header and different bitmap @@ -658,11 +845,11 @@ int _forwarder_forward_aggregated_interest( // Save copy of original bitmap to use as a reference // to generate bitmaps for sub-manifests - u32 original_bitmap[BITMAP_SIZE] = {0}; + hicn_uword original_bitmap[BITMAP_SIZE] = {0}; memcpy(&original_bitmap, int_manifest_header->request_bitmap, - BITMAP_SIZE * sizeof(u32)); + BITMAP_SIZE * sizeof(hicn_uword)); - int suffix_index = 0; // Position of suffix in initial manifest + size_t suffix_index = 0; // Position of suffix in initial manifest while (suffix_index < total_suffixes) { // If more than one sub-manifest, // clone original interest manifest and update suffix @@ -677,42 +864,55 @@ int _forwarder_forward_aggregated_interest( msgbuf = clone; } - u32 curr_bitmap[BITMAP_SIZE] = {0}; - int first_suffix_index_in_submanifest = suffix_index; + hicn_uword curr_bitmap[BITMAP_SIZE] = {0}; + size_t first_suffix_index_in_submanifest = suffix_index; suffix_index = interest_manifest_update_bitmap( original_bitmap, curr_bitmap, suffix_index, total_suffixes, n_suffixes_per_split); - int first_suffix_index_in_next_submanifest = suffix_index; + size_t first_suffix_index_in_next_submanifest = suffix_index; // Update manifest bitmap in current msgbuf interest_manifest_header_t *manifest = _forwarder_get_interest_manifest(msgbuf); assert(manifest != NULL); memcpy(manifest->request_bitmap, curr_bitmap, - BITMAP_SIZE * sizeof(u32)); + BITMAP_SIZE * sizeof(hicn_uword)); WITH_TRACE({ bitmap_print(manifest->request_bitmap, BITMAP_SIZE); printf("\n"); }); - // Update PIT entries for suffixes in current sub-manifest - nexthops_t *nexthops = - fib_entry_get_nexthops_from_strategy(fib_entry, msgbuf, false); - if (nexthops_get_curlen(nexthops) == 0) return -1; + /* + * Update PIT entries for suffixes in current sub-manifest. + * + * Note that strategy lookup affects the nexthops, and we need to + *restore the initial state before every lookup + */ + nexthops->flags = flags; + nexthops->cur_elts = cur_len; + nexthops = + strategy_lookup_nexthops(&fib_entry->strategy, nexthops, msgbuf); + + if (nexthops_get_curlen(nexthops) == 0) { + ERROR("Message %p returned an empty next hop set", msgbuf); + goto RESTORE; + } - for (int i = first_suffix_index_in_submanifest; + for (size_t i = first_suffix_index_in_submanifest; i < first_suffix_index_in_next_submanifest; i++) { - if (!is_bit_set(manifest->request_bitmap, i)) continue; + if (!bitmap_is_set_no_check(manifest->request_bitmap, i)) continue; pit_entry_t *pit_entry = &(entries[i]->u.pit_entry); - if (!pit_entry) return -1; + if (!pit_entry) goto RESTORE; pit_entry_set_fib_entry(pit_entry, fib_entry); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { pit_entry_egress_add(pit_entry, nexthop); }); } + // Serialize manifest before sending it + interest_manifest_serialize(int_manifest_header); + if (forwarder_forward_to_nexthops(forwarder, msgbuf_id, nexthops) <= 0) { ERROR("Message %p returned an empty next hop set", msgbuf); @@ -722,12 +922,21 @@ int _forwarder_forward_aggregated_interest( total_len += msgbuf_get_len(msgbuf); } - return total_len; + ret = total_len; + goto END; } default: - return -1; + break; } + +RESTORE: + /* Restore flags & curlen */ + nexthops->flags = flags; + nexthops->cur_elts = cur_len; + +END: + return ret; } static ssize_t forwarder_process_single_interest(forwarder_t *forwarder, @@ -742,6 +951,7 @@ static ssize_t forwarder_process_single_interest(forwarder_t *forwarder, pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id, &verdict, &data_msgbuf_id, &entry, msgbuf_get_name(msgbuf), forwarder->serve_from_cs); + _forwarder_update_interest_stats(forwarder, verdict, msgbuf, entry->has_expire_ts, entry->expire_ts); @@ -749,9 +959,7 @@ static ssize_t forwarder_process_single_interest(forwarder_t *forwarder, forwarder, msgbuf_pool, data_msgbuf_id, msgbuf_id, entry, verdict, false); // No route when trying to forward interest, remove from PIT - if (rc == -1) - pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry, - msgbuf_get_name(msgbuf)); + if (rc == -1) pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry); return msgbuf_get_len(msgbuf); } @@ -769,15 +977,16 @@ static ssize_t forwarder_process_aggregated_interest( int pos = 0; // Position of current suffix in manifest int n_suffixes_to_fwd = 0; u32 *suffix = (u32 *)(int_manifest_header + 1); - u32 seq = name_GetSegment(msgbuf_get_name(msgbuf)); + u32 seq = hicn_name_get_suffix(msgbuf_get_name(msgbuf)); - Name name_copy = EMPTY_NAME; - name_Copy(msgbuf_get_name(msgbuf), &name_copy); + hicn_name_t name_copy = HICN_NAME_EMPTY; + hicn_name_copy(&name_copy, msgbuf_get_name(msgbuf)); // The fist loop iteration handles the suffix in the header, // the following ones handle the suffiexes in the manifest while (true) { - if (!is_bit_set(int_manifest_header->request_bitmap, pos)) goto NEXT_SUFFIX; + if (!bitmap_is_set_no_check(int_manifest_header->request_bitmap, pos)) + goto NEXT_SUFFIX; // Update packet cache pkt_cache_on_interest(forwarder->pkt_cache, msgbuf_pool, msgbuf_id, @@ -794,14 +1003,13 @@ static ssize_t forwarder_process_aggregated_interest( msgbuf_id, entry, verdict, true); // No route when trying to forward interest, remove from PIT - if (rc == -1) - pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry, &name_copy); + if (rc == -1) pkt_cache_pit_remove_entry(forwarder->pkt_cache, entry); // Unset in bitmap if no interest forwarding needed, // otherwise increase count of suffixes to forward if (rc == -1 || verdict == PKT_CACHE_VERDICT_AGGREGATE_INTEREST || verdict == PKT_CACHE_VERDICT_FORWARD_DATA) { - unset_bit(int_manifest_header->request_bitmap, pos); + bitmap_unset_no_check(int_manifest_header->request_bitmap, pos); } else { n_suffixes_to_fwd++; } @@ -812,12 +1020,15 @@ static ssize_t forwarder_process_aggregated_interest( // Use next segment in manifest seq = *suffix; suffix++; - name_SetSegment(&name_copy, seq); + hicn_name_set_suffix(&name_copy, seq); WITH_DEBUG({ - char *nameString = name_ToString(&name_copy); - DEBUG("Next in manifest: %s", nameString); - free(nameString); + char buf[MAXSZ_HICN_PREFIX]; + int rc = + hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("Next in manifest: %s", buf); }); } @@ -825,8 +1036,7 @@ static ssize_t forwarder_process_aggregated_interest( if (n_suffixes_to_fwd == 0) return msgbuf_get_len(msgbuf); return _forwarder_forward_aggregated_interest(forwarder, int_manifest_header, - n_suffixes_to_fwd, msgbuf, - msgbuf_id, entries); + msgbuf, msgbuf_id, entries); } /** @@ -850,7 +1060,7 @@ static ssize_t forwarder_process_interest(forwarder_t *forwarder, connection_t *conn = connection_table_get_by_id(table, msgbuf_get_connection_id(msgbuf)); - assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST); + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); u32 n_suffixes = 0; interest_manifest_header_t *int_manifest_header = @@ -863,16 +1073,20 @@ static ssize_t forwarder_process_interest(forwarder_t *forwarder, conn->stats.interests.rx_bytes += msgbuf_get_len(msgbuf); WITH_DEBUG({ - char *nameString = name_ToString(msgbuf_get_name(msgbuf)); - DEBUG("INTEREST (%s) suffixes=%u msgbuf_id=%lu ingress=%u length=%u", - nameString, n_suffixes, msgbuf_id, msgbuf_get_connection_id(msgbuf), + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("INTEREST (%s) msgbuf_id=%lu ingress=%u length=%u", buf, msgbuf_id, + msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf)); + DEBUG("INTEREST (%s) suffixes=%u msgbuf_id=%lu ingress=%u length=%u", buf, + n_suffixes, msgbuf_id, msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf)); - free(nameString); }); // Cache suffixes for current prefix to (possibly) avoid double lookups pkt_cache_save_suffixes_for_prefix( - forwarder->pkt_cache, name_GetContentName(msgbuf_get_name(msgbuf))); + forwarder->pkt_cache, hicn_name_get_prefix(msgbuf_get_name(msgbuf))); if (!int_manifest_header) return forwarder_process_single_interest(forwarder, msgbuf_pool, msgbuf, @@ -888,7 +1102,9 @@ static void _forwarder_log_on_data(forwarder_t *forwarder, DEBUG("Message added to CS from PIT"); break; case PKT_CACHE_VERDICT_STORE_DATA: - DEBUG("Message added to CS (expired or no previous interest pending)"); + DEBUG( + "Message added to CS (expired or no previous interest " + "pending)"); break; case PKT_CACHE_VERDICT_CLEAR_DATA: break; @@ -921,10 +1137,12 @@ static ssize_t forwarder_process_data(forwarder_t *forwarder, off_t msgbuf_id) { msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); WITH_DEBUG({ - char *nameString = name_ToString(msgbuf_get_name(msgbuf)); - DEBUG("DATA (%s) msgbuf_id=%lu ingress=%u length=%u", nameString, msgbuf_id, + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("DATA (%s) msgbuf_id=%lu ingress=%u length=%u", buf, msgbuf_id, msgbuf_get_connection_id(msgbuf), msgbuf_get_len(msgbuf)); - free(nameString); }); const connection_table_t *table = forwarder_get_connection_table(forwarder); @@ -938,7 +1156,7 @@ static ssize_t forwarder_process_data(forwarder_t *forwarder, off_t msgbuf_id) { // Cache suffixes for current prefix to (possibly) avoid double lookups pkt_cache_save_suffixes_for_prefix( - forwarder->pkt_cache, name_GetContentName(msgbuf_get_name(msgbuf))); + forwarder->pkt_cache, hicn_name_get_prefix(msgbuf_get_name(msgbuf))); pkt_cache_verdict_t verdict = PKT_CACHE_VERDICT_ERROR; bool wrong_egress; @@ -955,17 +1173,13 @@ static ssize_t forwarder_process_data(forwarder_t *forwarder, off_t msgbuf_id) { forwarder->stats.countDroppedNoReversePath++; DEBUG("Message %lu did not match PIT, no reverse path", msgbuf_id); - // MOVE PROBE HOOK ELSEWHERE - // XXX relationship with forwarding strategy... insert hooks - // if the packet is a probe we need to analyze it // NOTE : probes are not stored in PIT if (msgbuf_is_probe(msgbuf)) { - fib_entry_t *entry = fib_match_message(forwarder->fib, msgbuf); + fib_entry_t *entry = fib_match_msgbuf(forwarder->fib, msgbuf); if (entry && fib_entry_strategy_type(entry) == STRATEGY_TYPE_BESTPATH) { nexthops_t probe_nexthops = NEXTHOPS_EMPTY; nexthops_add(&probe_nexthops, msgbuf_get_connection_id(msgbuf)); fib_entry_on_data(entry, &probe_nexthops, msgbuf, 0, ticks_now()); - // XXX TODO CONFIRM WE DON'T EXIT HERE ? } } forwarder_drop(forwarder, msgbuf_id); @@ -982,7 +1196,8 @@ void forwarder_flush_connections(forwarder_t *forwarder) { // DEBUG("[forwarder_flush_connections]"); const connection_table_t *table = forwarder_get_connection_table(forwarder); - for (unsigned i = 0; i < vector_len(forwarder->pending_conn); i++) { + unsigned num_pending_conn = (unsigned)vector_len(forwarder->pending_conn); + for (unsigned i = 0; i < num_pending_conn; i++) { unsigned conn_id = forwarder->pending_conn[i]; connection_t *conn = connection_table_at(table, conn_id); if (!connection_flush(conn)) { @@ -994,14 +1209,15 @@ void forwarder_flush_connections(forwarder_t *forwarder) { // DEBUG("[forwarder_flush_connections] done"); } +#if WITH_WLDR // XXX move to wldr file, worst case in connection. void forwarder_apply_wldr(const forwarder_t *forwarder, const msgbuf_t *msgbuf, connection_t *connection) { - // this are the checks needed to implement WLDR. We set wldr only on the STAs - // and we let the AP to react according to choice of the client. - // if the STA enables wldr using the set command, the AP enable wldr as well - // otherwise, if the STA disable it the AP remove wldr - // WLDR should be enabled only on the STAs using the command line + // this are the checks needed to implement WLDR. We set wldr only on the + // STAs and we let the AP to react according to choice of the client. if + // the STA enables wldr using the set command, the AP enable wldr as + // well otherwise, if the STA disable it the AP remove wldr WLDR should + // be enabled only on the STAs using the command line // TODO // disable WLDR command line on the AP if (msgbuf_has_wldr(msgbuf)) { @@ -1023,8 +1239,10 @@ void forwarder_apply_wldr(const forwarder_t *forwarder, const msgbuf_t *msgbuf, } } } +#endif -bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_add_or_update_route(forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, unsigned ingress_id) { assert(forwarder); assert(prefix); @@ -1032,7 +1250,7 @@ bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, configuration_t *config = forwarder_get_configuration(forwarder); char prefix_s[MAXSZ_IP_PREFIX]; - int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, prefix); + int rc = hicn_ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, prefix); assert(rc < MAXSZ_IP_PREFIX); if (rc < 0) return false; @@ -1041,9 +1259,9 @@ bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, // XXX TODO this should store options too strategy_type_t strategy_type = configuration_get_strategy(config, prefix_s); - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, prefix->family, prefix->address, - prefix->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len, + &name_prefix); fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix); if (!entry) { entry = fib_entry_create(&name_prefix, strategy_type, NULL, forwarder); @@ -1054,17 +1272,19 @@ bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, fib_entry_nexthops_add(entry, ingress_id); } + forwarder_on_route_event(forwarder, entry); + return true; } -bool forwarder_remove_route(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_remove_route(forwarder_t *forwarder, hicn_ip_prefix_t *prefix, unsigned ingress_id) { assert(forwarder); assert(prefix); - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, prefix->family, prefix->address, - prefix->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len, + &name_prefix); fib_remove(forwarder->fib, &name_prefix, ingress_id); return true; @@ -1072,31 +1292,32 @@ bool forwarder_remove_route(forwarder_t *forwarder, ip_prefix_t *prefix, #ifdef WITH_POLICY -bool forwarder_add_or_update_policy(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_add_or_update_policy(forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, hicn_policy_t *policy) { assert(forwarder); assert(prefix); assert(policy); - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, prefix->family, prefix->address, - prefix->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len, + &name_prefix); fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix); if (!entry) return false; + fib_entry_set_policy(entry, *policy); return true; } -bool forwarder_remove_policy(forwarder_t *forwarder, ip_prefix_t *prefix) { +bool forwarder_remove_policy(forwarder_t *forwarder, hicn_ip_prefix_t *prefix) { assert(forwarder); assert(prefix); - Name name_prefix = EMPTY_NAME; - name_CreateFromAddress(&name_prefix, prefix->family, prefix->address, - prefix->len); + hicn_prefix_t name_prefix = HICN_PREFIX_EMPTY; + hicn_prefix_create_from_ip_address_len(&prefix->address, prefix->len, + &name_prefix); fib_entry_t *entry = fib_contains(forwarder->fib, &name_prefix); - if (!entry) return false; fib_entry_set_policy(entry, POLICY_EMPTY); @@ -1106,14 +1327,30 @@ bool forwarder_remove_policy(forwarder_t *forwarder, ip_prefix_t *prefix) { #endif /* WITH_POLICY */ -void forwarder_remove_connection_id_from_routes(forwarder_t *forwarder, +void forwarder_remove_connection_id_from_routes(const forwarder_t *forwarder, unsigned connection_id) { + fib_entry_t **removed_entries = NULL; + size_t num_removed_entries; + assert(forwarder); - fib_remove_connection_id(forwarder->fib, connection_id); + fib_remove_connection(forwarder->fib, connection_id, &removed_entries, + &num_removed_entries); + + if (num_removed_entries > 0) { + assert(removed_entries); + + for (int i = 0; i < num_removed_entries; i++) { + fib_entry_t *entry = removed_entries[i]; + forwarder_on_route_event(forwarder, entry); + fib_remove_entry(forwarder->fib, entry); + } + free(removed_entries); + } } -void forwarder_add_strategy_options(forwarder_t *forwarder, Name *name_prefix, +void forwarder_add_strategy_options(forwarder_t *forwarder, + hicn_prefix_t *name_prefix, strategy_type_t strategy_type, strategy_options_t *strategy_options) { assert(forwarder); @@ -1127,18 +1364,18 @@ void forwarder_add_strategy_options(forwarder_t *forwarder, Name *name_prefix, fib_entry_add_strategy_options(entry, strategy_type, strategy_options); } -void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix, +void forwarder_set_strategy(forwarder_t *forwarder, hicn_prefix_t *prefix, strategy_type_t strategy_type, strategy_options_t *strategy_options) { assert(forwarder); - assert(name_prefix); + assert(prefix); assert(STRATEGY_TYPE_VALID(strategy_type)); /* strategy_options might be NULL */ - fib_entry_t *entry = fib_contains(forwarder->fib, name_prefix); + fib_entry_t *entry = fib_contains(forwarder->fib, prefix); if (!entry) { - // there is no exact match. so if the forwarding strategy is not in the list - // of strategies that can be set by the transport, return + // there is no exact match. so if the forwarding strategy is not in + // the list of strategies that can be set by the transport, return if (strategy_type != STRATEGY_TYPE_BESTPATH && strategy_type != STRATEGY_TYPE_REPLICATION) { return; @@ -1148,7 +1385,7 @@ void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix, // no knowledge of the length of the prefix. so we apply the strategy at the // matching fib entry, which later will be the one that will be used to send // interests with this name - entry = fib_match_name(forwarder->fib, name_prefix); + entry = fib_match_prefix(forwarder->fib, prefix); if (!entry) { return; // no fib match, return } @@ -1163,10 +1400,11 @@ cs_t *forwarder_get_cs(const forwarder_t *forwarder) { return pkt_cache_get_cs(forwarder->pkt_cache); } -// IMPORTANT: Use this function ONLY for read-only operations since a realloc -// would otherwise modify the returned copy but not the original msgbuf ids -// vector in the forwarder. This constraint cannot be enforced by returning a -// (const off_t *) because the vector_t macros still cast to (void **). +// IMPORTANT: Use this function ONLY for read-only operations since a +// realloc would otherwise modify the returned copy but not the original +// msgbuf ids vector in the forwarder. This constraint cannot be enforced +// by returning a (const off_t *) because the vector_t macros still cast +// to (void **). off_t *forwarder_get_acquired_msgbuf_ids(const forwarder_t *forwarder) { return forwarder->acquired_msgbuf_ids; } @@ -1182,25 +1420,18 @@ void forwarder_acquired_msgbuf_ids_push(const forwarder_t *forwarder, // ======================================================= -fib_t *forwarder_get_fib(forwarder_t *forwarder) { return forwarder->fib; } +fib_t *forwarder_get_fib(const forwarder_t *forwarder) { + return forwarder->fib; +} msgbuf_pool_t *forwarder_get_msgbuf_pool(const forwarder_t *forwarder) { return forwarder->msgbuf_pool; } -#ifdef WITH_MAPME -void forwarder_on_connection_event(const forwarder_t *forwarder, - const connection_t *connection, - connection_event_t event) { - mapme_on_connection_event(forwarder->mapme, connection, event); -} - mapme_t *forwarder_get_mapme(const forwarder_t *forwarder) { return forwarder->mapme; } -#endif /* WITH_MAPME */ - #ifdef WITH_POLICY_STATS const policy_stats_mgr_t *forwarder_get_policy_stats_mgr( const forwarder_t *forwarder) { @@ -1209,39 +1440,6 @@ const policy_stats_mgr_t *forwarder_get_policy_stats_mgr( #endif /* WITH_POLICY_STATS */ /** - * @brief Process a packet by creating the corresponding message buffer and - * dispatching it to the forwarder for further processing. - * @param[in] forwarder Forwarder instance. - * - */ -// XXX ??? XXX = process for listener as we are resolving connection id -// - -msgbuf_type_t get_type_from_packet(uint8_t *packet) { - if (messageHandler_IsTCP(packet)) { - if (messageHandler_IsData(packet)) { - return MSGBUF_TYPE_DATA; - } else if (messageHandler_IsInterest(packet)) { - return MSGBUF_TYPE_INTEREST; - } else { - return MSGBUF_TYPE_UNDEFINED; - } - - } else if (messageHandler_IsWldrNotification(packet)) { - return MSGBUF_TYPE_WLDR_NOTIFICATION; - - } else if (mapme_match_packet(packet)) { - return MSGBUF_TYPE_MAPME; - - } else if (*packet == REQUEST_LIGHT) { - return MSGBUF_TYPE_COMMAND; - - } else { - return MSGBUF_TYPE_UNDEFINED; - } -} - -/** * @brief Finalize (i.e. close fd and free internal data structures) * the current connection ("SELF") when the command is received. * The connection cannot be removed inside the command handling @@ -1268,7 +1466,6 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener, msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); assert(msgbuf); - uint8_t *packet = msgbuf_get_packet(msgbuf); size_t size = msgbuf_get_len(msgbuf); /* Connection lookup */ @@ -1281,81 +1478,128 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener, assert((conn_id != CONNECTION_ID_UNDEFINED) || listener); +#if 0 + /* + * We have a msgbuf with payload and size, we nee to populate other + * information, including packet type etc. + */ msgbuf_type_t type = get_type_from_packet(msgbuf_get_packet(msgbuf)); forwarder->stats.countReceived++; msgbuf->type = type; +#endif + /* Initialize packet buffer stored in msgbuf through libhicn */ + msgbuf_initialize_from_packet(msgbuf); + hicn_packet_analyze(msgbuf_get_pkbuf(msgbuf)); + msgbuf->connection_id = conn_id; msgbuf->recv_ts = now; - switch (type) { - case MSGBUF_TYPE_INTEREST: + hicn_name_t name; + +RETRY: + + switch (msgbuf_get_type(msgbuf)) { + case HICN_PACKET_TYPE_INTEREST: if (!connection_id_is_valid(msgbuf->connection_id)) { char conn_name[SYMBOLIC_NAME_LEN]; int rc = connection_table_get_random_name(table, conn_name); - if (rc < 0) return 0; + if (rc < 0) { + ERROR("Could not create name for new connection"); + goto DROP; + } unsigned connection_id = listener_create_connection(listener, conn_name, pair); + if (connection_id == CONNECTION_ID_UNDEFINED) { + ERROR("Could not create new connection"); + goto DROP; + } msgbuf->connection_id = connection_id; connection = connection_table_get_by_id(table, connection_id); } msgbuf->path_label = 0; // not used for interest packets - name_create_from_interest(packet, msgbuf_get_name(msgbuf)); + hicn_interest_get_name(msgbuf_get_pkbuf(msgbuf), &name); + msgbuf_set_name(msgbuf, &name); +#ifdef WITH_WLDR forwarder_apply_wldr(forwarder, msgbuf, connection); +#endif /* WITH_WLDR */ forwarder_process_interest(forwarder, msgbuf_id); pkt_cache_log(forwarder->pkt_cache); - return size; + break; - case MSGBUF_TYPE_DATA: - if (!connection_id_is_valid(msgbuf->connection_id)) - return forwarder_drop(forwarder, msgbuf_id); + case HICN_PACKET_TYPE_DATA: + /* This include probes */ + if (!connection_id_is_valid(msgbuf->connection_id)) { + ERROR("Invalid connection for data packet"); + goto DROP; + } msgbuf_init_pathlabel(msgbuf); - name_create_from_data(packet, msgbuf_get_name(msgbuf)); + hicn_data_get_name(msgbuf_get_pkbuf(msgbuf), &name); + msgbuf_set_name(msgbuf, &name); +#ifdef WITH_WLDR forwarder_apply_wldr(forwarder, msgbuf, connection); +#endif /* WITH_WLDR */ forwarder_process_data(forwarder, msgbuf_id); pkt_cache_log(forwarder->pkt_cache); - return size; + break; - case MSGBUF_TYPE_WLDR_NOTIFICATION: - if (!connection_id_is_valid(msgbuf->connection_id)) - return forwarder_drop(forwarder, msgbuf_id); + case HICN_PACKET_TYPE_WLDR_NOTIFICATION: + if (!connection_id_is_valid(msgbuf->connection_id)) { + ERROR("Invalid connection for WLDR packet"); + goto DROP; + } connection_wldr_handle_notification(connection, msgbuf); - return size; + break; - case MSGBUF_TYPE_MAPME: + case HICN_PACKET_TYPE_MAPME: // XXX what about acks ? if (!connection_id_is_valid(msgbuf->connection_id)) { char conn_name[SYMBOLIC_NAME_LEN]; int rc = connection_table_get_random_name(table, conn_name); - if (rc < 0) return 0; + if (rc < 0) { + ERROR("Could not create name for new connection"); + goto DROP; + } - msgbuf->connection_id = + unsigned connection_id = listener_create_connection(listener, conn_name, pair); + if (connection_id == CONNECTION_ID_UNDEFINED) { + ERROR("Could not create new connection"); + goto DROP; + } + msgbuf->connection_id = connection_id; } mapme_process(forwarder->mapme, msgbuf); - return size; + break; - case MSGBUF_TYPE_COMMAND: + case HICN_PACKET_TYPE_COMMAND: // Create the connection to send the ack back if (!connection_id_is_valid(msgbuf->connection_id)) { char conn_name[SYMBOLIC_NAME_LEN]; int rc = connection_table_get_random_name(table, conn_name); - if (rc < 0) return 0; + if (rc < 0) { + ERROR("Could not create name for new connection"); + goto DROP; + } unsigned connection_id = listener_create_connection(listener, conn_name, pair); + if (connection_id == CONNECTION_ID_UNDEFINED) { + ERROR("Could not create new connection"); + goto DROP; + } msgbuf->connection_id = connection_id; connection = connection_table_get_by_id(table, connection_id); } - msg_header_t *msg = (msg_header_t *)packet; + msg_header_t *msg = (msg_header_t *)msgbuf_get_packet(msgbuf); msgbuf->command.type = msg->header.command_id; if (!command_type_is_valid(msgbuf->command.type)) { - ERROR("Invalid command"); - return 0; + ERROR("Invalid command %d", msgbuf->command.type); + goto DROP; } size = command_process_msgbuf(forwarder, msgbuf); @@ -1364,19 +1608,32 @@ ssize_t forwarder_receive(forwarder_t *forwarder, listener_t *listener, return size; default: - ERROR("Invalid msgbuf type"); - forwarder_drop(forwarder, msgbuf_id); - return 0; + /* Commands are not recognized by the packet parser */ + if (msgbuf_is_command(msgbuf)) { + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); + goto RETRY; + } + goto DROP; } + + return size; + +DROP: + forwarder_drop(forwarder, msgbuf_id); + return 0; } void forwarder_log(forwarder_t *forwarder) { DEBUG( "Forwarder: received = %u (interest = %u, data = %u), dropped = %u " - "(interest = %u, data = %u, other = %u), forwarded = { interests = %u, " - "data = %u }, dropped = { connection_not_found = %u, send_failure = %u, " + "(interest = %u, data = %u, other = %u), forwarded = { interests = " + "%u, " + "data = %u }, dropped = { connection_not_found = %u, send_failure " + "= " + "%u, " "no_route_in_fib = %u }, interest processing = { aggregated = %u, " - "retransmitted = %u, satisfied_from_cs = %u, expired_interests = %u, " + "retransmitted = %u, satisfied_from_cs = %u, expired_interests = " + "%u, " "expired_data = %u }, data processing = { " "no_reverse_path = %u }\n", forwarder->stats.countReceived, forwarder->stats.countInterestsReceived, @@ -1396,4 +1653,4 @@ void forwarder_log(forwarder_t *forwarder) { forwarder_stats_t forwarder_get_stats(forwarder_t *forwarder) { return forwarder->stats; -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/core/forwarder.h b/hicn-light/src/hicn/core/forwarder.h index 2f940cf15..b7ce5ff4d 100644 --- a/hicn-light/src/hicn/core/forwarder.h +++ b/hicn-light/src/hicn/core/forwarder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -74,7 +74,7 @@ void forwarder_setup_local_listeners(forwarder_t *forwarder, uint16_t port); configuration_t *forwarder_get_configuration(forwarder_t *forwarder); -subscription_table_t *forwarder_get_subscriptions(forwarder_t *forwarder); +subscription_table_t *forwarder_get_subscriptions(const forwarder_t *forwarder); /** * Returns the set of currently active listeners @@ -84,7 +84,7 @@ subscription_table_t *forwarder_get_subscriptions(forwarder_t *forwarder); * @retval non-null The set of active listeners * @retval null An error */ -listener_table_t *forwarder_get_listener_table(forwarder_t *forwarder); +listener_table_t *forwarder_get_listener_table(const forwarder_t *forwarder); /** * Returns the forwrder's connection table @@ -122,40 +122,43 @@ void forwarder_cs_clear(forwarder_t *forwarder); /** * @brief Adds or updates a route on all the message processors */ -bool forwarder_add_or_update_route(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_add_or_update_route(forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, unsigned ingress_id); /** * @brief Removes a route from all the message processors */ -bool forwarder_remove_route(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_remove_route(forwarder_t *forwarder, hicn_ip_prefix_t *prefix, unsigned ingress_id); #ifdef WITH_POLICY /** * @brief Adds or updates a policy on the message processor */ -bool forwarder_add_or_update_policy(forwarder_t *forwarder, ip_prefix_t *prefix, +bool forwarder_add_or_update_policy(forwarder_t *forwarder, + hicn_ip_prefix_t *prefix, hicn_policy_t *policy); /** * @brief Removes a policy from the message processor */ -bool forwarder_remove_policy(forwarder_t *forwarder, ip_prefix_t *prefix); +bool forwarder_remove_policy(forwarder_t *forwarder, hicn_ip_prefix_t *prefix); #endif /* WITH_POLICY */ /** * Removes a connection id from all routes */ -void forwarder_remove_connection_id_from_routes(forwarder_t *forwarder, +void forwarder_remove_connection_id_from_routes(const forwarder_t *forwarder, unsigned connection_id); -void forwarder_add_strategy_options(forwarder_t *forwarder, Name *name_prefix, +void forwarder_add_strategy_options(forwarder_t *forwarder, + hicn_prefix_t *name_prefix, strategy_type_t strategy_type, strategy_options_t *strategy_options); -void forwarder_set_strategy(forwarder_t *forwarder, Name *name_prefix, +void forwarder_set_strategy(forwarder_t *forwarder, hicn_prefix_t *prefix, strategy_type_t strategy_type, strategy_options_t *strategy_options); @@ -178,7 +181,7 @@ void forwarder_acquired_msgbuf_ids_push(const forwarder_t *forwarder, * @param[in] forwarder - Pointer to the forwarder. * @returns Pointer to the hICN FIB. */ -fib_t *forwarder_get_fib(forwarder_t *forwarder); +fib_t *forwarder_get_fib(const forwarder_t *forwarder); /** * @brief Return the forwarder packet pool. @@ -190,6 +193,16 @@ msgbuf_pool_t *forwarder_get_msgbuf_pool(const forwarder_t *forwarder); #ifdef WITH_MAPME +void forwarder_on_route_event(const forwarder_t *forwarder, fib_entry_t *entry); + +int forwarder_add_connection(const forwarder_t *forwarder, + const char *symbolic_name, face_type_t type, + address_pair_t *pair, policy_tags_t tags, + int priority, face_state_t admin_state); + +int forwarder_remove_connection(const forwarder_t *forwarder, + unsigned connection_id, bool finalize); + /** * @brief Callback fired upon addition of a new connection through the * control protocol. diff --git a/hicn-light/src/hicn/core/interest_manifest.c b/hicn-light/src/hicn/core/interest_manifest.c deleted file mode 100644 index 1be8a3fb5..000000000 --- a/hicn-light/src/hicn/core/interest_manifest.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2022 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "interest_manifest.h" - -int_manifest_split_strategy_t disaggregation_strategy = - INT_MANIFEST_SPLIT_MAX_N_SUFFIXES; -unsigned N_SUFFIXES_PER_SPIT = 256; - -bool interest_manifest_is_valid(interest_manifest_header_t *int_manifest_header, - size_t payload_length) { - if (int_manifest_header->n_suffixes == 0 || - int_manifest_header->n_suffixes > MAX_SUFFIXES_IN_MANIFEST) { - ERROR("Manifest with invalid number of suffixes (%d)", - int_manifest_header->n_suffixes); - return false; - } - - uint32_t empty_bitmap[BITMAP_SIZE] = {0}; - if (memcmp(empty_bitmap, int_manifest_header->request_bitmap, - sizeof(empty_bitmap)) == 0) { - ERROR("Manifest with empty bitmap"); - return false; - } - - if (payload_length - sizeof(interest_manifest_header_t) != - int_manifest_header->n_suffixes * sizeof(u32)) { - ERROR("Size of suffixes in intereset manifest (%d) is not equal to %d", - payload_length - sizeof(interest_manifest_header_t), - int_manifest_header->n_suffixes * sizeof(u32)); - return false; - } - - return true; -} - -int interest_manifest_update_bitmap(const u32 *initial_bitmap, - u32 *bitmap_to_update, int start, int n, - int max_suffixes) { - int i = start, n_ones = 0; - while (i < n) { - if (is_bit_set(initial_bitmap, i)) { - set_bit(bitmap_to_update, i); - n_ones++; - } - i++; - - if (n_ones == max_suffixes) break; - } - - return i; -} diff --git a/hicn-light/src/hicn/core/interest_manifest.h b/hicn-light/src/hicn/core/interest_manifest.h deleted file mode 100644 index fcb2b9897..000000000 --- a/hicn-light/src/hicn/core/interest_manifest.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2022 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef HICNLIGHT_INTEREST_MANIFEST_H -#define HICNLIGHT_INTEREST_MANIFEST_H - -#include <string.h> -#include <stdbool.h> - -#include <hicn/util/log.h> -#include <hicn/base.h> - -typedef enum { - INT_MANIFEST_SPLIT_NONE, - INT_MANIFEST_SPLIT_MAX_N_SUFFIXES -} int_manifest_split_strategy_t; - -extern int_manifest_split_strategy_t disaggregation_strategy; -extern unsigned N_SUFFIXES_PER_SPIT; - -bool interest_manifest_is_valid(interest_manifest_header_t *int_manifest_header, - size_t payload_length); - -int interest_manifest_update_bitmap(const u32 *initial_bitmap, - u32 *bitmap_to_update, int start, int n, - int max_suffixes); - -#endif /* HICNLIGHT_INTEREST_MANIFEST_H */ diff --git a/hicn-light/src/hicn/core/listener.c b/hicn-light/src/hicn/core/listener.c index 188f0c317..a3c5c8a12 100644 --- a/hicn-light/src/hicn/core/listener.c +++ b/hicn-light/src/hicn/core/listener.c @@ -247,38 +247,8 @@ unsigned listener_create_connection(listener_t *listener, connection_table_print_by_pair(table); }) -#if 0 - DEBUG("Notification for new connections"); - // Generate notification message - flag_interface_type_t interface_type = - FLAG_INTERFACE_TYPE_WIRED | FLAG_INTERFACE_TYPE_CELLULAR; - struct { - cmd_header_t header; - hc_event_interface_update_t payload; - } msg = {.header = - { - .message_type = NOTIFICATION_LIGHT, - .command_id = EVENT_INTERFACE_UPDATE, - .length = 0, - .seq_num = 0, - }, - .payload = {.interface_type = interface_type}}; - size_t size = sizeof(msg); - - // Retrieve subscribed connections - subscription_table_t *subscriptions = - forwarder_get_subscriptions(listener->forwarder); - unsigned *subscribed_conn_ids = subscription_table_get_connections_for_topic( - subscriptions, TOPIC_CONNECTION); - - // Send notification to subscribed connections - for (int i = 0; i < vector_len(subscribed_conn_ids); i++) { - DEBUG("Sending notification to connection: %u", subscribed_conn_ids[i]); - const connection_t *conn = - connection_table_at(table, subscribed_conn_ids[i]); - connection_send_packet(conn, (uint8_t *)&msg, size); - } -#endif + forwarder_on_connection_event(listener->forwarder, connection, + CONNECTION_EVENT_CREATE); return connection_id; } @@ -441,4 +411,4 @@ void listener_setup_local(forwarder_t *forwarder, uint16_t port) { address_t localhost_ipv6_addr = ADDRESS6_LOCALHOST(port); listener_create(FACE_TYPE_UDP_LISTENER, &localhost_ipv6_addr, "lo", "lo_udp6", forwarder); -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/core/listener_table.c b/hicn-light/src/hicn/core/listener_table.c index 220b738bb..c130399a5 100644 --- a/hicn-light/src/hicn/core/listener_table.c +++ b/hicn-light/src/hicn/core/listener_table.c @@ -58,7 +58,7 @@ void listener_table_free(listener_table_t *table) { kh_foreach(table->id_by_key, k_key, v, { listener = listener_table_get_by_id(table, v); name = listener_get_name(listener); - INFO("Removing listner %s [%d]", name, listener->fd); + INFO("Removing listener %s [%d]", name, listener->fd); listener_finalize(listener); }); @@ -199,4 +199,4 @@ void listener_table_print_by_name(const listener_table_t *table) { INFO("%s:%d - %s\t\t\t\t(%u, %s)", addr_str, port, face_type_str(key->type), v, k); }) -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/core/listener_table.h b/hicn-light/src/hicn/core/listener_table.h index 7e2e99d7f..27c5daa04 100644 --- a/hicn-light/src/hicn/core/listener_table.h +++ b/hicn-light/src/hicn/core/listener_table.h @@ -161,9 +161,13 @@ listener_t *_listener_table_get_by_id(listener_table_t *table, off_t id); #define listener_table_get_listener_id(table, listener) \ (listener - table->listeners) -#define listener_table_foreach(table, listener, BODY) \ - pool_foreach( \ - table->listeners, listener, do { BODY } while (0)) +#define listener_table_foreach(table, listener, BODY) \ + do { \ + listener_t *listener; \ + (void)listener; \ + pool_foreach( \ + table->listeners, listener, do { BODY } while (0)); \ + } while (0) #define listener_table_enumerate(table, i, conn, BODY) \ pool_enumerate(table->listeners, (i), (conn), BODY) diff --git a/hicn-light/src/hicn/core/mapme.c b/hicn-light/src/hicn/core/mapme.c index dfb30da5c..b151d6cb0 100644 --- a/hicn-light/src/hicn/core/mapme.c +++ b/hicn-light/src/hicn/core/mapme.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -294,15 +294,6 @@ static void mapme_create_tfib(const mapme_t *mapme, fib_entry_t *entry) { fib_entry_set_user_data(entry, tfib, (void (*)(void **))mapme_release_tfib); } -int hicn_prefix_from_name(const Name *name, hicn_prefix_t *prefix) { - NameBitvector *bv = name_GetContentName(name); - ip_prefix_t ip_prefix; - nameBitvector_ToIPAddress(bv, &ip_prefix); - - /* The name length will be equal to ip address' prefix length */ - return hicn_prefix_create_from_ip_prefix(&ip_prefix, prefix); -} - /** * @brief Update/Notification heuristic: * @@ -350,12 +341,14 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, tfib = TFIB(entry); } - const Name *name = fib_entry_get_prefix(entry); + const hicn_prefix_t *prefix = fib_entry_get_prefix(entry); WITH_DEBUG({ - char *name_str = name_ToString(name); - DEBUG("sending IU/IN for name %s on all nexthops", name_str); - free(name_str); + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("sending IU/IN for name %s on all nexthops", buf); }) mapme_params_t params = { @@ -364,14 +357,8 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, .seq = tfib->seq, }; - hicn_prefix_t prefix; - if (hicn_prefix_from_name(name, &prefix) < 0) { - ERROR("Failed to create lib's name"); - return -1; - } - uint8_t packet[MTU]; - size_t size = hicn_mapme_create_packet(packet, &prefix, ¶ms); + size_t size = hicn_mapme_create_packet(packet, prefix, ¶ms); if (size <= 0) { ERROR("Could not create MAP-Me packet"); return -1; @@ -379,7 +366,6 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, connection_table_t *table = forwarder_get_connection_table(mapme->forwarder); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { INFO("sending mapme packet on connection %d", nexthop); const connection_t *conn = connection_table_get_by_id(table, nexthop); @@ -389,6 +375,7 @@ int mapme_send_to_nexthops(const mapme_t *mapme, fib_entry_t *entry, return 0; } +#if 0 /** * * Here nexthops is not necessarily FIB nexthops as we might advertise given FIB @@ -410,6 +397,7 @@ void mapme_maybe_send_to_nexthops(const mapme_t *mapme, fib_entry_t *fib_entry, mapme_send_to_nexthops(mapme, fib_entry, nexthops); } +#endif /****************************************************************************** * MAPME API @@ -423,15 +411,16 @@ int mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry) { /* Apply the policy of the fib_entry over all neighbours */ nexthops_t new_nexthops = NEXTHOPS_EMPTY; - nexthops_t *nexthops = - fib_entry_get_available_nexthops(entry, ~0, &new_nexthops); + nexthops_t *nexthops = fib_entry_get_mapme_nexthops(entry, &new_nexthops); /* We set force to true to avoid overriding the FIB cache */ - return mapme_set_adjacencies(mapme, entry, nexthops, true); + return mapme_set_adjacencies(mapme, entry, nexthops); } +// XXX this will change with the FIB cache +// XXX we are sometimes incrementing tfib seq for nothing int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry, - nexthops_t *nexthops, bool force) { + nexthops_t *nexthops) { if (mapme->enabled == false) { WARN("MAP-Me is NOT enabled"); return -1; @@ -449,12 +438,7 @@ int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry, nexthops_clear(&tfib->nexthops); tfib->seq++; - if (force) { - mapme_send_to_nexthops(mapme, entry, nexthops); - return 0; - } - - mapme_maybe_send_to_nexthops(mapme, entry, nexthops); + mapme_send_to_nexthops(mapme, entry, nexthops); return 0; } @@ -473,7 +457,7 @@ int mapme_update_adjacencies(const mapme_t *mapme, fib_entry_t *entry, if (inc_iu_seq) tfib->seq++; - mapme_maybe_send_to_nexthops(mapme, entry, &tfib->nexthops); + mapme_send_to_nexthops(mapme, entry, &tfib->nexthops); return 0; } @@ -490,6 +474,7 @@ int mapme_send_to_nexthop(const mapme_t *mapme, fib_entry_t *entry, return mapme_send_to_nexthops(mapme, entry, &nexthops); } +#if 0 /* * Callback called everytime a new connection is created by the control protocol */ @@ -539,9 +524,9 @@ void mapme_on_connection_event(const mapme_t *mapme, /* We need to send a MapMe update on the newly selected connections for * each concerned fib_entry : connection is involved, or no more involved */ const fib_t *fib = forwarder_get_fib(mapme->forwarder); - fib_entry_t *entry; fib_foreach_entry(fib, entry, { mapme_set_all_adjacencies(mapme, entry); }); } +#endif /*------------------------------------------------------------------------------ * Special Interest handling @@ -811,30 +796,25 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, uint8_t *ack_packet = msgbuf_get_packet(ack); size_t size = hicn_mapme_create_ack(ack_packet, params); - if (connection_send_packet(conn_in, ack_packet, size) < 0) { + if (!connection_send_packet(conn_in, ack_packet, size)) { /* We accept the packet knowing we will get a retransmit */ ERROR("Failed to send ACK packet"); } msgbuf_pool_put(msgbuf_pool, ack); - /* process received interest */ - uint8_t *packet = msgbuf_get_packet(msgbuf); - name_create_from_interest(packet, msgbuf_get_name(msgbuf)); - Name name = EMPTY_NAME; - name_Copy(msgbuf_get_name(msgbuf), &name); - name_setLen(&name, prefix->len); - WITH_DEBUG({ - char *name_str = name_ToString(&name); - DEBUG("Ack'ed interest : connection=%d prefix=%s seq=%d", ingress_id, - name_str, params->seq); - free(name_str); + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "%s", "(error)"); + DEBUG("Ack'ed interest : connection=%d prefix=%s seq=%d", ingress_id, buf, + params->seq); }); /* EPM on FIB */ const fib_t *fib = forwarder_get_fib(mapme->forwarder); - fib_entry_t *entry = fib_contains(fib, &name); + fib_entry_t *entry = fib_contains(fib, prefix); if (!entry) { #ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY if (mapme_create_fib_entry(mapme, &name, ingress_id) < 0) { @@ -883,7 +863,6 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, * This could might optimized for situations where nothing changes, but * this is very unlikely if not impossible... * */ - unsigned prevhop; nexthops_foreach(&entry->nexthops, prevhop, { nexthops_add(&tfib->nexthops, prevhop); }); nexthops_remove(&tfib->nexthops, ingress_id); @@ -943,23 +922,17 @@ static void mapme_on_interest(mapme_t *mapme, msgbuf_t *msgbuf, static void mapme_on_data(mapme_t *mapme, msgbuf_t *msgbuf, unsigned ingress_id, hicn_prefix_t *prefix, mapme_params_t *params) { - INFO("Receive IU/IN Ack on connection %d", ingress_id); - - uint8_t *packet = msgbuf_get_packet(msgbuf); - name_create_from_data(packet, msgbuf_get_name(msgbuf)); - Name name = EMPTY_NAME; - name_Copy(msgbuf_get_name(msgbuf), &name); - name_setLen(&name, prefix->len); - WITH_DEBUG({ - char *name_str = name_ToString(&name); - DEBUG("Received ack for name prefix=%s seq=%d on conn id=%d", name_str, + char buf[MAXSZ_HICN_PREFIX]; + int rc = hicn_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); + if (rc < 0 || rc >= MAXSZ_HICN_PREFIX) + snprintf(buf, MAXSZ_HICN_PREFIX, "(error)"); + DEBUG("Received ack for name prefix=%s seq=%d on conn id=%d", buf, params->seq, ingress_id); - free(name_str); }) const fib_t *fib = forwarder_get_fib(mapme->forwarder); - fib_entry_t *entry = fib_contains(fib, &name); + fib_entry_t *entry = fib_contains(fib, prefix); if (!entry) { INFO("Ignored ACK with no corresponding FIB entry"); return; @@ -1031,6 +1004,7 @@ void mapme_process(mapme_t *mapme, msgbuf_t *msgbuf) { } } +#if 0 /* * Returns true iif the message corresponds to a MAP-Me packet */ @@ -1048,6 +1022,7 @@ bool mapme_match_packet(const uint8_t *packet) { return false; } } +#endif void mapme_set_enable(mapme_t *mapme, bool enable) { mapme->enabled = enable; } void mapme_set_discovery(mapme_t *mapme, bool enable) { diff --git a/hicn-light/src/hicn/core/mapme.h b/hicn-light/src/hicn/core/mapme.h index 8c2ca477f..188607421 100644 --- a/hicn-light/src/hicn/core/mapme.h +++ b/hicn-light/src/hicn/core/mapme.h @@ -26,7 +26,7 @@ #include <stdbool.h> #include <stdint.h> -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> #include <hicn/hicn.h> #include "connection.h" @@ -87,7 +87,7 @@ int mapme_set_all_adjacencies(const mapme_t *mapme, fib_entry_t *entry); * @param [in] nexthops - next hops on which to send the update. */ int mapme_set_adjacencies(const mapme_t *mapme, fib_entry_t *entry, - nexthops_t *nexthops, bool force); + nexthops_t *nexthops); /** * @function mapme_update_adjacencies diff --git a/hicn-light/src/hicn/core/messageHandler.h b/hicn-light/src/hicn/core/messageHandler.h deleted file mode 100644 index fe26d0579..000000000 --- a/hicn-light/src/hicn/core/messageHandler.h +++ /dev/null @@ -1,660 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef HICNLIGHT_MESSAGE_HANDLER_H -#define HICNLIGHT_MESSAGE_HANDLER_H - -#include <stdlib.h> -#ifndef _WIN32 -#include <unistd.h> // close -#endif /* _WIN32 */ - -#include <hicn/hicn.h> - -//#include <hicn/core/connection_table.h> - -#define H(packet) ((hicn_header_t *)packet) -#define H6(packet) (H(packet)->v6.ip) -#define H6T(packet) (H(packet)->v6.tcp) -#define H4(packet) (H(packet)->v4.ip) -#define H4T(packet) (H(packet)->v4.tcp) - -#define HICN_V6_LEN(packet) (H6(packet).len) -#define HICN_V4_LEN(packet) (H4(packet).len) - -/*** codes and types ***/ -#define IPv6_TYPE 6 -#define IPv4_TYPE 4 -#define ICMP_WLDR_TYPE 42 -#define ICMP_WLDR_CODE 0 -#define ICMP_LB_TYPE 43 - -/*** masks and constants ***/ -#define PATH_LABEL_MASK 0x8000 // 1000 0000 0000 0000 -#define NOT_PATH_LABEL_MASK 0x7fff // 0111 0000 0000 0000 -#define UINT16_T_MASK 0x0000ffff // 1111 1111 1111 1111 - -/*** HICN ALLOWED PORTS ***/ -#define CONTROL_PORT 9695 -#define HTTP_PORT 8080 - -#define MIN_PROBE_SUFFIX 0xefffffff -#define MAX_PROBE_SUFFIX 0xffffffff - 1 - -// XXX Hardcoded packet format HF_INET6_TCP - -#define IPV6_DEFAULT_VERSION 6 -#define IPV6_DEFAULT_TRAFFIC_CLASS 0 -#define IPV6_DEFAULT_FLOW_LABEL 0 - -//#include <hicn/core/forwarder.h> - -//#ifdef WITH_MAPME -//#include <hicn/core/mapme.h> -//#include <hicn/socket/api.h> -//#endif /* WITH_MAPME */ - -#define BFD_PORT 3784 - -static inline uint8_t messageHandler_GetIPPacketType(const uint8_t *message) { - return HICN_IP_VERSION(message); -} - -static inline void messageHandler_UpdateTCPCheckSum(uint8_t *message, - uint16_t *old_val, - uint16_t *new_val, - uint8_t size) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv4_TYPE: - for (uint8_t i = 0; i < size; i++) { - uint16_t old_csum = ~(H4T(message).csum); - uint16_t not_old_val = ~(*old_val); - uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val; - - while (sum >> 16) { - sum = (sum >> 16) + (sum & UINT16_T_MASK); - } - - H4T(message).csum = ~sum; - ++old_val; - ++new_val; - } - break; - case IPv6_TYPE: - for (uint8_t i = 0; i < size; i++) { - uint16_t old_csum = ~(H6T(message).csum); - uint16_t not_old_val = ~(*old_val); - uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val; - - while (sum >> 16) { - sum = (sum >> 16) + (sum & UINT16_T_MASK); - } - - H6T(message).csum = ~sum; - ++old_val; - ++new_val; - } - break; - default: - return; - } -} - -static inline void messageHandler_UpdateIPv4CheckSum(uint8_t *message, - uint16_t *old_val, - uint16_t *new_val, - uint8_t size) { - for (uint8_t i = 0; i < size; i++) { - uint16_t old_csum = ~(H4(message).csum); - uint16_t not_old_val = ~(*old_val); - uint32_t sum = (uint32_t)old_csum + not_old_val + *new_val; - - while (sum >> 16) { - sum = (sum >> 16) + (sum & UINT16_T_MASK); - } - - H4(message).csum = ~sum; - ++old_val; - ++new_val; - } -} - -static inline size_t messageHandler_GetEmptyTCPPacketSize(unsigned ipVersion) { - if (ipVersion == IPv4_TYPE) - return IPV4_HDRLEN + TCP_HDRLEN; - else if (ipVersion == IPv6_TYPE) - return IPV6_HDRLEN + TCP_HDRLEN; - else - return 0; -} - -static inline size_t messageHandler_GetICMPPacketSize(unsigned ipVersion) { - if (ipVersion == IPv4_TYPE) - return IPV4_HDRLEN + ICMP_HDRLEN; - else if (ipVersion == IPv6_TYPE) - return IPV6_HDRLEN + ICMP_HDRLEN; - else - return 0; -} - -static inline size_t messageHandler_GetIPHeaderLength(unsigned ipVersion) { - if (ipVersion == IPv4_TYPE) - return IPV4_HDRLEN; - else if (ipVersion == IPv6_TYPE) - return IPV6_HDRLEN; - else - return 0; -} - -#if 0 -static inline bool messageHandler_IsValidHicnPacket(const uint8_t *message) { - uint8_t version = messageHandler_GetIPPacketType(message); - if (version == IPv6_TYPE || version == IPv4_TYPE) { - return true; - } - return false; -} -#endif - -static inline uint8_t messageHandler_NextHeaderType(const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return (uint8_t)H6(message).nxt; - case IPv4_TYPE: - return (uint8_t)H4(message).protocol; - default: - return 0; - } -} - -static inline bool messageHandler_IsTCP(const uint8_t *message) { - if (messageHandler_NextHeaderType(message) != IPPROTO_TCP) return false; - return true; -} - -static inline bool messageHandler_IsInterest(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return false; - - bool flag; - hicn_packet_test_ece(HF_INET6_TCP, (hicn_header_t *)message, - &flag); // ECE flag is set to 0 in interest packets - if (flag == false) return true; - return false; -} - -static inline bool messageHandler_IsData(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return false; - - bool flag; - hicn_packet_test_ece(HF_INET6_TCP, (hicn_header_t *)message, - &flag); // ECE flag is set to 1 in data packets - if (flag == true) return true; - return false; -} - -static inline bool messageHandler_IsWldrNotification(const uint8_t *message) { - // this function returns true only if the packet is an ICMP packet in Wldr - // form. type must be equal to ICMP_WLDR_TYPE and code equal to ICMP_WLDR_CODE - uint8_t next_header = messageHandler_NextHeaderType(message); - - const uint8_t *icmp_ptr; - if (next_header == IPPROTO_ICMP) { - icmp_ptr = message + IPV4_HDRLEN; - } else if (next_header == IPPROTO_ICMPV6) { - icmp_ptr = message + IPV6_HDRLEN; - } else { - return false; - } - - uint8_t type = ((_icmp_header_t *)icmp_ptr)->type; - uint8_t code = ((_icmp_header_t *)icmp_ptr)->code; - if (type == ICMP_WLDR_TYPE && code == ICMP_WLDR_CODE) { - return true; - } - - return false; -} - -static inline bool messageHandler_IsLoadBalancerProbe(const uint8_t *message) { - uint8_t next_header = messageHandler_NextHeaderType(message); - - const uint8_t *icmp_ptr; - if (next_header == IPPROTO_ICMP) { - icmp_ptr = message + IPV4_HDRLEN; - } else if (next_header == IPPROTO_ICMPV6) { - icmp_ptr = message + IPV6_HDRLEN; - } else { - return false; - } - - uint8_t type = ((_icmp_header_t *)icmp_ptr)->type; - if (type == ICMP_LB_TYPE) { - return true; - } - - return false; -} - -static inline uint16_t messageHandler_GetTotalPacketLength( - const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return ntohs((uint16_t)HICN_V6_LEN(message)) + IPV6_HDRLEN; - case IPv4_TYPE: - return ntohs((uint16_t)HICN_V4_LEN(message)); - default: - return 0; - } -} - -static inline uint32_t messageHandler_GetSegment(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return ntohl((uint32_t)H6T(message).seq); - case IPv4_TYPE: - return ntohl((uint32_t)H4T(message).seq); - default: - return 0; - } -} - -static inline uint16_t messageHandler_GetExpectedWldrLabel( - const uint8_t *message) { - const uint8_t *icmp_ptr; - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - icmp_ptr = message + IPV6_HDRLEN; - break; - case IPv4_TYPE: - icmp_ptr = message + IPV4_HDRLEN; - break; - default: - return 0; - } - - return ntohs( - ((_icmp_wldr_header_t *)icmp_ptr)->wldr_notification_lbl.expected_lbl); -} - -static inline uint16_t messageHandler_GetWldrLastReceived( - const uint8_t *message) { - const uint8_t *icmp_ptr; - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - icmp_ptr = message + IPV6_HDRLEN; - break; - case IPv4_TYPE: - icmp_ptr = message + IPV4_HDRLEN; - break; - default: - return 0; - } - - return ntohs( - ((_icmp_wldr_header_t *)icmp_ptr)->wldr_notification_lbl.received_lbl); -} - -static inline uint16_t messageHandler_GetWldrLabel(const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return ntohs((uint16_t)H6T(message).window); - case IPv4_TYPE: - return ntohs((uint16_t)H4T(message).window); - default: - return 0; - } -} - -static inline void messageHandler_SetWldrLabel(uint8_t *message, - uint16_t label) { - uint16_t old_val = messageHandler_GetWldrLabel(message); - - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - H6T(message).window = htons(label); - break; - case IPv4_TYPE: - H4T(message).window = htons(label); - break; - default: - break; - } - - messageHandler_UpdateTCPCheckSum(message, &old_val, &label, 1); -} - -static inline void messageHandler_ResetWldrLabel(uint8_t *message) { - messageHandler_SetWldrLabel(message, 0); -} - -static inline bool messageHandler_HasWldr(const uint8_t *message) { - if (messageHandler_IsTCP(message)) { - uint16_t lbl = messageHandler_GetWldrLabel(message); - if (lbl != 0) { - return true; - } - } - return false; -} - -static inline uint32_t messageHandler_GetPathLabel(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - uint32_t path_label; - int res = hicn_data_get_path_label((hicn_header_t *)message, &path_label); - if (res < 0) return 0; - return path_label; -} - -static inline void messageHandler_SetPathLabel(uint8_t *message, - uint32_t old_path_label, - uint32_t new_path_label) { - if (!messageHandler_IsTCP(message)) return; - - hicn_data_set_path_label((hicn_header_t *)message, new_path_label); - - messageHandler_UpdateTCPCheckSum(message, (uint16_t *)&old_path_label, - (uint16_t *)&new_path_label, 2); -} - -static inline void messageHandler_UpdatePathLabel(uint8_t *message, - uint8_t outFace) { - if (!messageHandler_IsTCP(message)) return; - - uint32_t pl_old_32bit = messageHandler_GetPathLabel(message); - uint8_t pl_old_8bit = (uint8_t)(pl_old_32bit >> 24UL); - uint32_t pl_new_32bit = - (uint32_t)((((pl_old_8bit << 1) | (pl_old_8bit >> 7)) ^ outFace) << 24UL); - - // XXX path label should be 8 bits now ? - messageHandler_SetPathLabel(message, pl_old_32bit, pl_new_32bit); -} - -static inline void messageHandler_ResetPathLabel(uint8_t *message) { - messageHandler_SetPathLabel(message, messageHandler_GetPathLabel(message), 0); -} - -static inline uint32_t messageHandler_GetInterestLifetime( - const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - hicn_lifetime_t lifetime; - int res = hicn_interest_get_lifetime((hicn_header_t *)message, &lifetime); - if (res < 0) return 0; - return lifetime; -} - -static inline bool messageHandler_SetInterestLifetime(uint8_t *message, - u32 lifetime) { - if (!messageHandler_IsTCP(message)) return false; - - int res = hicn_interest_set_lifetime((hicn_header_t *)message, lifetime); - if (res < 0) return false; - return true; -} - -static inline bool messageHandler_SetDataExpiryTime(uint8_t *message, - u32 lifetime) { - if (!messageHandler_IsTCP(message)) return false; - - int res = hicn_data_set_expiry_time((hicn_header_t *)message, lifetime); - if (res < 0) return false; - return true; -} - -static inline bool messageHandler_HasInterestLifetime(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return false; - - if (messageHandler_GetInterestLifetime(message) == 0) return false; - return true; -} - -static inline uint32_t messageHandler_GetContentExpiryTime( - const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - uint32_t expirationTime; - int res = - hicn_data_get_expiry_time((hicn_header_t *)message, &expirationTime); - if (res < 0) return 0; - return expirationTime; -} - -static inline bool messageHandler_HasContentExpiryTime(const uint8_t *message) { - if (!messageHandler_IsTCP(message)) return 0; - - uint32_t expirationTime; - int res = - hicn_data_get_expiry_time((hicn_header_t *)message, &expirationTime); - if (res < 0) return false; - - if (expirationTime == HICN_MAX_LIFETIME) return false; - - return true; -} - -static inline void *messageHandler_GetSource(const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return &H6(message).saddr; - break; - case IPv4_TYPE: - return &H4(message).saddr; - break; - default: - return NULL; - } -} - -static inline void *messageHandler_GetDestination(const uint8_t *message) { - switch (messageHandler_GetIPPacketType(message)) { - case IPv6_TYPE: - return &H6(message).daddr; - break; - case IPv4_TYPE: - return &H4(message).daddr; - break; - default: - return NULL; - } -} - -static inline void messageHandler_SetSource_IPv6(uint8_t *message, - struct in6_addr *address) { - if (messageHandler_IsTCP(message)) { - uint16_t *old_src = (uint16_t *)messageHandler_GetSource(message); - messageHandler_UpdateTCPCheckSum(message, old_src, (uint16_t *)address, 8); - } - H6(message).saddr.as_in6addr = *address; -} - -static inline void messageHandler_SetDestination_IPv6( - uint8_t *message, struct in6_addr *address) { - if (messageHandler_IsTCP(message)) { - uint16_t *old_dst = (uint16_t *)messageHandler_GetDestination(message); - messageHandler_UpdateTCPCheckSum(message, old_dst, (uint16_t *)address, 8); - } - H6(message).daddr.as_in6addr = *address; -} - -static inline void messageHandler_SetSource_IPv4(uint8_t *message, - uint32_t *address) { - // update tcp checksum - uint16_t *old_src = (uint16_t *)messageHandler_GetSource(message); - if (messageHandler_IsTCP(message)) { - messageHandler_UpdateTCPCheckSum(message, old_src, (uint16_t *)address, 2); - } - // update IPv4 cheksum - // the IPv4 checksum is not part of the psudo header for TCP checksum - // calculation we can update them separetelly - messageHandler_UpdateIPv4CheckSum(message, old_src, (uint16_t *)address, 2); - - H4(message).saddr.as_u32 = *address; -} - -static inline void messageHandler_SetDestination_IPv4(uint8_t *message, - uint32_t *address) { - uint16_t *old_dst = (uint16_t *)messageHandler_GetDestination(message); - if (messageHandler_IsTCP(message)) { - messageHandler_UpdateTCPCheckSum(message, old_dst, (uint16_t *)address, 2); - } - messageHandler_UpdateIPv4CheckSum(message, old_dst, (uint16_t *)address, 2); - H4(message).daddr.as_u32 = *address; -} - -static inline void messageHandler_SetWldrNotification(uint8_t *notification, - uint8_t *original, - uint16_t expected, - uint16_t received) { - hicn_header_t *h = (hicn_header_t *)notification; - switch (messageHandler_GetIPPacketType(original)) { - case IPv6_TYPE: { - *h = (hicn_header_t){.v6 = { - .ip = - (_ipv6_header_t){ - .version_class_flow = htonl( - (IPV6_DEFAULT_VERSION << 28) | - (IPV6_DEFAULT_TRAFFIC_CLASS << 20) | - (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)), - .len = htons(ICMP_HDRLEN), - .nxt = IPPROTO_ICMPV6, - .hlim = 5, - }, - /* - .wldr = - { - .type = ICMP_WLDR_TYPE, - .code = ICMP_WLDR_CODE, - .wldr_notification_lbl = - { - .expected_lbl = htons(expected), - .received_lbl = htons(received), - }, - },*/ - }}; - messageHandler_SetSource_IPv6( - notification, - (struct in6_addr *)messageHandler_GetDestination(original)); - messageHandler_SetDestination_IPv6( - notification, (struct in6_addr *)messageHandler_GetSource(original)); - break; - } - case IPv4_TYPE: { - break; - } - default: - break; - } -} - -static inline void messageHandler_ModifySuffix(uint8_t *packet, - uint32_t new_suffix) { - hicn_format_t format; - hicn_name_t name; - hicn_packet_get_format((hicn_header_t *)packet, &format); - hicn_interest_get_name(format, (hicn_header_t *)packet, &name); - hicn_name_set_seq_number(&name, new_suffix); - hicn_interest_set_name(format, (hicn_header_t *)packet, &name); -} - -static inline uint8_t *messageHandler_CreateProbePacket( - hicn_format_t format, uint32_t probe_lifetime) { - size_t header_length; - hicn_packet_get_header_length_from_format(format, &header_length); - - uint8_t *pkt = (uint8_t *)calloc(header_length, 1); - - hicn_packet_init_header(format, (hicn_header_t *)pkt); - - hicn_packet_set_dst_port(format, (hicn_header_t *)pkt, BFD_PORT); - hicn_interest_set_lifetime((hicn_header_t *)pkt, probe_lifetime); - - return pkt; -} - -static inline void messageHandler_CreateProbeReply(uint8_t *probe, - hicn_format_t format) { - hicn_name_t probe_name; - hicn_interest_get_name(format, (const hicn_header_t *)probe, &probe_name); - ip_address_t probe_locator; - hicn_interest_get_locator(format, (const hicn_header_t *)probe, - &probe_locator); - - uint16_t src_prt; - uint16_t dst_prt; - hicn_packet_get_src_port(format, (const hicn_header_t *)probe, &src_prt); - hicn_packet_get_dst_port(format, (const hicn_header_t *)probe, &dst_prt); - hicn_packet_set_src_port(format, (hicn_header_t *)probe, dst_prt); - hicn_packet_set_dst_port(format, (hicn_header_t *)probe, src_prt); - - hicn_data_set_name(format, (hicn_header_t *)probe, &probe_name); - hicn_data_set_locator(format, (hicn_header_t *)probe, &probe_locator); - hicn_data_set_expiry_time((hicn_header_t *)probe, 0); -} - -static inline hicn_name_t *messageHandler_CreateProbeName( - const ip_prefix_t *address) { - hicn_name_t *name = (hicn_name_t *)calloc(sizeof(hicn_name_t), 1); - hicn_name_create_from_ip_prefix(address, 0, name); - return name; -} - -static inline void messageHandler_SetProbeName(uint8_t *probe, - hicn_format_t format, - hicn_name_t *name, - uint32_t seq) { - hicn_name_set_seq_number(name, seq); - hicn_interest_set_name(format, (hicn_header_t *)probe, name); -} - -static inline bool messageHandler_IsAProbe(const uint8_t *packet) { - hicn_format_t format; - hicn_name_t name; - uint32_t seq; - hicn_packet_get_format((hicn_header_t *)packet, &format); - hicn_data_get_name(format, (hicn_header_t *)packet, &name); - hicn_name_get_seq_number(&name, &seq); - if (seq >= MIN_PROBE_SUFFIX && seq <= MAX_PROBE_SUFFIX) return true; - return false; - -#if 0 - // old probe version - uint16_t src_prt; - uint16_t dst_prt; - hicn_packet_get_src_port (HF_INET6_TCP, (const hicn_header_t *) packet, &src_prt); - hicn_packet_get_dst_port (HF_INET6_TCP, (const hicn_header_t *) packet, &dst_prt); - - if(dst_prt == BFD_PORT){ - //interest probe - return true; - } - - if(src_prt == BFD_PORT){ - //data (could be a probe) - uint32_t expiry_time; - hicn_data_get_expiry_time ((const hicn_header_t *) packet, &expiry_time); - if(expiry_time == 0){ - //this is a probe - return true; - } - } - - return false; -#endif -} - -#endif /* HICNLIGHT_MESSAGE_HANDLER_H */ diff --git a/hicn-light/src/hicn/core/msgbuf.c b/hicn-light/src/hicn/core/msgbuf.c index 299b20f9b..c58f7a7dc 100644 --- a/hicn-light/src/hicn/core/msgbuf.c +++ b/hicn-light/src/hicn/core/msgbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,3 +19,37 @@ */ #include "msgbuf.h" +#include "../strategies/probe_generator.h" + +int msgbuf_initialize(msgbuf_t *msgbuf) { + /* + * We define the format and the storage area of the packet buffer we + * manipulate + */ + hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf); + hicn_packet_set_buffer(pkbuf, msgbuf->packet, MTU, 0); + hicn_packet_init_header(pkbuf, 0); + return 0; +} + +int msgbuf_initialize_from_packet(msgbuf_t *msgbuf) { + hicn_packet_set_buffer(msgbuf_get_pkbuf(msgbuf), msgbuf->packet, MTU, + msgbuf_get_len(msgbuf)); + return 0; +} + +bool msgbuf_is_command(const msgbuf_t *msgbuf) { + return (*msgbuf->packet == REQUEST_LIGHT); +} + +bool msgbuf_is_probe(const msgbuf_t *msgbuf) { + hicn_name_t name; + hicn_name_suffix_t suffix; + + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); + + const hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf); + hicn_data_get_name(pkbuf, &name); + suffix = hicn_name_get_suffix(&name); + return (suffix >= MIN_PROBE_SUFFIX && suffix <= MAX_PROBE_SUFFIX); +} diff --git a/hicn-light/src/hicn/core/msgbuf.h b/hicn-light/src/hicn/core/msgbuf.h index e437f1d09..26fd47540 100644 --- a/hicn-light/src/hicn/core/msgbuf.h +++ b/hicn-light/src/hicn/core/msgbuf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -21,10 +21,10 @@ #ifndef HICNLIGHT_MSGBUF #define HICNLIGHT_MSGBUF -#include "name.h" +#include <hicn/name.h> #include "ticks.h" -#include "messageHandler.h" -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/hicn.h> +#include <hicn/ctrl/hicn-light.h> #define MTU 1500 #define INVALID_MSGBUF_ID ~0ul @@ -32,33 +32,19 @@ #define msgbuf_id_is_valid(msgbuf_id) \ ((unsigned long)msgbuf_id != INVALID_MSGBUF_ID) -#define foreach_msg_type \ - _(UNDEFINED) \ - _(INTEREST) \ - _(DATA) \ - _(WLDR_NOTIFICATION) \ - _(MAPME) \ - _(COMMAND) \ - _(N) - -typedef enum { -#define _(x) MSGBUF_TYPE_##x, - foreach_msg_type -#undef _ -} msgbuf_type_t; -#undef foreach_msg_type - typedef struct { - unsigned length; - msgbuf_type_t type; - unsigned connection_id; - Ticks recv_ts; - unsigned refs; - unsigned path_label; + hicn_packet_buffer_t pkbuf; + unsigned connection_id; // ingress + Ticks recv_ts; // timestamp + unsigned refs; // refcount + unsigned path_label; // XXX what is this ? + + // XXX Cache storage union { /* Interest or data packet */ struct { - Name name; + hicn_name_t name; + u32 name_hash; // XXX should be always populate when name is assigned } id; /* Command packet */ struct { @@ -68,53 +54,142 @@ typedef struct { uint8_t packet[MTU]; } msgbuf_t; -#define msgbuf_get_name(M) (&((M)->id.name)) +int msgbuf_initialize(msgbuf_t *msgbuf); +int msgbuf_initialize_from_packet(msgbuf_t *msgbuf); + +#define msgbuf_get_pkbuf(M) (&(M)->pkbuf) + +static inline hicn_packet_type_t msgbuf_get_type(const msgbuf_t *msgbuf) { + return hicn_packet_get_type(msgbuf_get_pkbuf(msgbuf)); +} + +static inline void msgbuf_set_type(msgbuf_t *msgbuf, hicn_packet_type_t type) { + hicn_packet_set_type(msgbuf_get_pkbuf(msgbuf), type); +} + +static inline const hicn_name_t *msgbuf_get_name(const msgbuf_t *msgbuf) { + hicn_packet_type_t type = msgbuf_get_type(msgbuf); + assert(type == HICN_PACKET_TYPE_INTEREST || type == HICN_PACKET_TYPE_DATA); + (void)type; + + return &msgbuf->id.name; +} + #define msgbuf_get_connection_id(M) ((M)->connection_id) -#define msgbuf_get_type(M) ((M)->type) -#define msgbuf_has_wldr(M) (messageHandler_HasWldr((M)->packet)) -#define msgbuf_get_len(M) ((M)->length) #define msgbuf_get_packet(M) ((M)->packet) #define msgbuf_get_command_type(M) ((M)->command.type) +#if WITH_WLDR +#define msgbuf_has_wldr(M) (messageHandler_HasWldr((M)->packet)) +#endif + +static inline void msgbuf_set_name(msgbuf_t *msgbuf, const hicn_name_t *name) { + msgbuf->id.name = *name; +} + +static inline size_t msgbuf_get_len(const msgbuf_t *msgbuf) { + return hicn_packet_get_len(msgbuf_get_pkbuf(msgbuf)); +} -// XXX TODO EXPLAIN THE CONSTANT -#define msgbuf_get_lifetime(M) \ - (NSEC_TO_TICKS(messageHandler_GetInterestLifetime((M)->packet) * 1000000ULL)) +static inline void msgbuf_set_len(msgbuf_t *msgbuf, size_t len) { + int rc = hicn_packet_set_len(msgbuf_get_pkbuf(msgbuf), len); + assert(rc == HICN_LIB_ERROR_NONE); // XXX + _unused(rc); +} + +static inline u32 msgbuf_get_name_hash(const msgbuf_t *msgbuf) { + hicn_packet_type_t type = msgbuf_get_type(msgbuf); + assert(type == HICN_PACKET_TYPE_INTEREST || type == HICN_PACKET_TYPE_DATA); + _unused(type); + return msgbuf->id.name_hash; +} // Lifetimes/expiry times in milliseconds -#define msgbuf_get_interest_lifetime(M) \ - (messageHandler_GetInterestLifetime((M)->packet)) -#define msgbuf_get_data_expiry_time(M) \ - (messageHandler_GetContentExpiryTime((M)->packet)) +static inline u32 msgbuf_get_interest_lifetime(const msgbuf_t *msgbuf) { + u32 lifetime; + int rc = hicn_interest_get_lifetime(msgbuf_get_pkbuf(msgbuf), &lifetime); + assert(rc == HICN_LIB_ERROR_NONE); // XXX + _unused(rc); + return lifetime; +} + +//#define msgbuf_get_lifetime(M) +// (NSEC_TO_TICKS(messageHandler_GetInterestLifetime((M)->packet) * +// 1000000ULL)) +#define msgbuf_get_lifetime msgbuf_get_interest_lifetime static inline bool msgbuf_set_interest_lifetime(msgbuf_t *msgbuf, u32 lifetime) { - return messageHandler_SetInterestLifetime(msgbuf->packet, lifetime); + int rc = hicn_interest_set_lifetime(msgbuf_get_pkbuf(msgbuf), lifetime); + return (rc == HICN_LIB_ERROR_NONE); } -static inline bool msgbuf_set_data_expiry_time(msgbuf_t *msgbuf, u32 lifetime) { - return messageHandler_SetDataExpiryTime(msgbuf->packet, lifetime); + +static inline u32 msgbuf_get_data_expiry_time(const msgbuf_t *msgbuf) { + u32 lifetime; + int rc = hicn_data_get_expiry_time(msgbuf_get_pkbuf(msgbuf), &lifetime); + assert(rc == HICN_LIB_ERROR_NONE); // XXX + _unused(rc); + return lifetime; } -#define msgbuf_is_probe(M) messageHandler_IsAProbe((M)->packet) +static inline bool msgbuf_set_data_expiry_time(msgbuf_t *msgbuf, u32 lifetime) { + int rc = hicn_data_set_expiry_time(msgbuf_get_pkbuf(msgbuf), lifetime); + return (rc == HICN_LIB_ERROR_NONE); +} /* Path label */ -#define msgbuf_init_pathlabel(M) \ - ((M)->path_label = messageHandler_GetPathLabel((M)->packet)) -#define msgbuf_update_pathlabel(M, outface) \ - { \ - messageHandler_SetPathLabel((M)->packet, \ - messageHandler_GetPathLabel((M)->packet), \ - (M)->path_label); \ - messageHandler_UpdatePathLabel((M)->packet, outface); \ - } -#define msgbuf_reset_pathlabel(M) \ - { \ - (M)->path_label = 0; \ - messageHandler_ResetPathLabel((M)->packet); \ - } +static inline void msgbuf_init_pathlabel(msgbuf_t *msgbuf) { + hicn_path_label_t pl; + int rc = hicn_data_get_path_label(msgbuf_get_pkbuf(msgbuf), &pl); + assert(rc == HICN_LIB_ERROR_NONE); + _unused(rc); + msgbuf->path_label = pl; +} + +static inline int msgbuf_get_path_label(const msgbuf_t *msgbuf, + hicn_path_label_t *pl) { + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); + return hicn_data_get_path_label(msgbuf_get_pkbuf(msgbuf), pl); +} + +static inline int msgbuf_set_path_label(msgbuf_t *msgbuf, + hicn_path_label_t pl) { + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); + return hicn_data_set_path_label(msgbuf_get_pkbuf(msgbuf), pl); +} + +static inline int msgbuf_update_pathlabel(msgbuf_t *msgbuf, + hicn_faceid_t outface) { + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); + + hicn_path_label_t pl, newpl; + if (msgbuf_get_path_label(msgbuf, &pl) < 0) return -1; + + update_path_label(pl, outface, &newpl); + + return msgbuf_set_path_label(msgbuf, newpl); +} + +static inline void msgbuf_reset_pathlabel(msgbuf_t *msgbuf) { + msgbuf->path_label = 0; + hicn_data_set_path_label(msgbuf_get_pkbuf(msgbuf), 0); + // ERROR ? +} + +static inline void msgbuf_modify_suffix(msgbuf_t *msgbuf, uint32_t new_suffix) { + hicn_name_t name; + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); + hicn_interest_get_name(msgbuf_get_pkbuf(msgbuf), &name); + hicn_name_set_suffix(&name, new_suffix); + hicn_interest_set_name(msgbuf_get_pkbuf(msgbuf), &name); +} + +bool msgbuf_is_command(const msgbuf_t *msgbuf); +bool msgbuf_is_probe(const msgbuf_t *msgbuf); /* WLDR */ +#if 0 #define msgbuf_reset_wldr_label(M) (messageHandler_ResetWldrLabel((M)->packet)) #define msgbuf_get_wldr_label(M) (messageHandler_GetWldrLabel((M)->packet)) #define msgbuf_get_wldr_expected_label(M) \ @@ -123,5 +198,6 @@ static inline bool msgbuf_set_data_expiry_time(msgbuf_t *msgbuf, u32 lifetime) { (messageHandler_GetWldrLastReceived((M)->packet)) #define msgbuf_set_wldr_label(M, label) \ (messageHandler_GetWldrLabel((M)->packet, label)) +#endif #endif /* HICNLIGHT_MSGBUF */ diff --git a/hicn-light/src/hicn/core/msgbuf_pool.c b/hicn-light/src/hicn/core/msgbuf_pool.c index a2092aaf6..892bd59a1 100644 --- a/hicn-light/src/hicn/core/msgbuf_pool.c +++ b/hicn-light/src/hicn/core/msgbuf_pool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,6 +19,7 @@ */ #include <hicn/util/pool.h> +#include <hicn/util/log.h> #include "msgbuf_pool.h" msgbuf_pool_t *_msgbuf_pool_create(size_t init_size, size_t max_size) { @@ -90,16 +91,20 @@ void msgbuf_pool_release(msgbuf_pool_t *msgbuf_pool, msgbuf_t **msgbuf_ptr) { if (msgbuf->refs == 0) { WITH_TRACE({ off_t msgbuf_id = msgbuf_pool_get_id(msgbuf_pool, msgbuf); - if (msgbuf->type != MSGBUF_TYPE_INTEREST && - msgbuf->type != MSGBUF_TYPE_DATA) { + if (msgbuf_get_type(msgbuf) != HICN_PACKET_TYPE_INTEREST && + msgbuf_get_type(msgbuf) != HICN_PACKET_TYPE_DATA) { TRACE("Msgbuf %d (%p) - put to msgbuf pool", msgbuf_id, msgbuf); } else { - char *name_str = name_ToString(msgbuf_get_name(msgbuf)); + char buf[MAXSZ_HICN_NAME]; + int rc = + hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_NAME) + snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)"); const char *msgbuf_type_str = - msgbuf->type == MSGBUF_TYPE_INTEREST ? "interest" : "data"; + msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST ? "interest" + : "data"; TRACE("Msgbuf %d (%p) - %s (%s) put to msgbuf pool", msgbuf_id, msgbuf, - name_str, msgbuf_type_str); - free(name_str); + buf, msgbuf_type_str); } }) diff --git a/hicn-light/src/hicn/core/name.c b/hicn-light/src/hicn/core/name.c deleted file mode 100644 index d30cebefc..000000000 --- a/hicn-light/src/hicn/core/name.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <assert.h> -#include <limits.h> -#include <hicn/hicn-light/config.h> -#include <stdbool.h> -#include <stdio.h> -#include <string.h> - -#include <hicn/core/messageHandler.h> -#include <hicn/core/name.h> -#include <hicn/util/log.h> -#include <hicn/util/hash.h> - -#define IPv6_TYPE 6 -#define IPv4_TYPE 4 - -static uint32_t _computeHash(Name *name) { - assert(name); - - uint32_t hash1 = nameBitvector_GetHash32(&(name->content_name)); - return hashlittle(&name->segment, sizeof(name->segment), hash1); -} - -// ============================================================================ - -void name_create_from_interest(const uint8_t *packet, Name *name) { - assert(packet); - assert(name); - - if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) { - nameBitvector_CreateFromIn6Addr( - &(name->content_name), - (struct in6_addr *)messageHandler_GetDestination(packet), 128); - } else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) { - nameBitvector_CreateFromInAddr( - &(name->content_name), - *((uint32_t *)messageHandler_GetDestination(packet)), 32); - } else { - ERROR("Error: unknown message type\n"); - return; - } - - name->segment = messageHandler_GetSegment(packet); - name->name_hash = _computeHash(name); -} - -void name_create_from_data(const uint8_t *packet, Name *name) { - assert(packet); - assert(name); - - if (messageHandler_GetIPPacketType(packet) == IPv6_TYPE) { - nameBitvector_CreateFromIn6Addr( - &(name->content_name), - (struct in6_addr *)messageHandler_GetSource(packet), 128); - } else if (messageHandler_GetIPPacketType(packet) == IPv4_TYPE) { - nameBitvector_CreateFromInAddr( - &(name->content_name), *((uint32_t *)messageHandler_GetSource(packet)), - 32); - } else { - printf("Error: unknown message type\n"); - return; - } - - name->segment = messageHandler_GetSegment(packet); - name->name_hash = _computeHash(name); -} - -void name_CreateFromAddress(Name *name, int family, ip_address_t addr, - uint8_t len) { - assert(name); - - switch (family) { - case AF_INET: - nameBitvector_CreateFromInAddr(&(name->content_name), addr.v4.as_u32, - len); - break; - case AF_INET6: - nameBitvector_CreateFromIn6Addr(&(name->content_name), - &addr.v6.as_in6addr, len); - break; - default: - return; - } - - name->segment = 0; - name->name_hash = _computeHash(name); -} - -void name_Copy(const Name *original, Name *copy) { - assert(original); - assert(copy); - - nameBitvector_Copy(&(original->content_name), &(copy->content_name)); - copy->segment = original->segment; - copy->name_hash = original->name_hash; -} - -uint32_t name_HashCode(const Name *name) { - assert(name); - return name->name_hash; -} - -NameBitvector *name_GetContentName(const Name *name) { - assert(name); - return (NameBitvector *)&(name->content_name); -} - -uint32_t name_GetSegment(const Name *name) { - assert(name); - return name->segment; -} - -void name_SetSegment(Name *name, uint32_t segment) { name->segment = segment; } - -bool name_Equals(const Name *a, const Name *b) { - assert(a); - assert(b); - - if ((nameBitvector_Equals(&(a->content_name), &(b->content_name)) && - a->segment == b->segment)) - return true; - return false; -} - -int name_Compare(const Name *a, const Name *b) { - assert(a); - assert(b); - - if (a == NULL && b == NULL) { - return 0; - } - if (a == NULL) { - return -1; - } - if (b == NULL) { - return +1; - } - - int res = nameBitvector_Compare(&(a->content_name), &(b->content_name)); - - if (res != 0) { - return res; - } else { - if (a->segment < b->segment) { - return -1; - } else if (a->segment > b->segment) { - return +1; - } else { - return 0; - } - } -} - -char *name_ToString(const Name *name) { - char *output = malloc(NI_MAXHOST * 2); - address_t address; - nameBitvector_ToAddress(name_GetContentName(name), &address); - - char addr_str[NI_MAXHOST]; - int err = address_to_string(&address, addr_str, NULL); - _ASSERT(!err); - - int chars_written = - snprintf(output, NI_MAXHOST * 2, "name=%s|%u", addr_str, name->segment); - _ASSERT(chars_written > 0); - - return output; -} - -void name_setLen(Name *name, uint8_t len) { - nameBitvector_setLen(&(name->content_name), len); - name->name_hash = _computeHash(name); -} - -#ifdef WITH_POLICY -uint32_t name_GetSuffix(const Name *name) { return name->segment; } - -uint8_t name_GetLen(const Name *name) { - return nameBitvector_GetLength(&(name->content_name)); -} -#endif /* WITH_POLICY */ diff --git a/hicn-light/src/hicn/core/name.h b/hicn-light/src/hicn/core/name.h deleted file mode 100644 index 23505243b..000000000 --- a/hicn-light/src/hicn/core/name.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef name_h -#define name_h - -#include <stdbool.h> -#include <stdlib.h> - -#include "nameBitvector.h" - -typedef struct { - NameBitvector content_name; - uint32_t segment; - uint32_t name_hash; -} Name; - -#define EMPTY_NAME \ - (Name) { .content_name = EMPTY_NAME_BITVECTOR, .segment = 0, .name_hash = 0, } - -/** - * Creates a name from packet - * - */ -void name_create_from_interest(const uint8_t *packet, Name *name); -void name_create_from_data(const uint8_t *packet, Name *name); - -/** - * returns a copy of the name - */ -void name_Copy(const Name *original, Name *copy); - -/** - * A hash value for use in hash tables - * - */ -uint32_t name_HashCode(const Name *name); - -/** - * Returns the content name without the segment value - * - */ -NameBitvector *name_GetContentName(const Name *name); - -/** - * Returns the segment value - * - */ -uint32_t name_GetSegment(const Name *name); - -/** - * Set the sequence number of the name provided - * - */ -void name_SetSegment(Name *name, uint32_t segment); - -/** - * Determine if two HicnName instances are equal. - */ -bool name_Equals(const Name *a, const Name *b); - -/** - * Compares two names and returns their ordering - * - */ -int name_Compare(const Name *a, const Name *b); - -/** - * return the name in string format (bitvector + segment number) - * - */ -char *name_ToString(const Name *name); - -/** - * @function message_setNameLen - * @abstract Sets a message name length - * @param [in] message - Interest message - * @param [in] len - Name length - */ -void name_setLen(Name *name, uint8_t len); - -/** - * Creates a name from a Address - * - */ -void name_CreateFromAddress(Name *name, int family, ip_address_t addr, - uint8_t len); - -#ifdef WITH_POLICY -uint32_t name_GetSuffix(const Name *name); -uint8_t name_GetLen(const Name *name); -#endif /* WITH_POLICY */ - -#endif // name_h diff --git a/hicn-light/src/hicn/core/nameBitvector.c b/hicn-light/src/hicn/core/nameBitvector.c deleted file mode 100644 index aa431879c..000000000 --- a/hicn-light/src/hicn/core/nameBitvector.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -#include <hicn/core/messageHandler.h> -#include <hicn/core/nameBitvector.h> - -#include <hicn/util/hash.h> -#include <hicn/ctrl/hicn-light-ng.h> - -#define DEFAULT_PORT 1234 - -const uint64_t BV_SIZE = 64; -const uint64_t WIDTH = 128; -const uint64_t ONE = 0x1; - -// address b000:0000:0000:0001:c000:0000:0000:0001 is encodend as follow -// [bits[0] uint64_t ] [bits[1] unit64_t ] -// ^ ^ ^ ^ -// 63 0 127 64 -// [1000 0000 ... 0000 1011] [1000 0000 ... 0000 0011] //binary -// 1 b 1 c //hex - -void nameBitvector_CreateFromInAddr(NameBitvector *bitvector, uint32_t addr, - uint8_t len) { - assert(bitvector); - - bitvector->bits[0] = 0; - bitvector->bits[1] = 0; - - uint8_t addr_1 = (addr & 0xff000000) >> 24; - uint8_t addr_2 = (addr & 0x00ff0000) >> 16; - uint8_t addr_3 = (addr & 0x0000ff00) >> 8; - uint8_t addr_4 = (addr & 0x000000ff); - - bitvector->bits[0] = (bitvector->bits[0] | addr_4) << 8; - bitvector->bits[0] = (bitvector->bits[0] | addr_3) << 8; - bitvector->bits[0] = (bitvector->bits[0] | addr_2) << 8; - bitvector->bits[0] = (bitvector->bits[0] | addr_1); - bitvector->bits[0] = bitvector->bits[0] << 32; - - bitvector->len = len; - - bitvector->IPversion = IPv4_TYPE; -} - -void nameBitvector_CreateFromIn6Addr(NameBitvector *bitvector, - struct in6_addr *addr, uint8_t len) { - assert(addr); - assert(bitvector); - - bitvector->bits[0] = 0; - bitvector->bits[1] = 0; - - for (int i = 0; i < 8; ++i) { - bitvector->bits[0] = (bitvector->bits[0] << 8) | addr->s6_addr[i]; - } - - for (int i = 8; i < 16; ++i) { - bitvector->bits[1] = (bitvector->bits[1] << 8) | addr->s6_addr[i]; - } - - bitvector->len = len; - - bitvector->IPversion = IPv6_TYPE; -} - -void nameBitvector_Copy(const NameBitvector *original, NameBitvector *copy) { - assert(original); - assert(copy); - - copy->bits[0] = original->bits[0]; - copy->bits[1] = original->bits[1]; - copy->len = original->len; - copy->IPversion = original->IPversion; -} - -uint8_t nameBitvector_GetLength(const NameBitvector *name) { return name->len; } - -uint32_t nameBitvector_GetHash32(const NameBitvector *name) { - return hash(&name->bits, 16); -} - -bool nameBitvector_Equals(const NameBitvector *a, const NameBitvector *b) { - if (nameBitvector_Compare(a, b) == 0) return true; - return false; -} - -int nameBitvector_Compare(const NameBitvector *a, const NameBitvector *b) { - if (a == NULL && b == NULL) { - return 0; - } - if (a == NULL) { - return -1; - } - if (b == NULL) { - return +1; - } - - if (a->bits[0] < b->bits[0]) { - return -1; - } else if (a->bits[0] > b->bits[0]) { - return +1; - } else if (a->bits[1] < b->bits[1]) { - return -1; - } else if (a->bits[1] > b->bits[1]) { - return +1; - } else if (a->len < b->len) { - return -1; - } else if (a->len > b->len) { - return +1; - } else { - return 0; - } -} - -int nameBitvector_testBit(const NameBitvector *name, uint8_t pos, bool *bit) { - if (pos >= name->len || pos > (WIDTH - 1)) return -1; - - *bit = - (name->bits[pos / BV_SIZE] & (ONE << ((BV_SIZE - 1) - (pos % BV_SIZE)))); - - return 0; -} - -// TODO XXX use ffs(ll) -uint64_t _diff_bit_log2(uint64_t val) { - // base 2 log of an uint64_t. This is the same as get the position of - // the highest bit set (or most significant bit set, MSB) - uint64_t result = 0; - - if (val & 0xFFFFFFFF00000000) { - val = val >> 32; - result = result | 32; - } - if (val & 0xFFFF0000) { - val = val >> 16; - result = result | 16; - } - if (val & 0xFF00) { - val = val >> 8; - result = result | 8; - } - if (val & 0xF0) { - val = val >> 4; - result = result | 4; - } - if (val & 0xC) { - val = val >> 2; - result = result | 2; - } - if (val & 0x2) { - val = val >> 1; - result = result | 1; - } - return result; -} - -uint32_t nameBitvector_lpm(const NameBitvector *a, const NameBitvector *b) { - uint32_t limit; - uint32_t prefix_len; - if (a->len < b->len) - limit = a->len; - else - limit = b->len; - - uint64_t diff = a->bits[0] ^ b->bits[0]; - if (diff) { - prefix_len = (uint32_t)(BV_SIZE - (_diff_bit_log2(diff) + 1)); - // printf("if 1 diff = %lu plen = %d\n", diff, prefix_len); - } else { - prefix_len = BV_SIZE; - diff = a->bits[1] ^ b->bits[1]; - if (diff) { - prefix_len += (BV_SIZE - (_diff_bit_log2(diff) + 1)); - // printf("if 2 diff = %lu plen = %d\n", diff, prefix_len); - } else { - prefix_len += BV_SIZE; - } - } - - if (prefix_len < limit) return prefix_len; - return limit; -} - -void nameBitvector_clear(NameBitvector *a, uint8_t start_from) { - for (uint8_t pos = start_from; pos < WIDTH; pos++) - a->bits[pos / BV_SIZE] &= ~(ONE << ((BV_SIZE - 1) - (pos % BV_SIZE))); -} - -int nameBitvector_ToIPAddress(const NameBitvector *name, ip_prefix_t *prefix) { - if (name->IPversion == IPv4_TYPE) { - struct in_addr *addr = (struct in_addr *)(&prefix->address.v4.buffer); - prefix->family = AF_INET; - prefix->len = IPV4_ADDR_LEN_BITS; - - uint32_t tmp_addr = name->bits[0] >> 32ULL; - uint8_t addr_1 = (tmp_addr & 0xff000000) >> 24; - uint8_t addr_2 = (tmp_addr & 0x00ff0000) >> 16; - uint8_t addr_3 = (tmp_addr & 0x0000ff00) >> 8; - uint8_t addr_4 = (tmp_addr & 0x000000ff); - - addr->s_addr = 0; - addr->s_addr = (addr->s_addr | addr_4) << 8; - addr->s_addr = (addr->s_addr | addr_3) << 8; - addr->s_addr = (addr->s_addr | addr_2) << 8; - addr->s_addr = (addr->s_addr | addr_1); - - } else { - struct in6_addr *addr = (struct in6_addr *)(&prefix->address.v6.buffer); - prefix->family = AF_INET6; - prefix->len = name->len; // IPV6_ADDR_LEN_BITS; - - for (int i = 0; i < 8; i++) { - addr->s6_addr[i] = (uint8_t)((name->bits[0] >> 8 * (7 - i)) & 0xFF); - } - - int x = 0; - for (int i = 8; i < 16; ++i) { - addr->s6_addr[i] = (uint8_t)((name->bits[1] >> 8 * (7 - x)) & 0xFF); - x++; - } - } - return true; -} - -void nameBitvector_setLen(NameBitvector *name, uint8_t len) { name->len = len; } - -void nameBitvector_ToAddress(const NameBitvector *name, address_t *address) { - if (name->IPversion == IPv4_TYPE) { - struct sockaddr_in *sin = address4(address); - sin->sin_family = AF_INET; - sin->sin_port = htons(DEFAULT_PORT); - - uint32_t tmp_addr = name->bits[0] >> 32ULL; - uint8_t addr_1 = (tmp_addr & 0xff000000) >> 24; - uint8_t addr_2 = (tmp_addr & 0x00ff0000) >> 16; - uint8_t addr_3 = (tmp_addr & 0x0000ff00) >> 8; - uint8_t addr_4 = (tmp_addr & 0x000000ff); - - sin->sin_addr.s_addr = 0; - sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_4) << 8; - sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_3) << 8; - sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_2) << 8; - sin->sin_addr.s_addr = (sin->sin_addr.s_addr | addr_1); - } else { - struct sockaddr_in6 *sin6 = address6(address); - sin6->sin6_family = AF_INET6; - sin6->sin6_port = htons(DEFAULT_PORT); - sin6->sin6_scope_id = 0; - sin6->sin6_flowinfo = 0; - - for (int i = 0; i < 8; i++) { - sin6->sin6_addr.s6_addr[i] = - (uint8_t)((name->bits[0] >> 8 * (7 - i)) & 0xFF); - } - - int x = 0; - for (int i = 8; i < 16; ++i) { - sin6->sin6_addr.s6_addr[i] = - (uint8_t)((name->bits[1] >> 8 * (7 - x)) & 0xFF); - x++; - } - } -} - -char *nameBitvector_ToString(const NameBitvector *name) { - char *output = malloc(WIDTH); - - address_t address; - nameBitvector_ToAddress(name, &address); - - // XXX TODO -#if 0 - sprintf(output, "prefix: %s len: %u", addressToString(packetAddr), name->len); -#else - snprintf(output, WIDTH, "%s", "ENOIMPL"); -#endif - - return output; -} diff --git a/hicn-light/src/hicn/core/nameBitvector.h b/hicn-light/src/hicn/core/nameBitvector.h deleted file mode 100644 index 549b26679..000000000 --- a/hicn-light/src/hicn/core/nameBitvector.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef name_bitvector_h -#define name_bitvector_h - -#include <hicn/hicn.h> -#include <stdint.h> -#include <stdlib.h> - -#include "address.h" - -#define NAME_LEN 2 -typedef struct __attribute__((__packed__)) { - uint64_t bits[NAME_LEN]; - uint32_t len; - uint32_t IPversion; -} NameBitvector; -static_assert(sizeof(NameBitvector) == 24, - "Name prefix should be stored on 24 bytes"); - -#define EMPTY_NAME_BITVECTOR \ - (NameBitvector) { .bits[0] = 0, .bits[1] = 0, .len = 0, .IPversion = 0, } - -void nameBitvector_CreateFromInAddr(NameBitvector *bitvector, uint32_t addr, - uint8_t len); - -void nameBitvector_CreateFromIn6Addr(NameBitvector *bitvector, - struct in6_addr *addr, uint8_t len); - -void nameBitvector_Copy(const NameBitvector *original, NameBitvector *copy); - -uint8_t nameBitvector_GetLength(const NameBitvector *name); - -uint32_t nameBitvector_GetHash32(const NameBitvector *name); - -bool nameBitvector_Equals(const NameBitvector *a, const NameBitvector *b); - -int nameBitvector_Compare(const NameBitvector *a, const NameBitvector *b); - -int nameBitvector_testBit(const NameBitvector *name, uint8_t pos, bool *bit); - -uint32_t nameBitvector_lpm(const NameBitvector *a, const NameBitvector *b); - -void nameBitvector_clear(NameBitvector *a, uint8_t start_from); - -int nameBitvector_ToIPAddress(const NameBitvector *name, ip_prefix_t *prefix); -void nameBitvector_setLen(NameBitvector *name, uint8_t len); - -void nameBitvector_ToAddress(const NameBitvector *name, address_t *address); - -char *nameBitvector_ToString(const NameBitvector *name); - -#endif // name_bitvector_h diff --git a/hicn-light/src/hicn/core/nexthops.c b/hicn-light/src/hicn/core/nexthops.c index 190f09ab0..70089399d 100644 --- a/hicn-light/src/hicn/core/nexthops.c +++ b/hicn-light/src/hicn/core/nexthops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,6 +18,8 @@ * \brief Nexthops implementation */ +#include <hicn/util/hash.h> + #include "nexthops.h" int nexthops_disable(nexthops_t *nexthops, off_t offset) { @@ -34,7 +36,6 @@ void nexthops_reset(nexthops_t *nexthops) { off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop) { off_t id; - unsigned i, n; nexthops_enumerate(nexthops, i, n, { if (n == nexthop) return i; }); @@ -45,7 +46,6 @@ off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop) { } off_t nexthops_remove(nexthops_t *nexthops, nexthop_t nexthop) { - unsigned i, n; nexthops_enumerate(nexthops, i, n, { if (n == nexthop) { nexthops->num_elts--; @@ -59,7 +59,6 @@ off_t nexthops_remove(nexthops_t *nexthops, nexthop_t nexthop) { } bool nexthops_contains(nexthops_t *nexthops, unsigned nexthop) { - unsigned n; nexthops_foreach(nexthops, n, { if (n == nexthop) return true; }); @@ -67,7 +66,6 @@ bool nexthops_contains(nexthops_t *nexthops, unsigned nexthop) { } off_t nexthops_find(nexthops_t *nexthops, unsigned nexthop) { - unsigned i, n; nexthops_enumerate(nexthops, i, n, { if (n == nexthop) return i; }); @@ -75,7 +73,6 @@ off_t nexthops_find(nexthops_t *nexthops, unsigned nexthop) { } unsigned nexthops_get_one(nexthops_t *nexthops) { - unsigned n; nexthops_foreach(nexthops, n, { return n; }); return INVALID_NEXTHOP; } @@ -92,8 +89,6 @@ int nexthops_select(nexthops_t *nexthops, off_t i) { void nexthops_set_priority(nexthops_t *nexthops, nexthop_t nexthop, int priority) { - unsigned i; - nexthop_t nh; nexthops_enumerate(nexthops, i, nh, { if (nexthop == nh) nexthops_set_priority_by_id(nexthops, i, priority); }); @@ -112,8 +107,6 @@ void nexthops_reset_priority_by_id(nexthops_t *nexthops, off_t i) { } void nexthops_reset_priorities(nexthops_t *nexthops) { - unsigned i; - nexthop_t nh; nexthops_enumerate(nexthops, i, nh, { (void)nh; nexthops_reset_priority(nexthops, i); @@ -121,7 +114,6 @@ void nexthops_reset_priorities(nexthops_t *nexthops) { } bool nexthops_equal(nexthops_t *a, nexthops_t *b) { - unsigned n; if (nexthops_get_len(a) != nexthops_get_len(b)) return false; nexthops_foreach(a, n, { if (!nexthops_contains(b, n)) return false; @@ -139,4 +131,19 @@ void nexthops_copy(nexthops_t *src, nexthops_t *dst) { dst->cur_elts = src->cur_elts; } +/* Adapted from Jenkins hash (commutative) */ +uint32_t nexthops_get_hash(nexthops_t *nexthops) { + uint32_t hash = 0; + + nexthops_foreach(nexthops, nh, { + hash += nh; + hash += hash << 10; + hash ^= hash >> 6; + }); + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return hash; +} + #endif /* WITH_POLICY */ diff --git a/hicn-light/src/hicn/core/nexthops.h b/hicn-light/src/hicn/core/nexthops.h index 2a7fc0b32..ff83199a6 100644 --- a/hicn-light/src/hicn/core/nexthops.h +++ b/hicn-light/src/hicn/core/nexthops.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -106,21 +106,24 @@ int nexthops_disable(nexthops_t *nexthops, off_t offset); void nexthops_reset(nexthops_t *nexthops); -#define nexthops_enumerate(NH, i, X, BODY) \ +#define nexthops_enumerate(NH, I, X, BODY) \ do { \ - for ((i) = 0; (i) < nexthops_get_len(NH); (i)++) { \ - if (nexthops_is_disabled((NH), (i))) continue; \ - X = (NH)->elts[(i)]; \ + nexthop_t X; \ + (void)X; \ + unsigned I; \ + (void)I; \ + for ((I) = 0; (I) < nexthops_get_len(NH); (I)++) { \ + if (nexthops_is_disabled((NH), (I))) continue; \ + X = (NH)->elts[(I)]; \ do { \ BODY \ } while (0); \ } \ } while (0) -#define nexthops_foreach(NH, X, BODY) \ - do { \ - unsigned _nexthops_var(i); \ - nexthops_enumerate((NH), _nexthops_var(i), (X), {BODY}); \ +#define nexthops_foreach(NH, X, BODY) \ + do { \ + nexthops_enumerate((NH), _nexthops_var(i), X, {BODY}); \ } while (0) off_t nexthops_add(nexthops_t *nexthops, nexthop_t nexthop); @@ -173,4 +176,6 @@ void nexthops_copy(nexthops_t *src, nexthops_t *dst); #endif /* WITH_POLICY */ +uint32_t nexthops_get_hash(nexthops_t *nexthops); + #endif /* HICNLIGHT_NEXTHOPS_H */ diff --git a/hicn-light/src/hicn/core/packet_cache.c b/hicn-light/src/hicn/core/packet_cache.c index 8bd188c8b..9d0b041c3 100644 --- a/hicn-light/src/hicn/core/packet_cache.c +++ b/hicn-light/src/hicn/core/packet_cache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -16,48 +16,121 @@ /** * \file packet_cache.c * \brief Implementation of hICN packet cache + * + * _get_suffixes : first level lookup to return the suffixes + * + * _remove_suffix : Remove suffix from the two level packet cache structure + * + * __add_suffix : Add a packet cache entry in the second level of the + * two-level data structure _add_suffix : Add a packet cache entry in the both + * the first and second level of the two-level data tructure (helper) + * + * __get_suffix : Lookup in the second level of the packet cache + * + * _get_suffix : Lookup in both the first and second levels of the packet cache + * + * ---- + * + * pkt_cache_save_suffixes_for_prefix : always done at packet reception to keep + * the latest suffixes + * + * pkt_cache_reset_suffixes_for_prefix + * + * ---- + * + * pkt_cache_allocate + * + * pkt_cache_add_to_index + * + * pkt_cache_remove_from_index + * + * pkt_cache_pit_remove_entry + * + * pkt_cache_cs_remove_entry + * + * pkt_cache_add_to_pit + * pkt_cache_add_to_cs + * + * _pkt_cache_add_to_pit + * used by pkt_cache_add_to_pit + * plt_cache_update_pit + * _pkt_cache_add_to_cs + * + * pkt_cache_pit_to_cs + * pkt_cache_cs_to_pit + * + * pkt_cache_update_pit : when an interest expired + * pkt_cache_update_cs + * + * pkt_cache_try_aggregate_in_pit + * + * + * */ #include "packet_cache.h" +const char *_pkt_cache_verdict_str[] = { +#define _(x) [PKT_CACHE_VERDICT_##x] = #x, + foreach_kh_verdict +#undef _ +}; + /****************************************************************************** * Low-level operations on the hash table ******************************************************************************/ +/** + * Free the two level packet cache structure (helper) + */ void _prefix_map_free(kh_pkt_cache_prefix_t *prefix_to_suffixes) { - const NameBitvector *key; + const hicn_name_prefix_t *key; kh_pkt_cache_suffix_t *value; kh_foreach(prefix_to_suffixes, key, value, { - free((NameBitvector *)key); + //(void)key; + free((hicn_name_prefix_t *)key); kh_destroy_pkt_cache_suffix(value); }); kh_destroy_pkt_cache_prefix(prefix_to_suffixes); } +/** + * Perform the first level lookup to return the suffixes (helper) + */ kh_pkt_cache_suffix_t *_get_suffixes(kh_pkt_cache_prefix_t *prefix_to_suffixes, - const NameBitvector *prefix) { + const hicn_name_prefix_t *prefix, + bool create) { khiter_t k = kh_get_pkt_cache_prefix(prefix_to_suffixes, prefix); - // Return suffixes found + /* Return suffixes if found... */ if (k != kh_end(prefix_to_suffixes)) { kh_pkt_cache_suffix_t *suffixes = kh_val(prefix_to_suffixes, k); return suffixes; } + if (!create) return NULL; + + /* ... otherwise populate the first level and return the newly added entry. + */ kh_pkt_cache_suffix_t *suffixes = kh_init_pkt_cache_suffix(); - NameBitvector *nb_copy = (NameBitvector *)malloc(sizeof(NameBitvector)); - *nb_copy = *prefix; + + hicn_name_prefix_t *prefix_copy = malloc(sizeof(hicn_name_prefix_t)); + *prefix_copy = *prefix; int rc; - k = kh_put_pkt_cache_prefix(prefix_to_suffixes, nb_copy, &rc); + k = kh_put_pkt_cache_prefix(prefix_to_suffixes, prefix_copy, &rc); assert(rc == KH_ADDED || rc == KH_RESET); kh_value(prefix_to_suffixes, k) = suffixes; return suffixes; } +/** + * Remove suffix from the two level packet cache structure (helper) + */ void _remove_suffix(kh_pkt_cache_prefix_t *prefixes, - const NameBitvector *prefix, uint32_t suffix) { - kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix); + const hicn_name_prefix_t *prefix, + const hicn_name_suffix_t suffix) { + kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix, false); assert(suffixes != NULL); khiter_t k = kh_get_pkt_cache_suffix(suffixes, suffix); @@ -67,60 +140,90 @@ void _remove_suffix(kh_pkt_cache_prefix_t *prefixes, // TODO(eloparco): Remove prefix if no associated suffixes? } -void __add_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix, +/** + * Add a packet cache entry in the second level of the two-level data structure + * (helper) + */ +void __add_suffix(kh_pkt_cache_suffix_t *suffixes, hicn_name_suffix_t suffix, unsigned val) { + // INFO("suffix add suffixes=%p suffix=%d val=%d", suffixes, suffix, val); int rc; khiter_t k = kh_put_pkt_cache_suffix(suffixes, suffix, &rc); assert(rc == KH_ADDED || rc == KH_RESET); kh_value(suffixes, k) = val; } -void _add_suffix(kh_pkt_cache_prefix_t *prefixes, const NameBitvector *prefix, - uint32_t suffix, unsigned val) { - kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix); +/** + * Add a packet cache entry in the both the first and second level of the + * two-level data tructure (helper) + */ +void _add_suffix(kh_pkt_cache_prefix_t *prefixes, + const hicn_name_prefix_t *prefix, + const hicn_name_suffix_t suffix, unsigned val) { + kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix, true); assert(suffixes != NULL); __add_suffix(suffixes, suffix, val); } -unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix, - int *rc) { - *rc = KH_FOUND; +/** + * Lookup in the second level of the packet cache (helper) + */ +unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, + hicn_name_suffix_t suffix) { khiter_t k = kh_get_pkt_cache_suffix(suffixes, suffix); // Not Found if (k == kh_end(suffixes)) { - *rc = KH_NOT_FOUND; - return -1; + return HICN_INVALID_SUFFIX; } unsigned index = kh_val(suffixes, k); return index; } +unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes, + const hicn_name_prefix_t *prefix, + hicn_name_suffix_t suffix) { + /* create is false as this function is always called by lookup */ + kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix, false); + if (!suffixes) { + return HICN_INVALID_SUFFIX; + } + return __get_suffix(suffixes, suffix); +} + +/** + * Lookup in both the first and second levels of the packet cache (helper) + */ +unsigned _get_suffix_from_name(kh_pkt_cache_prefix_t *prefixes, + const hicn_name_t *name) { + const hicn_name_prefix_t *prefix = hicn_name_get_prefix(name); + const hicn_name_suffix_t suffix = hicn_name_get_suffix(name); + + return _get_suffix(prefixes, prefix, suffix); +} + void pkt_cache_save_suffixes_for_prefix(pkt_cache_t *pkt_cache, - const NameBitvector *prefix) { + const hicn_name_prefix_t *prefix) { // Cached prefix matches the current one - if (nameBitvector_Compare(&pkt_cache->cached_prefix, prefix) == 0) return; + if (hicn_name_prefix_equals(&pkt_cache->cached_prefix, prefix)) return; + + char buf[MAXSZ_HICN_PREFIX]; + hicn_name_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, &pkt_cache->cached_prefix); + hicn_name_prefix_snprintf(buf, MAXSZ_HICN_PREFIX, prefix); // Update cached prefix information pkt_cache->cached_prefix = *prefix; pkt_cache->cached_suffixes = - _get_suffixes(pkt_cache->prefix_to_suffixes, prefix); + _get_suffixes(pkt_cache->prefix_to_suffixes, prefix, true); // XXX + // } void pkt_cache_reset_suffixes_for_prefix(pkt_cache_t *pkt_cache) { pkt_cache->cached_suffixes = NULL; } -unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes, - const NameBitvector *prefix, uint32_t suffix, int *rc) { - kh_pkt_cache_suffix_t *suffixes = _get_suffixes(prefixes, prefix); - assert(suffixes != NULL); - - return __get_suffix(suffixes, suffix, rc); -} - /****************************************************************************** * Public API ******************************************************************************/ @@ -136,7 +239,7 @@ pkt_cache_t *pkt_cache_create(size_t cs_size) { pkt_cache->prefix_to_suffixes = kh_init_pkt_cache_prefix(); pool_init(pkt_cache->entries, DEFAULT_PKT_CACHE_SIZE, 0); - pkt_cache->cached_prefix = EMPTY_NAME_BITVECTOR; + pkt_cache->cached_prefix = HICN_NAME_PREFIX_EMPTY; pkt_cache->cached_suffixes = NULL; return pkt_cache; @@ -157,50 +260,71 @@ void pkt_cache_free(pkt_cache_t *pkt_cache) { } kh_pkt_cache_suffix_t *pkt_cache_get_suffixes(const pkt_cache_t *pkt_cache, - const NameBitvector *prefix) { - return _get_suffixes(pkt_cache->prefix_to_suffixes, prefix); + const hicn_name_prefix_t *prefix, + bool create) { + return _get_suffixes(pkt_cache->prefix_to_suffixes, prefix, create); } -pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache, - const Name *name) { +pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache) { pkt_cache_entry_t *entry = NULL; pool_get(pkt_cache->entries, entry); - if (!entry) return NULL; + assert(entry); + return entry; +} +void pkt_cache_add_to_index(const pkt_cache_t *pkt_cache, + const pkt_cache_entry_t *entry) { off_t id = entry - pkt_cache->entries; + /* It is important that the name used for the index is the one in the packet + * cache entry, which is common for PIT and CS + */ + const hicn_name_t *name = &entry->name; + if (pkt_cache->cached_suffixes) { - __add_suffix(pkt_cache->cached_suffixes, name_GetSegment(name), + __add_suffix(pkt_cache->cached_suffixes, hicn_name_get_suffix(name), (unsigned int)id); } else { - _add_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name), - name_GetSegment(name), (unsigned int)id); + _add_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name), + hicn_name_get_suffix(name), (unsigned int)id); } +} - return entry; +/** + * Remove a name pointer to the packet cache index (helper) + */ +void pkt_cache_remove_from_index(const pkt_cache_t *pkt_cache, + const hicn_name_t *name) { + _remove_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name), + hicn_name_get_suffix(name)); + +// TODO +#if 0 + khiter_t k = kh_get_pkt_cache_name(pkt_cache->index_by_name, name); + assert(k != kh_end(pkt_cache->index_by_name)); + kh_del(pkt_cache_name, pkt_cache->index_by_name, k); +#endif } pit_t *pkt_cache_get_pit(pkt_cache_t *pkt_cache) { return pkt_cache->pit; } cs_t *pkt_cache_get_cs(pkt_cache_t *pkt_cache) { return pkt_cache->cs; } -pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name, +pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, + const hicn_name_t *name, msgbuf_pool_t *msgbuf_pool, pkt_cache_lookup_t *lookup_result, off_t *entry_id, bool is_serve_from_cs_enabled) { - int rc; - - unsigned index = -1; + unsigned index = HICN_INVALID_SUFFIX; if (pkt_cache->cached_suffixes) { index = - __get_suffix(pkt_cache->cached_suffixes, name_GetSegment(name), &rc); + __get_suffix(pkt_cache->cached_suffixes, hicn_name_get_suffix(name)); } else { - index = _get_suffix(pkt_cache->prefix_to_suffixes, - name_GetContentName(name), name_GetSegment(name), &rc); + index = _get_suffix_from_name(pkt_cache->prefix_to_suffixes, name); } - if (rc == KH_NOT_FOUND) { + if (index == HICN_INVALID_SUFFIX) { *lookup_result = PKT_CACHE_LU_NONE; return NULL; } @@ -237,9 +361,10 @@ void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, off_t msgbuf_id = entry->u.cs_entry.msgbuf_id; msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); - const Name *name = msgbuf_get_name(msgbuf); - _remove_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name), - name_GetSegment(name)); + // XXX const hicn_name_t *name = msgbuf_get_name(msgbuf); + _remove_suffix(pkt_cache->prefix_to_suffixes, + hicn_name_get_prefix(&entry->name), + hicn_name_get_suffix(&entry->name)); // Do not update the LRU cache for evicted entries if (!is_evicted) cs_vft[pkt_cache->cs->type]->remove_entry(pkt_cache, entry); @@ -248,28 +373,34 @@ void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, pool_put(pkt_cache->entries, entry); WITH_DEBUG({ - char *name_str = name_ToString(msgbuf_get_name(msgbuf)); - DEBUG("Packet %s removed from CS", name_str); - free(name_str); + char buf[MAXSZ_HICN_NAME]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, &entry->name); + if (rc < 0 || rc >= MAXSZ_HICN_NAME) + snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)"); + DEBUG("Packet %s removed from CS", buf); }) msgbuf_pool_release(msgbuf_pool, &msgbuf); } void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache, - pkt_cache_entry_t *entry, const Name *name) { + pkt_cache_entry_t *entry) { assert(pkt_cache); assert(entry); assert(entry->entry_type == PKT_CACHE_PIT_TYPE); - _remove_suffix(pkt_cache->prefix_to_suffixes, name_GetContentName(name), - name_GetSegment(name)); + const hicn_name_t *name = &entry->name; + _remove_suffix(pkt_cache->prefix_to_suffixes, hicn_name_get_prefix(name), + hicn_name_get_suffix(name)); + pool_put(pkt_cache->entries, entry); WITH_DEBUG({ - char *name_str = name_ToString(name); - DEBUG("Packet %s removed from PIT", name_str); - free(name_str); + char buf[MAXSZ_HICN_NAME]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, name); + if (rc < 0 || rc >= MAXSZ_HICN_NAME) + snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)"); + DEBUG("Packet %s removed from PIT", buf); }) } @@ -279,8 +410,9 @@ void _pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, entry->u.cs_entry = (cs_entry_t){.msgbuf_id = msgbuf_id, .lru = {.prev = INVALID_ENTRY_ID, .next = INVALID_ENTRY_ID}}; - entry->create_ts = ticks_now(); - entry->expire_ts = ticks_now() + msgbuf_get_data_expiry_time(msgbuf); + Ticks now = ticks_now(); + entry->create_ts = now; + entry->expire_ts = now + msgbuf_get_data_expiry_time(msgbuf); entry->has_expire_ts = true; entry->entry_type = PKT_CACHE_CS_TYPE; @@ -299,18 +431,21 @@ void _pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, msgbuf_pool_acquire(msgbuf); } -void pkt_cache_pit_to_cs(pkt_cache_t *pkt_cache, - pkt_cache_entry_t *interest_entry, - msgbuf_pool_t *msgbuf_pool, msgbuf_t *data_msgbuf, - off_t data_msgbuf_id, off_t entry_id) { +void pkt_cache_pit_to_cs(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, + msgbuf_pool_t *msgbuf_pool, msgbuf_t *msgbuf, + off_t msgbuf_id, off_t entry_id) { assert(pkt_cache); - assert(interest_entry); - assert(interest_entry->entry_type == PKT_CACHE_PIT_TYPE); + assert(entry); + assert(entry->entry_type == PKT_CACHE_PIT_TYPE); - _pkt_cache_add_to_cs(pkt_cache, interest_entry, msgbuf_pool, data_msgbuf, - data_msgbuf_id, entry_id); + _pkt_cache_add_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id, + entry_id); } +/** + * entry : newly allocated cache entry + * msgbuf : used for name, ingress connection id and lifetime + */ void _pkt_cache_add_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, const msgbuf_t *msgbuf) { entry->u.pit_entry = (pit_entry_t){ @@ -366,11 +501,13 @@ void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool, pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache, const msgbuf_t *msgbuf, - const Name *name) { + const hicn_name_t *name) { assert(pkt_cache); - pkt_cache_entry_t *entry = pkt_cache_allocate(pkt_cache, name); + pkt_cache_entry_t *entry = pkt_cache_allocate(pkt_cache); + entry->name = *name; _pkt_cache_add_to_pit(pkt_cache, entry, msgbuf); + pkt_cache_add_to_index(pkt_cache, entry); return entry; } @@ -379,12 +516,13 @@ pkt_cache_entry_t *pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, msgbuf_t *msgbuf, off_t msgbuf_id) { assert(pkt_cache); - pkt_cache_entry_t *entry = - pkt_cache_allocate(pkt_cache, msgbuf_get_name(msgbuf)); + pkt_cache_entry_t *entry = pkt_cache_allocate(pkt_cache); + const hicn_name_t *name = msgbuf_get_name(msgbuf); + entry->name = *name; off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry); _pkt_cache_add_to_cs(pkt_cache, entry, msgbuf_pool, msgbuf, msgbuf_id, entry_id); - + pkt_cache_add_to_index(pkt_cache, entry); return entry; } @@ -404,7 +542,8 @@ void pkt_cache_update_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, - const msgbuf_t *msgbuf, const Name *name) { + const msgbuf_t *msgbuf, + const hicn_name_t *name) { assert(pkt_cache); assert(entry); assert(entry->entry_type == PKT_CACHE_PIT_TYPE); @@ -422,15 +561,17 @@ bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache, if (is_aggregated) pit_entry_ingress_add(pit_entry, connection_id); WITH_DEBUG({ - char *name_str = name_ToString(name); + char buf[MAXSZ_HICN_NAME]; + int rc = hicn_name_snprintf(buf, MAXSZ_HICN_NAME, msgbuf_get_name(msgbuf)); + if (rc < 0 || rc >= MAXSZ_HICN_NAME) + snprintf(buf, MAXSZ_HICN_NAME, "%s", "(error)"); if (is_aggregated) { - DEBUG("Interest %s already existing (expiry %lu): aggregate", name_str, + DEBUG("Interest %s already existing (expiry %lu): aggregate", buf, entry->expire_ts); } else { - DEBUG("Interest %s already existing (expiry %lu): retransmit", name_str, + DEBUG("Interest %s already existing (expiry %lu): retransmit", buf, entry->expire_ts); } - free(name_str); }) return is_aggregated; @@ -445,7 +586,7 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, assert(msgbuf_id_is_valid(msgbuf_id)); msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); - assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA); + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA); *wrong_egress = false; off_t entry_id; @@ -487,7 +628,7 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, entry_id); *verdict = PKT_CACHE_VERDICT_FORWARD_DATA; } else { - pkt_cache_pit_remove_entry(pkt_cache, entry, msgbuf_get_name(msgbuf)); + pkt_cache_pit_remove_entry(pkt_cache, entry); *verdict = PKT_CACHE_VERDICT_CLEAR_DATA; } @@ -503,7 +644,7 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, entry_id); *verdict = PKT_CACHE_VERDICT_STORE_DATA; } else { - pkt_cache_pit_remove_entry(pkt_cache, entry, msgbuf_get_name(msgbuf)); + pkt_cache_pit_remove_entry(pkt_cache, entry); *verdict = PKT_CACHE_VERDICT_CLEAR_DATA; } return NULL; @@ -543,12 +684,13 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool, off_t msgbuf_id, pkt_cache_verdict_t *verdict, off_t *data_msgbuf_id, pkt_cache_entry_t **entry_ptr, - const Name *name, bool is_serve_from_cs_enabled) { + const hicn_name_t *name, + bool is_serve_from_cs_enabled) { assert(pkt_cache); assert(msgbuf_id_is_valid(msgbuf_id)); msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); - assert(msgbuf_get_type(msgbuf) == MSGBUF_TYPE_INTEREST); + assert(msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_INTEREST); off_t entry_id; pkt_cache_lookup_t lookup_result; @@ -628,7 +770,7 @@ void pkt_cache_cs_clear(pkt_cache_t *pkt_cache) { }); // Reset cached prefix - pkt_cache->cached_prefix = EMPTY_NAME_BITVECTOR; + pkt_cache->cached_prefix = HICN_NAME_PREFIX_EMPTY; pkt_cache->cached_suffixes = NULL; // Re-create CS diff --git a/hicn-light/src/hicn/core/packet_cache.h b/hicn-light/src/hicn/core/packet_cache.h index 47926fcdc..dcbc20c7d 100644 --- a/hicn-light/src/hicn/core/packet_cache.h +++ b/hicn-light/src/hicn/core/packet_cache.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -69,6 +69,10 @@ typedef enum { #undef _ } pkt_cache_verdict_t; +extern const char *_pkt_cache_verdict_str[]; + +#define pkt_cache_verdict_str(x) _pkt_cache_verdict_str[x] + #define foreach_kh_lookup \ _(INTEREST_NOT_EXPIRED) \ _(INTEREST_EXPIRED) \ @@ -83,10 +87,12 @@ typedef enum { } pkt_cache_lookup_t; KHASH_MAP_INIT_INT(pkt_cache_suffix, unsigned); -KHASH_INIT(pkt_cache_prefix, const NameBitvector *, kh_pkt_cache_suffix_t *, 1, - nameBitvector_GetHash32, nameBitvector_Equals); +KHASH_INIT(pkt_cache_prefix, const hicn_name_prefix_t *, + kh_pkt_cache_suffix_t *, 1, hicn_name_prefix_get_hash, + hicn_name_prefix_equals); typedef struct { + hicn_name_t name; pkt_cache_entry_type_t entry_type; Ticks create_ts; @@ -109,7 +115,7 @@ typedef struct { // Cached prefix info to avoid double lookups, // used for both single interest speculation and interest manifest - NameBitvector cached_prefix; + hicn_name_prefix_t cached_prefix; kh_pkt_cache_suffix_t *cached_suffixes; } pkt_cache_t; @@ -123,12 +129,29 @@ pkt_cache_t *pkt_cache_create(size_t cs_size); /** * @brief Add an entry with the specified name to the packet cache. * - * @param[in] pkt_cache Pointer to the msgbuf pool data structure to use. + * @param[in] pkt_cache Pointer to the pool data structure to use. * @param[in, out] entry Empty entry that will be used to return the * allocated one from the msgbuf pool. - * * @param[in] name Name to use + * @param[in] name hicn_name_t to use + * + * NOTE: unlike other pools, PIT and CS entries allocation does not update the + * index as the key is a hicn_name_t * which should point to : + * - the name inside the PIT entry (which is thus not set during allocation), + * - the name inside the msgbuf_t in the CS entry, which is always available + * during the lifetime of the cache entry. + * + * The index is therefore updated in pkt_cache_add_to_pit and + * pkt_cache_add_to_cs functions. + * + * */ -pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache, const Name *name); +pkt_cache_entry_t *pkt_cache_allocate(pkt_cache_t *pkt_cache); + +void pkt_cache_add_to_index(const pkt_cache_t *pkt_cache, + const pkt_cache_entry_t *entry); + +void pkt_cache_remove_from_index(const pkt_cache_t *pkt_cache, + const hicn_name_t *name); /** * @brief Free a packet cache data structure. @@ -150,8 +173,8 @@ pit_t *pkt_cache_get_pit(pkt_cache_t *pkt_cache); * @brief Get a reference to the CS data structure contained in the packet * cache. * - * @param[in] pkt_cache Pointer to the packet cache data structure to get the CS - * from. + * @param[in] pkt_cache Pointer to the packet cache data structure to get the + * CS from. */ cs_t *pkt_cache_get_cs(pkt_cache_t *pkt_cache); @@ -170,13 +193,13 @@ size_t pkt_cache_get_size(pkt_cache_t *pkt_cache); size_t pkt_cache_get_num_cs_stale_entries(pkt_cache_t *pkt_cache); /** - * @brief Change the maximum capacity of the content store (LRU eviction will be - * used after reaching the provided size) + * @brief Change the maximum capacity of the content store (LRU eviction will + * be used after reaching the provided size) * * @param[in] pkt_cache Pointer to the packet cache data structure to use * @param[in] size Maximum size of the content store - * @return int 0 if success, -1 if the provided maximum size is smaller than the - * number of elements currently stored in the CS + * @return int 0 if success, -1 if the provided maximum size is smaller than + * the number of elements currently stored in the CS */ int pkt_cache_set_cs_size(pkt_cache_t *pkt_cache, size_t size); @@ -203,8 +226,8 @@ size_t pkt_cache_get_pit_size(pkt_cache_t *pkt_cache); #define pkt_cache_at(pkt_cache, i) (pkt_cache->entries + i) /** - * @brief Retrieve from the packet cache the entry associated with the specified - * name. + * @brief Retrieve from the packet cache the entry associated with the + * specified name. * * @param[in] pkt_cache Pointer to the packet cache data structure to retrieve * the entry from @@ -217,7 +240,8 @@ size_t pkt_cache_get_pit_size(pkt_cache_t *pkt_cache); * allowed to serve contents from the CS * @return pkt_cache_entry_t* Entry retrieved, NULL if none found */ -pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, const Name *name, +pkt_cache_entry_t *pkt_cache_lookup(pkt_cache_t *pkt_cache, + const hicn_name_t *name, msgbuf_pool_t *msgbuf_pool, pkt_cache_lookup_t *lookup_result, off_t *entry_id, @@ -260,11 +284,10 @@ void pkt_cache_cs_remove_entry(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, * @brief Remove a PIT entry from the packet cache. * * @param[in] pkt_cache Pointer to the packet cache data structure to use - * @param[in] entry Pointer to the PITe entry to remove - * @param[in] name Name associated with the PIT entry to remove + * @param[in] entry Pointer to the PIT entry to remove */ void pkt_cache_pit_remove_entry(pkt_cache_t *pkt_cache, - pkt_cache_entry_t *entry, const Name *name); + pkt_cache_entry_t *entry); /** * @brief Convert a PIT entry to a CS entry. @@ -311,7 +334,7 @@ void pkt_cache_cs_to_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, */ pkt_cache_entry_t *pkt_cache_add_to_pit(pkt_cache_t *pkt_cache, const msgbuf_t *msgbuf, - const Name *name); + const hicn_name_t *name); /** * @brief Add CS entry to the packet cache. @@ -329,7 +352,8 @@ pkt_cache_entry_t *pkt_cache_add_to_cs(pkt_cache_t *pkt_cache, msgbuf_t *msgbuf, off_t msgbuf_id); /** - * @brief Update PIT entry in the packet cache in case of an expired PIT entry. + * @brief Update PIT entry in the packet cache in case of an expired PIT + * entry. * * @param[in] pkt_cache Pointer to the packet cache data structure to use * @param[in, out] entry Pointer to the PIT entry to update @@ -371,7 +395,8 @@ void pkt_cache_update_cs(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool, */ bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache, pkt_cache_entry_t *entry, - const msgbuf_t *msgbuf, const Name *name); + const msgbuf_t *msgbuf, + const hicn_name_t *name); /** * @brief Cache prefix info (prefix + associated suffixes) to speed up lookups. @@ -380,7 +405,7 @@ bool pkt_cache_try_aggregate_in_pit(pkt_cache_t *pkt_cache, * @param[in] prefix Name prefix to cache */ void pkt_cache_save_suffixes_for_prefix(pkt_cache_t *pkt_cache, - const NameBitvector *prefix); + const hicn_name_prefix_t *prefix); /** * @brief Reset cached prefix info to force double lookups. @@ -393,7 +418,8 @@ void pkt_cache_reset_suffixes_for_prefix(pkt_cache_t *pkt_cache); /** * @brief Handle data packet reception. - * @details Perform packet cache lookup and execute operations based on it. If: + * @details Perform packet cache lookup and execute operations based on it. + * If: * - INTEREST not expired: Convert PIT entry to CS entry; return the * nexthops (that can be used to forward the data * packet now stored in the CS) @@ -409,7 +435,8 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, /** * @brief Handle interest packet reception. - * @details Perform packet cache lookup and execute operations based on it. If: + * @details Perform packet cache lookup and execute operations based on it. + * If: * - No match: Do nothing * - DATA not expired: get data message from CS * - INTEREST not expired: Aggregate or retransmit the interest received; @@ -419,23 +446,28 @@ nexthops_t *pkt_cache_on_data(pkt_cache_t *pkt_cache, void pkt_cache_on_interest(pkt_cache_t *pkt_cache, msgbuf_pool_t *msgbuf_pool, off_t msgbuf_id, pkt_cache_verdict_t *verdict, off_t *data_msgbuf_id, pkt_cache_entry_t **entry_ptr, - const Name *name, bool is_serve_from_cs_enabled); + const hicn_name_t *name, + bool is_serve_from_cs_enabled); /********* Low-level operations on the hash table *********/ #ifdef WITH_TESTS -unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix, - int *rc); +unsigned __get_suffix(kh_pkt_cache_suffix_t *suffixes, + hicn_name_suffix_t suffix); unsigned _get_suffix(kh_pkt_cache_prefix_t *prefixes, - const NameBitvector *prefix, uint32_t suffix, int *rc); -void __add_suffix(kh_pkt_cache_suffix_t *suffixes, uint32_t suffix, + const hicn_name_prefix_t *prefix, + hicn_name_suffix_t suffix); +void __add_suffix(kh_pkt_cache_suffix_t *suffixes, hicn_name_suffix_t suffix, unsigned val); -void _add_suffix(kh_pkt_cache_prefix_t *prefixes, const NameBitvector *prefix, - uint32_t suffix, unsigned val); +void _add_suffix(kh_pkt_cache_prefix_t *prefixes, + const hicn_name_prefix_t *prefix, hicn_name_suffix_t suffix, + unsigned val); void _remove_suffix(kh_pkt_cache_prefix_t *prefixes, - const NameBitvector *prefix, uint32_t suffix); + const hicn_name_prefix_t *prefix, + hicn_name_suffix_t suffix); void _prefix_map_free(kh_pkt_cache_prefix_t *prefix_to_suffixes); kh_pkt_cache_suffix_t *_get_suffixes(kh_pkt_cache_prefix_t *prefix_to_suffixes, - const NameBitvector *prefix); + const hicn_name_prefix_t *prefix, + bool create); #endif /************** Content Store *****************************/ diff --git a/hicn-light/src/hicn/core/policy_stats.c b/hicn-light/src/hicn/core/policy_stats.c index 1acbccf69..470e74a24 100644 --- a/hicn-light/src/hicn/core/policy_stats.c +++ b/hicn-light/src/hicn/core/policy_stats.c @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifdef WITH_POLICY_STATS // This has to be included first because of _GNU_SOURCE @@ -24,7 +39,6 @@ static int policy_stats_mgr_tick(void* mgr_arg, int fd, void* data) { /* Loop over FIB entries to compute statistics from counters */ const fib_t* fib = forwarder_get_fib(mgr->forwarder); - fib_entry_t* entry; fib_foreach_entry(fib, entry, { policy_stats_update(&entry->policy_stats, &entry->policy_counters, now); @@ -59,7 +73,6 @@ void policy_stats_on_retransmission(const policy_stats_mgr_t* mgr, policy_counters_t* counters, const nexthops_t* nexthops) { connection_table_t* table = forwarder_get_connection_table(mgr->forwarder); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { #ifdef WITH_POLICY const connection_t* conn = connection_table_at(table, nexthop); @@ -97,7 +110,6 @@ void policy_stats_on_data(const policy_stats_mgr_t* mgr, policy_stats_t* stats, size_t msg_size = msgbuf_get_len(msgbuf); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { #ifdef WITH_POLICY const connection_t* conn = connection_table_at(table, nexthop); @@ -121,7 +133,6 @@ void policy_stats_on_timeout(const policy_stats_mgr_t* mgr, #ifdef WITH_POLICY connection_table_t* table = forwarder_get_connection_table(mgr->forwarder); - unsigned nexthop; nexthops_foreach(nexthops, nexthop, { const connection_t* conn = connection_table_at(table, nexthop); if (!conn) continue; diff --git a/hicn-light/src/hicn/core/strategy_vft.h b/hicn-light/src/hicn/core/strategy_vft.h index 0256cba57..55e61db17 100644 --- a/hicn-light/src/hicn/core/strategy_vft.h +++ b/hicn-light/src/hicn/core/strategy_vft.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -24,13 +24,11 @@ #include "../strategies/best_path.h" #include "../strategies/load_balancer.h" -#include "../strategies/low_latency.h" #include "../strategies/random.h" #include "../strategies/replication.h" typedef union { strategy_load_balancer_options_t load_balancer; - strategy_low_latency_options_t low_latency; strategy_random_options_t random; strategy_replication_options_t replication; strategy_bestpath_options_t bestpath; @@ -42,7 +40,6 @@ typedef struct { #endif /* WITH_POLICY */ union { strategy_load_balancer_nexthop_state_t load_balancer; - strategy_low_latency_nexthop_state_t low_latency; strategy_random_nexthop_state_t random; strategy_replication_nexthop_state_t replication; strategy_bestpath_nexthop_state_t bestpath; @@ -58,7 +55,6 @@ typedef struct { typedef union { strategy_load_balancer_state_t load_balancer; - strategy_low_latency_state_t low_latency; strategy_random_state_t random; strategy_replication_state_t replication; strategy_bestpath_state_t bestpath; diff --git a/hicn-light/src/hicn/core/subscription.c b/hicn-light/src/hicn/core/subscription.c index ad4006531..fb954a245 100644 --- a/hicn-light/src/hicn/core/subscription.c +++ b/hicn-light/src/hicn/core/subscription.c @@ -17,12 +17,6 @@ bool topics_contains(hc_topics_t topic_list, hc_topic_t topic) { #define topic_is_set(topic_list, topic_index) \ ((topic_list) & (1 << (topic_index))) -const char *event_str[] = { -#define _(x) [EVENT_##x] = #x, - foreach_event_type -#undef _ -}; - /*----------------------------------------------------------------------------* * Subscriptions *----------------------------------------------------------------------------*/ @@ -56,13 +50,13 @@ int subscription_table_add_topics_for_connection( int ret = vector_push(subscriptions->table[topic_index], connection_id); if (ret < 0) { ERROR("Unable to perform subscription for connection %d, topic %s", - connection_id, object_str(topic_index)); + connection_id, object_type_str(topic_index)); return -1; } if (num_duplicates > 0) { DEBUG("Connection %d had already a subscription for topic %s", - connection_id, object_str(topic_index)); + connection_id, object_type_str(topic_index)); is_subscription_already_present = true; } } @@ -111,14 +105,14 @@ unsigned *subscription_table_get_connections_for_topic( } void subscription_table_print(subscription_table_t *subscriptions) { - for (int topic_index = OBJECT_UNDEFINED + 1; topic_index < NUM_TOPICS; + for (int topic_index = OBJECT_TYPE_UNDEFINED + 1; topic_index < NUM_TOPICS; topic_index++) { printf("topic %s (%lu subscription/s) from connection/s: [ ", - object_str(topic_index), + object_type_str(topic_index), (unsigned long)vector_len(subscriptions->table[topic_index])); unsigned *connection_id; vector_foreach(subscriptions->table[topic_index], connection_id, { printf("%d ", *connection_id); }); printf("]\n"); } -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/io/base.c b/hicn-light/src/hicn/io/base.c index cd7362956..38d36efbe 100644 --- a/hicn-light/src/hicn/io/base.c +++ b/hicn-light/src/hicn/io/base.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -42,7 +42,7 @@ ssize_t io_read_single_fd(int fd, msgbuf_t *msgbuf, address_t *address) { return -1; } - msgbuf->length = (unsigned int)n; + msgbuf_set_len(msgbuf, (size_t)n); *address = ADDRESS_ANY(AF_UNSPEC, 0); // XXX placeholder, see hicn.c } @@ -50,12 +50,18 @@ ssize_t io_read_single_fd(int fd, msgbuf_t *msgbuf, address_t *address) { } ssize_t io_read_single_socket(int fd, msgbuf_t *msgbuf, address_t *address) { - struct sockaddr_storage *sa = &address->as_ss; + struct sockaddr *sa = &(address->as_sa); socklen_t sa_len = sizeof(sa); uint8_t *packet = msgbuf_get_packet(msgbuf); ssize_t n = recvfrom(fd, packet, MTU, 0, (struct sockaddr *)sa, &sa_len); - msgbuf->length = (unsigned int)n; + msgbuf_set_len(msgbuf, (size_t)n); + +#ifdef __APPLE__ + // set __uint8_t sin_len to 0 + uint8_t *ptr = (uint8_t *)sa; + *ptr = 0x0; +#endif /* __APPLE__ */ return n; } @@ -92,6 +98,7 @@ ssize_t io_read_batch_socket(int fd, msgbuf_t **msgbuf, address_t **address, for (;;) { n = recvmmsg(fd, msghdr, batch_size, /* flags */ 0, /* timeout */ NULL); + // INFO("Got n=%d messages", n); if (n == 0) return 0; if (n < 0) { if (errno == EINTR) continue; // XXX was break; @@ -112,7 +119,7 @@ ssize_t io_read_batch_socket(int fd, msgbuf_t **msgbuf, address_t **address, */ for (int i = 0; i < n; i++) { struct mmsghdr *msg = &msghdr[i]; - msgbuf[i]->length = msg->msg_len; + msgbuf_set_len(msgbuf[i], msg->msg_len); memcpy(address[i], msg->msg_hdr.msg_name, msg->msg_hdr.msg_namelen); } diff --git a/hicn-light/src/hicn/io/hicn.c b/hicn-light/src/hicn/io/hicn.c index d019a49c1..c5859fbe3 100644 --- a/hicn-light/src/hicn/io/hicn.c +++ b/hicn-light/src/hicn/io/hicn.c @@ -433,8 +433,8 @@ static bool connection_hicn_send(connection_t *connection, msgbuf_t *msgbuf, // return 0; //} // -static int connection_hicn_send_packet(const connection_t *connection, - const uint8_t *packet, size_t size) { +static bool connection_hicn_send_packet(const connection_t *connection, + const uint8_t *packet, size_t size) { assert(connection); assert(packet); diff --git a/hicn-light/src/hicn/io/tcp.c b/hicn-light/src/hicn/io/tcp.c index 50591c3fc..a924b6330 100644 --- a/hicn-light/src/hicn/io/tcp.c +++ b/hicn-light/src/hicn/io/tcp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -37,7 +37,6 @@ #include "../core/listener_vft.h" #include "../core/msgbuf.h" #include "../core/forwarder.h" -#include "../core/messageHandler.h" // 128 KB output queue #define OUTPUT_QUEUE_BYTES (128 * 1024) @@ -336,8 +335,8 @@ static bool connection_tcp_send(connection_t *connection, msgbuf_t *msgbuf, return true; } -static int connection_tcp_send_packet(const connection_t *connection, - const uint8_t *packet, size_t size) { +static bool connection_tcp_send_packet(const connection_t *connection, + const uint8_t *packet, size_t size) { /* Not implemented for local connections */ // XXX shall we set the pointer to NULL and add a check ? diff --git a/hicn-light/src/hicn/io/udp.c b/hicn-light/src/hicn/io/udp.c index 149d53aea..b06ee7bce 100644 --- a/hicn-light/src/hicn/io/udp.c +++ b/hicn-light/src/hicn/io/udp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -58,7 +58,6 @@ #include "../core/forwarder.h" #include "../core/listener.h" #include "../core/listener_vft.h" -#include "../core/messageHandler.h" #include "../core/msgbuf.h" //#include "../hicn-light/config.h" @@ -336,11 +335,12 @@ static int connection_udp_initialize(connection_t *connection) { static void connection_udp_finalize(connection_t *connection) { assert(connection); assert(connection->type == FACE_TYPE_UDP); - +#ifdef __linux__ connection_udp_data_t *data = connection->data; assert(data); ring_free(data->ring); +#endif /* __linux__ */ } static bool connection_udp_flush(connection_t *connection) { @@ -374,7 +374,7 @@ SEND: msgbuf_t *msgbuf = msgbuf_pool_at(msgbuf_pool, msgbuf_id); // update path label - if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) { + if (msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA) { msgbuf_update_pathlabel(msgbuf, connection_get_id(connection)); connection->stats.data.tx_pkts++; @@ -460,7 +460,7 @@ static bool connection_udp_send(connection_t *connection, msgbuf_t *msgbuf, #endif /* __linux__ */ /* Send one */ // update the path label befor send the packet - if (msgbuf_get_type(msgbuf) == MSGBUF_TYPE_DATA) { + if (msgbuf_get_type(msgbuf) == HICN_PACKET_TYPE_DATA) { msgbuf_update_pathlabel(msgbuf, connection_get_id(connection)); connection->stats.data.tx_pkts++; @@ -478,8 +478,9 @@ static bool connection_udp_send(connection_t *connection, msgbuf_t *msgbuf, return false; } else { // this print is for debugging - printf("Incorrect write length %zd, expected %u: (%d) %s\n", - writeLength, msgbuf_get_len(msgbuf), errno, strerror(errno)); + printf("Incorrect write length %zd, expected %lu: (%d) %s\n", + writeLength, (long unsigned int)msgbuf_get_len(msgbuf), errno, + strerror(errno)); return false; } } @@ -532,8 +533,8 @@ connection_udp_sendv(const connection_t * connection, struct iovec * iov, } #endif -static int connection_udp_send_packet(const connection_t *connection, - const uint8_t *packet, size_t size) { +static bool connection_udp_send_packet(const connection_t *connection, + const uint8_t *packet, size_t size) { assert(connection); assert(packet); @@ -555,16 +556,16 @@ static int connection_udp_send_packet(const connection_t *connection, ssize_t n = send(connection->fd, packet, size, 0); if (n < 0) { perror("sendto"); - return -1; + return false; } #else const address_t *remote = connection_get_remote(connection); ssize_t n = sendto(connection->fd, packet, size, 0, address_sa(remote), address_socklen(remote)); - if (n < 0) return -1; + if (n < 0) return false; #endif - return 0; + return true; } #define connection_udp_read_single \ diff --git a/hicn-light/src/hicn/socket/api.c b/hicn-light/src/hicn/socket/api.c index e39ebf4b5..db377aecd 100644 --- a/hicn-light/src/hicn/socket/api.c +++ b/hicn-light/src/hicn/socket/api.c @@ -43,7 +43,7 @@ static hicn_conf_t hicn_default_conf = { struct ip_rule_state_ { char tun_name[IF_NAMESIZE]; - ip_prefix_t prefix; + hicn_ip_prefix_t prefix; uint32_t table_id; uint8_t priority; uint8_t address_family; @@ -193,7 +193,7 @@ int hicn_socket_cmp(hicn_socket_t *a, hicn_socket_t *b) { return b->fd - a->fd; } -ip_prefix_t *hicn_socket_get_src_ip(hicn_socket_t *socket) { +hicn_ip_prefix_t *hicn_socket_get_src_ip(hicn_socket_t *socket) { if (socket->type != HS_CONNECTION) { return NULL; } @@ -241,7 +241,8 @@ int hicn_set_local_endpoint(hicn_socket_t *socket, const char *local_ip_address, */ /* Copy the local IP address inside the connection */ - rc = ip_prefix_pton(local_ip_address, &socket->connection.tun_ip_address); + rc = + hicn_ip_prefix_pton(local_ip_address, &socket->connection.tun_ip_address); if (rc < 0) { rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR; goto end; @@ -251,14 +252,14 @@ end: return rc; } -int hicn_get_local_address(const ip_prefix_t *remote_address, - ip_prefix_t *local_address) { +int hicn_get_local_address(const hicn_ip_prefix_t *remote_address, + hicn_ip_prefix_t *local_address) { int rc = 0; uint32_t interface_id; char remote_address_str[INET_MAX_ADDRSTRLEN + 4]; - rc = ip_prefix_ntop_short(remote_address, remote_address_str, - sizeof(remote_address_str)); + rc = hicn_ip_prefix_ntop_short(remote_address, remote_address_str, + sizeof(remote_address_str)); if (rc < 0) { rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; goto ERR; @@ -289,7 +290,7 @@ ERR: int hicn_set_remote_endpoint(hicn_socket_t *socket, const char *remote_ip_address) { int af, rc = HICN_SOCKET_ERROR_NONE; - ip_prefix_t addr; + hicn_ip_prefix_t addr; af = get_addr_family(remote_ip_address); if ((af != AF_INET6) && (af != AF_INET)) { @@ -297,7 +298,7 @@ int hicn_set_remote_endpoint(hicn_socket_t *socket, } /* Bind local endpoint if not done yet */ - if (ip_prefix_empty(&socket->connection.tun_ip_address)) { + if (hicn_ip_prefix_empty(&socket->connection.tun_ip_address)) { char local_ip_address[INET_MAX_ADDRSTRLEN + 4]; /* Local interface id */ @@ -327,8 +328,8 @@ int hicn_set_remote_endpoint(hicn_socket_t *socket, ///// /* Convert to representation format */ - rc = - ip_prefix_ntop_short(&addr, local_ip_address, sizeof(local_ip_address)); + rc = hicn_ip_prefix_ntop_short(&addr, local_ip_address, + sizeof(local_ip_address)); if (rc < 0) { rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; goto ERR; @@ -445,8 +446,8 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { return rc; } - ip_prefix_t ip_prefix; - rc = ip_prefix_pton(prefix, &ip_prefix); + hicn_ip_prefix_t hicn_ip_prefix; + rc = hicn_ip_prefix_pton(prefix, &hicn_ip_prefix); if (rc < 0) { return rc; } @@ -457,7 +458,7 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { if (punting_table_id == -1) punting_table_id = socket->connection.table_id; - rc = ops.add_prio_rule(&ip_prefix, ip_prefix.family, 0, + rc = ops.add_prio_rule(&hicn_ip_prefix, hicn_ip_prefix.family, 0, socket->connection.table_id); if (rc < 0) { return rc; @@ -467,8 +468,8 @@ int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { sizeof(rules_to_remove[rules_counter].tun_name), "NONE"); if (rc != EOK) return -1; - rules_to_remove[rules_counter].prefix = ip_prefix; - rules_to_remove[rules_counter].address_family = ip_prefix.family; + rules_to_remove[rules_counter].prefix = hicn_ip_prefix; + rules_to_remove[rules_counter].address_family = hicn_ip_prefix.family; rules_to_remove[rules_counter].table_id = socket->connection.table_id; rules_to_remove[rules_counter].priority = 0; ++rules_counter; diff --git a/hicn-light/src/hicn/socket/api.h b/hicn-light/src/hicn/socket/api.h index a0356e035..3caf9ef1e 100644 --- a/hicn-light/src/hicn/socket/api.h +++ b/hicn-light/src/hicn/socket/api.h @@ -83,7 +83,7 @@ typedef struct hicn_socket_s { union { struct { - ip_prefix_t tun_ip_address; + hicn_ip_prefix_t tun_ip_address; uint32_t interface_id; /* ID of the corresponding table : avoid default values of 0, 32766 and @@ -162,8 +162,8 @@ void hicn_free(hicn_socket_helper_t *hicn); * * @return 0 in case of success, -1 otherwise. */ -int hicn_get_local_address(const ip_prefix_t *remote_address, - ip_prefix_t *local_address); +int hicn_get_local_address(const hicn_ip_prefix_t *remote_address, + hicn_ip_prefix_t *local_address); /* hICN socket */ diff --git a/hicn-light/src/hicn/socket/ops.h b/hicn-light/src/hicn/socket/ops.h index 1bee7c6f6..854b0c461 100644 --- a/hicn-light/src/hicn/socket/ops.h +++ b/hicn-light/src/hicn/socket/ops.h @@ -17,10 +17,10 @@ typedef struct { int (*get_output_ifid)(const char *ip_address, uint8_t address_family, uint32_t *interface_id); int (*get_ip_addr)(uint32_t interface_id, uint8_t address_family, - ip_prefix_t *ip_address); - int (*set_ip_addr)(uint32_t interface_id, ip_prefix_t *ip_address); + hicn_ip_prefix_t *ip_address); + int (*set_ip_addr)(uint32_t interface_id, hicn_ip_prefix_t *ip_address); int (*up_if)(uint32_t interface_id); - int (*add_in_route_table)(const ip_prefix_t *prefix, + int (*add_in_route_table)(const hicn_ip_prefix_t *prefix, const uint32_t interface_id, const uint8_t table_id); int (*add_in_route_table_s)(const char *prefix, const uint32_t interface_id, @@ -30,23 +30,23 @@ typedef struct { const uint8_t table_id, int default_route); int (*del_out_route)(const char *gateway, const uint8_t address_family, const uint8_t table_id); - int (*del_lo_route)(const ip_prefix_t *ip_address); + int (*del_lo_route)(const hicn_ip_prefix_t *ip_address); int (*add_rule)(const char *interface_name, const uint8_t address_family, const uint8_t table_id); int (*del_rule)(const char *interface_name, const uint8_t address_family, const uint8_t table_id); - int (*add_neigh_proxy)(const ip_prefix_t *ip_address, + int (*add_neigh_proxy)(const hicn_ip_prefix_t *ip_address, const uint32_t interface_id); - int (*add_prio_rule)(const ip_prefix_t *ip_address, + int (*add_prio_rule)(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority, const uint8_t table_id); - int (*add_lo_prio_rule)(const ip_prefix_t *ip_address, + int (*add_lo_prio_rule)(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority); - int (*del_prio_rule)(const ip_prefix_t *ip_address, + int (*del_prio_rule)(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority, const uint8_t table_id); - int (*del_lo_prio_rule)(const ip_prefix_t *ip_address, + int (*del_lo_prio_rule)(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority); } hicn_socket_ops_t; diff --git a/hicn-light/src/hicn/socket/ops_linux.c b/hicn-light/src/hicn/socket/ops_linux.c index d741fd2e6..a3675e929 100644 --- a/hicn-light/src/hicn/socket/ops_linux.c +++ b/hicn-light/src/hicn/socket/ops_linux.c @@ -62,13 +62,13 @@ int _nl_get_output_ifid(const char *ip_address, uint8_t address_family, * @see getifaddrs */ int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, - ip_prefix_t *ip_address); + hicn_ip_prefix_t *ip_address); -int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *ip_address); +int _nl_set_ip_addr(uint32_t interface_id, hicn_ip_prefix_t *ip_address); int _nl_up_if(uint32_t interface_id); -int _nl_add_in_route_table(const ip_prefix_t *prefix, +int _nl_add_in_route_table(const hicn_ip_prefix_t *prefix, const uint32_t interface_id, const uint8_t table_id); int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id, const uint8_t table_id); @@ -79,25 +79,25 @@ int _nl_add_out_route(const char *gateway, const uint8_t address_family, int _nl_del_out_route(const char *gateway, const uint8_t address_family, const uint8_t table_id); -int _nl_del_lo_route(const ip_prefix_t *ip_address); +int _nl_del_lo_route(const hicn_ip_prefix_t *ip_address); int _nl_add_rule(const char *interface_name, const uint8_t address_family, const uint8_t table_id); int _nl_del_rule(const char *interface_name, const uint8_t address_family, const uint8_t table_id); -int _nl_add_neigh_proxy(const ip_prefix_t *ip_address, +int _nl_add_neigh_proxy(const hicn_ip_prefix_t *ip_address, const uint32_t interface_id); -int _nl_add_prio_rule(const ip_prefix_t *ip_address, +int _nl_add_prio_rule(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority, const uint8_t table_id); -int _nl_add_lo_prio_rule(const ip_prefix_t *ip_address, +int _nl_add_lo_prio_rule(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority); -int _nl_del_prio_rule(const ip_prefix_t *ip_address, +int _nl_del_prio_rule(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority, const uint8_t table_id); -int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address, +int _nl_del_lo_prio_rule(const hicn_ip_prefix_t *ip_address, const uint8_t address_family, const uint32_t priority); #endif /* HICN_NETLINK_H */ @@ -533,7 +533,7 @@ ERR: } int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, - ip_prefix_t *prefix) { + hicn_ip_prefix_t *prefix) { char buffer[BUFSIZE]; struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; size_t n; @@ -602,7 +602,7 @@ ERR_SOCKET: return HICN_SOCKET_ERROR_UNSPEC; } -int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *prefix) { +int _nl_set_ip_addr(uint32_t interface_id, hicn_ip_prefix_t *prefix) { char buffer[BUFSIZE]; struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; size_t n; @@ -622,14 +622,15 @@ int _nl_set_ip_addr(uint32_t interface_id, ip_prefix_t *prefix) { .payload.ifa_index = interface_id}; /* Set attributes = length/type/value */ - struct rtattr ifa_address = {RTA_LENGTH(ip_address_len(prefix->family)), + struct rtattr ifa_address = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), IFA_ADDRESS}; - const void *address = ip_address_get_buffer(&prefix->address, prefix->family); + const void *address = + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR_ADDRESS; const struct iovec iov[] = { {&msg, sizeof(msg)}, {&ifa_address, sizeof(ifa_address)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, }; msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); @@ -967,7 +968,7 @@ ERR_SOCKET: * ip route del 1:2::2 dev lo table local * */ -int _nl_del_lo_route(const ip_prefix_t *prefix) { +int _nl_del_lo_route(const hicn_ip_prefix_t *prefix) { char buffer[BUFSIZE]; struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; size_t n; @@ -993,17 +994,20 @@ int _nl_del_lo_route(const ip_prefix_t *prefix) { /* Set attribute = length/type/value */ uint32_t one = 1; - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), RTA_DST}; + struct rtattr a_dst = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + RTA_DST}; struct rtattr a_ifid_lo = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; - const void *address = ip_address_get_buffer(&prefix->address, prefix->family); + const void *address = + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; - const struct iovec iov[] = {{&msg, sizeof(msg)}, - /* Ip address */ - {&a_dst, sizeof(a_dst)}, - {(void *)address, ip_address_len(prefix->family)}, - /* Interface id */ - {&a_ifid_lo, sizeof(a_ifid_lo)}, - {&one, sizeof(one)}}; + const struct iovec iov[] = { + {&msg, sizeof(msg)}, + /* Ip address */ + {&a_dst, sizeof(a_dst)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, + /* Interface id */ + {&a_ifid_lo, sizeof(a_ifid_lo)}, + {&one, sizeof(one)}}; msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); @@ -1131,7 +1135,7 @@ ERR_SOCKET: * ip -6 neigh add proxy 1:2::2 dev hicnc-cons-eth0 2>&1 | grep nei * */ -int _nl_add_neigh_proxy(const ip_prefix_t *prefix, +int _nl_add_neigh_proxy(const hicn_ip_prefix_t *prefix, const uint32_t interface_id) { /* Buffer for holding the response, with appropriate casting on the header */ char buffer[BUFSIZE]; @@ -1156,9 +1160,11 @@ int _nl_add_neigh_proxy(const ip_prefix_t *prefix, }; /* Message attributes = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), NDA_DST}; + struct rtattr a_dst = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + NDA_DST}; - const void *address = ip_address_get_buffer(&prefix->address, prefix->family); + const void *address = + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; /* Iovec describing the packets */ @@ -1166,7 +1172,7 @@ int _nl_add_neigh_proxy(const ip_prefix_t *prefix, {&msg, sizeof(msg)}, /* Ip address */ {&a_dst, sizeof(a_dst)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, }; msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); @@ -1204,7 +1210,7 @@ ERR: /* ip -6 route add 0:1::/64 dev hicn-if0 table 100 */ /* ip -6 route add 0:2::/64 dev hicn-if1 table 100 */ -int _nl_add_in_route_table(const ip_prefix_t *prefix, +int _nl_add_in_route_table(const hicn_ip_prefix_t *prefix, const uint32_t interface_id, const uint8_t table_id) { /* Buffer for holding the response, with appropriate casting on the header */ @@ -1236,10 +1242,12 @@ int _nl_add_in_route_table(const ip_prefix_t *prefix, }; /* Message attributes = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix->family)), RTA_DST}; + struct rtattr a_dst = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + RTA_DST}; struct rtattr a_oif = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; - const void *address = ip_address_get_buffer(&prefix->address, prefix->family); + const void *address = + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; /* Iovec describing the packets */ @@ -1247,7 +1255,7 @@ int _nl_add_in_route_table(const ip_prefix_t *prefix, {&msg, sizeof(msg)}, /* Destination prefix / ip address */ {&a_dst, sizeof(a_dst)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, /* Output interface */ {&a_oif, sizeof(a_oif)}, {(void *)&interface_id, sizeof(uint32_t)}, @@ -1291,9 +1299,9 @@ ERR: int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id, const uint8_t table_id) { int rc; - ip_prefix_t ip_address; + hicn_ip_prefix_t ip_address; - rc = ip_prefix_pton(prefix, &ip_address); + rc = hicn_ip_prefix_pton(prefix, &ip_address); if (rc < 0) { return rc; } @@ -1306,7 +1314,7 @@ int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id) { } /* ip -6 rule add from b001::/16 prio 0 table 100 */ -int _nl_add_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, +int _nl_add_prio_rule(const hicn_ip_prefix_t *prefix, uint8_t address_family, const uint32_t priority, const uint8_t table_id) { /* Buffer for holding the response, with appropriate casting on the header */ char buffer[BUFSIZE]; @@ -1341,18 +1349,19 @@ int _nl_add_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, if (prefix) { /* Message attributes = length/type/value */ - struct rtattr a_src = {RTA_LENGTH(ip_address_len(prefix->family)), FRA_SRC}; + struct rtattr a_src = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + FRA_SRC}; struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; const void *address = - ip_address_get_buffer(&prefix->address, prefix->family); + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; /* Iovec describing the packets */ const struct iovec iov[] = { {&msg, sizeof(msg)}, /* Source prefix / prefix */ {&a_src, sizeof(a_src)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, /* Priority */ {&a_prio, sizeof(a_prio)}, {(void *)&priority, sizeof(uint32_t)}, @@ -1403,13 +1412,13 @@ ERR: return HICN_SOCKET_ERROR_UNSPEC; } -int _nl_add_lo_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, +int _nl_add_lo_prio_rule(const hicn_ip_prefix_t *prefix, uint8_t address_family, const uint32_t priority) { return _nl_add_prio_rule(prefix, address_family, priority, RT_TABLE_LOCAL); } /* ip -6 rule del from all prio 0 table local */ -int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, +int _nl_del_prio_rule(const hicn_ip_prefix_t *prefix, uint8_t address_family, const uint32_t priority, const uint8_t table_id) { /* Buffer for holding the response, with appropriate casting on the header */ char buffer[BUFSIZE]; @@ -1444,11 +1453,12 @@ int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, /* Message attributes = length/type/value */ if (prefix) { - struct rtattr a_src = {RTA_LENGTH(ip_address_len(prefix->family)), FRA_SRC}; + struct rtattr a_src = {RTA_LENGTH(hicn_ip_address_len(prefix->family)), + FRA_SRC}; struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; const void *address = - ip_address_get_buffer(&prefix->address, prefix->family); + hicn_ip_address_get_buffer(&prefix->address, prefix->family); if (!address) goto ERR; /* Iovec describing the packets */ @@ -1456,7 +1466,7 @@ int _nl_del_prio_rule(const ip_prefix_t *prefix, uint8_t address_family, {&msg, sizeof(msg)}, /* Source prefix / prefix */ {&a_src, sizeof(a_src)}, - {(void *)address, ip_address_len(prefix->family)}, + {(void *)address, hicn_ip_address_len(prefix->family)}, /* Priority */ {&a_prio, sizeof(a_prio)}, {(void *)&priority, sizeof(uint32_t)}, @@ -1509,8 +1519,8 @@ ERR: return HICN_SOCKET_ERROR_UNSPEC; } -int _nl_del_lo_prio_rule(const ip_prefix_t *ip_address, uint8_t address_family, - const uint32_t priority) { +int _nl_del_lo_prio_rule(const hicn_ip_prefix_t *ip_address, + uint8_t address_family, const uint32_t priority) { return _nl_del_prio_rule(ip_address, address_family, priority, RT_TABLE_LOCAL); } diff --git a/hicn-light/src/hicn/strategies/CMakeLists.txt b/hicn-light/src/hicn/strategies/CMakeLists.txt index 15ae93fea..434106a44 100644 --- a/hicn-light/src/hicn/strategies/CMakeLists.txt +++ b/hicn-light/src/hicn/strategies/CMakeLists.txt @@ -13,7 +13,6 @@ list(APPEND HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/load_balancer.h - ${CMAKE_CURRENT_SOURCE_DIR}/low_latency.h ${CMAKE_CURRENT_SOURCE_DIR}/random.h ${CMAKE_CURRENT_SOURCE_DIR}/replication.h ${CMAKE_CURRENT_SOURCE_DIR}/best_path.h @@ -23,7 +22,6 @@ list(APPEND HEADER_FILES list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/load_balancer.c - ${CMAKE_CURRENT_SOURCE_DIR}/low_latency.c ${CMAKE_CURRENT_SOURCE_DIR}/random.c ${CMAKE_CURRENT_SOURCE_DIR}/replication.c ${CMAKE_CURRENT_SOURCE_DIR}/best_path.c diff --git a/hicn-light/src/hicn/strategies/best_path.c b/hicn-light/src/hicn/strategies/best_path.c index 35a07c43f..9223cc8ac 100644 --- a/hicn-light/src/hicn/strategies/best_path.c +++ b/hicn-light/src/hicn/strategies/best_path.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -88,8 +88,20 @@ static void bestpath_update_remote_node(strategy_entry_t *entry, strategy_state_t *state = &entry->state.bestpath; strategy_bestpath_options_t *options = &entry->options.bestpath; off_t offset = nexthops_find(nexthops, state->best_nexthop); + + /* Backup flags and cur_len: because our code is called from + * strategy_on_data / check_stop_probing / stop_probing + * which does not expect the nexthop flags to be modified. + */ + uint_fast32_t flags = nexthops->flags; + size_t cur_len = nexthops_get_curlen(nexthops); + nexthops_select(nexthops, offset); update_remote_node_paths(nexthops, entry->forwarder, options->local_prefixes); + + /* Restore flags & curlen */ + nexthops->flags = flags; + nexthops->cur_elts = cur_len; } // probing functions @@ -104,9 +116,8 @@ static void start_probing(strategy_entry_t *entry) { static void stop_probing(strategy_entry_t *entry, nexthops_t *nexthops) { strategy_state_t *state = &entry->state.bestpath; - nexthop_t best_nexthop, nexthop; + nexthop_t best_nexthop; best_nexthop = state->best_nexthop; - unsigned i; unsigned int min_cost = ~0; unsigned current_nexthop_cost = ~0; @@ -164,8 +175,6 @@ static void send_probes(strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) { strategy_state_t *state = &entry->state.bestpath; - unsigned i; - nexthop_t nexthop; bool sent_max_probes = false; nexthops_enumerate(nexthops, i, nexthop, { if (get_sent_probes(nexthop_state(nexthops, i)) < MAX_PROBES) { @@ -241,6 +250,7 @@ static nexthops_t *strategy_bestpath_lookup_nexthops(strategy_entry_t *entry, strategy_state_t *state = &entry->state.bestpath; off_t best_nexthop_offset = nexthops_find(nexthops, state->best_nexthop); + // TODO explain the purpose of this test if (nexthops_len == 1) { nexthop_t nh = nexthops_get_one(nexthops); if (state->best_nexthop != nh) { @@ -265,7 +275,7 @@ static nexthops_t *strategy_bestpath_lookup_nexthops(strategy_entry_t *entry, // send a probe for each interest received send_probes(entry, nexthops, msgbuf); - uint32_t suffix = name_GetSuffix(msgbuf_get_name(msgbuf)); + uint32_t suffix = hicn_name_get_suffix(msgbuf_get_name(msgbuf)); if (suffix >= MIN_PROBE_SUFFIX && suffix <= MAX_PROBE_SUFFIX) { // this packet is a probe from the transport, so register it Ticks time = get_probe_send_time(state->pg, suffix); @@ -302,7 +312,7 @@ static int strategy_bestpath_on_data(strategy_entry_t *entry, strategy_state_t *state = &entry->state.bestpath; if (state->probing_state == PROBING_OFF) return 0; - uint32_t seq = name_GetSuffix(msgbuf_get_name(msgbuf)); + uint32_t seq = hicn_name_get_suffix(msgbuf_get_name(msgbuf)); if (seq >= MIN_PROBE_SUFFIX && seq <= MAX_PROBE_SUFFIX) { if (pitEntryCreation != 0) { // this is not a probe sent by the forwader. do not use it in the probing @@ -311,7 +321,6 @@ static int strategy_bestpath_on_data(strategy_entry_t *entry, return 0; } - unsigned nexthop, i; Ticks send_time = get_probe_send_time(state->pg, seq); if (send_time != 0) { Ticks rtt = ticks_now() - send_time; diff --git a/hicn-light/src/hicn/strategies/load_balancer.c b/hicn-light/src/hicn/strategies/load_balancer.c index 709efcf23..0e1a170f7 100644 --- a/hicn-light/src/hicn/strategies/load_balancer.c +++ b/hicn-light/src/hicn/strategies/load_balancer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -58,8 +58,6 @@ static inline void update_state_dec(nexthop_state_t *state) { } static inline void reset_all(nexthops_t *nexthops) { - unsigned i; - nexthop_t nexthop; nexthops_enumerate(nexthops, i, nexthop, { (void)nexthop; nexthops->state[i].load_balancer = NEXTHOP_STATE_INIT; @@ -95,9 +93,9 @@ static int strategy_load_balancer_remove_nexthop(strategy_entry_t *entry, static nexthops_t *strategy_load_balancer_lookup_nexthops( strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) { + if (nexthops_get_curlen(nexthops) == 0) return nexthops; /* Compute the sum of weights of potential next hops */ double sum = 0; - unsigned i, nexthop; nexthops_enumerate(nexthops, i, nexthop, { (void)nexthop; sum += nexthops_state(nexthops, i).load_balancer.weight; @@ -125,10 +123,7 @@ static int strategy_load_balancer_on_timeout( * nexthops, we can allow for linear search that will be very efficient * CPU-wise. */ - nexthop_t timeout_nexthop; nexthops_foreach(timeout_nexthops, timeout_nexthop, { - nexthop_t nexthop; - unsigned i; nexthops_enumerate(nexthops, i, nexthop, { if (nexthop == timeout_nexthop) update_state_dec(nexthop_state(nexthops, i)); diff --git a/hicn-light/src/hicn/strategies/local_prefixes.c b/hicn-light/src/hicn/strategies/local_prefixes.c index 23d72ae80..25927ac69 100644 --- a/hicn-light/src/hicn/strategies/local_prefixes.c +++ b/hicn-light/src/hicn/strategies/local_prefixes.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -16,13 +16,12 @@ #include "local_prefixes.h" #include <hicn/core/forwarder.h> #include <hicn/core/nexthops.h> -#include <hicn/core/name.h> #include <hicn/core/mapme.h> #define MAX_PREFIXES 10 struct local_prefixes_s { - Name local_prefixes[MAX_PREFIXES]; + hicn_prefix_t local_prefixes[MAX_PREFIXES]; unsigned len; }; @@ -38,9 +37,10 @@ unsigned local_prefixes_get_len(local_prefixes_t *prefixes) { return prefixes->len; } -bool contain_prefix(local_prefixes_t *prefixes, Name *name) { +bool contain_prefix(const local_prefixes_t *prefixes, + const hicn_prefix_t *prefix) { for (unsigned i = 0; i < prefixes->len; i++) { - if (name_Equals(&(prefixes->local_prefixes[i]), name)) return true; + if (hicn_prefix_equals(&(prefixes->local_prefixes[i]), prefix)) return true; } return false; } @@ -51,19 +51,19 @@ void local_prefixes_add_prefixes(local_prefixes_t *prefixes, unsigned i = 0; while ((i < new_prefixes->len) && (prefixes->len < MAX_PREFIXES)) { if (!contain_prefix(prefixes, &(new_prefixes->local_prefixes[i]))) { - name_Copy(&new_prefixes->local_prefixes[i], - &prefixes->local_prefixes[prefixes->len]); + hicn_prefix_copy(&prefixes->local_prefixes[prefixes->len], + &new_prefixes->local_prefixes[i]); prefixes->len++; } i++; } } -void local_prefixes_add_prefix(local_prefixes_t *prefixes, const void *prefix) { +void local_prefixes_add_prefix(local_prefixes_t *prefixes, + const hicn_prefix_t *prefix) { if (prefixes->len >= MAX_PREFIXES) return; - Name *n = (Name *)prefix; - if (!contain_prefix(prefixes, n)) { - name_Copy(n, &(prefixes->local_prefixes[prefixes->len])); + if (!contain_prefix(prefixes, prefix)) { + hicn_prefix_copy(&(prefixes->local_prefixes[prefixes->len]), prefix); prefixes->len++; } } @@ -74,8 +74,9 @@ void update_remote_node_paths(const void *nexthops, const void *forwarder, struct mapme_s *mapme = forwarder_get_mapme((forwarder_t *)forwarder); fib_t *fib = forwarder_get_fib((forwarder_t *)forwarder); for (unsigned i = 0; i < prefixes->len; i++) { - fib_entry_t *entry = fib_match_name(fib, &prefixes->local_prefixes[i]); + fib_entry_t *entry = fib_match_prefix(fib, &prefixes->local_prefixes[i]); if (!entry) continue; - mapme_set_adjacencies(mapme, entry, (nexthops_t *)nexthops, false); + // XXX we don't want to force + mapme_set_adjacencies(mapme, entry, (nexthops_t *)nexthops); } } diff --git a/hicn-light/src/hicn/strategies/local_prefixes.h b/hicn-light/src/hicn/strategies/local_prefixes.h index 833a48057..9d7d8ec78 100644 --- a/hicn-light/src/hicn/strategies/local_prefixes.h +++ b/hicn-light/src/hicn/strategies/local_prefixes.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -24,6 +24,8 @@ #ifndef HICNLIGHT_LOCAL_PREFIXES_H #define HICNLIGHT_LOCAL_PREFIXES_H +#include <hicn/name.h> + typedef struct local_prefixes_s local_prefixes_t; local_prefixes_t* create_local_prefixes(); @@ -35,7 +37,8 @@ unsigned local_prefixes_get_len(local_prefixes_t* prefixes); void local_prefixes_add_prefixes(local_prefixes_t* prefixes, local_prefixes_t* new_prefixes); -void local_prefixes_add_prefix(local_prefixes_t* prefixes, const void* prefix); +void local_prefixes_add_prefix(local_prefixes_t* prefixes, + const hicn_prefix_t* prefix); void update_remote_node_paths(const void* nexthops, const void* forwarder, local_prefixes_t* prefixes); diff --git a/hicn-light/src/hicn/strategies/low_latency.c b/hicn-light/src/hicn/strategies/low_latency.c deleted file mode 100644 index 1e5a74c1a..000000000 --- a/hicn-light/src/hicn/strategies/low_latency.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if 0 - -#include <hicn/hicn-light/config.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <math.h> - -#include <hicn/base/khash.h> - -#include <parc/assert/parc_Assert.h> -#include <parc/algol/parc_HashMap.h> -#include <parc/algol/parc_Memory.h> -#include <parc/algol/parc_Object.h> -#include <parc/algol/parc_Unsigned.h> - -#include <hicn/core/messageHandler.h> - -#include "low_latency.h" - -#define STABILITY_FACTOR 15 -#define MAX_SWITCH_TRY 10 -#define MAX_LATENCY_DIFF 10 -#define MAX_TOLLERATED_LATENCY_DIFF 15 -#define MAX_ROUNDS_MP_WITHOUT_CHECK 2 -#define MAX_ROUNDS_AVOIDING_MULTIPATH 40 /* about 20 sec */ -#define MAX_ROUNDS_WITH_ERROR 4 -#define PROBE_LIFETIME 500 /* ms */ - -#define MAX_ROUNS_WITHOUT_PROBES 4 - -/* - * If we do not receives probes for 4 rounds it means that we had no responce - * from any producer for 2 sec we can say that this interface is daed - */ -#define MIN_NON_LOSSY_ROUNDS 10 - -/* - * Number of rounds in non lossy mode before switch to no lossy state - * Defaults to 10 % - */ -#define MAX_LOSS_RATE 0.10 - -/* Shorthands */ -#define nexthop_state_t strategy_low_latency_nexthop_state_t -#define state_t strategy_low_latency_state_t - -#define NEXTHOP_STATE_INIT \ - { \ - .in_use = false, .is_allowed = true, .sent_packets = 0, \ - .last_try_to_switch_round = 0, .try_to_switch_counter = 0, \ - .recevied_probes = 0, .rounds_without_probes = 0, .sent_probes = 0, \ - .lost_probes = 0, .non_lossy_rounds = MIN_NON_LOSSY_ROUNDS, \ - .avg_rtt = -1.0, .avg_rtt_in_use = -1.0, .avg_queue = 0.0001, \ - .avg_loss_rate = 0.0, \ - } - -// XXX ???? -#define STATE_INIT \ - {} - -static - void -strategy_low_latency_SendProbesCB(int fd, PARCEventType which_event, void *data) -{ - parcAssertTrue(which_event & PARCEventType_Timeout, - "Event incorrect, expecting %X set, got %X", - PARCEventType_Timeout, which_event); - - StrategyLowLatency *ll = (StrategyLowLatency *) data; - - //delete old pending probes - if(parcHashMap_Size(ll->pending_probes_ticks) != 0){ - Ticks now = forwarder_GetTicks(ll->forwarder); - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->pending_probes_ticks); - NumberSet *to_remove = numberSet_Create(); - while(parcIterator_HasNext(iterator)) { - PARCUnsigned *parc_seq = (PARCUnsigned *) parcIterator_Next(iterator); - PARCUnsigned *parc_time = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_ticks, parc_seq); - Ticks sent_time = parcUnsigned_GetUnsigned(parc_time); - if((now - sent_time) > PROBE_LIFETIME){ - //probes to delete - numberSet_Add(to_remove, parcUnsigned_GetUnsigned(parc_seq)); - } - } - parcIterator_Release(&iterator); - - for(int i = 0; i < numberSet_Length(to_remove); i++){ - PARCUnsigned *prob_seq = parcUnsigned_Create(numberSet_GetItem(to_remove,i)); - PARCUnsigned *cid = (PARCUnsigned *) parcHashMap_Get(ll->pending_probes_faces, prob_seq); - StrategyNexthopStateLL *state = - (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid); - strategyNexthopStateLL_LostProbe(state); - parcHashMap_Remove(ll->pending_probes_ticks, prob_seq); - parcHashMap_Remove(ll->pending_probes_faces, prob_seq); - parcUnsigned_Release(&prob_seq); - } - numberSet_Release(&to_remove); - } - - ConnectionTable * ct = forwarder_GetConnectionTable(ll->forwarder); - - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while(parcIterator_HasNext(iterator)){ - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - Connection *conn = - (Connection *)connectionTable_FindById(ct, - parcUnsigned_GetUnsigned(cid)); - if(!conn) - continue; - - StrategyNexthopStateLL *state = - (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid); - - //probe only usable paths - if(!strategyNexthopStateLL_IsAllowed(state)) - continue; - - uint32_t seq = rand(); - messageHandler_SetProbeName(ll->probe, HF_INET6_TCP, - ll->name, seq); - connection_Probe(conn, ll->probe); - - PARCUnsigned *parc_seq = parcUnsigned_Create(seq); - Ticks now = forwarder_GetTicks(ll->forwarder); - PARCUnsigned *parc_time = parcUnsigned_Create((unsigned int)now); - parcHashMap_Put(ll->pending_probes_ticks, parc_seq, parc_time); - parcHashMap_Put(ll->pending_probes_faces, parc_seq, cid); - strategyNexthopStateLL_SentProbe(state); - parcUnsigned_Release(&parc_seq); - parcUnsigned_Release(&parc_time); - } - parcIterator_Release(&iterator); - - struct timeval timeout = {0,50000}; - parcEventTimer_Start(ll->sendProbes, &timeout); -} - -static -void -strategy_low_latency_SendMapmeUpdate(StrategyLowLatency *ll, - const NumberSet * nexthops){ - MapMe * mapme = forwarder_getMapmeInstance(ll->forwarder); - FIB * fib = forwarder_getFib((Forwarder*) ll->forwarder); - for(unsigned i = 0; i < ll->related_prefixes_len; i++){ - FibEntry *fibEntry = fib_MatchName(fib, ll->related_prefixes[i]); - if (!fibEntry) - continue; - mapme_maybe_send_to_nexthops(mapme, fibEntry, nexthops); - } -} - -static -void -strategy_low_latency_SelectBestFaces(StrategyLowLatency *ll, bool new_round) -{ - - StrategyNexthopStateLL * old_faces[2]; - old_faces[0] = ll->bestFaces[0]; - old_faces[1] = ll->bestFaces[1]; - - if(new_round){ - ll->round++; - } - - if(parcHashMap_Size(ll->strategy_state) == 0){ - ll->bestFaces[0] = NULL; - ll->bestFaces[1] = NULL; - ll->use2paths = false; - goto NEW_ROUND; - } - - if(ll->use2paths && ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL){ - //multipath case - - if(!strategyNexthopStateLL_IsLossy(ll->bestFaces[0]) - && !strategyNexthopStateLL_IsLossy(ll->bestFaces[1]) - && strategyNexthopStateLL_IsAllowed(ll->bestFaces[0]) - && strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){ - - if(ll->rounds_in_multipath < MAX_ROUNDS_MP_WITHOUT_CHECK){ - //we are at the first rounds of the multipath let's wait a bit - //(MAX_ROUNDS_MP_WITHOUT_CHECK) to make the queuing converge - ll->rounds_in_multipath++; - goto NEW_ROUND; - } - - //we need to decide if we want ot keep using two paths or not - ll->rounds_in_multipath++; - double rtt0 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]); - double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]); - double diff = fabs(rtt0 - rtt1); - - if(diff < MAX_LATENCY_DIFF){ - //everything is working, keep using the two paths - ll->rounds_with_error = 0; - goto NEW_ROUND; - } - - //check for how many rounds we had problems - if(ll->rounds_with_error < MAX_ROUNDS_WITH_ERROR && - diff < MAX_TOLLERATED_LATENCY_DIFF){ - //we can tollerate few round with errors - ll->rounds_with_error++; - goto NEW_ROUND; - } - - //prevent the usage of multiple paths - ll->rounds_with_error = 0; - ll->avoid_multipath = true; - ll->rounds_avoiding_multipath = 0; - } //else - //at least one of the two path is lossy - //or it is not allowed by the policies. - //search for a better possibility - } - - ll->bestFaces[0] = NULL; - ll->bestFaces[1] = NULL; - - //check if there is at least one non lossy connection - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - bool check_losses = true; - bool found_good_face = false; - while(parcIterator_HasNext(iterator) && !found_good_face){ - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - const StrategyNexthopStateLL *state = parcHashMap_Get(ll->strategy_state, cid); - if(!strategyNexthopStateLL_IsLossy(state) && - strategyNexthopStateLL_IsAllowed(state)){ - found_good_face = true; - } - } - parcIterator_Release(&iterator); - if(!found_good_face){ - // all the available faces are lossy, so we take into account only - // the latency computed with the probes - check_losses = false; - } - - if(ll->bestFaces[0] == NULL){ - //try to take a random face - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - bool face_found = false; - while(parcIterator_HasNext(iterator) && !face_found) { - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - StrategyNexthopStateLL *state = (StrategyNexthopStateLL *) - parcHashMap_Get(ll->strategy_state, cid); - - if((check_losses && strategyNexthopStateLL_IsLossy(state)) || - !strategyNexthopStateLL_IsAllowed(state)){ - //skip the face - continue; - } - - ll->bestFaces[0] = state; - face_found = true; - } - parcIterator_Release(&iterator); - } - - if(ll->bestFaces[0] == NULL){ - //no usable face exists - ll->bestFaces[0] = NULL; - ll->bestFaces[1] = NULL; - ll->use2paths = false; - goto NEW_ROUND; - } - - double bestRtt = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]); - - if(ll->avoid_multipath) - ll->rounds_avoiding_multipath++; - - if(ll->rounds_avoiding_multipath > MAX_ROUNDS_AVOIDING_MULTIPATH){ - ll->avoid_multipath = false; - ll->rounds_avoiding_multipath = 0; - } - - iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while (parcIterator_HasNext(iterator)) { - - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - StrategyNexthopStateLL *state = (StrategyNexthopStateLL *) - parcHashMap_Get(ll->strategy_state, cid); - double rtt = strategyNexthopStateLL_GetRTTLive(state); - - if((check_losses && strategyNexthopStateLL_IsLossy(state)) || - !strategyNexthopStateLL_IsAllowed(state)){ - //skip the face - continue; - } - - if(rtt + STABILITY_FACTOR < bestRtt){ - //maybe we found a better face - double rttInUse = strategyNexthopStateLL_GetRTTInUse(state); - unsigned try = strategyNexthopStateLL_GetTryToSwitch(state); - - //we check the rtt in use to check if the new face that we found - //gets congested when we use it to send the traffic - if(rttInUse < bestRtt || try > MAX_SWITCH_TRY){ - //we have a new best face! - strategyNexthopStateLL_ResetTryToSwitch((StrategyNexthopStateLL*) state); - bestRtt = rtt; - if(ll->bestFaces[0] != NULL) - strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[0]); - ll->bestFaces[0] = (StrategyNexthopStateLL*) state; - }else{ - //in this case we should switch but we wait MAX_SWITCH_TRY - //before switch to avoid ossillations between different paths - strategyNexthopStateLL_IncreaseTryToSwitch( - (StrategyNexthopStateLL*) state, ll->round); - } - } - } - - parcIterator_Release(&iterator); - - if(ll->bestFaces[0] == NULL){ - //we found no face so return - ll->bestFaces[0] = NULL; - ll->bestFaces[1] = NULL; - ll->use2paths = false; - goto NEW_ROUND; - } - - if(parcHashMap_Size(ll->strategy_state) == 1 || ll->avoid_multipath){ - //in this case (one face available or avoid multipath) we stop the - //search here. Just reset face 1 if needed - if(ll->bestFaces[1] != NULL){ - strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]); - ll->bestFaces[1] = NULL; - } - ll->use2paths = false; - goto NEW_ROUND; - } - - //if we are here we have more than 1 interface, so we search for a second one - //to use in case of multipath - iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while (parcIterator_HasNext(iterator)) { - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - if(parcUnsigned_GetUnsigned(cid) != - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])){ - - StrategyNexthopStateLL *state = (StrategyNexthopStateLL *) - parcHashMap_Get(ll->strategy_state, cid); - - if((check_losses && strategyNexthopStateLL_IsLossy(state)) || - !strategyNexthopStateLL_IsAllowed(state)){ - //skip the face - continue; - } - - if(ll->bestFaces[1] == NULL){ - //in case of 2 faces we should pass always here - ll->bestFaces[1] = state; - }else{ - //TODO this must be tested with more then 2 faces - double rtt1 = strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]); - double rttNewFace = strategyNexthopStateLL_GetRTTLive(state); - if(rttNewFace + STABILITY_FACTOR < rtt1){ - strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]); - ll->bestFaces[1] = state; - } - } - } - } - parcIterator_Release(&iterator); - - if(ll->bestFaces[1] != NULL){ - //we are not using the second face yet so we use the normal rtt for comparison - double rtt0 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[0]); - double rtt1 = strategyNexthopStateLL_GetRTTProbe(ll->bestFaces[1]); - double diff = fabs(rtt0 - rtt1); - if(diff < MAX_LATENCY_DIFF) { - //let's start to use 2 paths - ll->rounds_with_error = 0; - ll->use2paths = true; - ll->rounds_in_multipath = 0; - }else{ - //we use only one path - strategyNexthopStateLL_SetUnusedFace(ll->bestFaces[1]); - ll->bestFaces[1] = NULL; - ll->use2paths = false; - } - }else{ - ll->use2paths = false; - } - -NEW_ROUND: - { - Logger * log = forwarder_GetLogger(ll->forwarder); - if(log != NULL && - logger_IsLoggable(log, LoggerFacility_Strategy, PARCLogLevel_Info)){ - if(ll->use2paths){ - logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info, - __func__, "use 2 paths. rtt face %d = %f queue = %f is_lossy = %d," - "rtt face %d = %f queue = %f is_lossy = %d\n", - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]), - strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]), - strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]), - strategyNexthopStateLL_IsLossy(ll->bestFaces[0]), - strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]), - strategyNexthopStateLL_GetRTTLive(ll->bestFaces[1]), - strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]), - strategyNexthopStateLL_IsLossy(ll->bestFaces[1])); - }else{ - if(ll->bestFaces[0] != NULL){ - logger_Log(log, LoggerFacility_Strategy, - PARCLogLevel_Info, __func__, - "use 1 path. rtt face %d = %f is_lossy = %d, " - "(avoid multipath = %d)\n", - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]), - strategyNexthopStateLL_GetRTTLive(ll->bestFaces[0]), - strategyNexthopStateLL_IsLossy(ll->bestFaces[0]), - ll->avoid_multipath); - }else{ - logger_Log(log, LoggerFacility_Strategy, PARCLogLevel_Info, - __func__, "no face to use!\n"); - } - } - } - } - - //update the round only at the end for all the faces - if(new_round){ - PARCIterator * iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while (parcIterator_HasNext(iterator)) { - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - strategyNexthopStateLL_StartNewRound((StrategyNexthopStateLL *) - parcHashMap_Get(ll->strategy_state, cid)); - } - parcIterator_Release(&iterator); - } - - //mapme updates - //if ll->bestFaces[0] == NULL we don't have any output faces - //so don't need to send any updates since we are disconnected - if(ll->related_prefixes_len != 0){ - if(ll->bestFaces[0] != NULL){ - NumberSet *out = numberSet_Create(); - if(old_faces[0] == NULL || - (strategyNexthopStateLL_GetFaceId(ll->bestFaces[0]) != - strategyNexthopStateLL_GetFaceId(old_faces[0]))){ - //there is a new face 0 so we need a map me update - //if ll->bestFaces[1] != NULL we need to send the update - //even if it is the same as before - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - if(ll->bestFaces[1] != NULL){ - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[1])); - } - strategy_low_latency_SendMapmeUpdate(ll,out); - }else{ - if(ll->bestFaces[1] != NULL){ - if(old_faces[1] == NULL || - (strategyNexthopStateLL_GetFaceId(ll->bestFaces[1]) != - strategyNexthopStateLL_GetFaceId(old_faces[1]))){ - //send a mapme both with face 0 and face 1 - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[1])); - strategy_low_latency_SendMapmeUpdate(ll,out); - } - }else{ - if(old_faces[1] != NULL){ - //in the previuos round we were using two faces, now only one - //send update with only face 0 - numberSet_Add(out, - strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - strategy_low_latency_SendMapmeUpdate(ll,out); - } - } - } - numberSet_Release(&out); - } - } -} - -static -void -strategy_low_latency_BestFaceCB(int fd, PARCEventType which_event, void *data) -{ - parcAssertTrue(which_event & PARCEventType_Timeout, - "Event incorrect, expecting %X set, got %X", - PARCEventType_Timeout, which_event); - - StrategyLowLatency * ll = (StrategyLowLatency *) data; - strategy_low_latency_SelectBestFaces(ll, true); - - struct timeval timeout = {0, 500000}; - parcEventTimer_Start(ll->computeBestFace, &timeout); -} - -static -void -_startTimers(strategy_entry_t * entry) -{ - struct timeval timeoutProbes = {0, 10000}; - struct timeval timeoutBF = {1, 0}; - - parcEventTimer_Start(entry->state.sendProbes, &timeoutProbes); - parcEventTimer_Start(entry->state.computeBestFace, &timeoutBF); -} - -static -void -_stopTimers(strategy_entry_t * entry) -{ - parcEventTimer_Stop(entry->state.sendProbes); - parcEventTimer_Stop(entry->state.computeBestFace); -} - -static -void -strategy_low_latency_initialize(strategy_entry_t * entry) -{ - srand((unsigned int)time(NULL)); - - /* XXX TODO Three hashmaps to initialize */ - strategy->strategy_state = parcHashMap_Create(); - strategy->pending_probes_ticks = parcHashMap_Create(); - strategy->pending_probes_faces = parcHashMap_Create(); - - Dispatcher *dispatcher = forwarder_GetDispatcher((Forwarder *)ll->forwarder); - ip_prefix_t address; - nameBitvector_ToIPAddress(name_GetContentName( - fibEntry_GetPrefix(fibEntry)), &address); - - entry->state = { - .probe = messageHandler_CreateProbePacket(HF_INET6_TCP, PROBE_LIFETIME), - .name = messageHandler_CreateProbeName(&address); - .sendProbes = dispatcher_CreateTimer(dispatcher, false, - strategy_low_latency_SendProbesCB, ll); - .round = 0; - .rounds_in_multipath = 0; - .rounds_with_error = 0; - .rounds_avoiding_multipath = 0; - .use2paths = false; - .avoid_multipath = false; - .computeBestFace = dispatcher_CreateTimer(dispatcher, false, - strategy_low_latency_BestFaceCB, ll); - .related_prefixes_len = related_prefixes_len; - // XXX TODO - .related_prefixes = malloc(sizeof(Name *) * related_prefixes_len); - }; - - for(unsigned i = 0; i < entry->state.related_prefixes_len; i++){ - entry->state.related_prefixes[i] = name_Copy(related_prefixes[i]); - } -} - -static -void -strategy_low_latency_finalize(strategy_entry_t * entry) -{ - _stopTimers(entry); - - parcEventTimer_Destroy(&(strategy->sendProbes)); - parcEventTimer_Destroy(&(strategy->computeBestFace)); - - if (parcHashMap_Size(strategy->strategy_state) > 0) { - PARCIterator *it = parcHashMap_CreateKeyIterator(strategy->strategy_state); - while (parcIterator_HasNext(it)) { - PARCUnsigned *cid = parcIterator_Next(it); - StrategyNexthopStateLL *state = - (StrategyNexthopStateLL *)parcHashMap_Get(strategy->strategy_state, cid); - parcObject_Release((void**)&state); - } - parcIterator_Release(&it); - } - - parcHashMap_Release(&(strategy->strategy_state)); - parcHashMap_Release(&(strategy->pending_probes_ticks)); - parcHashMap_Release(&(strategy->pending_probes_faces)); - - parcMemory_Deallocate(&(strategy->probe)); - parcMemory_Deallocate(&(strategy->name)); - - for(unsigned i = 0; i < strategy->related_prefixes_len; i++){ - name_Release(&(strategy->related_prefixes[i])); - } - free(strategy->related_prefixes); - - parcMemory_Deallocate((void **)&strategy); - parcMemory_Deallocate((void **)&impl); - *strategyPtr = NULL; -} - -static -void -strategy_low_latency_add_nexthop(strategy_entry_t * entry, unsigned nexthop, nexthop_state_t * state) -{ - PARCUnsigned *cid = parcUnsigned_Create(connectionId); - - StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context; - - if (!parcHashMap_Contains(ll->strategy_state, cid)) { - StrategyNexthopStateLL *state = strategyNexthopStateLL_Create(connectionId); - parcHashMap_Put(ll->strategy_state, cid, state); - if(ll->bestFaces[0] == NULL){ - ll->bestFaces[0] = state; - } - } - - if(parcHashMap_Size(ll->strategy_state) >= 2){ - _startTimers(strategy); - } - - parcUnsigned_Release(&cid); -} - -static -void -strategy_low_latency_remove_nexthop(strategy_entry_t * entry, unsigned nexthop, nexthop_state_t * state) -{ - bool reset_bestFaces = false; - - if((entry->state.bestFaces[0] != NULL && - strategyNexthopStateLL_GetFaceId(entry->state.bestFaces[0]) == connectionId) || - (entry->state.bestFaces[1] != NULL && - strategyNexthopStateLL_GetFaceId(entry->state.bestFaces[1]) == connectionId)){ - reset_bestFaces = true; - } - - PARCUnsigned *cid = parcUnsigned_Create(connectionId); - - if (parcHashMap_Contains(entry->state.strategy_state, cid)) { - parcHashMap_Remove(entry->state.strategy_state, cid); - } - - if(reset_bestFaces){ - entry->state.bestFaces[0] = NULL; - entry->state.bestFaces[1] = NULL; - strategy_low_latency_SelectBestFaces(ll, false); - } - - if(parcHashMap_Size(entry->state.strategy_state) < 2){ - _stopTimers(strategy); - } - - parcUnsigned_Release(&cid); -} - -static -nexthops_t * -strategy_low_latency_lookup_nexthops(strategy_entry_t * entry, - const msgbuf_t * msgbuf) -{ - //unsigned out_connection; - NumberSet *out = numberSet_Create(); - - StrategyLowLatency *ll = (StrategyLowLatency *)strategy->context; - - //update is_allowed flag of all the next hops - PARCIterator *iterator = parcHashMap_CreateKeyIterator(ll->strategy_state); - while(parcIterator_HasNext(iterator)){ - PARCUnsigned *cid = (PARCUnsigned *) parcIterator_Next(iterator); - StrategyNexthopStateLL *state = - (StrategyNexthopStateLL *) parcHashMap_Get(ll->strategy_state, cid); - if(numberSet_Contains(nexthops, parcUnsigned_GetUnsigned(cid))){ - strategyNexthopStateLL_SetIsAllowed(state,true); - }else{ - strategyNexthopStateLL_SetIsAllowed(state,false); - } - } - parcIterator_Release(&iterator); - - if(ll->bestFaces[0] != NULL && - !strategyNexthopStateLL_IsAllowed(ll->bestFaces[0])){ - //if ll->bestFaces[0] is not allowed we need to find a new face - strategy_low_latency_SelectBestFaces(ll, false); - } - - //at this point ll->bestFaces[0] must be allowed - //single path case - if(ll->bestFaces[0] != NULL && (ll->bestFaces[1] == NULL || !ll->use2paths)){ - strategyNexthopStateLL_SendPacket(ll->bestFaces[0]); - numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - - //multipath case - }else if(ll->bestFaces[0] != NULL && ll->bestFaces[1] != NULL && ll->use2paths){ - //it may happen that ll->bestFaces[1] is not allowed, in that case we send on - //ll->bestFaces[0] until the next best face selection - if(!strategyNexthopStateLL_IsAllowed(ll->bestFaces[1])){ - strategyNexthopStateLL_SendPacket(ll->bestFaces[0]); - numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - }else{ - double queue0 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[0]); - double queue1 = strategyNexthopStateLL_GetQueuing(ll->bestFaces[1]); - double prob0 = 0.5; - if(queue0 > 1 || queue1 > 1){ - prob0 = 1.0 - (queue0 / (queue0 + queue1)); - } - double coin = ((double) rand() / (RAND_MAX)); - if(coin < prob0){ - strategyNexthopStateLL_SendPacket(ll->bestFaces[0]); - numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[0])); - }else{ - strategyNexthopStateLL_SendPacket(ll->bestFaces[1]); - numberSet_Add(out, strategyNexthopStateLL_GetFaceId(ll->bestFaces[1])); - } - } - } - return out; -} - - - -static -void -strategy_low_latency_on_data(strategy_entry_t * entry, - const nexthops_t * nexthops, const msgbuf_t * msgbuf, - Ticks pitEntryCreation, Ticks objReception) -{ - if (!msgbuf_is_probe(msgbuf)) - return; - - uint32_t seq = messageHandler_GetSegment(message_FixedHeader(objectMessage)); - if (!parcHashMap_Contains(ll->pending_probes_ticks, seq)) - return; // unexpected - - /* A single nexthop is expected */ - unsigned nexthop; - nexthops_foreach(nexthops, nexthop, { - const StrategyNexthopStateLL *state = - parcHashMap_Get(ll->strategy_state, nexthop); - if (!state) - // this may happen if we remove a face/route while downloading a file - // we should ignore this timeout - continue; - - Ticks time = parcUnsigned_GetUnsigned( - parcHashMap_Get(ll->pending_probes_ticks, seq)); - Ticks now = forwarder_GetTicks(ll->forwarder); - Ticks RTT = now - time; - if(RTT <= 0) - RTT = 1; - strategyNexthopStateLL_AddRttSample( - (StrategyNexthopStateLL *) state, (unsigned int)RTT); - parcHashMap_Remove(ll->pending_probes_ticks, seq); - } - }; -} - -static -void -strategy_low_latency_on_timeout(strategy_entry_t * entry, const nexthops_t * nexthops) -{ - /* Nothing to do */ -} - -DECLARE_STRATEGY(low_latency); - -#undef nexthop_state_t -#undef state_t - -#endif diff --git a/hicn-light/src/hicn/strategies/low_latency.h b/hicn-light/src/hicn/strategies/low_latency.h deleted file mode 100644 index 6b3001637..000000000 --- a/hicn-light/src/hicn/strategies/low_latency.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Forward on the path with lowest latency - */ - -#ifndef HICNLIGHT_STRATEGY_LOW_LATENCY_H -#define HICNLIGHT_STRATEGY_LOW_LATENCY_H - -struct name_s; - -#include <hicn/strategy.h> - -typedef struct { - void *_; -} strategy_low_latency_nexthop_state_t; - -typedef struct { - void *_; -} strategy_low_latency_state_t; - -typedef struct { - // Name ** related_prefixes; - struct name_s *related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - unsigned related_prefixes_len; -} strategy_low_latency_options_t; - -#if 0 - -/* - * We have global state in addition to state associated for each next hop : - */ -typedef struct { - bool in_use; - bool is_allowed; // XXX TODO the policy may not allow the use of this face -// unsigned face_id; - unsigned sent_packets; - /* switch metrics */ - unsigned last_try_to_switch_round; - unsigned try_to_switch_counter; - /* probes counters */ - unsigned recevied_probes; - unsigned rounds_without_probes; - unsigned sent_probes; - unsigned lost_probes; - unsigned non_lossy_rounds; - /* Averages */ - double avg_rtt; - double avg_rtt_in_use; - double avg_queue; - double avg_loss_rate; -} strategy_low_latency_nexthop_state_t; - -typedef struct { - // hash map from connectionId to StrategyNexthopStateLL - //PARCHashMap *strategy_state; - // XXX This is now store in each nexthop state - - /* - * Hhash map from sequence number to ticks (sent time) - * - * TODO improvement: the tick and face id could be stored in the probe and - * repeated in the reply to avoid state to be maintained. - * - * Also, in case we have few probes, linear scan might be more effective - */ - PARCHashMap *pending_probes_ticks; - - /* hash map from sequence number to face id */ - PARCHashMap *pending_probes_faces; - - const Forwarder * forwarder; - PARCEventTimer *sendProbes; - PARCEventTimer *computeBestFace; - uint8_t * probe; - hicn_name_t * name; - StrategyNexthopStateLL * bestFaces[2]; - unsigned round; - unsigned rounds_in_multipath; - unsigned rounds_with_error; - unsigned rounds_avoiding_multipath; - bool use2paths; - bool avoid_multipath; -} strategy_low_latency_state_t; - -#endif - -#endif /* HICNLIGHT_STRATEGY_LOW_LATENCY_H */ diff --git a/hicn-light/src/hicn/strategies/probe_generator.c b/hicn-light/src/hicn/strategies/probe_generator.c index bc141e518..fd0bf5471 100644 --- a/hicn-light/src/hicn/strategies/probe_generator.c +++ b/hicn-light/src/hicn/strategies/probe_generator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -87,8 +87,7 @@ int generate_probe(probe_generator_t *pg, const msgbuf_t *msgbuf, uint32_t seq = get_seq_number(pg); if (seq == 0) return -1; - - messageHandler_ModifySuffix(msgbuf_get_packet(probe), seq); + msgbuf_modify_suffix(probe, seq); connection_send(conn, probe_offset, true); connection_flush(conn); add_to_map(pg, seq, ticks_now()); diff --git a/hicn-light/src/hicn/strategies/probe_generator.h b/hicn-light/src/hicn/strategies/probe_generator.h index 7a9f3a58a..065d824a1 100644 --- a/hicn-light/src/hicn/strategies/probe_generator.h +++ b/hicn-light/src/hicn/strategies/probe_generator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -20,6 +20,9 @@ #include <hicn/core/ticks.h> #include <hicn/core/msgbuf.h> +#define MIN_PROBE_SUFFIX 0xefffffff +#define MAX_PROBE_SUFFIX 0xffffffff - 1 + KHASH_MAP_INIT_INT64(bp_map, Ticks); struct forwarder_s; diff --git a/hicn-light/src/hicn/strategies/random.c b/hicn-light/src/hicn/strategies/random.c index 5b076df7c..aabae73bc 100644 --- a/hicn-light/src/hicn/strategies/random.c +++ b/hicn-light/src/hicn/strategies/random.c @@ -53,6 +53,7 @@ static int strategy_random_remove_nexthop(strategy_entry_t *entry, static nexthops_t *strategy_random_lookup_nexthops(strategy_entry_t *entry, nexthops_t *nexthops, const msgbuf_t *msgbuf) { + if (nexthops_get_curlen(nexthops) == 0) return nexthops; nexthops_select(nexthops, rand() % nexthops_get_len(nexthops)); return nexthops; } diff --git a/hicn-light/src/hicn/test/CMakeLists.txt b/hicn-light/src/hicn/test/CMakeLists.txt index 65e216c1e..cbe939297 100644 --- a/hicn-light/src/hicn/test/CMakeLists.txt +++ b/hicn-light/src/hicn/test/CMakeLists.txt @@ -1,19 +1,13 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 Cisco and/or its affiliates. include(BuildMacros) list(APPEND TESTS_SRC - test-bitmap.cc test-configuration.cc - test-hash.cc - test-khash.cc + test-fib.cc test-loop.cc - test-pool.cc test-parser.cc test-ctrl.cc - test-ring.cc - test-vector.cc - test-interest_manifest.cc test-msgbuf_pool.cc test-nexthops.cc test-connection_table.cc @@ -26,8 +20,8 @@ list(APPEND TESTS_SRC test-subscription.cc test-local_prefixes.cc test-probe_generator.cc - ${CMAKE_CURRENT_SOURCE_DIR}/../config/command_listener.c - ${CMAKE_CURRENT_SOURCE_DIR}/../config/command_route.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_listener.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../ctrl/libhicnctrl/src/commands/command_route.c main.cc ) @@ -39,6 +33,7 @@ build_executable(hicn_light_tests DEPENDS gtest ${LIBHICNCTRL_STATIC} ${LIBHICN_LIGHT_SHARED} COMPONENT ${HICN_LIGHT} DEFINITIONS "${COMPILER_DEFINITIONS}" + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) add_test_internal(hicn_light_tests) diff --git a/hicn-light/src/hicn/test/test-bitmap.cc b/hicn-light/src/hicn/test/test-bitmap.cc deleted file mode 100644 index 1fd21a1bb..000000000 --- a/hicn-light/src/hicn/test/test-bitmap.cc +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#include <netinet/in.h> - -extern "C" { -#define WITH_TESTS -#include <hicn/util/bitmap.h> -} - -#define DEFAULT_SIZE 10 - -class BitmapTest : public ::testing::Test { - protected: - BitmapTest() {} - - virtual ~BitmapTest() {} - - bitmap_t* bitmap; -}; - -/* - * TEST: bitmap allocation - */ -TEST_F(BitmapTest, BitmapAllocation) { - int rc; - - /* - * We take a value < 32 on purpose to avoid confusion on the choice of a 32 - * or 64 bit integer for storage - */ - size_t size_not_pow2 = DEFAULT_SIZE; - bitmap_init(bitmap, size_not_pow2, 0); - - /* - * Bitmap should have been allocated with a size rounded to the next power - * of 2 - */ - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - /* By default, no element should be set */ - EXPECT_FALSE(bitmap_is_set(bitmap, 0)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 0)); - - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - EXPECT_FALSE(bitmap_is_set(bitmap, size_not_pow2 - 1)); - EXPECT_TRUE(bitmap_is_unset(bitmap, size_not_pow2 - 1)); - - /* Bitmap should not have been reallocated */ - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - /* After setting a bit after the end, bitmap should have been reallocated */ - bitmap_set(bitmap, sizeof(bitmap[0]) * 8 - 1); - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - /* After setting a bit after the end, bitmap should have been reallocated */ - rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8); - EXPECT_GE(rc, 0); - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2UL); - - rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8 + 1); - EXPECT_GE(rc, 0); - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2UL); - - bitmap_free(bitmap); - - size_t size_pow2 = 16; - - /* Limiting test for allocation size */ - bitmap_init(bitmap, size_pow2, 0); - EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1UL); - - bitmap_free(bitmap); -} - -TEST_F(BitmapTest, BitmapSet) { - bitmap_init(bitmap, DEFAULT_SIZE, 0); - - bitmap_set(bitmap, 20); - EXPECT_TRUE(bitmap_is_set(bitmap, 20)); - EXPECT_FALSE(bitmap_is_unset(bitmap, 20)); - EXPECT_FALSE(bitmap_is_set(bitmap, 19)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 19)); - - // Test edge cases (i.e. start and end of block) - off_t start_position = 0; - bitmap_set(bitmap, start_position); - EXPECT_TRUE(bitmap_is_set(bitmap, start_position)); - EXPECT_FALSE(bitmap_is_unset(bitmap, start_position)); - - off_t end_position = BITMAP_WIDTH(bitmap) - 1; - bitmap_set(bitmap, end_position); - EXPECT_TRUE(bitmap_is_set(bitmap, end_position)); - EXPECT_FALSE(bitmap_is_unset(bitmap, end_position)); - - bitmap_free(bitmap); -} - -TEST_F(BitmapTest, BitmapUnSet) { - bitmap_init(bitmap, DEFAULT_SIZE, 0); - - bitmap_set(bitmap, 20); - bitmap_set(bitmap, 19); - bitmap_unset(bitmap, 20); - EXPECT_FALSE(bitmap_is_set(bitmap, 20)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 20)); - EXPECT_TRUE(bitmap_is_set(bitmap, 19)); - EXPECT_FALSE(bitmap_is_unset(bitmap, 19)); - - bitmap_free(bitmap); -} - -TEST_F(BitmapTest, BitmapSetTo) { - bitmap_init(bitmap, DEFAULT_SIZE, 0); - - bitmap_set_to(bitmap, 40); - EXPECT_TRUE(bitmap_is_set(bitmap, 20)); - EXPECT_TRUE(bitmap_is_set(bitmap, 21)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 41)); - EXPECT_TRUE(bitmap_is_unset(bitmap, 42)); - - bitmap_free(bitmap); -} diff --git a/hicn-light/src/hicn/test/test-connection_table.cc b/hicn-light/src/hicn/test/test-connection_table.cc index d17de7c2c..171921b53 100644 --- a/hicn-light/src/hicn/test/test-connection_table.cc +++ b/hicn-light/src/hicn/test/test-connection_table.cc @@ -27,6 +27,7 @@ extern "C" { #define WITH_TESTS #include <hicn/core/connection_table.h> +#include <hicn/util/log.h> } #define CONNECTION_NAME "connection_name_test" @@ -275,7 +276,7 @@ TEST_F(ConnectionTableTest, GenerateConnNameExhaustion) { bool unable_to_allocate = false; // Force name exhaustion - int i, n_connections = 1 + USHRT_MAX; + int n_connections = 1 + USHRT_MAX; for (int i = 0; i <= n_connections; i++) { int rc = connection_table_get_random_name(conn_table_, conn_name); if (rc < 0) { diff --git a/hicn-light/src/hicn/test/test-ctrl.cc b/hicn-light/src/hicn/test/test-ctrl.cc index e24b47f27..f0d3e7c37 100644 --- a/hicn-light/src/hicn/test/test-ctrl.cc +++ b/hicn-light/src/hicn/test/test-ctrl.cc @@ -18,7 +18,7 @@ extern "C" { #include <hicn/util/log.h> #include <hicn/ctrl.h> -#include <hicn/config/parse.h> +#include <hicn/ctrl/parse.h> #include <hicn/ctrl/route.h> #include <hicn/util/sstrncpy.h> } @@ -27,7 +27,7 @@ class CtrlTest : public ::testing::Test { protected: CtrlTest() { log_conf.log_level = LOG_INFO; - s_ = hc_sock_create_forwarder(HICNLIGHT_NG); + s_ = hc_sock_create_forwarder(FORWARDER_TYPE_HICNLIGHT); } virtual ~CtrlTest() { hc_sock_free(s_); } @@ -40,7 +40,7 @@ class CtrlTest : public ::testing::Test { * Here we test the serialization of the commands i.e. from command * to message sent to the forwarder. */ - +#if 0 TEST_F(CtrlTest, AddValidListener) { std::string cmd = "add listener udp udp0 10.0.0.1 9695 eth0"; ASSERT_EQ(parse(cmd.c_str(), &command_), 0); @@ -81,7 +81,7 @@ TEST_F(CtrlTest, AddListenerInvalidLocalAddress) { hc_result_t *result = hc_listener_create_conf(s_, &command_.object.listener); bool success = hc_result_get_success(s_, result); - EXPECT_FALSE(success); + EXPECT_EQ(success, false); } TEST_F(CtrlTest, AddListenerEmptyLocalAddress) { @@ -193,4 +193,5 @@ TEST_F(CtrlTest, RouteNameOrID) { route.face_id = 1; snprintf(route.name, SYMBOLIC_NAME_LEN, "%s", "1test"); EXPECT_EQ(hc_route_validate(&route), -1); -}
\ No newline at end of file +} +#endif diff --git a/hicn-light/src/hicn/test/test-fib.cc b/hicn-light/src/hicn/test/test-fib.cc new file mode 100644 index 000000000..5db47415f --- /dev/null +++ b/hicn-light/src/hicn/test/test-fib.cc @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" { +#define WITH_TESTS +#include <hicn/util/ip_address.h> +#include <hicn/config/configuration.h> +#include <hicn/core/forwarder.h> +#include <hicn/core/fib.h> +} + +/* + * TODO + * - test max_size + */ + +#define DEFAULT_SIZE 10 +#define ARRAY_SIZE(a) ((sizeof(a) / sizeof(*(a)))) + +class FibTest : public ::testing::Test { + protected: + FibTest() { fib = fib_create(NULL); } + virtual ~FibTest() { fib_free(fib); } + + configuration_t *configuration; + forwarder_t *forwarder; + fib_t *fib; +}; + +void _fib_add_prefix(fib_t *fib, const hicn_prefix_t *prefix) { + fib_entry_t *entry = + fib_entry_create(prefix, STRATEGY_TYPE_UNDEFINED, NULL, NULL); + fib_add(fib, entry); +} + +static const hicn_prefix_t p0010 = (hicn_prefix_t){ + .name = {.v6 = {.as_u64 = {0x1122334455667788, 0x9900aabbccddeeff}}}, + .len = 4}; + +/* TEST: Fib allocation and initialization */ +TEST_F(FibTest, FibAddOne) { + /* Empty fib should be valid */ + + const hicn_prefix_t *empty_prefix_array[] = {}; + bool empty_used_array[] = {}; + EXPECT_TRUE(fib_is_valid(fib)); + EXPECT_TRUE(fib_check_preorder(fib, empty_prefix_array, empty_used_array)); + + const hicn_prefix_t *prefix_array[] = {&p0010}; + bool used_array[] = {true}; + + for (unsigned i = 0; i < ARRAY_SIZE(prefix_array); i++) { + if (!used_array[i]) continue; + _fib_add_prefix(fib, prefix_array[i]); + } + + fib_dump(fib); + + EXPECT_TRUE(fib_is_valid(fib)); + EXPECT_TRUE(fib_check_preorder(fib, prefix_array, used_array)); + + /* Check that free indices and bitmaps are correctly updated */ +} diff --git a/hicn-light/src/hicn/test/test-interest_manifest.cc b/hicn-light/src/hicn/test/test-interest_manifest.cc deleted file mode 100644 index 6408a3f2a..000000000 --- a/hicn-light/src/hicn/test/test-interest_manifest.cc +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -extern "C" { -#include <hicn/core/interest_manifest.h> -} - -static constexpr size_t WORD_SIZE = 32; - -class InterestManifestTest : public ::testing::Test { - protected: - InterestManifestTest() {} - virtual ~InterestManifestTest() {} -}; - -TEST_F(InterestManifestTest, OneWordBitmapUpdate) { - u32 initial_bitmap[1]; - u32 curr_bitmap[1] = {0}; - initial_bitmap[0] = 0x00000b07; // 000000000000000000000101100000111 - - // Consume first 4 'one' bits (i.e. suffixes), reaching position 9 - int pos = 0, max_suffixes = 4; - pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap, pos, - WORD_SIZE, max_suffixes); - EXPECT_EQ(pos, 9); - EXPECT_EQ(curr_bitmap[0], 0x00000107); - - // Consume the remaining 2 'one' bits, reaching end of bitmap - u32 curr_bitmap2[1] = {0}; - pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap2, pos, - WORD_SIZE, max_suffixes); - EXPECT_EQ(pos, WORD_SIZE); - EXPECT_EQ(curr_bitmap2[0], 0x00000a00); - - // Consume all suffixes at once - u32 curr_bitmap3[1] = {0}; - max_suffixes = 16; - pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap3, 0, - WORD_SIZE, max_suffixes); - EXPECT_EQ(pos, WORD_SIZE); - EXPECT_EQ(curr_bitmap3[0], initial_bitmap[0]); -} - -TEST_F(InterestManifestTest, TwoWordBitmapUpdate) { - u32 initial_bitmap[2]; - initial_bitmap[0] = 0x00000b07; - initial_bitmap[1] = 0x00000b07; - // -> 100000000000000000000101100000111000000000000000000000101100000111 - - int expected_pos[] = {34, 64}; - u32 expected_bitmap[][2] = {{0x00000b07, 0x00000003}, {0x0, 0x00000b04}}; - - // Loop to consume all suffixes - int pos = 0, max_suffixes = 8, i = 0, len = WORD_SIZE * 2; - while (pos != len) { - u32 curr_bitmap[2] = {0}; - pos = interest_manifest_update_bitmap(initial_bitmap, curr_bitmap, pos, len, - max_suffixes); - - EXPECT_EQ(pos, expected_pos[i]); - EXPECT_EQ(curr_bitmap[0], expected_bitmap[i][0]); - EXPECT_EQ(curr_bitmap[1], expected_bitmap[i][1]); - i++; - } -}
\ No newline at end of file diff --git a/hicn-light/src/hicn/test/test-khash.cc b/hicn-light/src/hicn/test/test-khash.cc deleted file mode 100644 index f437f8858..000000000 --- a/hicn-light/src/hicn/test/test-khash.cc +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#include <netinet/in.h> - -extern "C" { -#include <hicn/util/khash.h> -} - -KHASH_MAP_INIT_INT(int, unsigned char) - -typedef struct { - unsigned key; - unsigned char val; -} int_unpack_t; - -typedef struct { - unsigned key; - unsigned char val; -} __attribute__((__packed__)) int_packed_t; - -#define hash_eq(a, b) ((a).key == (b).key) -#define hash_func(a) ((a).key) - -KHASH_INIT(iun, int_unpack_t, char, 0, hash_func, hash_eq) -KHASH_INIT(ipk, int_packed_t, char, 0, hash_func, hash_eq) - -class KHashTest : public ::testing::Test { - protected: - KHashTest() {} - - virtual ~KHashTest() { - // You can do clean-up work that doesn't throw exceptions here. - } - - // If the constructor and destructor are not enough for setting up - // and cleaning up each test, you can define the following methods: - - virtual void SetUp() { khash = kh_init(int); } - - virtual void TearDown() { kh_destroy(int, khash); } - khash_t(int) * khash; -}; - -TEST_F(KHashTest, KhashIntSize) { - int ret; - int k; - int size = kh_size(khash); - - EXPECT_EQ(size, 0); - k = kh_put(int, khash, 10, &ret); - if (ret == 1) { - kh_val(khash, k) = 10; - } - size = kh_size(khash); - EXPECT_EQ(size, 1); -} - -TEST_F(KHashTest, KhashIntPut) { - int ret; - int k; - k = kh_put(int, khash, 10, &ret); - if (ret == 1) { - kh_val(khash, k) = 10; - } - int size = kh_size(khash); - EXPECT_EQ(size, 1); - k = kh_put(int, khash, 20, &ret); - if (ret == 1) { - kh_val(khash, k) = 20; - } - size = kh_size(khash); - EXPECT_EQ(size, 2); -} - -TEST_F(KHashTest, KhashCheckValue) { - int ret; - int k; - k = kh_put(int, khash, 10, &ret); - if (ret == 1) { - kh_val(khash, k) = 100; - } - k = kh_put(int, khash, 20, &ret); - if (ret == 1) { - kh_val(khash, k) = 200; - } - - k = kh_put(int, khash, 10, &ret); - int val = -1; - if (!ret) val = kh_val(khash, k); - EXPECT_EQ(val, 100); - - k = kh_put(int, khash, 20, &ret); - val = -1; - if (!ret) val = kh_val(khash, k); - EXPECT_EQ(val, 200); -} - -// Check that there are no collisions in case of same key hash -typedef struct { - int x; -} Key; -#define hash_key(key) 1 // Hash is always 1 to simulate collisions -#define key_hash_eq(a, b) (a->x == b->x) // Function used in case of collisions -KHASH_INIT(test_map, const Key *, unsigned, 1, hash_key, key_hash_eq); - -TEST_F(KHashTest, Collisions) { - int ret; - khiter_t k; - - kh_test_map_t *map = kh_init(test_map); - Key key1 = {.x = 10}; - Key key2 = {.x = 11}; - - k = kh_put_test_map(map, &key1, &ret); - EXPECT_EQ(ret, 1); - kh_val(map, k) = 15; - - k = kh_put_test_map(map, &key2, &ret); - EXPECT_EQ(ret, 1); - kh_val(map, k) = 27; - - k = kh_get_test_map(map, &key1); - ASSERT_NE(k, kh_end(map)); - unsigned val = kh_val(map, k); - EXPECT_EQ(val, 15u); - - k = kh_get_test_map(map, &key2); - ASSERT_NE(k, kh_end(map)); - val = kh_val(map, k); - EXPECT_EQ(val, 27u); - - kh_destroy_test_map(map); -} diff --git a/hicn-light/src/hicn/test/test-listener_table.cc b/hicn-light/src/hicn/test/test-listener_table.cc index b2ed0c276..f4af02ee1 100644 --- a/hicn-light/src/hicn/test/test-listener_table.cc +++ b/hicn-light/src/hicn/test/test-listener_table.cc @@ -27,6 +27,7 @@ extern "C" { #define WITH_TESTS #include <hicn/core/listener_table.h> +#include <hicn/util/log.h> } #define LISTENER_NAME "listener_name_test" @@ -217,7 +218,6 @@ TEST_F(ListenerTableTest, Iterate) { listener_2->key = key_2; // Iterate over the listener table and count the listeners - listener_t *l; int count = 0; listener_table_foreach(listener_table_, l, { count++; }); EXPECT_EQ(count, 2); diff --git a/hicn-light/src/hicn/test/test-local_prefixes.cc b/hicn-light/src/hicn/test/test-local_prefixes.cc index 80eb46501..52b1c746e 100644 --- a/hicn-light/src/hicn/test/test-local_prefixes.cc +++ b/hicn-light/src/hicn/test/test-local_prefixes.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -28,7 +28,6 @@ extern "C" { #define WITH_TESTS #include <hicn/strategies/local_prefixes.h> #include <hicn/core/strategy.h> -#include <hicn/core/name.h> } const char *name_str1 = "b001::0"; @@ -51,53 +50,65 @@ class LocalPrefixesTest : public ::testing::Test { }; TEST_F(LocalPrefixesTest, LocalPrefixesAddName) { + int rc; local_prefixes_t *lp = create_local_prefixes(); EXPECT_FALSE(lp == nullptr); - ip_address_t result; - inet_pton(AF_INET6, name_str1, (struct in6_addr *)&result); - Name name1; - name_CreateFromAddress(&name1, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str2, (struct in6_addr *)&result); - Name name2; - name_CreateFromAddress(&name2, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str3, (struct in6_addr *)&result); - Name name3; - name_CreateFromAddress(&name3, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str4, (struct in6_addr *)&result); - Name name4; - name_CreateFromAddress(&name4, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str5, (struct in6_addr *)&result); - Name name5; - name_CreateFromAddress(&name5, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str6, (struct in6_addr *)&result); - Name name6; - name_CreateFromAddress(&name6, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str7, (struct in6_addr *)&result); - Name name7; - name_CreateFromAddress(&name7, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str8, (struct in6_addr *)&result); - Name name8; - name_CreateFromAddress(&name8, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str9, (struct in6_addr *)&result); - Name name9; - name_CreateFromAddress(&name9, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str10, (struct in6_addr *)&result); - Name name10; - name_CreateFromAddress(&name10, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str11, (struct in6_addr *)&result); - Name name11; - name_CreateFromAddress(&name11, AF_INET6, result, 128); + hicn_ip_address_t result = IP_ADDRESS_EMPTY; + hicn_ip_address_pton(name_str1, &result); + hicn_prefix_t name1; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name1); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str2, &result); + hicn_prefix_t name2; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name2); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str3, &result); + hicn_prefix_t name3; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name3); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str4, &result); + hicn_prefix_t name4; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name4); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str5, &result); + hicn_prefix_t name5; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name5); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str6, &result); + hicn_prefix_t name6; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name6); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str7, &result); + hicn_prefix_t name7; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name7); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str8, &result); + hicn_prefix_t name8; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name8); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str9, &result); + hicn_prefix_t name9; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name9); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str10, &result); + hicn_prefix_t name10; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name10); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str11, &result); + hicn_prefix_t name11; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name11); + EXPECT_EQ(rc, 0); local_prefixes_add_prefix(lp, &name1); EXPECT_EQ(local_prefixes_get_len(lp), (unsigned)1); @@ -142,29 +153,34 @@ TEST_F(LocalPrefixesTest, LocalPrefixesAddName) { } TEST_F(LocalPrefixesTest, LocalPrefixesAddPrefixes) { + int rc; local_prefixes_t *lp = create_local_prefixes(); EXPECT_FALSE(lp == nullptr); - ip_address_t result; + hicn_ip_address_t result; local_prefixes_t *lp1 = create_local_prefixes(); EXPECT_FALSE(lp1 == nullptr); - inet_pton(AF_INET6, name_str1, (struct in6_addr *)&result); - Name name1; - name_CreateFromAddress(&name1, AF_INET6, result, 128); + hicn_ip_address_pton(name_str1, &result); + hicn_prefix_t name1; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name1); + EXPECT_EQ(rc, 0); - inet_pton(AF_INET6, name_str2, (struct in6_addr *)&result); - Name name2; - name_CreateFromAddress(&name2, AF_INET6, result, 128); + hicn_ip_address_pton(name_str2, &result); + hicn_prefix_t name2; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name2); + EXPECT_EQ(rc, 0); - inet_pton(AF_INET6, name_str3, (struct in6_addr *)&result); - Name name3; - name_CreateFromAddress(&name3, AF_INET6, result, 128); + hicn_ip_address_pton(name_str3, &result); + hicn_prefix_t name3; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name3); + EXPECT_EQ(rc, 0); - inet_pton(AF_INET6, name_str4, (struct in6_addr *)&result); - Name name4; - name_CreateFromAddress(&name4, AF_INET6, result, 128); + hicn_ip_address_pton(name_str4, &result); + hicn_prefix_t name4; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name4); + EXPECT_EQ(rc, 0); local_prefixes_add_prefix(lp1, &name1); local_prefixes_add_prefix(lp1, &name2); @@ -182,33 +198,40 @@ TEST_F(LocalPrefixesTest, LocalPrefixesAddPrefixes) { local_prefixes_t *lp2 = create_local_prefixes(); EXPECT_FALSE(lp2 == nullptr); - inet_pton(AF_INET6, name_str5, (struct in6_addr *)&result); - Name name5; - name_CreateFromAddress(&name5, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str6, (struct in6_addr *)&result); - Name name6; - name_CreateFromAddress(&name6, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str7, (struct in6_addr *)&result); - Name name7; - name_CreateFromAddress(&name7, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str8, (struct in6_addr *)&result); - Name name8; - name_CreateFromAddress(&name8, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str9, (struct in6_addr *)&result); - Name name9; - name_CreateFromAddress(&name9, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str10, (struct in6_addr *)&result); - Name name10; - name_CreateFromAddress(&name10, AF_INET6, result, 128); - - inet_pton(AF_INET6, name_str11, (struct in6_addr *)&result); - Name name11; - name_CreateFromAddress(&name11, AF_INET6, result, 128); + hicn_ip_address_pton(name_str5, &result); + hicn_prefix_t name5; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name5); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str6, &result); + hicn_prefix_t name6; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name6); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str7, &result); + hicn_prefix_t name7; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name7); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str8, &result); + hicn_prefix_t name8; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name8); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str9, &result); + hicn_prefix_t name9; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name9); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str10, &result); + hicn_prefix_t name10; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name10); + EXPECT_EQ(rc, 0); + + hicn_ip_address_pton(name_str11, &result); + hicn_prefix_t name11; + rc = hicn_prefix_create_from_ip_address_len(&result, 128, &name11); + EXPECT_EQ(rc, 0); local_prefixes_add_prefix(lp2, &name5); local_prefixes_add_prefix(lp2, &name6); diff --git a/hicn-light/src/hicn/test/test-msgbuf_pool.cc b/hicn-light/src/hicn/test/test-msgbuf_pool.cc index e9c8e6424..0a78a7a5d 100644 --- a/hicn-light/src/hicn/test/test-msgbuf_pool.cc +++ b/hicn-light/src/hicn/test/test-msgbuf_pool.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -100,7 +100,7 @@ TEST_F(MsgbufPoolTest, AcquireMsgbuf) { // Get msgbuf from msgbuf_pool off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); @@ -119,7 +119,7 @@ TEST_F(MsgbufPoolTest, ReleaseMsgbuf) { // Get msgbuf from msgbuf_pool off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); @@ -137,7 +137,7 @@ TEST_F(MsgbufPoolTest, ReleaseNotAcquiredMsgbuf) { // Get valid msgbuf from msgbuf_pool off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); @@ -157,7 +157,7 @@ TEST_F(MsgbufPoolTest, MultipleAcquireAndReleaseMsgbuf) { // Get msgbuf from msgbuf_pool off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); @@ -177,7 +177,7 @@ TEST_F(MsgbufPoolTest, MultipleAcquireAndReleaseMsgbuf) { TEST_F(MsgbufPoolTest, CloneMsgbuf) { msgbuf_t *msgbuf = NULL; off_t msgbuf_id = msgbuf_pool_get(msgbuf_pool, &msgbuf); - msgbuf->type = MSGBUF_TYPE_COMMAND; + msgbuf_set_type(msgbuf, HICN_PACKET_TYPE_COMMAND); EXPECT_NE(msgbuf, nullptr); EXPECT_NE(msgbuf_id_is_valid((unsigned long)msgbuf_id), 0); diff --git a/hicn-light/src/hicn/test/test-packet_cache.cc b/hicn-light/src/hicn/test/test-packet_cache.cc index 0b4b214f0..76fdb4516 100644 --- a/hicn-light/src/hicn/test/test-packet_cache.cc +++ b/hicn-light/src/hicn/test/test-packet_cache.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -31,8 +31,6 @@ static constexpr unsigned MSGBUF_ID = 0; static constexpr unsigned MSGBUF_ID_2 = 1; static constexpr unsigned MSGBUF_ID_3 = 2; static constexpr unsigned FIVE_SECONDS = 5000; -static constexpr unsigned IPV4_LEN = 32; -static constexpr unsigned IPV6_LEN = 128; static constexpr int N_OPS = 50000; @@ -40,39 +38,50 @@ class PacketCacheTest : public ::testing::Test { protected: PacketCacheTest() { pkt_cache = pkt_cache_create(CS_SIZE); - name = (Name *)malloc(sizeof(Name)); - name_CreateFromAddress(name, AF_INET, IPV4_ANY, IPV4_LEN); + int rc = hicn_name_create_from_ip_address(IPV4_ANY, 0, &name); + EXPECT_EQ(rc, 0); msgbuf_pool = msgbuf_pool_create(); - msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name); + msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name); } virtual ~PacketCacheTest() { - free(name); msgbuf_pool_free(msgbuf_pool); pkt_cache_free(pkt_cache); } msgbuf_t *msgbuf_create(msgbuf_pool_t *msgbuf_pool, unsigned conn_id, - Name *name, + hicn_name_t *name, std::optional<Ticks> lifetime = FIVE_SECONDS) { msgbuf_t *msgbuf; msgbuf_pool_get(msgbuf_pool, &msgbuf); msgbuf->connection_id = conn_id; - name_Copy(name, msgbuf_get_name(msgbuf)); - hicn_packet_init_header(HF_INET6_TCP, - (hicn_header_t *)msgbuf_get_packet(msgbuf)); + msgbuf_set_name(msgbuf, name); + + hicn_packet_set_format(msgbuf_get_pkbuf(msgbuf), + HICN_PACKET_FORMAT_IPV6_TCP); + hicn_packet_set_type(msgbuf_get_pkbuf(msgbuf), HICN_PACKET_TYPE_INTEREST); + + hicn_packet_buffer_t *pkbuf = msgbuf_get_pkbuf(msgbuf); + hicn_packet_set_buffer(pkbuf, msgbuf->packet, MTU, 0); + + int rc = hicn_packet_init_header(msgbuf_get_pkbuf(msgbuf), 0); + EXPECT_EQ(rc, 0); + + // Same as 'msgbuf_set_data_expiry_time', + // it would write in the same field msgbuf_set_interest_lifetime(msgbuf, *lifetime); return msgbuf; } - Name get_name_from_prefix(const char *prefix_str) { - ip_address_t prefix; + hicn_name_t get_name_from_prefix(const char *prefix_str) { + hicn_ip_address_t prefix; inet_pton(AF_INET6, prefix_str, (struct in6_addr *)&prefix); - Name name; - name_CreateFromAddress(&name, AF_INET6, prefix, IPV6_LEN); + hicn_name_t name; + int rc = hicn_name_create_from_ip_address(prefix, 0, &name); + EXPECT_EQ(rc, 0); return name; } @@ -80,39 +89,33 @@ class PacketCacheTest : public ::testing::Test { pkt_cache_t *pkt_cache; pkt_cache_entry_t *entry = nullptr; msgbuf_pool_t *msgbuf_pool; - Name *name; + hicn_name_t name; msgbuf_t *msgbuf; }; TEST_F(PacketCacheTest, LowLevelOperations) { - int rc; kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix(); - NameBitvector *prefix = name_GetContentName(name); + const hicn_name_prefix_t *prefix = hicn_name_get_prefix(&name); _add_suffix(prefix_to_suffixes, prefix, 1, 11); _add_suffix(prefix_to_suffixes, prefix, 2, 22); - unsigned id = _get_suffix(prefix_to_suffixes, prefix, 1, &rc); - EXPECT_EQ(rc, KH_FOUND); - EXPECT_EQ(id, 11); + unsigned id = _get_suffix(prefix_to_suffixes, prefix, 1); + EXPECT_EQ(id, 11UL); - id = _get_suffix(prefix_to_suffixes, prefix, 2, &rc); - EXPECT_EQ(rc, KH_FOUND); - EXPECT_EQ(id, 22); + id = _get_suffix(prefix_to_suffixes, prefix, 2); + EXPECT_EQ(id, 22UL); - id = _get_suffix(prefix_to_suffixes, prefix, 5, &rc); - EXPECT_EQ(rc, KH_NOT_FOUND); - EXPECT_EQ(id, -1); + id = _get_suffix(prefix_to_suffixes, prefix, 5); + EXPECT_EQ(id, HICN_INVALID_SUFFIX); _add_suffix(prefix_to_suffixes, prefix, 5, 55); - id = _get_suffix(prefix_to_suffixes, prefix, 5, &rc); - EXPECT_EQ(rc, KH_FOUND); - EXPECT_EQ(id, 55); + id = _get_suffix(prefix_to_suffixes, prefix, 5); + EXPECT_EQ(id, 55UL); _remove_suffix(prefix_to_suffixes, prefix, 2); _add_suffix(prefix_to_suffixes, prefix, 2, 222); - id = _get_suffix(prefix_to_suffixes, prefix, 2, &rc); - EXPECT_EQ(rc, KH_FOUND); - EXPECT_EQ(id, 222); + id = _get_suffix(prefix_to_suffixes, prefix, 2); + EXPECT_EQ(id, 222UL); _prefix_map_free(prefix_to_suffixes); } @@ -133,15 +136,17 @@ TEST_F(PacketCacheTest, CreatePacketCache) { TEST_F(PacketCacheTest, AddPacketCacheEntry) { // Add entry to the packet cache - entry = pkt_cache_allocate(pkt_cache, name); + entry = pkt_cache_allocate(pkt_cache); EXPECT_NE(entry, nullptr); + entry->name = name; ASSERT_EQ(pkt_cache_get_size(pkt_cache), 1u); + pkt_cache_add_to_index(pkt_cache, entry); // Get entry by name pkt_cache_lookup_t lookup_result; off_t entry_id; - pkt_cache_entry_t *entry = pkt_cache_lookup(pkt_cache, name, msgbuf_pool, - &lookup_result, &entry_id, true); + pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, + true); EXPECT_NE(lookup_result, PKT_CACHE_LU_NONE); } @@ -165,7 +170,7 @@ TEST_F(PacketCacheTest, GetPIT) { TEST_F(PacketCacheTest, LookupEmpty) { pkt_cache_lookup_t lookup_result; off_t entry_id; - pkt_cache_entry_t *entry = pkt_cache_lookup(pkt_cache, name, msgbuf_pool, + pkt_cache_entry_t *entry = pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_NONE); @@ -174,15 +179,17 @@ TEST_F(PacketCacheTest, LookupEmpty) { TEST_F(PacketCacheTest, AddEntryAndLookup) { // Add entry to the packet cache - entry = pkt_cache_allocate(pkt_cache, name); + entry = pkt_cache_allocate(pkt_cache); + entry->name = name; entry->entry_type = PKT_CACHE_PIT_TYPE; ASSERT_NE(entry, nullptr); + pkt_cache_add_to_index(pkt_cache, entry); // Perform lookup pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_TRUE(lookup_result == PKT_CACHE_LU_INTEREST_NOT_EXPIRED || lookup_result == PKT_CACHE_LU_INTEREST_EXPIRED); @@ -192,7 +199,7 @@ TEST_F(PacketCacheTest, AddEntryAndLookup) { TEST_F(PacketCacheTest, AddToPIT) { // Check if entry properly created - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); ASSERT_NE(entry, nullptr); EXPECT_EQ(entry->entry_type, PKT_CACHE_PIT_TYPE); EXPECT_TRUE(pit_entry_ingress_contains(&entry->u.pit_entry, CONN_ID)); @@ -203,7 +210,7 @@ TEST_F(PacketCacheTest, AddToPIT) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } @@ -229,14 +236,14 @@ TEST_F(PacketCacheTest, AddToCS) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, PitToCS) { // Prepare PIT entry - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u); @@ -261,7 +268,7 @@ TEST_F(PacketCacheTest, PitToCS) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } @@ -286,18 +293,19 @@ TEST_F(PacketCacheTest, CsToPIT) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, UpdateInPIT) { // Prepare PIT entry - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry); - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name); // Check if entry properly updated @@ -311,7 +319,7 @@ TEST_F(PacketCacheTest, UpdateInPIT) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } @@ -322,8 +330,9 @@ TEST_F(PacketCacheTest, UpdateInCS) { pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID); off_t entry_id = pkt_cache_get_entry_id(pkt_cache, entry); - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name); // Check if entry properly updated @@ -338,18 +347,18 @@ TEST_F(PacketCacheTest, UpdateInCS) { // Check if hashtable correctly updated pkt_cache_lookup_t lookup_result; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, RemoveFromPIT) { // Prepare PIT entry - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u); - pkt_cache_pit_remove_entry(pkt_cache, entry, name); + pkt_cache_pit_remove_entry(pkt_cache, entry); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 0u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u); @@ -357,7 +366,7 @@ TEST_F(PacketCacheTest, RemoveFromPIT) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_NONE); EXPECT_EQ(lu_entry, nullptr); } @@ -383,15 +392,16 @@ TEST_F(PacketCacheTest, RemoveFromCS) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_NONE); EXPECT_EQ(lu_entry, nullptr); } TEST_F(PacketCacheTest, AddTwoEntriesToCS) { // Prepare another msgbuf - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name); pkt_cache_entry_t *entry_1 = @@ -412,16 +422,17 @@ TEST_F(PacketCacheTest, AddTwoEntriesToCS) { TEST_F(PacketCacheTest, AggregateInPIT) { // Prepare another msgbuf - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID_2, &new_name); // Check if entry properly created (use sleep to get an updated ts) - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); Ticks old_lifetime = entry->expire_ts; std::this_thread::sleep_for(std::chrono::milliseconds(100)); bool is_aggregated = - pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, name); + pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, &name); Ticks new_lifetime = entry->expire_ts; ASSERT_NE(entry, nullptr); @@ -433,23 +444,24 @@ TEST_F(PacketCacheTest, AggregateInPIT) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, RetransmissionInPIT) { // Prepare another msgbuf (using same connection ID) - Name new_name; - name_CreateFromAddress(&new_name, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t new_name; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &new_name); + EXPECT_EQ(rc, 0); msgbuf_t *new_msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &new_name); // Check if entry properly created (use sleep to get an updated ts) - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); Ticks old_lifetime = entry->expire_ts; std::this_thread::sleep_for(std::chrono::milliseconds(100)); bool is_aggregated = - pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, name); + pkt_cache_try_aggregate_in_pit(pkt_cache, entry, new_msgbuf, &name); Ticks new_lifetime = entry->expire_ts; ASSERT_NE(entry, nullptr); @@ -461,17 +473,17 @@ TEST_F(PacketCacheTest, RetransmissionInPIT) { pkt_cache_lookup_t lookup_result; off_t entry_id; pkt_cache_entry_t *lu_entry = pkt_cache_lookup( - pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, true); + pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_NOT_EXPIRED); EXPECT_EQ(lu_entry, entry); } TEST_F(PacketCacheTest, LookupExpiredInterest) { // Prepare msgbuf with 0 as interest lifetime - msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0); + msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name, 0); // Add to PIT - pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, name); + pkt_cache_entry_t *entry = pkt_cache_add_to_pit(pkt_cache, msgbuf, &name); ASSERT_NE(entry, nullptr); // Wait to make the interest expire @@ -479,14 +491,14 @@ TEST_F(PacketCacheTest, LookupExpiredInterest) { pkt_cache_lookup_t lookup_result; off_t entry_id; - pkt_cache_lookup(pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, + pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_INTEREST_EXPIRED); } TEST_F(PacketCacheTest, LookupExpiredData) { // Prepare msgbuf with 0 as data expiry time - msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0); + msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name, 0); // Add to CS pkt_cache_entry_t *entry = @@ -498,25 +510,27 @@ TEST_F(PacketCacheTest, LookupExpiredData) { pkt_cache_lookup_t lookup_result; off_t entry_id; - pkt_cache_lookup(pkt_cache, name, msgbuf_pool, &lookup_result, &entry_id, + pkt_cache_lookup(pkt_cache, &name, msgbuf_pool, &lookup_result, &entry_id, true); EXPECT_EQ(lookup_result, PKT_CACHE_LU_DATA_EXPIRED); } TEST_F(PacketCacheTest, GetStaleEntries) { // Add to CS a msgbuf with immediate expiration (i.e. stale) - msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, name, 0); + msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, CONN_ID, &name, 0); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, MSGBUF_ID); // Add to CS another msgbuf with immediate expiration (i.e. stale) - Name name_2; - name_CreateFromAddress(&name_2, AF_INET, IPV4_LOOPBACK, IPV4_LEN); + hicn_name_t name_2; + int rc = hicn_name_create_from_ip_address(IPV4_LOOPBACK, 0, &name_2); + EXPECT_EQ(rc, 0); msgbuf_t *msgbuf_2 = msgbuf_create(msgbuf_pool, CONN_ID, &name_2, 0); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf_2, MSGBUF_ID_2); // Add to CS a msgbuf with 5-seconds expiration (i.e. not stale) - Name name_3; - name_CreateFromAddress(&name_3, AF_INET6, IPV6_LOOPBACK, IPV6_LEN); + hicn_name_t name_3; + rc = hicn_name_create_from_ip_address(IPV6_LOOPBACK, 0, &name_3); + EXPECT_EQ(rc, 0); msgbuf_t *msgbuf_3 = msgbuf_create(msgbuf_pool, CONN_ID, &name_3, FIVE_SECONDS); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf_3, MSGBUF_ID_3); @@ -526,17 +540,19 @@ TEST_F(PacketCacheTest, GetStaleEntries) { } TEST_F(PacketCacheTest, GetMultipleStaleEntries) { - ip_address_t addr; + hicn_ip_address_t addr; char name[30]; const int NUM_STALES = 10; + int rc; // Add to CS multiple msgbufs with immediate expiration (i.e. 0 seconds), // resulting in stale entries for (int i = 0; i < NUM_STALES; i++) { snprintf(name, 30, "b001::%d", i); inet_pton(AF_INET6, name, (struct in6_addr *)&addr); - Name name; - name_CreateFromAddress(&name, AF_INET6, addr, IPV6_LEN); + hicn_name_t name; + rc = hicn_name_create_from_ip_address(addr, 0, &name); + EXPECT_EQ(rc, 0); msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, i, &name, 0); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, i); @@ -547,8 +563,9 @@ TEST_F(PacketCacheTest, GetMultipleStaleEntries) { for (int i = NUM_STALES; i < 15; i++) { snprintf(name, 30, "b001::%d", i); inet_pton(AF_INET6, name, (struct in6_addr *)&addr); - Name name; - name_CreateFromAddress(&name, AF_INET6, addr, IPV6_LEN); + hicn_name_t name; + rc = hicn_name_create_from_ip_address(addr, 0, &name); + EXPECT_EQ(rc, 0); msgbuf_t *msgbuf = msgbuf_create(msgbuf_pool, i, &name, FIVE_SECONDS); pkt_cache_add_to_cs(pkt_cache, msgbuf_pool, msgbuf, i); @@ -559,23 +576,22 @@ TEST_F(PacketCacheTest, GetMultipleStaleEntries) { } TEST_F(PacketCacheTest, PerformanceDoubleLookup) { - Name tmp = get_name_from_prefix("b001::0"); + hicn_name_t tmp = get_name_from_prefix("b001::0"); auto elapsed_time_double = get_execution_time([&]() { kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix(); // Add to hash table for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seq); - _add_suffix(prefix_to_suffixes, name_GetContentName(&tmp), - name_GetSegment(&tmp), name_GetSegment(&tmp)); + hicn_name_set_suffix(&tmp, seq); + _add_suffix(prefix_to_suffixes, hicn_name_get_prefix(&tmp), + hicn_name_get_suffix(&tmp), hicn_name_get_suffix(&tmp)); } // Read from hash table - int rc; for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seq); - _get_suffix(prefix_to_suffixes, name_GetContentName(&tmp), seq, &rc); + hicn_name_set_suffix(&tmp, seq); + _get_suffix(prefix_to_suffixes, hicn_name_get_prefix(&tmp), seq); } _prefix_map_free(prefix_to_suffixes); @@ -584,24 +600,24 @@ TEST_F(PacketCacheTest, PerformanceDoubleLookup) { } TEST_F(PacketCacheTest, PerformanceCachedLookup) { - Name tmp = get_name_from_prefix("b001::0"); + hicn_name_t tmp = get_name_from_prefix("b001::0"); auto elapsed_time_single = get_execution_time([&]() { kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix(); kh_pkt_cache_suffix_t *suffixes = - _get_suffixes(prefix_to_suffixes, name_GetContentName(&tmp)); + _get_suffixes(prefix_to_suffixes, hicn_name_get_prefix(&tmp), true); // Add to hash table for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seq); - __add_suffix(suffixes, name_GetSegment(&tmp), name_GetSegment(&tmp)); + hicn_name_set_suffix(&tmp, seq); + __add_suffix(suffixes, hicn_name_get_suffix(&tmp), + hicn_name_get_suffix(&tmp)); } // Read from hash table - int rc; for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seq); - __get_suffix(suffixes, name_GetSegment(&tmp), &rc); + hicn_name_set_suffix(&tmp, seq); + __get_suffix(suffixes, hicn_name_get_suffix(&tmp)); } _prefix_map_free(prefix_to_suffixes); @@ -610,7 +626,7 @@ TEST_F(PacketCacheTest, PerformanceCachedLookup) { } TEST_F(PacketCacheTest, PerformanceCachedLookupRandom) { - Name tmp = get_name_from_prefix("b001::0"); + hicn_name_t tmp = get_name_from_prefix("b001::0"); // Prepare random sequence numbers std::random_device rd; @@ -622,19 +638,19 @@ TEST_F(PacketCacheTest, PerformanceCachedLookupRandom) { auto elapsed_time_single_rand = get_execution_time([&]() { kh_pkt_cache_prefix_t *prefix_to_suffixes = kh_init_pkt_cache_prefix(); kh_pkt_cache_suffix_t *suffixes = - _get_suffixes(prefix_to_suffixes, name_GetContentName(&tmp)); + _get_suffixes(prefix_to_suffixes, hicn_name_get_prefix(&tmp), true); // Add to hash table for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seqs[seq]); - __add_suffix(suffixes, name_GetSegment(&tmp), name_GetSegment(&tmp)); + hicn_name_set_suffix(&tmp, seqs[seq]); + __add_suffix(suffixes, hicn_name_get_suffix(&tmp), + hicn_name_get_suffix(&tmp)); } // Read from hash table - int rc; for (int seq = 0; seq < N_OPS; seq++) { - name_SetSegment(&tmp, seqs[seq]); - __get_suffix(suffixes, name_GetSegment(&tmp), &rc); + hicn_name_set_suffix(&tmp, seqs[seq]); + __get_suffix(suffixes, hicn_name_get_suffix(&tmp)); } _prefix_map_free(prefix_to_suffixes); @@ -643,17 +659,17 @@ TEST_F(PacketCacheTest, PerformanceCachedLookupRandom) { } TEST_F(PacketCacheTest, Clear) { - Name tmp_name1, tmp_name2; + hicn_name_t tmp_name1, tmp_name2; cs_t *cs = pkt_cache_get_cs(pkt_cache); // Create name and add to msgbuf pool - name_Copy(name, &tmp_name1); - name_SetSegment(&tmp_name1, 1); + hicn_name_copy(&tmp_name1, &name); + hicn_name_set_suffix(&tmp_name1, 1); msgbuf_t *tmp_msgbuf1 = msgbuf_create(msgbuf_pool, CONN_ID_2, &tmp_name1); // Create (another) name and add to msgbuf pool - name_Copy(name, &tmp_name2); - name_SetSegment(&tmp_name2, 2); + hicn_name_copy(&tmp_name2, &name); + hicn_name_set_suffix(&tmp_name2, 2); msgbuf_t *tmp_msgbuf2 = msgbuf_create(msgbuf_pool, CONN_ID_2, &tmp_name2); // Add to packet cache (2 entries in the CS, 1 in the PIT) @@ -665,7 +681,7 @@ TEST_F(PacketCacheTest, Clear) { ASSERT_EQ(pkt_cache_get_size(pkt_cache), 3u); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 2u); - ASSERT_EQ(cs->num_entries, 2u); + ASSERT_EQ(cs->num_entries, 2); ASSERT_EQ(cs->stats.lru.countAdds, 2u); // Clear packet cache (i.e. remove content packets from packet cache): @@ -677,6 +693,6 @@ TEST_F(PacketCacheTest, Clear) { ASSERT_EQ(pkt_cache_get_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_pit_size(pkt_cache), 1u); ASSERT_EQ(pkt_cache_get_cs_size(pkt_cache), 0u); - ASSERT_EQ(cs->num_entries, 0u); + ASSERT_EQ(cs->num_entries, 0); ASSERT_EQ(cs->stats.lru.countAdds, 0u); -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/test/test-parser.cc b/hicn-light/src/hicn/test/test-parser.cc index 3a8d2cdb2..2e396b97d 100644 --- a/hicn-light/src/hicn/test/test-parser.cc +++ b/hicn-light/src/hicn/test/test-parser.cc @@ -17,7 +17,7 @@ extern "C" { #include <hicn/util/log.h> -#include <hicn/config/parse.h> +#include <hicn/ctrl/parse.h> } class ParserTest : public ::testing::Test { @@ -68,4 +68,4 @@ TEST_F(ParserTest, AddListenerInvalidPortString) { TEST_F(ParserTest, UnknownCommnad) { std::string cmd = "add face"; ASSERT_EQ(parse(cmd.c_str(), &command_), -1); -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/test/test-pool.cc b/hicn-light/src/hicn/test/test-pool.cc deleted file mode 100644 index 8cd891d6a..000000000 --- a/hicn-light/src/hicn/test/test-pool.cc +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#include <netinet/in.h> - -extern "C" { -#define WITH_TESTS -#include <hicn/util/pool.h> -} - -/* - * TODO - * - test max_size - */ - -#define DEFAULT_SIZE 10 - -class PoolTest : public ::testing::Test { - protected: - PoolTest() {} - virtual ~PoolTest() {} - - int *pool; -}; - -TEST_F(PoolTest, PoolAllocation) { - int rc; - - pool_init(pool, DEFAULT_SIZE, 0); - - size_t pool_size = next_pow2(DEFAULT_SIZE); - - EXPECT_EQ(pool_get_alloc_size(pool), pool_size); - - /* Check that free indices and bitmaps are correctly initialize */ - off_t *fi = pool_get_free_indices(pool); - EXPECT_EQ(vector_len(fi), pool_size); - EXPECT_EQ(fi[0], (long)(pool_size - 1)); - EXPECT_EQ(fi[pool_size - 1], 0); - - /* The allocated size of the underlying vector should be the next power of two - */ - EXPECT_EQ(vector_get_alloc_size(fi), pool_size); - - bitmap_t *fb = pool_get_free_bitmap(pool); - EXPECT_TRUE(bitmap_is_set(fb, 0)); - EXPECT_TRUE(bitmap_is_set(fb, pool_size - 2)); - EXPECT_TRUE(bitmap_is_set(fb, pool_size - 1)); - EXPECT_TRUE(bitmap_is_unset(fb, pool_size)); - - /* Getting elements from the pool should correctly update the free indices - * and bitmap */ - int *elt; - - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - EXPECT_EQ(vector_len(fi), pool_size - 1); - EXPECT_TRUE(bitmap_is_unset(fb, 0)); - - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - EXPECT_EQ(vector_len(fi), pool_size - 2); - EXPECT_TRUE(bitmap_is_unset(fb, 1)); - - for (unsigned i = 0; i < pool_size - 4; i++) { - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - } - - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - EXPECT_EQ(vector_len(fi), 1UL); - EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 2)); - - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - EXPECT_EQ(vector_len(fi), 0UL); - EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1)); - - /* - * Getting elements within the allocated range should not have triggered a - * resize - */ - EXPECT_EQ(pool_len(pool), pool_size); - - /* - * Getting elements once the allocated range has been exceeded should - * trigger a resize - */ - rc = pool_get(pool, elt); - EXPECT_GE(rc, 0); - - EXPECT_EQ(pool_get_alloc_size(pool), pool_size * 2); - - EXPECT_EQ(pool_len(pool), pool_size + 1); - - /* - * Doubling the size, we should have again pool_size elements free, minus 1 - */ - EXPECT_EQ(pool_get_free_indices_size(pool), pool_size - 1); - - /* - * NOTE: this is wrong as there has been a realloc and the old fi - * pointer is now invalid - */ - // EXPECT_EQ(vector_len(fi), pool_size - 1); - - /* And the bitmap should also be correctly modified */ - fb = pool_get_free_bitmap(pool); - EXPECT_TRUE(bitmap_is_unset(fb, pool_size)); - - /* Check that surrounding values are also correct */ - EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1)); - EXPECT_TRUE(bitmap_is_set(fb, pool_size + 1)); - - /* Setting elements after should through */ - - /* Check that free indices and bitmaps are correctly updated */ - - pool_free(pool); -} - -TEST_F(PoolTest, PoolPut) { - pool_init(pool, DEFAULT_SIZE, 0); - - int *elt; - pool_get(pool, elt); - *elt = 10; - pool_put(pool, elt); - - pool_free(pool); -} - -TEST_F(PoolTest, PoolGetForceBitmapRealloc) { - const int N = 64; - int *elts[N]; - int *elt = NULL; - pool_init(pool, N, 0); - - for (int i = 0; i < N; i++) pool_get(pool, elts[i]); - pool_get(pool, elt); - - pool_free(pool); -} - -TEST_F(PoolTest, PoolGetAfterReleasing) { - int *elt1 = NULL, *elt2 = NULL, *tmp = NULL; - pool_init(pool, DEFAULT_SIZE, 0); - - // If two elements are requested... - off_t id1 = pool_get(pool, elt1); - pool_get(pool, tmp); - - // ...and the first one is released... - pool_put(pool, elt1); - - // ...requesting a new one should return - // the first one (that was freed) - off_t id2 = pool_get(pool, elt2); - EXPECT_EQ(id1, id2); - EXPECT_EQ(elt1, elt2); - - pool_free(pool); -} - -TEST_F(PoolTest, PoolGetMultipleElementsAfterReleasing) { - const int N = 2; - int *elts[N]; - pool_init(pool, N, 0); - - for (int i = 0; i < N; i++) pool_get(pool, elts[i]); - for (int i = 0; i < N; i++) pool_put(pool, elts[i]); - for (int i = 0; i < N; i++) pool_get(pool, elts[i]); - - pool_free(pool); -} diff --git a/hicn-light/src/hicn/test/test-ring.cc b/hicn-light/src/hicn/test/test-ring.cc deleted file mode 100644 index ab96d76c0..000000000 --- a/hicn-light/src/hicn/test/test-ring.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> -#include <netinet/in.h> - -extern "C" { -#define WITH_TESTS -#include <hicn/util/ring.h> -} - -#define DEFAULT_SIZE 10UL - -class RingTest : public ::testing::Test { - protected: - RingTest() { ring_init(ring, DEFAULT_SIZE); } - virtual ~RingTest() { ring_free(ring); } - - int *ring = NULL; -}; - -/* TEST: Ring allocation and initialization */ -TEST_F(RingTest, RingAddOne) { - int val = -1; - /* Allocated size should be the next power of two */ - EXPECT_EQ(ring_get_size(ring), 0UL); - ring_add_value(ring, 1); - EXPECT_EQ(ring_get_size(ring), 1UL); - ring_get(ring, 0, &val); - EXPECT_EQ(val, 1); - EXPECT_EQ(ring_get_size(ring), 1UL); - ring_advance(ring, 1); - EXPECT_EQ(ring_get_size(ring), 0UL); -} - -TEST_F(RingTest, RingAddMany) { - size_t i = 0; - int val = -1; - size_t count = 0; - - /* Allocated size should be the next power of two */ - EXPECT_EQ(ring_get_size(ring), 0UL); - for (unsigned i = 0; i < DEFAULT_SIZE; i++) ring_add_value(ring, i); - EXPECT_EQ(ring_get_size(ring), DEFAULT_SIZE); - - count = 0; - ring_enumerate_n(ring, i, &val, 1, { - EXPECT_EQ(val, (int)(i)); - count++; - }); - EXPECT_EQ(count, 1UL); - - count = 0; - ring_enumerate_n(ring, i, &val, DEFAULT_SIZE, { - EXPECT_EQ(val, (int)(i)); - count++; - }); - EXPECT_EQ(count, DEFAULT_SIZE); - - count = 0; - ring_enumerate_n(ring, i, &val, DEFAULT_SIZE + 1, { - EXPECT_EQ(val, (int)(i)); - count++; - }); - EXPECT_EQ(count, DEFAULT_SIZE); - - // Drop one - ring_add_value(ring, DEFAULT_SIZE); - EXPECT_EQ(ring_get_size(ring), DEFAULT_SIZE); - - count = 0; - ring_enumerate_n(ring, i, &val, DEFAULT_SIZE, { - EXPECT_EQ(val, (int)(i + 1)); // all values shoud be shifted - count++; - }); - EXPECT_EQ(count, DEFAULT_SIZE); - - ring_advance(ring, DEFAULT_SIZE); - EXPECT_EQ(ring_get_size(ring), 0UL); -} diff --git a/hicn-light/src/hicn/test/test-strategy-replication.cc b/hicn-light/src/hicn/test/test-strategy-replication.cc index ab7dae1f7..2924173cb 100644 --- a/hicn-light/src/hicn/test/test-strategy-replication.cc +++ b/hicn-light/src/hicn/test/test-strategy-replication.cc @@ -152,7 +152,6 @@ TEST_F(StrategyReplicationTest, MultipleNexthops) { /* Retrieve candidate */ - unsigned nexthop; unsigned tests = 0; nexthops_foreach(nexthops, nexthop, { EXPECT_TRUE(nexthop == NEXTHOP_ID1 || nexthop == NEXTHOP_ID2); diff --git a/hicn-light/src/hicn/test/test-subscription.cc b/hicn-light/src/hicn/test/test-subscription.cc index f89254e67..5fd3ab57d 100644 --- a/hicn-light/src/hicn/test/test-subscription.cc +++ b/hicn-light/src/hicn/test/test-subscription.cc @@ -40,10 +40,10 @@ TEST_F(SubscriptionTest, SetTopic) { TEST_F(SubscriptionTest, GetObjectFromTopic) { hc_object_type_t object_type = object_from_topic(TOPIC_STRATEGY); - EXPECT_EQ(object_type, OBJECT_STRATEGY); + EXPECT_EQ(object_type, OBJECT_TYPE_STRATEGY); object_type = object_from_topic(TOPIC_FACE); - EXPECT_EQ(object_type, OBJECT_FACE); + EXPECT_EQ(object_type, OBJECT_TYPE_FACE); } TEST_F(SubscriptionTest, AddSubscription) { @@ -201,4 +201,4 @@ TEST_F(SubscriptionTest, GetConnectionsForSubscription) { subscription_table_get_connections_for_topic(subscriptions, TOPIC_FACE); EXPECT_EQ(vector_len(conn_ids), 1u); EXPECT_EQ(conn_ids[0], (unsigned)CONN_ID); -}
\ No newline at end of file +} diff --git a/hicn-light/src/hicn/test/test-vector.cc b/hicn-light/src/hicn/test/test-vector.cc deleted file mode 100644 index dda71fd0c..000000000 --- a/hicn-light/src/hicn/test/test-vector.cc +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> - -extern "C" { -#include <hicn/util/vector.h> -} - -static constexpr size_t DEFAULT_SIZE = 10; -static constexpr size_t N_ELEMENTS = 5; - -class VectorTest : public ::testing::Test { - protected: - VectorTest() { vector_init(vector, DEFAULT_SIZE, 0); } - virtual ~VectorTest() { vector_free(vector); } - - int *vector = NULL; -}; - -TEST_F(VectorTest, VectorAllocateAndResize) { - // Allocated size should be the next power of two - EXPECT_EQ(vector_get_alloc_size(vector), 16UL); - - // Setting elements within the allocated size should not trigger a resize - vector_ensure_pos(vector, 15); - EXPECT_EQ(vector_get_alloc_size(vector), 16UL); - - // Setting elements after should through - vector_ensure_pos(vector, 16); - EXPECT_EQ(vector_get_alloc_size(vector), 32UL); -} - -TEST_F(VectorTest, VectorSize) { - EXPECT_EQ(vector_len(vector), 0); - - // Check size after pushing one element - vector_push(vector, 1); - EXPECT_EQ(vector_len(vector), 1); - - // Check size after pushing additional elements - vector_push(vector, 2); - vector_push(vector, 3); - EXPECT_EQ(vector_len(vector), 3); - - // Try adding multiple elements - const int n_elements_to_add = 5; - size_t expected_new_len = vector_len(vector) + n_elements_to_add; - for (int i = 0; i < n_elements_to_add; i++) vector_push(vector, i); - EXPECT_EQ(vector_len(vector), expected_new_len); -} - -TEST_F(VectorTest, VectorCheckValue) { - // Add elements - vector_push(vector, 109); - vector_push(vector, 200); - EXPECT_EQ(vector_at(vector, 0), 109); - EXPECT_EQ(vector_at(vector, 1), 200); - - // Update element - vector_set(vector, 1, 400); - EXPECT_EQ(vector_at(vector, 1), 400); - - // Add at last available position - size_t prev_size = vector_len(vector); - vector_set(vector, vector_len(vector) - 1, 123); - EXPECT_EQ(vector_at(vector, vector_len(vector) - 1), 123); - EXPECT_EQ(prev_size, vector_len(vector)) << "Size should not have changed"; -} - -TEST_F(VectorTest, RemoveElement) { - // Populate vector - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i); - EXPECT_EQ(vector_len(vector), N_ELEMENTS); - for (size_t i = 0; i < vector_len(vector); i++) - EXPECT_EQ(vector_at(vector, i), (int)i); - - // Remove element - int value_to_remove = 3; - int num_removed = vector_remove_unordered(vector, value_to_remove); - - EXPECT_EQ(vector_len(vector), N_ELEMENTS - 1); - EXPECT_EQ(num_removed, 1); - for (size_t i = 0; i < vector_len(vector); i++) - EXPECT_NE(vector_at(vector, i), value_to_remove); -} - -TEST_F(VectorTest, RemoveNonExistingElement) { - // Push some initial values - vector_push(vector, 1); - vector_push(vector, 2); - vector_push(vector, 3); - EXPECT_EQ(vector_len(vector), 3); - - // Remove non-existing element - int num_removed = vector_remove_unordered(vector, 5); - EXPECT_EQ(num_removed, 0); - size_t prev_size = vector_len(vector); - EXPECT_EQ(prev_size, vector_len(vector)) << "Size should not have changed"; -} - -TEST_F(VectorTest, RemoveDuplicatedElement) { - // Populate vector - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i); - EXPECT_EQ(vector_len(vector), N_ELEMENTS); - for (size_t i = 0; i < vector_len(vector); i++) - EXPECT_EQ(vector_at(vector, i), (int)i); - vector_set(vector, 0, 3); // Duplicate element - - // Remove (duplicated) elements - int value_to_remove = 3; - int num_removed = vector_remove_unordered(vector, value_to_remove); - - EXPECT_EQ(vector_len(vector), N_ELEMENTS - 2); - EXPECT_EQ(num_removed, 2); - for (size_t i = 0; i < vector_len(vector); i++) - EXPECT_NE(vector_at(vector, i), value_to_remove); -} - -TEST_F(VectorTest, Iterate) { - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i); - - int count = 0; - int *elem; - vector_foreach(vector, elem, { EXPECT_EQ(*elem, count++); }); -} - -TEST_F(VectorTest, MultipleResize) { - // Use small vector (size=1) to force multiple realloc operations - int *small_vector; - vector_init(small_vector, 1, 0); - - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(small_vector, i); - - for (size_t i = 0; i < N_ELEMENTS; i++) - EXPECT_EQ(vector_at(small_vector, i), (int)i); - - EXPECT_EQ(vector_len(small_vector), 5UL); - EXPECT_EQ(vector_get_alloc_size(small_vector), 8UL); - - vector_free(small_vector); -} - -TEST_F(VectorTest, MaxSize) { - const int max_size = 4; - - // Fill the vector until max size is reached - int *small_vector; - vector_init(small_vector, 2, max_size); - for (int i = 0; i < max_size; i++) vector_push(small_vector, i); - - // Try expanding or appending elements should fail - int rc = vector_ensure_pos(small_vector, max_size); - EXPECT_EQ(rc, -1); - rc = vector_push(small_vector, 123); - EXPECT_EQ(rc, -1); - - vector_free(small_vector); -} - -TEST_F(VectorTest, Contains) { - // No elements - EXPECT_EQ(vector_contains(vector, 1), false); - - // Push one element - vector_push(vector, 1); - EXPECT_EQ(vector_contains(vector, 1), true); - - // Update element - vector_set(vector, 0, 2); - EXPECT_EQ(vector_contains(vector, 1), false); - EXPECT_EQ(vector_contains(vector, 2), true); -} - -TEST_F(VectorTest, Remove) { - // Remove element at invalid position - int rc = vector_remove_at(vector, 2); - EXPECT_EQ(rc, -1); // Failure - - // Push two elements and remove the second one - vector_push(vector, 1); - vector_push(vector, 2); - rc = vector_remove_at(vector, 1); - EXPECT_EQ(rc, 0); // Success - EXPECT_EQ(vector_len(vector), 1); - - // Push another element: it should replace the previous one - vector_push(vector, 3); - EXPECT_EQ(vector_len(vector), 2); - EXPECT_EQ(vector_at(vector, 1), 3); -} - -TEST_F(VectorTest, RemoveInTheMiddle) { - for (size_t i = 0; i < N_ELEMENTS; i++) vector_push(vector, i); - - // Remove element in central position - int rc = vector_remove_at(vector, 2); - EXPECT_EQ(rc, 0); // Success - EXPECT_EQ(vector_contains(vector, 2), false); - EXPECT_EQ(vector_len(vector), N_ELEMENTS - 1); - - // Check if elements have been shifted (preserving the order) - int expected[] = {0, 1, 3, 4}; - for (int i = 0; i < vector_len(vector); i++) - EXPECT_EQ(vector_at(vector, i), expected[i]); -} - -TEST_F(VectorTest, Reset) { - vector_push(vector, 1); - vector_push(vector, 2); - EXPECT_EQ(vector_len(vector), 2); - - vector_reset(vector); - EXPECT_EQ(vector_len(vector), 0); - - vector_push(vector, 5); - EXPECT_EQ(vector_len(vector), 1); - EXPECT_EQ(vector_contains(vector, 5), true); - EXPECT_EQ(vector_at(vector, 0), 5); -}
\ No newline at end of file diff --git a/hicn-light/src/hicn/test/test-hash.cc b/hicn-light/src/hicn/test/test_hash.cc index 3b03a08a6..c742aa248 100644 --- a/hicn-light/src/hicn/test/test-hash.cc +++ b/hicn-light/src/hicn/test/test_hash.cc @@ -187,8 +187,7 @@ TEST(HashTest, PerformanceComparisonBigStruct) { TEST(HashTest, CollisionsComparison) { small_struct_t small_struct = {0}; std::unordered_set<uint32_t> hashes; - int n_collisions_fnv = 0, n_collisions_jenkins = 0, n_collisions_murmur = 0, - n_collisions_xxhash = 0; + int n_collisions_fnv = 0, n_collisions_jenkins = 0; // FNV for (int i = 0; i < 10 * N_HASHES; i++) { diff --git a/hicn-plugin/src/CMakeLists.txt b/hicn-plugin/src/CMakeLists.txt index d232b4ab1..3b89e4b53 100644 --- a/hicn-plugin/src/CMakeLists.txt +++ b/hicn-plugin/src/CMakeLists.txt @@ -180,7 +180,7 @@ set(COMPILE_DEFINITIONS if (${CMAKE_BUILD_TYPE} MATCHES "Debug") list(APPEND COMPILE_DEFINITIONS "-DHICN_DDEBUG" - "-DCLIB_DEBUG" + # "-DCLIB_DEBUG" ) endif() @@ -249,4 +249,4 @@ build_module(${HICN_API_TEST_PLUGIN} ############################################################## if (${BUILD_TESTS}) add_subdirectory(test) -endif()
\ No newline at end of file +endif() diff --git a/hicn-plugin/src/data_fwd_node.c b/hicn-plugin/src/data_fwd_node.c index f909ae536..981dc2c5e 100644 --- a/hicn-plugin/src/data_fwd_node.c +++ b/hicn-plugin/src/data_fwd_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -253,8 +253,7 @@ hicn_satisfy_faces (vlib_main_t *vm, u32 bi0, hicn_pcs_entry_t *pitp, always_inline void clone_data_to_cs (hicn_pit_cs_t *pitcs, hicn_pcs_entry_t *pcs_entry, - u32 buffer_index, hicn_header_t *hicn0, f64 tnow, - hicn_lifetime_t dmsg_lifetime) + u32 buffer_index, f64 tnow, hicn_lifetime_t dmsg_lifetime) { /* * At this point we think we're safe to proceed. Store the CS buf in @@ -314,7 +313,6 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, u8 isv6; u32 bi0; u32 next0 = HICN_DATA_FWD_NEXT_ERROR_DROP; - hicn_header_t *hicn0; hicn_buffer_t *hicnb0; const hicn_strategy_vft_t *strategy_vft0 = NULL; const hicn_dpo_vft_t *dpo_vft0; @@ -364,7 +362,6 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, // Get hicn buffer and state hicnb0 = hicn_get_buffer (b0); - hicn0 = (hicn_header_t *) (vlib_buffer_get_current (b0)); hicn_get_internal_state (hicnb0, &pcs_entry_id, &strategy_vft0, &dpo_vft0, &dpo_ctx_id0); @@ -442,7 +439,7 @@ hicn_data_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, { // Clone data packet in the content store and convert the PIT // entry into a CS entry - clone_data_to_cs (rt->pitcs, pcs_entry, bi0, hicn0, tnow, + clone_data_to_cs (rt->pitcs, pcs_entry, bi0, tnow, dmsg_lifetime); } else @@ -520,4 +517,4 @@ VLIB_REGISTER_NODE(hicn_data_fwd_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */
\ No newline at end of file + */ diff --git a/hicn-plugin/src/data_pcslookup_node.c b/hicn-plugin/src/data_pcslookup_node.c index 55ddda9c4..5ae6958f5 100644 --- a/hicn-plugin/src/data_pcslookup_node.c +++ b/hicn-plugin/src/data_pcslookup_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -97,8 +97,9 @@ hicn_data_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, stats.pkts_data_count += 1; // Lookup the name in the PIT - ret = hicn_pcs_lookup_one (rt->pitcs, hicn_buffer_get_name (b0), - &pcs_entry); + hicn_name_t name; + hicn_packet_get_name (&hicn_get_buffer (b0)->pkbuf, &name); + ret = hicn_pcs_lookup_one (rt->pitcs, &name, &pcs_entry); if (ret == HICN_ERROR_NONE) { @@ -197,4 +198,4 @@ VLIB_REGISTER_NODE(hicn_data_pcslookup_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */
\ No newline at end of file + */ diff --git a/hicn-plugin/src/faces/app/face_prod.c b/hicn-plugin/src/faces/app/face_prod.c index 1e569b82b..73e2a1262 100644 --- a/hicn-plugin/src/faces/app/face_prod.c +++ b/hicn-plugin/src/faces/app/face_prod.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -285,6 +285,7 @@ hicn_face_prod_add (fib_prefix_t *prefix, u32 sw_if, u32 *cs_reserved, } face = hicn_face_get (&local_app_ip, sw_if, &hicn_face_hashtb, adj_index); + assert (face); *faceid = hicn_dpoi_get_index (face); diff --git a/hicn-plugin/src/faces/app/face_prod_node.c b/hicn-plugin/src/faces/app/face_prod_node.c index 8adb7dce7..93e80d1ac 100644 --- a/hicn-plugin/src/faces/app/face_prod_node.c +++ b/hicn-plugin/src/faces/app/face_prod_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -100,16 +100,16 @@ match_ip6_name (u8 *name, const fib_prefix_t *prefix) } static_always_inline u32 -hicn_face_prod_next_from_data_hdr (vlib_buffer_t *b) +hicn_face_prod_next_from_data_hdr (vlib_main_t *vm, vlib_buffer_t *b) { u8 is_v6; int match_res = 1; int ret = 0; - hicn_name_t *name; + hicn_name_t name; hicn_face_prod_state_t *prod_face = NULL; // 1 - ensure the packet is hicn and its format is correct - ret = hicn_data_parse_pkt (b); + ret = hicn_data_parse_pkt (b, vlib_buffer_length_in_chain (vm, b)); if (PREDICT_FALSE (ret)) { return HICN_FACE_PROD_NEXT_ERROR_DROP; @@ -124,14 +124,14 @@ hicn_face_prod_next_from_data_hdr (vlib_buffer_t *b) // of this face const fib_prefix_t *prefix = &prod_face->prefix; is_v6 = hicn_buffer_is_v6 (b); - name = &hicn_get_buffer (b)->name; + hicn_packet_get_name (&hicn_get_buffer (b)->pkbuf, &name); if (PREDICT_TRUE (!is_v6 && ip46_address_is_ip4 (&prefix->fp_addr))) { - match_res = match_ip4_name (&name->prefix.ip4.as_u32, prefix); + match_res = match_ip4_name (&name.prefix.v4.as_u32, prefix); } else if (PREDICT_TRUE (is_v6 && !ip46_address_is_ip4 (&prefix->fp_addr))) { - match_res = match_ip6_name (name->prefix.ip6.as_u8, prefix); + match_res = match_ip6_name (name.prefix.v6.as_u8, prefix); } // 4 - if match found, forward data to next hicn node @@ -230,10 +230,10 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicnb3->flags = HICN_FACE_FLAGS_DEFAULT; // parse packets and get next node - next0 = hicn_face_prod_next_from_data_hdr (b0); - next1 = hicn_face_prod_next_from_data_hdr (b1); - next2 = hicn_face_prod_next_from_data_hdr (b2); - next3 = hicn_face_prod_next_from_data_hdr (b3); + next0 = hicn_face_prod_next_from_data_hdr (vm, b0); + next1 = hicn_face_prod_next_from_data_hdr (vm, b1); + next2 = hicn_face_prod_next_from_data_hdr (vm, b2); + next3 = hicn_face_prod_next_from_data_hdr (vm, b3); stats.pkts_data_count += 4; // counters @@ -304,7 +304,7 @@ hicn_face_prod_input_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicnb0 = hicn_get_buffer (b0); hicnb0->flags = HICN_FACE_FLAGS_DEFAULT; - next0 = hicn_face_prod_next_from_data_hdr (b0); + next0 = hicn_face_prod_next_from_data_hdr (vm, b0); stats.pkts_data_count++; // counters @@ -357,4 +357,4 @@ VLIB_REGISTER_NODE(hicn_face_prod_input_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */
\ No newline at end of file + */ diff --git a/hicn-plugin/src/faces/face.c b/hicn-plugin/src/faces/face.c index 4ee1c283f..58c1c34c8 100644 --- a/hicn-plugin/src/faces/face.c +++ b/hicn-plugin/src/faces/face.c @@ -303,9 +303,6 @@ hicn_face_add (const dpo_id_t *dpo_nh, ip46_address_t *nat_address, int sw_if, hicn_face_id_t *pfaceid) { - hicn_face_flags_t flags = (hicn_face_flags_t) 0; - flags |= HICN_FACE_FLAGS_FACE; - hicn_face_t *face; face = diff --git a/hicn-plugin/src/faces/face_node.c b/hicn-plugin/src/faces/face_node.c index e2fb79d17..0d2e70fbe 100644 --- a/hicn-plugin/src/faces/face_node.c +++ b/hicn-plugin/src/faces/face_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -25,6 +25,9 @@ #include "../hicn.h" #include "../parser.h" +#include <hicn/error.h> +#include <hicn/util/ip_address.h> + /** * @File * @@ -140,7 +143,7 @@ typedef enum ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current (b0); \ \ /* Parse packet and cache useful info in opaque2 */ \ - ret0 = hicn_data_parse_pkt (b0); \ + ret0 = hicn_data_parse_pkt (b0, vlib_buffer_length_in_chain (vm, b0)); \ is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \ ret0 = (ret0 == HICN_ERROR_NONE) || \ (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \ @@ -235,8 +238,8 @@ typedef enum ip_hdr1 = (IP_HEADER_##ipv *) vlib_buffer_get_current (b1); \ \ /* Parse packet and cache useful info in opaque2 */ \ - ret0 = hicn_data_parse_pkt (b0); \ - ret1 = hicn_data_parse_pkt (b1); \ + ret0 = hicn_data_parse_pkt (b0, vlib_buffer_length_in_chain (vm, b0)); \ + ret1 = hicn_data_parse_pkt (b1, vlib_buffer_length_in_chain (vm, b1)); \ is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \ is_icmp1 = ret1 == HICN_ERROR_PARSER_MAPME_PACKET; \ ret0 = (ret0 == HICN_ERROR_NONE) || \ @@ -545,18 +548,17 @@ hicn_face_rewrite_interest (vlib_main_t *vm, vlib_buffer_t *b0, * hicn_face_match_probe(b0, face, next)) */ /* return; */ - hicn_header_t *hicn = vlib_buffer_get_current (b0); + hicn_packet_buffer_t *pkbuf = &hicn_get_buffer (b0)->pkbuf; u8 is_v4 = ip46_address_is_ip4 (&face->nat_addr) && !ip6_address_is_loopback (&face->nat_addr.ip6); // hicn_face_ip_t *ip_face = (hicn_face_ip_t *) face->data; - ip46_address_t temp_addr; - ip46_address_reset (&temp_addr); - hicn_type_t type = hicn_get_buffer (b0)->type; - int ret = hicn_ops_vft[type.l1]->rewrite_interest ( - type, &hicn->protocol, &face->nat_addr, &temp_addr); + hicn_ip_address_t temp_addr; + ip46_address_reset (&(temp_addr.as_ip46)); + hicn_ip_address_t *face_nat_addr = (hicn_ip_address_t *) &face->nat_addr; + int ret = hicn_interest_rewrite (pkbuf, face_nat_addr, &temp_addr); if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED) { ensure_offload_flags (b0, is_v4); @@ -887,4 +889,4 @@ VLIB_REGISTER_NODE (hicn6_face_output_node) = { * Local Variables: * eval: (c-set-style "gnu") * End: - */
\ No newline at end of file + */ diff --git a/hicn-plugin/src/faces/iface_node.c b/hicn-plugin/src/faces/iface_node.c index 2f651beb8..598a68db6 100644 --- a/hicn-plugin/src/faces/iface_node.c +++ b/hicn-plugin/src/faces/iface_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -21,6 +21,9 @@ #include "../cache_policies/cs_lru.h" #include "../parser.h" +#include <hicn/error.h> +#include <hicn/util/ip_address.h> + /** * @File * @@ -200,7 +203,8 @@ typedef enum ip_hdr = (IP_HEADER_##ipv *) vlib_buffer_get_current (b0); \ \ /* Parse packet and cache useful info in opaque2 */ \ - ret0 = hicn_interest_parse_pkt (b0); \ + ret0 = \ + hicn_interest_parse_pkt (b0, vlib_buffer_length_in_chain (vm, b0)); \ is_icmp0 = (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \ ret0 = (ret0 == HICN_ERROR_NONE) || \ (ret0 == HICN_ERROR_PARSER_MAPME_PACKET); \ @@ -304,8 +308,10 @@ typedef enum stats.pkts_interest_count += 2; \ \ /* Parse packet and cache useful info in opaque2 */ \ - ret0 = hicn_interest_parse_pkt (b0); \ - ret1 = hicn_interest_parse_pkt (b1); \ + ret0 = \ + hicn_interest_parse_pkt (b0, vlib_buffer_length_in_chain (vm, b0)); \ + ret1 = \ + hicn_interest_parse_pkt (b1, vlib_buffer_length_in_chain (vm, b1)); \ is_icmp0 = ret0 == HICN_ERROR_PARSER_MAPME_PACKET; \ is_icmp1 = ret1 == HICN_ERROR_PARSER_MAPME_PACKET; \ ret0 = (ret0 == HICN_ERROR_NONE) || \ @@ -655,17 +661,19 @@ hicn_rewrite_iface_data4 (vlib_main_t *vm, vlib_buffer_t *b0, vnet_buffer (b0)->ip.adj_index[VLIB_TX] = iface->dpo.dpoi_index; *next = iface->dpo.dpoi_next_node; - hicn_header_t *hicn = vlib_buffer_get_current (b0); - ip46_address_t temp_addr; - ip46_address_reset (&temp_addr); - hicn_type_t type = hicn_get_buffer (b0)->type; + hicn_packet_buffer_t *pkbuf = &hicn_get_buffer (b0)->pkbuf; + + hicn_ip_address_t temp_addr; + ip46_address_reset (&(temp_addr.as_ip46)); + + hicn_ip_address_t *iface_nat_addr = (hicn_ip_address_t *) &(iface->nat_addr); + u8 flags = hicn_get_buffer (b0)->flags; u8 reset_pl = flags & HICN_BUFFER_FLAGS_FROM_CS; - ret = hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol, - &(iface->nat_addr), &(temp_addr), - iface->pl_id, reset_pl); + ret = hicn_data_rewrite (pkbuf, iface_nat_addr, &(temp_addr), iface->pl_id, + reset_pl); if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED) { @@ -693,17 +701,17 @@ hicn_rewrite_iface_data6 (vlib_main_t *vm, vlib_buffer_t *b0, vnet_buffer (b0)->ip.adj_index[VLIB_TX] = iface->dpo.dpoi_index; *next = iface->dpo.dpoi_next_node; - hicn_header_t *hicn = vlib_buffer_get_current (b0); + hicn_packet_buffer_t *pkbuf = &hicn_get_buffer (b0)->pkbuf; + + hicn_ip_address_t temp_addr; + ip46_address_reset (&(temp_addr.as_ip46)); - ip46_address_t temp_addr; - ip46_address_reset (&temp_addr); - hicn_type_t type = hicn_get_buffer (b0)->type; + hicn_ip_address_t *iface_nat_addr = (hicn_ip_address_t *) &(iface->nat_addr); u8 flags = hicn_get_buffer (b0)->flags; u8 reset_pl = flags & HICN_BUFFER_FLAGS_FROM_CS; - ret = hicn_ops_vft[type.l1]->rewrite_data (type, &hicn->protocol, - &(iface->nat_addr), &(temp_addr), - iface->pl_id, reset_pl); + ret = hicn_data_rewrite (pkbuf, iface_nat_addr, &(temp_addr), iface->pl_id, + reset_pl); if (ret == HICN_LIB_ERROR_REWRITE_CKSUM_REQUIRED) { @@ -1007,4 +1015,4 @@ VLIB_REGISTER_NODE (hicn6_iface_output_node) = { * Local Variables: * eval: (c-set-style "gnu") * End: - */
\ No newline at end of file + */ diff --git a/hicn-plugin/src/hicn.h b/hicn-plugin/src/hicn.h index 3b197d6b4..84d268357 100644 --- a/hicn-plugin/src/hicn.h +++ b/hicn-plugin/src/hicn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -16,20 +16,7 @@ #ifndef __HICN_H__ #define __HICN_H__ -#define ip_address_t hicn_ip_address_t -#define ip_address_cmp hicn_ip_address_cmp -#define ip_prefix_t hicn_ip_prefix_t -#define ip_prefix_cmp hicn_ip_prefix_cmp -#undef ip_prefix_len -#define ip_prefix_len hicn_ip_prefix_len #include <hicn/hicn.h> -#undef ip_address_t -#undef ip_address_cmp -#undef ip_prefix_t -#undef ip_prefix_cmp -#undef ip_prefix_len -#define ip_prefix_len(_a) (_a)->len - #include "faces/face.h" #include <netinet/in.h> @@ -61,6 +48,11 @@ typedef u8 weight_t; typedef struct { /** + * Cached packet info + */ + hicn_packet_buffer_t pkbuf; + + /** * IDs to prefetch a PIT/CS entry (4) */ u32 pcs_entry_id; @@ -85,15 +77,24 @@ typedef struct */ hicn_face_id_t face_id; - /** - * Cached packet info - */ - hicn_type_t type; + /* + hicn_packet_type_t type; + hicn_packet_format_t format; hicn_name_t name; + */ u16 port; + u16 payload_type; hicn_lifetime_t lifetime; } hicn_buffer_t; +STATIC_ASSERT (offsetof (hicn_buffer_t, pcs_entry_id) == 28, ""); +STATIC_ASSERT (offsetof (hicn_buffer_t, vft_id) == 32, ""); +STATIC_ASSERT (offsetof (hicn_buffer_t, dpo_ctx_id) == 36, ""); +STATIC_ASSERT (offsetof (hicn_buffer_t, flags) == 40, ""); +STATIC_ASSERT (offsetof (hicn_buffer_t, face_id) == 44, ""); +// STATIC_ASSERT (offsetof (hicn_buffer_t, name) == 48, ""); +// + name = 16+4 = 20 +// opaque : u32[14] = 56 STATIC_ASSERT (sizeof (hicn_buffer_t) <= STRUCT_SIZE_OF (vlib_buffer_t, opaque2), "hICN buffer opaque2 meta-data too large for vlib_buffer"); @@ -104,6 +105,7 @@ hicn_get_buffer (vlib_buffer_t *b0) return (hicn_buffer_t *) &(b0->opaque2[0]); } +#if 0 always_inline u8 hicn_is_v6 (hicn_header_t *pkt_hdr) { @@ -113,13 +115,16 @@ hicn_is_v6 (hicn_header_t *pkt_hdr) always_inline hicn_name_t * hicn_buffer_get_name (vlib_buffer_t *b) { - return &hicn_get_buffer (b)->name; + return hicn_packet_get_name(&hicn_get_buffer (b)->pkbuf); } +#endif always_inline u8 hicn_buffer_is_v6 (vlib_buffer_t *b0) { - return hicn_get_buffer (b0)->type.l1 == IPPROTO_IPV6; + hicn_packet_format_t format = + hicn_packet_get_format (&hicn_get_buffer (b0)->pkbuf); + return format.l1 == IPPROTO_IPV6; } always_inline void @@ -135,6 +140,12 @@ hicn_buffer_get_lifetime (vlib_buffer_t *b) return hicn_get_buffer (b)->lifetime; } +always_inline hicn_payload_type_t +hicn_buffer_get_payload_type (vlib_buffer_t *b) +{ + return hicn_get_buffer (b)->payload_type; +} + #endif /* __HICN_H__ */ /* diff --git a/hicn-plugin/src/interest_pcslookup_node.c b/hicn-plugin/src/interest_pcslookup_node.c index a9ff9ba29..ab6a31e08 100644 --- a/hicn-plugin/src/interest_pcslookup_node.c +++ b/hicn-plugin/src/interest_pcslookup_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -104,8 +104,10 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, stats.pkts_processed++; // Check if the interest is in the PCS already - ret = hicn_pcs_lookup_one (rt->pitcs, &hicn_get_buffer (b0)->name, - &pcs_entry); + hicn_name_t name; + hicn_packet_get_name (&hicn_get_buffer (b0)->pkbuf, &name); + ret = hicn_pcs_lookup_one (rt->pitcs, &name, &pcs_entry); + //&hicn_get_buffer (b0)->name, if (ret == HICN_ERROR_NONE) { @@ -124,6 +126,12 @@ hicn_interest_pcslookup_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, stats.pkts_interest_count++; + // Interest manifest? + if (hicn_buffer_get_payload_type (b0) == HPT_MANIFEST) + { + ; + } + // Maybe trace if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && (b0->flags & VLIB_BUFFER_IS_TRACED))) @@ -203,4 +211,4 @@ VLIB_REGISTER_NODE(hicn_interest_pcslookup_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */
\ No newline at end of file + */ diff --git a/hicn-plugin/src/mapme_ack_node.c b/hicn-plugin/src/mapme_ack_node.c index ea4834665..13ae7ee67 100644 --- a/hicn-plugin/src/mapme_ack_node.c +++ b/hicn-plugin/src/mapme_ack_node.c @@ -67,7 +67,7 @@ hicn_mapme_process_ack (vlib_main_t *vm, vlib_buffer_t *b, /* return true; */ /* } */ - dpo = fib_epm_lookup (&(prefix.name), prefix.len); + dpo = fib_epm_lookup (&(prefix.name.as_ip46), prefix.len); if (!dpo) { HICN_ERROR ("Ignored ACK for non-existing FIB entry %U. Ignored.", diff --git a/hicn-plugin/src/mapme_ctrl_node.c b/hicn-plugin/src/mapme_ctrl_node.c index 5314c49a0..e3d340e53 100644 --- a/hicn-plugin/src/mapme_ctrl_node.c +++ b/hicn-plugin/src/mapme_ctrl_node.c @@ -194,7 +194,7 @@ hicn_mapme_process_ctrl (vlib_main_t *vm, vlib_buffer_t *b, /* We forge the ACK which we be the packet forwarded by the node */ hicn_mapme_create_ack (vlib_buffer_get_current (b), ¶ms); - dpo = fib_epm_lookup (&prefix.name, prefix.len); + dpo = fib_epm_lookup (&prefix.name.as_ip46, prefix.len); if (!dpo) { #ifdef HICN_MAPME_ALLOW_NONEXISTING_FIB_ENTRY diff --git a/hicn-plugin/src/mapme_eventmgr.c b/hicn-plugin/src/mapme_eventmgr.c index c7ae4ecd7..bbfe77819 100644 --- a/hicn-plugin/src/mapme_eventmgr.c +++ b/hicn-plugin/src/mapme_eventmgr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -22,6 +22,8 @@ #include <vnet/fib/ip4_fib.h> #include <vnet/fib/ip6_fib.h> +#include <hicn/mapme.h> + #define DEFAULT_TIMEOUT 1.0 /* s */ /** @@ -196,7 +198,7 @@ hicn_mapme_on_face_added (vlib_main_t *vm, hicn_face_id_t face) static_always_inline void * get_packet_buffer (vlib_main_t *vm, u32 node_index, u32 dpoi_index, - ip46_address_t *addr, hicn_type_t type) + ip46_address_t *addr, hicn_packet_format_t format) { vlib_frame_t *f; vlib_buffer_t *b; // for newly created packet @@ -216,7 +218,10 @@ get_packet_buffer (vlib_main_t *vm, u32 node_index, u32 dpoi_index, /* Face information for next hop node index */ vnet_buffer (b)->ip.adj_index[VLIB_TX] = dpoi_index; - hicn_get_buffer (b)->type = type; + + hicn_packet_buffer_t *pkbuf = &hicn_get_buffer (b)->pkbuf; + hicn_packet_set_format (pkbuf, format); + hicn_packet_init_header (pkbuf, 0); /* Enqueue the packet right now */ f = vlib_get_frame_to_node (vm, node_index); @@ -227,8 +232,8 @@ get_packet_buffer (vlib_main_t *vm, u32 node_index, u32 dpoi_index, // pointer to IP layer ? do we need to prepare for ethernet ??? buffer = vlib_buffer_get_current (b); - b->current_length = - (type.l1 == IPPROTO_IPV6) ? HICN_MAPME_V6_HDRLEN : HICN_MAPME_V4_HDRLEN; + b->current_length = (format.l1 == IPPROTO_IPV6) ? EXPECTED_MAPME_V6_HDRLEN : + EXPECTED_MAPME_V4_HDRLEN; return buffer; } @@ -255,8 +260,8 @@ hicn_mapme_send_message (vlib_main_t *vm, const hicn_prefix_t *prefix, u8 *buffer = get_packet_buffer ( vm, node_index, face, (ip46_address_t *) prefix, - (params->protocol == IPPROTO_IPV6) ? HICN_TYPE_IPV6_ICMP : - HICN_TYPE_IPV4_ICMP); + (params->protocol == IPPROTO_IPV6) ? HICN_PACKET_FORMAT_IPV6_ICMP : + HICN_PACKET_FORMAT_IPV4_ICMP); n = hicn_mapme_create_packet (buffer, prefix, params); if (n <= 0) { @@ -282,7 +287,7 @@ hicn_mapme_send_updates (vlib_main_t *vm, hicn_prefix_t *prefix, dpo_id_t dpo, mapme_params_t params = { .protocol = - ip46_address_is_ip4 (&prefix->name) ? IPPROTO_IP : IPPROTO_IPV6, + ip46_address_is_ip4 (&prefix->name.as_ip46) ? IPPROTO_IP : IPPROTO_IPV6, .type = UPDATE, .seq = tfib->seq, }; diff --git a/hicn-plugin/src/parser.h b/hicn-plugin/src/parser.h index 3c21a33f8..f9b3e43ae 100644 --- a/hicn-plugin/src/parser.h +++ b/hicn-plugin/src/parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -26,62 +26,27 @@ * @file parser.h */ -#define PARSE(PACKET_TYPE) \ +#define PARSE(PACKET_TYPE, SIZE) \ do \ { \ if (pkt == NULL) \ return HICN_ERROR_PARSER_PKT_INVAL; \ \ - int ret = HICN_LIB_ERROR_NONE; \ + int ret = HICN_ERROR_NONE; \ \ - hicn_header_t *pkt_hdr; \ - u8 *ip_pkt; \ - u8 ip_proto; \ - int isv6; \ - u8 next_proto_offset; \ - hicn_type_t type; \ - hicn_name_t *name; \ u16 *port; \ hicn_lifetime_t *lifetime; \ + hicn_payload_type_t payload_type; \ \ - /* start parsing first fields to get the protocols */ \ - pkt_hdr = vlib_buffer_get_current (pkt); \ - isv6 = hicn_is_v6 (pkt_hdr); \ - \ - ip_pkt = vlib_buffer_get_current (pkt); \ - ip_proto = (1 - isv6) * IPPROTO_IP + (isv6) *IPPROTO_IPV6; \ - \ - /* in the ipv6 header the next header field is at byte 6 in the ipv4*/ \ - /* header the protocol field is at byte 9*/ \ - next_proto_offset = 6 + (1 - isv6) * 3; \ - \ - /* get type info*/ \ - type.l4 = IPPROTO_NONE; \ - type.l3 = ip_pkt[next_proto_offset] == IPPROTO_UDP ? IPPROTO_ENCAP : \ - IPPROTO_NONE; \ - type.l2 = ip_pkt[next_proto_offset]; \ - type.l1 = ip_proto; \ + hicn_packet_buffer_t *pkbuf = &hicn_get_buffer (pkt)->pkbuf; \ \ - /* cache hicn packet type in opaque2*/ \ - hicn_get_buffer (pkt)->type = type; \ - \ - /* get name and name length*/ \ - name = &hicn_get_buffer (pkt)->name; \ - ret = hicn_ops_vft[type.l1]->get_##PACKET_TYPE##_name ( \ - type, &pkt_hdr->protocol, name); \ - if (PREDICT_FALSE (ret)) \ - { \ - if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6) \ - { \ - return HICN_ERROR_PARSER_MAPME_PACKET; \ - } \ - return HICN_ERROR_PARSER_PKT_INVAL; \ - } \ + hicn_packet_set_buffer (pkbuf, vlib_buffer_get_current (pkt), (SIZE), \ + (SIZE)); \ + hicn_packet_analyze (&hicn_get_buffer (pkt)->pkbuf); \ \ /* get source port*/ \ port = &hicn_get_buffer (pkt)->port; \ - hicn_ops_vft[type.l1]->get_source_port (type, &pkt_hdr->protocol, \ - port); \ + hicn_packet_get_src_port (pkbuf, port); \ if (PREDICT_FALSE (ret)) \ { \ return HICN_ERROR_PARSER_PKT_INVAL; \ @@ -89,16 +54,34 @@ \ /* get lifetime*/ \ lifetime = &hicn_get_buffer (pkt)->lifetime; \ - hicn_ops_vft[type.l1]->get_lifetime (type, &pkt_hdr->protocol, \ - lifetime); \ + hicn_packet_get_lifetime (pkbuf, lifetime); \ \ if (*lifetime > hicn_main.pit_lifetime_max_ms) \ *lifetime = hicn_main.pit_lifetime_max_ms; \ \ + /* get payload type */ \ + hicn_packet_get_payload_type (pkbuf, &payload_type); \ + hicn_get_buffer (pkt)->payload_type = (u16) (payload_type); \ return ret; \ } \ while (0) +#if 0 + hicn_name_t *name; \ + + /* get name and name length*/ + name = &hicn_get_buffer (pkt)->name; + ret = hicn_##PACKET_TYPE##_get_name (pkbuf, name); + if (PREDICT_FALSE (ret)) + { + if (type.l2 == IPPROTO_ICMPV4 || type.l2 == IPPROTO_ICMPV6) + { + return HICN_ERROR_PARSER_MAPME_PACKET; + } + return HICN_ERROR_PARSER_PKT_INVAL; + } +#endif + /** * @brief Parse a interest packet * @@ -111,9 +94,9 @@ * ipv6 */ always_inline int -hicn_interest_parse_pkt (vlib_buffer_t *pkt) +hicn_interest_parse_pkt (vlib_buffer_t *pkt, uword size) { - PARSE (interest); + PARSE (interest, size); } /** @@ -128,9 +111,9 @@ hicn_interest_parse_pkt (vlib_buffer_t *pkt) * ipv6 */ always_inline int -hicn_data_parse_pkt (vlib_buffer_t *pkt) +hicn_data_parse_pkt (vlib_buffer_t *pkt, uword size) { - PARSE (data); + PARSE (data, size); } #endif /* __HICN_PARSER_H__ */ @@ -139,4 +122,4 @@ hicn_data_parse_pkt (vlib_buffer_t *pkt) * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */
\ No newline at end of file + */ diff --git a/hicn-plugin/src/pcs.h b/hicn-plugin/src/pcs.h index fa5a68b27..f9cb7bd91 100644 --- a/hicn-plugin/src/pcs.h +++ b/hicn-plugin/src/pcs.h @@ -259,8 +259,8 @@ hicn_pcs_get_exp_time (f64 cur_time_sec, u64 lifetime_msec) always_inline void hicn_pcs_get_key_from_name (clib_bihash_kv_24_8_t *kv, const hicn_name_t *name) { - kv->key[0] = name->prefix.ip6.as_u64[0]; - kv->key[1] = name->prefix.ip6.as_u64[1]; + kv->key[0] = name->prefix.v6.as_u64[0]; + kv->key[1] = name->prefix.v6.as_u64[1]; kv->key[2] = name->suffix; } diff --git a/hicn-plugin/src/pg.c b/hicn-plugin/src/pg.c index 05172345b..78380a804 100644 --- a/hicn-plugin/src/pg.c +++ b/hicn-plugin/src/pg.c @@ -61,9 +61,37 @@ hicnpg_server_restack (hicnpg_server_t *hicnpg_server) static hicnpg_server_t * hicnpg_server_from_fib_node (fib_node_t *node) { +#if 1 ASSERT (hicnpg_server_fib_node_type == node->fn_type); return ((hicnpg_server_t *) (((char *) node) - STRUCT_OFFSET_OF (hicnpg_server_t, fib_node))); +#else + hicn_header_t *h0 = vlib_buffer_get_current (b0); + + /* Generate the right src and dst corresponding to flow and iface */ + ip46_address_t src_addr = { + .ip4 = hicnpg_main.pgen_clt_src_addr.ip4, + }; + hicn_name_t dst_name = { + .prefix.v4.as_u32 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip4.as_u32, + .suffix = seq_number, + }; + + src_addr.ip4.as_u32 += clib_host_to_net_u32 (iface); + dst_name.prefix.v4.as_u32 += clib_net_to_host_u32 (next_flow); + + /* Update locator and name */ + hicn_type_t type = hicn_get_buffer (b0)->type; + HICN_OPS4->set_interest_locator (type, &h0->protocol, + (hicn_ip_address_t *) &src_addr); + HICN_OPS4->set_interest_name (type, &h0->protocol, &dst_name); + + /* Update lifetime (currently L4 checksum is not updated) */ + HICN_OPS4->set_lifetime (type, &h0->protocol, interest_lifetime); + + /* Update checksums */ + HICN_OPS4->update_checksums (type, &h0->protocol, 0, 0); +#endif } /** @@ -74,7 +102,35 @@ hicnpg_server_fib_back_walk (fib_node_t *node, fib_node_back_walk_ctx_t *ctx) { hicnpg_server_restack (hicnpg_server_from_fib_node (node)); +#if 1 return FIB_NODE_BACK_WALK_CONTINUE; +#else + /* Generate the right src and dst corresponding to flow and iface */ + ip46_address_t src_addr = { + .ip6 = hicnpg_main.pgen_clt_src_addr.ip6, + }; + hicn_name_t dst_name = { + .prefix.v6.as_u64 = { + hicnpg_main.pgen_clt_hicn_name->fp_addr.ip6.as_u64[0], + hicnpg_main.pgen_clt_hicn_name->fp_addr.ip6.as_u64[1], + }, + .suffix = seq_number, + }; + src_addr.ip6.as_u32[3] += clib_host_to_net_u32 (iface); + dst_name.prefix.v6.as_u32[3] += clib_net_to_host_u32 (next_flow); + + /* Update locator and name */ + hicn_type_t type = hicn_get_buffer (b0)->type; + HICN_OPS6->set_interest_locator (type, &h0->protocol, + (hicn_ip_address_t *) &src_addr); + HICN_OPS6->set_interest_name (type, &h0->protocol, &dst_name); + + /* Update lifetime */ + HICN_OPS6->set_lifetime (type, &h0->protocol, interest_lifetime); + + /* Update checksums */ + calculate_tcp_checksum_v6 (vm, b0); +#endif } /** @@ -311,4 +367,4 @@ hicn_pg_init (vlib_main_t *vm) * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */
\ No newline at end of file + */ diff --git a/hicn-plugin/src/pg_node.c b/hicn-plugin/src/pg_node.c index 1a99d3fa2..3d94c1cd1 100644 --- a/hicn-plugin/src/pg_node.c +++ b/hicn-plugin/src/pg_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,6 +18,9 @@ #include <vnet/pg/pg.h> #include <vnet/ip/ip.h> #include <vnet/ethernet/ethernet.h> +#include <vnet/ip/ip4_packet.h> +#include <vnet/ip/ip6_packet.h> +#include <vnet/tcp/tcp_packet.h> #include "hicn.h" #include "pg.h" @@ -130,6 +133,7 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, u8 isv6_0; u8 isv6_1; u32 n_left_to_next; + uword size; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -178,7 +182,8 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, vnet_buffer (b1)->sw_if_index[VLIB_RX] = hpgm->sw_if; /* Check icn packets, locate names */ - if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE) + size = vlib_buffer_length_in_chain (vm, b0); + if (hicn_interest_parse_pkt (b0, size) == HICN_ERROR_NONE) { /* this node grabs only interests */ isv6_0 = hicn_buffer_is_v6 (b0); @@ -204,7 +209,8 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, next0 = isv6_0 ? HICNPG_INTEREST_NEXT_V6_LOOKUP : HICNPG_INTEREST_NEXT_V4_LOOKUP; } - if (hicn_interest_parse_pkt (b1) == HICN_ERROR_NONE) + size = vlib_buffer_length_in_chain (vm, b1); + if (hicn_interest_parse_pkt (b1, size) == HICN_ERROR_NONE) { /* this node grabs only interests */ isv6_1 = hicn_buffer_is_v6 (b1); @@ -292,7 +298,8 @@ hicnpg_client_interest_node_fn (vlib_main_t *vm, vlib_node_runtime_t *node, vnet_buffer (b0)->sw_if_index[VLIB_RX] = hpgm->sw_if; /* Check icn packets, locate names */ - if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE) + size = vlib_buffer_length_in_chain (vm, b0); + if (hicn_interest_parse_pkt (b0, size) == HICN_ERROR_NONE) { /* this node grabs only interests */ isv6_0 = hicn_buffer_is_v6 (b0); @@ -363,30 +370,28 @@ void hicn_rewrite_interestv4 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number, u16 interest_lifetime, u32 next_flow, u32 iface) { - hicn_header_t *h0 = vlib_buffer_get_current (b0); - + hicn_packet_buffer_t *pkbuf = &hicn_get_buffer (b0)->pkbuf; /* Generate the right src and dst corresponding to flow and iface */ ip46_address_t src_addr = { .ip4 = hicnpg_main.pgen_clt_src_addr.ip4, }; hicn_name_t dst_name = { - .prefix.ip4 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip4, + .prefix.v4.as_u32 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip4.as_u32, .suffix = seq_number, }; src_addr.ip4.as_u32 += clib_host_to_net_u32 (iface); - dst_name.prefix.ip4.as_u32 += clib_net_to_host_u32 (next_flow); + dst_name.prefix.v4.as_u32 += clib_net_to_host_u32 (next_flow); /* Update locator and name */ - hicn_type_t type = hicn_get_buffer (b0)->type; - HICN_OPS4->set_interest_locator (type, &h0->protocol, &src_addr); - HICN_OPS4->set_interest_name (type, &h0->protocol, &dst_name); + hicn_interest_set_locator (pkbuf, (hicn_ip_address_t *) &src_addr); + hicn_interest_set_name (pkbuf, &dst_name); /* Update lifetime (currently L4 checksum is not updated) */ - HICN_OPS4->set_lifetime (type, &h0->protocol, interest_lifetime); + hicn_interest_set_lifetime (pkbuf, interest_lifetime); /* Update checksums */ - HICN_OPS4->update_checksums (type, &h0->protocol, 0, 0); + hicn_packet_compute_checksum (pkbuf); } /** @@ -409,28 +414,27 @@ void hicn_rewrite_interestv6 (vlib_main_t *vm, vlib_buffer_t *b0, u32 seq_number, u16 interest_lifetime, u32 next_flow, u32 iface) { - hicn_header_t *h0 = vlib_buffer_get_current (b0); + hicn_packet_buffer_t *pkbuf = &hicn_get_buffer (b0)->pkbuf; /* Generate the right src and dst corresponding to flow and iface */ ip46_address_t src_addr = { .ip6 = hicnpg_main.pgen_clt_src_addr.ip6, }; hicn_name_t dst_name = { - .prefix.ip6 = hicnpg_main.pgen_clt_hicn_name->fp_addr.ip6, + .prefix = (hicn_ip_address_t) (hicnpg_main.pgen_clt_hicn_name->fp_addr), .suffix = seq_number, }; src_addr.ip6.as_u32[3] += clib_host_to_net_u32 (iface); - dst_name.prefix.ip6.as_u32[3] += clib_net_to_host_u32 (next_flow); + dst_name.prefix.v6.as_u32[3] += clib_net_to_host_u32 (next_flow); /* Update locator and name */ - hicn_type_t type = hicn_get_buffer (b0)->type; - HICN_OPS6->set_interest_locator (type, &h0->protocol, &src_addr); - HICN_OPS6->set_interest_name (type, &h0->protocol, &dst_name); - + hicn_interest_set_locator (pkbuf, (hicn_ip_address_t *) &src_addr); + hicn_interest_set_name (pkbuf, &dst_name); /* Update lifetime */ - HICN_OPS6->set_lifetime (type, &h0->protocol, interest_lifetime); + hicn_interest_set_lifetime (pkbuf, interest_lifetime); /* Update checksums */ + hicn_packet_compute_checksum (pkbuf); calculate_tcp_checksum_v6 (vm, b0); } @@ -811,6 +815,7 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node, u32 hpgi0, hpgi1; hicnpg_server_t *hpg0, *hpg1; u32 n_left_to_next; + uword size; from = vlib_frame_vector_args (frame); @@ -863,7 +868,8 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hpg0 = hicnpg_server_get (hpgi0); hpg1 = hicnpg_server_get (hpgi1); - if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE) + size = vlib_buffer_length_in_chain (vm, b0); + if (hicn_interest_parse_pkt (b0, size) == HICN_ERROR_NONE) { vlib_buffer_t *rb = NULL; rb = vlib_get_buffer (vm, hpg0->buffer_index); @@ -875,7 +881,8 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node, HICNPG_SERVER_NEXT_V4_LOOKUP; } - if (hicn_interest_parse_pkt (b1) == HICN_ERROR_NONE) + size = vlib_buffer_length_in_chain (vm, b1); + if (hicn_interest_parse_pkt (b1, size) == HICN_ERROR_NONE) { vlib_buffer_t *rb = NULL; rb = vlib_get_buffer (vm, hpg1->buffer_index); @@ -944,7 +951,8 @@ hicnpg_node_server_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hpgi0 = vnet_buffer (b0)->ip.adj_index[VLIB_TX]; hpg0 = hicnpg_server_get (hpgi0); - if (hicn_interest_parse_pkt (b0) == HICN_ERROR_NONE) + size = vlib_buffer_length_in_chain (vm, b0); + if (hicn_interest_parse_pkt (b0, size) == HICN_ERROR_NONE) { /* this node grabs only interests */ vlib_buffer_t *rb = NULL; @@ -995,10 +1003,10 @@ void convert_interest_to_data_v4 (vlib_main_t *vm, vlib_buffer_t *b0, vlib_buffer_t *rb, u32 bi0) { - hicn_header_t *h0 = vlib_buffer_get_current (b0); + ip4_header_t *ip4 = vlib_buffer_get_current (b0); /* Get the packet length */ - u16 pkt_len = clib_net_to_host_u16 (h0->v4.ip.len); + u16 pkt_len = clib_net_to_host_u16 (ip4->length); /* * Rule of thumb: We want the size of the IP packet to be <= 1500 bytes @@ -1013,14 +1021,14 @@ convert_interest_to_data_v4 (vlib_main_t *vm, vlib_buffer_t *b0, b0 = vlib_get_buffer (vm, bi0); - h0 = vlib_buffer_get_current (b0); + ip4 = vlib_buffer_get_current (b0); - ip4_address_t src_addr = h0->v4.ip.saddr; - h0->v4.ip.saddr = h0->v4.ip.daddr; - h0->v4.ip.daddr = src_addr; + ip4_address_t src_addr = ip4->src_address; + ip4->src_address = ip4->dst_address; + ip4->dst_address = src_addr; - h0->v4.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); - h0->v4.ip.csum = ip4_header_checksum ((ip4_header_t *) &(h0->v4.ip)); + ip4->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); + ip4->checksum = ip4_header_checksum (ip4); calculate_tcp_checksum_v4 (vm, b0); } @@ -1028,11 +1036,11 @@ void convert_interest_to_data_v6 (vlib_main_t *vm, vlib_buffer_t *b0, vlib_buffer_t *rb, u32 bi0) { - hicn_header_t *h0 = vlib_buffer_get_current (b0); + ip6_header_t *ip6 = vlib_buffer_get_current (b0); /* Get the packet length */ uint16_t pkt_len = - clib_net_to_host_u16 (h0->v6.ip.len) + sizeof (ip6_header_t); + clib_net_to_host_u16 (ip6->payload_length) + sizeof (ip6_header_t); /* * Figure out how many bytes we can add to the content @@ -1049,15 +1057,17 @@ convert_interest_to_data_v6 (vlib_main_t *vm, vlib_buffer_t *b0, b0 = vlib_get_buffer (vm, bi0); - h0 = vlib_buffer_get_current (b0); - ip6_address_t src_addr = h0->v6.ip.saddr; - h0->v6.ip.saddr = h0->v6.ip.daddr; - h0->v6.ip.daddr = src_addr; + ip6 = vlib_buffer_get_current (b0); + ip6_address_t src_addr = ip6->src_address; + ip6->src_address = ip6->dst_address; + ip6->dst_address = src_addr; + + ip6->payload_length = clib_host_to_net_u16 ( + vlib_buffer_length_in_chain (vm, b0) - sizeof (ip6_header_t)); - h0->v6.ip.len = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) - - sizeof (ip6_header_t)); - h0->v6.tcp.data_offset_and_reserved |= 0x0f; - h0->v6.tcp.urg_ptr = htons (0xffff); + tcp_header_t *tcp = (tcp_header_t *) (ip6 + 1); + tcp->data_offset_and_reserved |= 0x0f; + tcp->urgent_pointer = htons (0xffff); calculate_tcp_checksum_v6 (vm, b0); } diff --git a/hicn-plugin/src/strategy_node.c b/hicn-plugin/src/strategy_node.c index 565f3e496..5f5a10749 100644 --- a/hicn-plugin/src/strategy_node.c +++ b/hicn-plugin/src/strategy_node.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -160,7 +160,10 @@ hicn_strategy_fn (vlib_main_t *vm, vlib_node_runtime_t *node, hicn_buffer_get_lifetime (b0)); // Add entry to PIT table - ret = hicn_pcs_pit_insert (rt->pitcs, pcs_entry, &hicnb0->name); + hicn_name_t name; + hicn_packet_get_name (&hicnb0->pkbuf, &name); + ret = hicn_pcs_pit_insert (rt->pitcs, pcs_entry, &name); + //&hicnb0->name); if (PREDICT_FALSE (ret != HICN_ERROR_NONE)) { @@ -285,4 +288,4 @@ VLIB_REGISTER_NODE (hicn_strategy_node) = * fd.io coding-style-patch-verification: ON * * Local Variables: eval: (c-set-style "gnu") End: - */
\ No newline at end of file + */ diff --git a/internal/cmake/Modules/CheckSafeC.cmake b/internal/cmake/Modules/CheckSafeC.cmake new file mode 100644 index 000000000..fe0b996bd --- /dev/null +++ b/internal/cmake/Modules/CheckSafeC.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2017-2022 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +macro(CheckSafeC) + if(INTERNAL_ENVIRONMENT_FOUND) + set(SAFEC_DEPENDENCY "ciscosafec") + endif() +endmacro()
\ No newline at end of file diff --git a/internal/cmake/Modules/CheckSsl.cmake b/internal/cmake/Modules/CheckSsl.cmake new file mode 100644 index 000000000..bf1b11737 --- /dev/null +++ b/internal/cmake/Modules/CheckSsl.cmake @@ -0,0 +1,19 @@ +# Copyright (c) 2017-2022 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +macro(CheckSsl) + if("${OPENSSL_INCLUDE_DIR}" MATCHES ".*cisco.*") + set(OPENSSL_DEPENDENCY "tk-libssl1.1") + set(OPENSSL_DEPENDENCY_DEV "tk-libssl-dev") + endif() +endmacro()
\ No newline at end of file diff --git a/internal/cmake/Modules/FindCiscoSafeC.cmake b/internal/cmake/Modules/FindCiscoSafeC.cmake new file mode 100644 index 000000000..9f723a018 --- /dev/null +++ b/internal/cmake/Modules/FindCiscoSafeC.cmake @@ -0,0 +1,54 @@ +# Copyright (c) 2017-2022 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######################################## +# +# Find the CiscoSafeC libraries and includes +# This module sets: +# CISCOSAFEC_FOUND: True if CiscoSafeC was found +# CISCOSAFEC_LIBRARY: The CiscoSafeC library +# CISCOSAFEC_LIBRARIES: The CiscoSafeC library and dependencies +# CISCOSAFEC_INCLUDE_DIR: The CiscoSafeC include dir +# + +set(CISCOSAFEC_SEARCH_PATH_LIST + ${CISCOSAFEC_HOME} + $ENV{CISCOSAFEC_HOME} + /usr/local + /opt + /usr +) + +find_path(CISCOSAFEC_INCLUDE_DIR safec_config.h + HINTS ${CISCOSAFEC_SEARCH_PATH_LIST} + PATH_SUFFIXES include include/safec + DOC "Find the CiscoSafeC includes" +) + +find_library(CISCOSAFEC_LIBRARY NAMES ciscosafec + HINTS ${CISCOSAFEC_SEARCH_PATH_LIST} + PATH_SUFFIXES lib + DOC "Find the CiscoSafeC libraries" +) + +set(CISCOSAFEC_LIBRARIES ${CISCOSAFEC_LIBRARY}) +set(CISCOSAFEC_INCLUDE_DIRS ${CISCOSAFEC_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +set(CISCOSAFEC_FOUND False) + +if (NOT "${CISCOSAFEC_INCLUDE_DIR}" STREQUAL "") + set(CISCOSAFEC_FOUND True) + find_package_handle_standard_args(CiscoSafeC DEFAULT_MSG CISCOSAFEC_LIBRARY CISCOSAFEC_INCLUDE_DIR) + mark_as_advanced(CISCOSAFEC_LIBRARY CISCOSAFEC_INCLUDE_DIR) +endif () diff --git a/internal/cmake/Modules/ImportInternal.cmake b/internal/cmake/Modules/ImportInternal.cmake new file mode 100644 index 000000000..73cdac1a7 --- /dev/null +++ b/internal/cmake/Modules/ImportInternal.cmake @@ -0,0 +1,23 @@ +# Copyright (c) 2017-2022 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +macro(ImportInternal) + find_package(CiscoSafeC) + if (CiscoSafeC_FOUND) + list(APPEND COMPILER_DEFINITIONS + "-DENABLE_SAFEC" + ) + list(APPEND THIRD_PARTY_LIBRARIES ${CISCOSAFEC_LIBRARY}) + list(APPEND THIRD_PARTY_INCLUDE_DIRS ${CISCOSAFEC_INCLUDE_DIR}) + endif() +endmacro()
\ No newline at end of file diff --git a/internal/cmake/Modules/SetRelyGitRepo.cmake b/internal/cmake/Modules/SetRelyGitRepo.cmake new file mode 100644 index 000000000..facdc19b9 --- /dev/null +++ b/internal/cmake/Modules/SetRelyGitRepo.cmake @@ -0,0 +1,20 @@ +# Copyright (c) 2017-2022 Cisco and/or its affiliates. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +macro(SetRelyGitRepo) + if(DEFINED ENV{BITBUCKET_USERNAME} AND DEFINED ENV{BITBUCKET_PASSWORD}) + set(GIT_REPO https://$ENV{BITBUCKET_USERNAME}:$ENV{BITBUCKET_PASSWORD}@bitbucket-eng-gpk1.cisco.com/bitbucket/scm/icn/rely.git) + else() + set(GIT_REPO ssh://git@bitbucket-eng-gpk1.cisco.com:7999/icn/rely.git) + endif() +endmacro()
\ No newline at end of file diff --git a/lib/includes/CMakeLists.txt b/lib/includes/CMakeLists.txt index 392c2c94e..61af7eca8 100644 --- a/lib/includes/CMakeLists.txt +++ b/lib/includes/CMakeLists.txt @@ -24,29 +24,19 @@ set(LIBHICN_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/hicn/hicn.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/base.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/common.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/compat.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/error.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/face.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/header.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/mapme.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/name.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/packet.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/policy.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/ops.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/strategy.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/validation.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn/interest_manifest.h PARENT_SCOPE ) -set(LIBHICN_HEADER_FILES_PROTOCOL - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/ah.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/icmp.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/icmprd.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/ipv4.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/ipv6.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/tcp.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/udp.h - ${CMAKE_CURRENT_SOURCE_DIR}/hicn/protocol/new.h +set(LIBHICN_HEADER_FILES_UTIL ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/array.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/bitmap.h ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/hash.h @@ -63,3 +53,6 @@ set(LIBHICN_HEADER_FILES_PROTOCOL ${CMAKE_CURRENT_SOURCE_DIR}/hicn/util/vector.h PARENT_SCOPE ) + +set_property(GLOBAL PROPERTY LIBHICN_HEADER_FILES_UTIL_PROPERTY "${LIBHICN_HEADER_FILES_UTIL}") + diff --git a/lib/includes/hicn/base.h b/lib/includes/hicn/base.h index b825619b7..0a6ac7321 100644 --- a/lib/includes/hicn/base.h +++ b/lib/includes/hicn/base.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,8 +32,16 @@ /* Default header fields */ #define HICN_DEFAULT_TTL 254 +#define SYMBOLIC_NAME_LEN 16 + +/* hICN attribute types */ + +/* Face id */ + typedef u32 hicn_faceid_t; -typedef u8 hicn_pathlabel_t; + +/* Lifetime */ + typedef u32 hicn_lifetime_t; #define HICN_MAX_LIFETIME_SCALED 0xFFFF @@ -56,6 +64,9 @@ typedef u32 hicn_lifetime_t; * currently used by an hypothetical signed MAP-Me update : * [IPPROTO_ICMPRD, IPPROTO_AH, IPPROTO_ICMP, IPPROTO_IPV6] */ + +#define HICN_FORMAT_LEN 4 + typedef union { /** protocol layers representation */ @@ -82,82 +93,166 @@ typedef union }; /** u32 representation */ u32 as_u32; -} hicn_type_t; + u8 as_u8[HICN_FORMAT_LEN]; +} hicn_packet_format_t; /* Common protocol layers */ /* Common protocol layers */ #ifndef _WIN32 -#define HICN_TYPE(x, y, z, t) \ - (hicn_type_t) \ +#define HICN_PACKET_FORMAT(x, y, z, t) \ + (hicn_packet_format_t) \ { \ { \ .l1 = x, .l2 = y, .l3 = z, .l4 = t \ } \ } #else -inline hicn_type_t -HICN_TYPE (int x, int y, int z, int t) +inline const hicn_packet_format_t +HICN_PACKET_FORMAT (int x, int y, int z, int t) { - hicn_type_t type; - type.l1 = x; - type.l2 = y; - type.l3 = z; - type.l4 = t; - return type; + hicn_packet_format_t format; + format.l1 = x; + format.l2 = y; + format.l3 = z; + format.l4 = t; + return format; } #endif -#define HICN_TYPE_IPV4_TCP \ - HICN_TYPE (IPPROTO_IP, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE) -#define HICN_TYPE_IPV4_ICMP \ - HICN_TYPE (IPPROTO_IP, IPPROTO_ICMP, IPPROTO_NONE, IPPROTO_NONE) -#define HICN_TYPE_IPV6_TCP \ - HICN_TYPE (IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE) -#define HICN_TYPE_IPV6_ICMP \ - HICN_TYPE (IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_NONE, IPPROTO_NONE) -#define HICN_TYPE_NEW \ - HICN_TYPE (IPPROTO_ENCAP, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE) -#define HICN_TYPE_IPV4_UDP \ - HICN_TYPE (IPPROTO_IP, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_NONE) -#define HICN_TYPE_IPV6_UDP \ - HICN_TYPE (IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_NONE) -#define HICN_TYPE_IPV4_TCP_AH \ - HICN_TYPE (IPPROTO_IP, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE) -#define HICN_TYPE_IPV4_ICMP_AH \ - HICN_TYPE (IPPROTO_IP, IPPROTO_ICMP, IPPROTO_AH, IPPROTO_NONE) -#define HICN_TYPE_IPV6_TCP_AH \ - HICN_TYPE (IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE) -#define HICN_TYPE_IPV6_ICMP_AH \ - HICN_TYPE (IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_AH, IPPROTO_NONE) -#define HICN_TYPE_NEW_AH \ - HICN_TYPE (IPPROTO_ENCAP, IPPROTO_AH, IPPROTO_NONE, IPPROTO_NONE) -#define HICN_TYPE_IPV6_UDP_AH \ - HICN_TYPE (IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_AH) -#define HICN_TYPE_IPV4_UDP_AH \ - HICN_TYPE (IPPROTO_IP, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_AH) -#define HICN_TYPE_NONE \ - HICN_TYPE (IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE) +extern const char *const _protocol_str[]; + +#define protocol_str(x) protocol_str[x] + +int hicn_packet_format_snprintf (char *s, size_t size, + hicn_packet_format_t format); + +#define MAXSZ_HICN_PACKET_FORMAT 4 * 4 + 3 // ICMP/ICMP/ICMP/ICMP + +#if !defined(__cplusplus) +#define constexpr const +#endif + +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV4_TCP = + HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV4_ICMP = + HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_ICMP, IPPROTO_NONE, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV6_TCP = + HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_NONE, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV6_ICMP = + HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_NONE, + IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_NEW = + HICN_PACKET_FORMAT (IPPROTO_ENCAP, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV4_UDP = + HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV6_UDP = + HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV4_TCP_AH = + HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV4_ICMP_AH = + HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_ICMP, IPPROTO_AH, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV6_TCP_AH = + HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_AH, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV6_ICMP_AH = + HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_ICMPV6, IPPROTO_AH, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_NEW_AH = + HICN_PACKET_FORMAT (IPPROTO_ENCAP, IPPROTO_AH, IPPROTO_NONE, IPPROTO_NONE); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV6_UDP_AH = + HICN_PACKET_FORMAT (IPPROTO_IPV6, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_AH); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_IPV4_UDP_AH = + HICN_PACKET_FORMAT (IPPROTO_IP, IPPROTO_UDP, IPPROTO_ENCAP, IPPROTO_AH); +static constexpr hicn_packet_format_t HICN_PACKET_FORMAT_NONE = + HICN_PACKET_FORMAT (IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE, IPPROTO_NONE); + +/** + * @brief Return the hICN format with an additional AH header + * @param [in] format - hICN packet format + * @return Updated hICN packet format + */ +static inline hicn_packet_format_t +hicn_get_ah_format (hicn_packet_format_t format) +{ + hicn_packet_format_t ret = format; + for (unsigned i = 0; i < HICN_FORMAT_LEN; i++) + { + switch (ret.as_u8[i]) + { + case IPPROTO_AH: + return ret; + case IPPROTO_NONE: + ret.as_u8[i] = IPPROTO_AH; + return ret; + default: + break; + } + } + return ret; +} + +/* + * MAX(IPV4_HDRLEN (20), IPV6_HDRLEN (40)) + * + MAX (TCP_HDRLEN (20), UDP_HDRLEN (8), ICMP_HDRLEN (8), NEW_HDRLEN (32)) + * + AH_HDRLEN + */ +#define HICN_HDRLEN_MAX 72 /** * @brief Check if type is none. * @return 1 if none, 0 otherwise */ static inline int -hicn_type_is_none (hicn_type_t type) +hicn_type_is_none (hicn_packet_format_t format) { - return (type.l1 == IPPROTO_NONE) && (type.l2 == IPPROTO_NONE) && - (type.l3 == IPPROTO_NONE) && (type.l4 == IPPROTO_NONE); + return (format.l1 == IPPROTO_NONE) && (format.l2 == IPPROTO_NONE) && + (format.l3 == IPPROTO_NONE) && (format.l4 == IPPROTO_NONE); } +#define _is_ipv4(format) (format.l1 == IPPROTO_IP) +#define _is_ipv6(format) (format.l1 == IPPROTO_IPV6) +#define _is_tcp(format) (format.l2 == IPPROTO_TCP) +#define _is_udp(format) (format.l2 == IPPROTO_UDP) +#define _is_icmp(format) \ + ((format.l2 == IPPROTO_ICMP) || (format.l2 == IPPROTO_ICMPV6)) +#define _is_cmpr(format) ((format & HFO_CMPR) >> 5) +#define _is_ah(format) \ + ((format.l1 == IPPROTO_AH) || (format.l2 == IPPROTO_AH) || \ + (format.l3 == IPPROTO_AH)) + +/* + * @brief hICN packet types + * + * probes are like normal interest & data but: + * - interests use BFD port as the destination + * - data use BFD port as the source + expiry time must be 0. + * if any of these conditions is not met, the packet is still matched as an + * interest or data packet. + * + */ + +#define foreach_packet_type \ + _ (UNDEFINED) \ + _ (INTEREST) \ + _ (DATA) \ + _ (WLDR_NOTIFICATION) \ + _ (MAPME) \ + _ (PROBE) \ + _ (COMMAND) \ + _ (N) + /** * @brief hICN Packet type */ typedef enum { - HICN_PACKET_TYPE_INTEREST, - HICN_PACKET_TYPE_DATA, - HICN_PACKET_N_TYPE, +#define _(x) HICN_PACKET_TYPE_##x, + foreach_packet_type +#undef _ } hicn_packet_type_t; +#undef foreach_type + +extern const char *_hicn_packet_type_str[]; + +#define hicn_packet_type_str(x) _hicn_packet_type_str[x] /** * @brief hICN Payload type @@ -172,60 +267,11 @@ typedef enum HPT_UNSPEC = 999 } hicn_payload_type_t; -/*************************************************************** - * Interest Manifest - ***************************************************************/ - -#define MAX_SUFFIXES_IN_MANIFEST 255 -#define WORD_WIDTH (sizeof (uint32_t) * 8) -#define BITMAP_SIZE ((MAX_SUFFIXES_IN_MANIFEST + 1) / WORD_WIDTH) - -typedef struct -{ - /* This can be 16 bits, but we use 32 bits for alignment */ - uint32_t n_suffixes; - - uint32_t request_bitmap[BITMAP_SIZE]; - - /* Followed by the list of prefixes to ask */ - /* ... */ -} interest_manifest_header_t; - -// Bitmap operations - -static inline void -set_bit (uint32_t *bitmap, int i) -{ - size_t offset = i / WORD_WIDTH; - size_t pos = i % WORD_WIDTH; - bitmap[offset] |= ((uint32_t) 1 << pos); -} - -static inline void -unset_bit (uint32_t *bitmap, int i) -{ - size_t offset = i / WORD_WIDTH; - size_t pos = i % WORD_WIDTH; - bitmap[offset] &= ~((uint32_t) 1 << pos); -} +/* Path label */ -static inline bool -is_bit_set (const uint32_t *bitmap, int i) -{ - size_t offset = i / WORD_WIDTH; - size_t pos = i % WORD_WIDTH; - return bitmap[offset] & ((uint32_t) 1 << pos); -} +typedef u8 hicn_path_label_t; -static inline void -bitmap_print (u32 *bitmap, size_t n_words) -{ - for (size_t word = 0; word < n_words; word++) - { - for (int bit = 31; bit >= 0; bit--) - (is_bit_set (&bitmap[word], bit)) ? printf ("1") : printf ("0"); - } -} +#define INVALID_PATH_LABEL 0 /** * @brief Path label computations @@ -237,28 +283,28 @@ bitmap_print (u32 *bitmap, size_t n_words) * NOTE: this computation is not (yet) part of the hICN specification. */ -#define HICN_PATH_LABEL_MASK 0x000000ff -#define HICN_PATH_LABEL_SIZE 8 +#define HICN_PATH_LABEL_MASK 0x000000ff +#define HICN_PATH_LABEL_SIZE_BITS sizeof (hicn_path_label_t) * 8 /** * @brief Path label update - * @param [in] current_label Current pathlabel + * @param [in] current_label Current path_label * @param [in] face_id The face identifier to combine into the path label - * @param [out] new_label Computed pathlabel + * @param [out] new_label Computed path_label * * This function updates the current_label based on the new face_id, and * returns */ static inline void -update_pathlabel (hicn_pathlabel_t current_label, hicn_faceid_t face_id, - hicn_pathlabel_t *new_label) +update_path_label (hicn_path_label_t current_label, hicn_faceid_t face_id, + hicn_path_label_t *new_label) { - hicn_pathlabel_t pl_face_id = - (hicn_pathlabel_t) (face_id & HICN_PATH_LABEL_MASK); + hicn_path_label_t pl_face_id = + (hicn_path_label_t) (face_id & HICN_PATH_LABEL_MASK); - *new_label = - ((current_label << 1) | (current_label >> (HICN_PATH_LABEL_SIZE - 1))) ^ - pl_face_id; + *new_label = ((current_label << 1) | + (current_label >> (HICN_PATH_LABEL_SIZE_BITS - 1))) ^ + pl_face_id; } /*************************************************************** diff --git a/lib/includes/hicn/common.h b/lib/includes/hicn/common.h index 1998099db..64aca8f1f 100644 --- a/lib/includes/hicn/common.h +++ b/lib/includes/hicn/common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -36,25 +36,11 @@ #include <stdint.h> #include <assert.h> -/* Concise type definitions */ +#include <hicn/util/types.h> -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -/* - * Code annotations - * - * NOTE: these are defined by default in VPP. - */ - -#ifndef HICN_VPP_PLUGIN - -#define PREDICT_FALSE(x) (x) -#define PREDICT_TRUE(x) (x) -#define STRUCT_SIZE_OF(type, member) sizeof (((type *) 0)->member) -#define ASSERT +#define HICN_EXPECT_FALSE(x) __builtin_expect ((x), 1) +#define HICN_EXPECT_TRUE(x) __builtin_expect ((x), 0) +#define HICN_UNUSED(x) x __attribute__ ((unused)) #ifndef NDEBUG #define _ASSERT(x) assert (x) @@ -62,36 +48,6 @@ typedef uint8_t u8; #define _ASSERT(x) ((void) (x)) #endif -#define STATIC_ASSERT(x) - -/* Architecture-dependent uword size */ -#if INTPTR_MAX == INT64_MAX -#define log2_uword_bits 6 -#elif INTPTR_MAX == INT32_MAX -#define log2_uword_bits 5 -#else -#error "Impossible to detect architecture" -#endif - -#define uword_bits (1 << log2_uword_bits) - -/* Word types. */ -#if uword_bits == 64 -/* 64 bit word machines. */ -typedef u64 uword; -#else -/* 32 bit word machines. */ -typedef u32 uword; -#endif - -typedef uword ip_csum_t; - -#else - -#include <vppinfra/clib.h> - -#endif /* ! HICN_VPP_PLUGIN */ - /* * Windows compilers do not support named initilizers when .h files are * included inside C++ files. For readability, we either use the following @@ -178,11 +134,11 @@ int get_addr_family (const char *ip_address); */ static inline u16 -ip_csum_fold (ip_csum_t c) +ip_csum_fold (hicn_ip_csum_t c) { /* Reduce to 16 bits. */ #if uword_bits == 64 - c = (c & (ip_csum_t) 0xffffffff) + (c >> (ip_csum_t) 32); + c = (c & (hicn_ip_csum_t) 0xffffffff) + (c >> (hicn_ip_csum_t) 32); c = (c & 0xffff) + (c >> 16); #endif @@ -192,18 +148,18 @@ ip_csum_fold (ip_csum_t c) return (u16) c; } -static inline ip_csum_t -ip_csum_with_carry (ip_csum_t sum, ip_csum_t x) +static inline hicn_ip_csum_t +ip_csum_with_carry (hicn_ip_csum_t sum, hicn_ip_csum_t x) { - ip_csum_t t = sum + x; + hicn_ip_csum_t t = sum + x; return t + (t < x); } /* Update checksum changing field at even byte offset from x -> 0. */ -static inline ip_csum_t -ip_csum_add_even (ip_csum_t c, ip_csum_t x) +static inline hicn_ip_csum_t +ip_csum_add_even (hicn_ip_csum_t c, hicn_ip_csum_t x) { - ip_csum_t d; + hicn_ip_csum_t d; d = c - x; @@ -214,8 +170,8 @@ ip_csum_add_even (ip_csum_t c, ip_csum_t x) } /* Update checksum changing field at even byte offset from 0 -> x. */ -static inline ip_csum_t -ip_csum_sub_even (ip_csum_t c, ip_csum_t x) +static inline hicn_ip_csum_t +ip_csum_sub_even (hicn_ip_csum_t c, hicn_ip_csum_t x) { return ip_csum_with_carry (c, x); } @@ -265,40 +221,71 @@ csum (const void *addr, size_t size, u16 init) * Query IP version from packet (either 4 or 6) * (version is located as same offsets in both protocol headers) */ -#define HICN_IP_VERSION(packet) \ - ((hicn_header_t *) packet)->protocol.ipv4.version - -#ifndef ntohll -static inline uint64_t -ntohll (uint64_t input) +typedef struct { - uint64_t return_val = input; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + u8 dummy : 4; + u8 version : 4; +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 version : 4; + u8 dummy : 4; +#else +#error "Unsupported endianness" +#endif +} ip_version_t; +#define HICN_IP_VERSION(packet) ((ip_version_t *) packet)->version + +/* + * Endianess utils + */ + #if (__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__) - uint8_t *tmp = (uint8_t *) &return_val; - - tmp[0] = (uint8_t) (input >> 56); - tmp[1] = (uint8_t) (input >> 48); - tmp[2] = (uint8_t) (input >> 40); - tmp[3] = (uint8_t) (input >> 32); - tmp[4] = (uint8_t) (input >> 24); - tmp[5] = (uint8_t) (input >> 16); - tmp[6] = (uint8_t) (input >> 8); - tmp[7] = (uint8_t) (input >> 0); +#define HICN_LITTLE_ENDIAN_ARCH +#else +#define HICN_BIG_ENDIAN_ARCH #endif - return return_val; +static inline u16 +hicn_conditional_swap_u16 (u16 value) +{ +#ifdef HICN_LITTLE_ENDIAN_ARCH + value = __builtin_bswap16 (value); +#endif + + return value; } -static inline uint64_t -htonll (uint64_t input) +static inline u32 +hicn_conditional_swap_u32 (u32 value) { - return (ntohll (input)); +#ifdef HICN_LITTLE_ENDIAN_ARCH + value = __builtin_bswap32 (value); +#endif + + return value; } + +static inline u64 +hicn_conditional_swap_u64 (u64 value) +{ +#ifdef HICN_LITTLE_ENDIAN_ARCH + value = __builtin_bswap64 (value); #endif -#define round_pow2(x, pow2) (((x) + (pow2) -1) & ~((pow2) -1)) + return value; +} + +#define hicn_net_to_host_16(x) hicn_conditional_swap_u16 ((u16) (x)) +#define hicn_net_to_host_32(x) hicn_conditional_swap_u32 ((u32) (x)) +#define hicn_net_to_host_64(x) hicn_conditional_swap_u64 ((u64) (x)) + +#define hicn_host_to_net_16(x) hicn_conditional_swap_u16 ((u16) (x)) +#define hicn_host_to_net_32(x) hicn_conditional_swap_u32 ((u32) (x)) +#define hicn_host_to_net_64(x) hicn_conditional_swap_u64 ((u64) (x)) + +#define hicn_round_pow2(x, pow2) (((x) + (pow2) -1) & ~((pow2) -1)) -#define _SIZEOF_ALIGNED(x, size) round_pow2 (sizeof (x), size) +#define _SIZEOF_ALIGNED(x, size) hicn_round_pow2 (sizeof (x), size) #define SIZEOF_ALIGNED(x) _SIZEOF_ALIGNED (x, sizeof (void *)) /* Definitions for builtins unavailable on MSVC */ @@ -336,6 +323,7 @@ uint32_t __inline __builtin_clzl2 (uint64_t value) #endif #define next_pow2(x) (x <= 1 ? 1 : 1ul << (64 - __builtin_clzl (x - 1))) +#define _unused(x) ((void) (x)) #endif /* HICN_COMMON_H */ diff --git a/lib/includes/hicn/compat.h b/lib/includes/hicn/compat.h deleted file mode 100644 index 98c035b57..000000000 --- a/lib/includes/hicn/compat.h +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file compat.h - * @brief Implementation of the compatibility layer. - * - * The structure of the core API has evolved to support operations of a variety - * of packet formats in addition to IPv4/TCP and IPv6/TCP, namely with the use - * of ICMP for signalization and AH headers for integrity. The new API format - * has been designed to scale better with the multiplicity of packet formats, - * and provide a unified interface on top. We maintain an interface for the - * former API in this file, which mainly acts as a wrapper on top of new calls. - */ -#ifndef HICN_COMPAT_H -#define HICN_COMPAT_H - -#include "common.h" -#include "header.h" -#include "name.h" - -/* HICN format options */ -#define HFO_INET 1 << 0 -#define HFO_INET6 1 << 1 -#define HFO_TCP 1 << 2 -#define HFO_UDP 1 << 3 -#define HFO_ICMP 1 << 4 -#define HFO_CMPR 1 << 5 -#define HFO_AH 1 << 6 - -#define _is_ipv4(format) ((format & HFO_INET)) -#define _is_ipv6(format) ((format & HFO_INET6) >> 1) -#define _is_tcp(format) ((format & HFO_TCP) >> 2) -#define _is_udp(format) ((format & HFO_UDP) >> 3) -#define _is_icmp(format) ((format & HFO_ICMP) >> 4) -#define _is_cmpr(format) ((format & HFO_CMPR) >> 5) -#define _is_ah(format) ((format & HFO_AH) >> 6) - -typedef enum -{ - HF_UNSPEC = 0, - HF_INET_TCP = HFO_INET | HFO_TCP, - HF_INET6_TCP = HFO_INET6 | HFO_TCP, - HF_INET_ICMP = HFO_INET | HFO_ICMP, - HF_INET6_ICMP = HFO_INET6 | HFO_ICMP, - HF_NEW = HFO_CMPR, - HF_INET_UDP = HFO_INET | HFO_UDP | HFO_CMPR, - HF_INET6_UDP = HFO_INET6 | HFO_UDP | HFO_CMPR, - HF_INET_TCP_AH = HFO_INET | HFO_TCP | HFO_AH, - HF_INET6_TCP_AH = HFO_INET6 | HFO_TCP | HFO_AH, - HF_INET_ICMP_AH = HFO_INET | HFO_ICMP | HFO_AH, - HF_INET6_ICMP_AH = HFO_INET6 | HFO_ICMP | HFO_AH, - HF_NEW_AH = HFO_CMPR | HFO_AH, - HF_INET_UDP_AH = HFO_INET | HFO_UDP | HFO_CMPR | HFO_AH, - HF_INET6_UDP_AH = HFO_INET6 | HFO_UDP | HFO_CMPR | HFO_AH, -} hicn_format_t; - -/** - * @brief Add AH header to current format. E.g. if format is IP + TCP, this - * will change it to IP = TCP + AH - * - * @param [in] format - The input format - * @return The format with the AH bit set to 1 - */ -static inline hicn_format_t -hicn_get_ah_format (hicn_format_t format) -{ - return (hicn_format_t) (format | HFO_AH); -} - -/** - * Minimum required header length to determine the type and length of a - * supposed hICN packet. This should be equal to the maximum value over all - * possible hICN packet formats, and less than the minimum possible IP packet - * size. - */ -#define HICN_V6_MIN_HDR_LEN 6 /* bytes */ -#define HICN_V4_MIN_HDR_LEN 4 /* bytes */ - -// #define HICN_MIN_HDR_LEN ((HICN_V6_MIN_HDR_LEN > HICN_V4_MIN_HDR_LEN) ? -// HICN_V6_MIN_HDR_LEN : HICN_V4_MIN_HDR_LEN) -#define HICN_MIN_HDR_LEN HICN_V6_MIN_HDR_LEN - -hicn_type_t hicn_header_to_type (const hicn_header_t *h); - -/** - * @brief Parse packet headers and return hICN format - * @param [in] format - hICN Format - * @param [in, out] packet - Buffer containing the hICN header to be - * initialized - * @return hICN error code - */ -int hicn_packet_init_header (hicn_format_t format, hicn_header_t *packet); - -/** - * @brief Parse packet headers and return hICN format - * @param [in] h - hICN header - * @param [out] format - hICN format - * @return hICN error code - */ -int hicn_packet_get_format (const hicn_header_t *packet, - hicn_format_t *format); - -/** - * @brief Update checksums in packet headers - * @param [in] format - hICN format - * @param [in,out] packet - packet header - * @return hICN error code - */ -int hicn_packet_compute_checksum (hicn_format_t format, hicn_header_t *packet); - -/** - * @brief compute the checksum of the packet header, adding init_sum to the - * final value - * @param [in] format - hICN format - * @param [in,out] packet - packet header - * @param [in] init_sum - value to add to the final checksum - * @return hICN error code - */ -int hicn_packet_compute_header_checksum (hicn_format_t format, - hicn_header_t *packet, u16 init_sum); - -/** - * @brief Verify checksums in packet headers - * @param [in] format - hICN format - * @param [in,out] packet - packet header - * @return hICN error code - */ -int hicn_packet_check_integrity_no_payload (hicn_format_t format, - hicn_header_t *packet, - u16 init_sum); - -// this is not accounted here -/** - * @brief Return total length of hicn headers (but signature payload) - * @param [in] format - hICN format - * @param [out] header_length - Total length of headers - * @return hICN error code - */ -int hicn_packet_get_header_length_from_format (hicn_format_t format, - size_t *header_length); - -/** - * @brief Return total length of hicn headers (before payload) - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] header_length - Total length of headers - * @return hICN error code - */ -int hicn_packet_get_header_length (hicn_format_t format, - const hicn_header_t *packet, - size_t *header_length); - -/** - * @brief Return payload length - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] payload_length - payload length - * @return hICN error code - */ -int hicn_packet_get_payload_length (hicn_format_t format, - const hicn_header_t *packet, - size_t *payload_length); - -/** - * @brief Sets payload length - * @param [in] format - hICN format - * @param [in,out] packet - packet header - * @param [in] payload_length - payload length - * @return hICN error code - */ -int hicn_packet_set_payload_length (hicn_format_t format, - hicn_header_t *packet, - const size_t payload_length); - -/** - * @brief Compare two hICN packets - * @param [in] packet_1 - First packet - * @param [in] packet_2 - Second packet - * @return 0 if both packets are considered equal, any other value otherwise. - */ -int hicn_packet_compare (const hicn_header_t *packet1, - const hicn_header_t *packet2); - -/** - * @brief Retrieve the name of an interest/data packet - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] name - name holding the result - * @param [in] is_interest - Flag to determine whether it is an interest (1) or - * data packet (0) - * @return hICN error code - */ -int hicn_packet_get_name (hicn_format_t format, const hicn_header_t *packet, - hicn_name_t *name, u8 is_interest); - -/** - * @brief Sets the name of an interest/data packet - * @param [in] format - hICN format - * @param [in,out] packet - packet header - * @param [in] name - name to set into packet - * @param [in] is_interest - Flag to determine whether it is an interest (1) or - * data packet (0) - * @return hICN error code - */ -int hicn_packet_set_name (hicn_format_t format, hicn_header_t *packet, - const hicn_name_t *name, u8 is_interest); - -/** - * @brief Sets the payload of a packet - * @param [in] format - hICN format - * @param [in,out] packet - packet header - * @param [in] payload - payload to set - * @param [in] payload_length - size of the payload to set - * @return hICN error code - * - * NOTE: - * - The buffer holding payload is assumed sufficiently large - * - This function updates header fields with the new length, but no checksum. - */ -int hicn_packet_set_payload (hicn_format_t format, hicn_header_t *packet, - const u8 *payload, u16 payload_length); - -/** - * @brief Retrieves the payload of a packet - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] payload - pointer to buffer for storing the result - * @param [out] payload_length - size of the retreived payload - * @param [in] hard_copy - Flag : if true (eg. 1), a copy of the payload is - * made into the payload buffer, otherwise (0) the pointer is changed to point - * to the payload offset in the packet. - * @return hICN error code - * - * NOTE: - * - The buffer holding payload is assumed sufficiently large - */ -int hicn_packet_get_payload (hicn_format_t format, const hicn_header_t *packet, - u8 **payload, size_t *payload_size, - bool hard_copy); - -/** - * @brief Retrieve the locator of an interest / data packet - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] ip_address - retrieved locator - * @param [in] is_interest - Flag to determine whether it is an interest (1) or - * data packet (0) - * @return hICN error code - */ -int hicn_packet_get_locator (hicn_format_t format, const hicn_header_t *packet, - ip_address_t *prefix, bool is_interest); - -/** - * @brief Sets the locator of an interest / data packet - * @param [in] format - hICN format - * @param [in,out] packet - packet header - * @param [out] ip_address - retrieved locator - * @param [in] is_interest - Flag to determine whether it is an interest (1) or - * data packet (0) - * @return hICN error code - */ -int hicn_packet_set_locator (hicn_format_t format, hicn_header_t *packet, - const ip_address_t *prefix, bool is_interest); - -/** - * @brief Retrieves the signature size - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] bytes - Retrieved signature size - * @return hICN error code - */ -int hicn_packet_get_signature_size (hicn_format_t format, - const hicn_header_t *packet, - size_t *bytes); - -/** - * @brief Sets the signature size - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [in] bytes - Retrieved signature size - * @return hICN error code - */ -int hicn_packet_set_signature_size (hicn_format_t format, - hicn_header_t *packet, size_t bytes); - -/** - * @brief Sets the signature size - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [in] signature_timestamp - Signature timestamp to set - * @return hICN error code - */ -int hicn_packet_set_signature_timestamp (hicn_format_t format, - hicn_header_t *h, - uint64_t signature_timestamp); - -/** - * @brief Sets the signature size - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] signature_timestamp - Retrieved signature timestamp - * @return hICN error code - */ -int hicn_packet_get_signature_timestamp (hicn_format_t format, - const hicn_header_t *h, - uint64_t *signature_timestamp); - -/** - * @brief Sets the signature size - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [in] validation_algorithm - Validation algorithm to set - * @return hICN error code - */ -int hicn_packet_set_validation_algorithm (hicn_format_t format, - hicn_header_t *h, - uint8_t validation_algorithm); - -/** - * @brief Sets the signature size - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] validation_algorithm - Retrieved validation algorithm - * @return hICN error code - */ -int hicn_packet_get_validation_algorithm (hicn_format_t format, - const hicn_header_t *h, - uint8_t *validation_algorithm); - -/** - * @brief Sets the signature size - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [in] key_id - Key id to set - * @return hICN error code - */ -int hicn_packet_set_key_id (hicn_format_t format, hicn_header_t *h, - uint8_t *key_id); - -/** - * @brief Sets the signature size - * @param [in] format - hICN format - * @param [in] packet - packet header - * @param [out] key_id - Retrieved key id - * @return hICN error code - */ -int hicn_packet_get_key_id (hicn_format_t format, hicn_header_t *h, - uint8_t **key_id, uint8_t *key_id_length); - -/** - * @brief Retrieves the packet hop limit - * @param [in] packet - packet header - * @param [out] hops - Retrieved hop limit - * @return hICN error code - */ -int hicn_packet_get_hoplimit (const hicn_header_t *packet, u8 *hops); - -/** - * @brief Sets the packet hop limit - * @param [in] packet - packet header - * @param [in] hops - Hop limit to set - * @return hICN error code - */ -int hicn_packet_set_hoplimit (hicn_header_t *packet, u8 hops); - -/** - * @brief Check if this packet is interest - * - * @param format - hICN format - * @param packet - Packet header - * @return hICN error code - */ -int hicn_packet_is_interest (hicn_format_t format, const hicn_header_t *h, - int *ret); - -/** - * @brief Mark this packet as interest - * - * @param format - hICN format - * @param packet - Packet header - * @return hICN error code - */ -int hicn_packet_set_interest (hicn_format_t format, hicn_header_t *packet); - -/** - * @brief Mark this packet as data - * - * @param format - hICN format - * @param packet - Packet header - * @return hICN error code - */ -int hicn_packet_set_data (hicn_format_t format, hicn_header_t *h); - -int hicn_packet_copy_header (hicn_format_t format, const hicn_header_t *packet, - hicn_header_t *destination, bool copy_ah); - -int hicn_packet_get_lifetime (hicn_format_t format, - const hicn_header_t *packet, u32 *lifetime); -int hicn_packet_set_lifetime (hicn_format_t format, hicn_header_t *packet, - u32 lifetime); -int hicn_packet_get_reserved_bits (const hicn_header_t *packet, - u8 *reserved_bits); -int hicn_packet_set_reserved_bits (hicn_header_t *packet, - const u8 reserved_bits); -int hicn_packet_get_payload_type (hicn_format_t format, - const hicn_header_t *packet, - hicn_payload_type_t *payload_type); -int hicn_packet_set_payload_type (hicn_format_t format, hicn_header_t *packet, - const hicn_payload_type_t payload_type); - -int hicn_packet_set_syn (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_reset_syn (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_test_syn (hicn_format_t format, const hicn_header_t *packet, - bool *flag); -int hicn_packet_set_ack (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_reset_ack (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_test_ack (hicn_format_t format, const hicn_header_t *packet, - bool *flag); -int hicn_packet_set_rst (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_reset_rst (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_test_rst (hicn_format_t format, const hicn_header_t *packet, - bool *flag); -int hicn_packet_set_fin (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_reset_fin (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_test_fin (hicn_format_t format, const hicn_header_t *packet, - bool *flag); -int hicn_packet_set_ece (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_reset_ece (hicn_format_t format, hicn_header_t *packet); -int hicn_packet_test_ece (hicn_format_t format, const hicn_header_t *packet, - bool *flag); - -int hicn_packet_set_src_port (hicn_format_t format, hicn_header_t *packet, - u16 src_port); -int hicn_packet_get_src_port (hicn_format_t format, - const hicn_header_t *packet, u16 *src_port); -int hicn_packet_set_dst_port (hicn_format_t format, hicn_header_t *packet, - u16 dst_port); -int hicn_packet_get_dst_port (hicn_format_t format, - const hicn_header_t *packet, u16 *dst_port); -int hicn_packet_get_signature (hicn_format_t format, hicn_header_t *packet, - uint8_t **sign_buf); - -/* Interest */ -int hicn_interest_get_name (hicn_format_t format, - const hicn_header_t *interest, hicn_name_t *name); -int hicn_interest_set_name (hicn_format_t format, hicn_header_t *interest, - const hicn_name_t *name); -int hicn_interest_get_locator (hicn_format_t format, - const hicn_header_t *interest, - ip_address_t *prefix); -int hicn_interest_set_locator (hicn_format_t format, hicn_header_t *interest, - const ip_address_t *prefix); -int hicn_interest_compare (const hicn_header_t *interest_1, - const hicn_header_t *interest_2); -int hicn_interest_set_lifetime (hicn_header_t *interest, u32 lifetime); -int hicn_interest_get_lifetime (const hicn_header_t *interest, u32 *lifetime); -int hicn_interest_get_header_length (hicn_format_t format, - const hicn_header_t *interest, - size_t *header_length); -int hicn_interest_get_payload_length (hicn_format_t format, - const hicn_header_t *interest, - size_t *payload_length); -int hicn_interest_set_payload (hicn_format_t format, hicn_header_t *interest, - const u8 *payload, size_t payload_length); -int hicn_interest_get_payload (hicn_format_t format, - const hicn_header_t *interest, u8 **payload, - size_t *payload_size, bool hard_copy); -int hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t *packet); - -/* Data */ - -int hicn_data_get_name (hicn_format_t format, const hicn_header_t *data, - hicn_name_t *name); -int hicn_data_set_name (hicn_format_t format, hicn_header_t *data, - const hicn_name_t *name); -int hicn_data_get_locator (hicn_format_t format, const hicn_header_t *data, - ip_address_t *prefix); -int hicn_data_set_locator (hicn_format_t format, hicn_header_t *data, - const ip_address_t *prefix); -int hicn_data_compare (const hicn_header_t *data_1, - const hicn_header_t *data_2); -int hicn_data_get_expiry_time (const hicn_header_t *data, u32 *expiry_time); -int hicn_data_set_expiry_time (hicn_header_t *data, u32 expiry_time); -int hicn_data_get_header_length (hicn_format_t format, hicn_header_t *data, - size_t *header_length); -int hicn_data_get_payload_length (hicn_format_t format, - const hicn_header_t *data, - size_t *payload_length); -int hicn_data_get_path_label (const hicn_header_t *data, u32 *path_label); -int hicn_data_set_path_label (hicn_header_t *data, u32 path_label); -int hicn_data_get_payload (hicn_format_t format, const hicn_header_t *data, - u8 **payload, size_t *payload_size, bool hard_copy); -int hicn_data_set_payload (hicn_format_t format, hicn_header_t *data, - const u8 *payload, size_t payload_length); -int hicn_data_get_payload_type (const hicn_header_t *data, - hicn_payload_type_t *payload_type); -int hicn_data_set_payload_type (hicn_header_t *data, - hicn_payload_type_t payload_type); -int hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet); -int hicn_data_is_last (hicn_format_t format, hicn_header_t *h, int *is_last); -int hicn_data_set_last (hicn_format_t format, hicn_header_t *h); - -int hicn_packet_get_signature_padding (hicn_format_t format, - const hicn_header_t *h, size_t *bytes); -int hicn_packet_set_signature_padding (hicn_format_t format, hicn_header_t *h, - size_t bytes); - -#endif /* HICN_COMPAT_H */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/lib/includes/hicn/error.h b/lib/includes/hicn/error.h index d769ef693..9926c9cd8 100644 --- a/lib/includes/hicn/error.h +++ b/lib/includes/hicn/error.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -47,6 +47,8 @@ typedef enum extern const char *HICN_LIB_ERROR_STRING[]; +#define HICN_LIB_IS_ERROR(rc) (rc < 0) + #define hicn_strerror(errno) (char *) (HICN_LIB_ERROR_STRING[-errno]) #endif /* HICN_ERROR_H */ diff --git a/lib/includes/hicn/face.h b/lib/includes/hicn/face.h index 31906afab..fbdacec5f 100644 --- a/lib/includes/hicn/face.h +++ b/lib/includes/hicn/face.h @@ -37,6 +37,7 @@ /* Netdevice type */ #include <net/if.h> // IFNAMSIZ +#include "base.h" #define foreach_netdevice_type \ _ (UNDEFINED) \ @@ -58,10 +59,17 @@ typedef enum #undef _ } netdevice_type_t; +typedef uint32_t netdevice_flags_t; +#define NETDEVICE_FLAGS_EMPTY 0 +#define netdevice_flags_clear(F) (F = 0) +#define netdevice_flags_add(F, T) ((F) |= 1 << (T)) +#define netdevice_flags_remove(F, T) ((F) &= ~(1 << (T))) +#define netdevice_flags_has(F, T) ((F) & (1 << (T))) + extern const char *_netdevice_type_str[]; #define netdevice_type_str(x) _netdevice_type_str[x] -#define NETDEVICE_INVALID_INDEX ~0 +#define INVALID_NETDEVICE_ID ~0 /* Netdevice */ @@ -97,6 +105,7 @@ int netdevice_set_name (netdevice_t *netdevice, const char *name); int netdevice_update_index (netdevice_t *netdevice); int netdevice_update_name (netdevice_t *netdevice); int netdevice_cmp (const netdevice_t *nd1, const netdevice_t *nd2); +bool netdevice_is_empty (const netdevice_t *netdevice); #define NETDEVICE_UNDEFINED_INDEX 0 @@ -175,9 +184,12 @@ face_type_t face_type_from_str (const char *str); /* Face */ typedef u32 face_id_t; +#define INVALID_FACE_ID ~0 typedef struct { + face_id_t id; + char name[SYMBOLIC_NAME_LEN]; face_type_t type; face_state_t admin_state; face_state_t state; @@ -191,16 +203,16 @@ typedef struct */ netdevice_t netdevice; int family; /* To access family independently of face type */ - ip_address_t local_addr; - ip_address_t remote_addr; + hicn_ip_address_t local_addr; + hicn_ip_address_t remote_addr; u16 local_port; u16 remote_port; } face_t; int face_initialize (face_t *face); int face_initialize_udp (face_t *face, const char *interface_name, - const ip_address_t *local_addr, u16 local_port, - const ip_address_t *remote_addr, u16 remote_port, + const hicn_ip_address_t *local_addr, u16 local_port, + const hicn_ip_address_t *remote_addr, u16 remote_port, int family); int face_initialize_udp_sa (face_t *face, const char *interface_name, const struct sockaddr *local_addr, @@ -208,8 +220,8 @@ int face_initialize_udp_sa (face_t *face, const char *interface_name, face_t *face_create (); face_t *face_create_udp (const char *interface_name, - const ip_address_t *local_addr, u16 local_port, - const ip_address_t *remote_addr, u16 remote_port, + const hicn_ip_address_t *local_addr, u16 local_port, + const hicn_ip_address_t *remote_addr, u16 remote_port, int family); face_t *face_create_udp_sa (const char *interface_name, const struct sockaddr *local_addr, diff --git a/lib/includes/hicn/header.h b/lib/includes/hicn/header.h deleted file mode 100644 index 208e35d68..000000000 --- a/lib/includes/hicn/header.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file header.h - * @brief hICN header data structures. - * - * NOTE: These structures are used as convenient facade for accessing - * the encapsulated headers. They are not written taking compiler padding - * into account, then a sizeof() on these struct could not give the expected - * result. For accessing the size of the hicn headers use the macros at the end - * of this file. - */ - -#ifndef HICN_HEADER_H -#define HICN_HEADER_H - -#include "common.h" -#include "protocol.h" - -typedef struct -{ - _ipv6_header_t ip; - union - { - _tcp_header_t tcp; - struct - { - _udp_header_t udp; - _new_header_t newhdr; - }; - _icmp_header_t icmp; - _icmp_wldr_header_t wldr; - }; -} hicn_v6_hdr_t; - -typedef struct -{ - _ipv6_header_t ip; - union - { - struct - { - _tcp_header_t tcp; - _ah_header_t ah; - }; - struct - { - _udp_header_t udp; - _new_header_t newhdr; - _ah_header_t udp_ah; - }; - struct - { - _icmp_header_t icmp; - _ah_header_t icmp_ah; - }; - }; -} hicn_v6ah_hdr_t; - -// For ipv4 we need to use packed structs as fields may be aligned to 64 bits -// (So for instance tcp header may start at byte #24 instead of byte 20) -typedef PACKED (struct { - _ipv4_header_t ip; - union - { - _tcp_header_t tcp; - struct - { - _udp_header_t udp; - _new_header_t newhdr; - }; - _icmp_header_t icmp; - _icmp_wldr_header_t wldr; - }; -}) hicn_v4_hdr_t; - -typedef PACKED (struct { - _ipv4_header_t ip; - union - { - struct - { - _tcp_header_t tcp; - _ah_header_t ah; - }; - struct - { - _udp_header_t udp; - _new_header_t newhdr; - _ah_header_t udp_ah; - }; - struct - { - _icmp_header_t icmp; - _ah_header_t icmp_ah; - }; - }; -}) hicn_v4ah_hdr_t; - -typedef union -{ - /* To deprecate as redundant with hicn_type_t */ - hicn_v6_hdr_t v6; - hicn_v6ah_hdr_t v6ah; - hicn_v4_hdr_t v4; - hicn_v4ah_hdr_t v4ah; - - hicn_protocol_t protocol; -} hicn_header_t; - -#define HICN_V6_TCP_HDRLEN (IPV6_HDRLEN + TCP_HDRLEN) -#define HICN_V6_ICMP_HDRLEN (IPV6_HDRLEN + ICMP_HDRLEN) -#define HICN_V6_WLDR_HDRLEN (IPV6_HDRLEN + ICMPWLDR_HDRLEN) - -#define HICN_V6_TCP_AH_HDRLEN (HICN_V6_TCP_HDRLEN + AH_HDRLEN) -#define HICN_V6_ICMP_AH_HDRLEN (HICN_V6_ICMP_HDRLEN + AH_HDRLEN) - -#define HICN_V4_TCP_HDRLEN (IPV4_HDRLEN + TCP_HDRLEN) -#define HICN_V4_ICMP_HDRLEN (IPV4_HDRLEN + ICMP_HDRLEN) -#define HICN_V4_WLDR_HDRLEN (IPV4_HDRLEN + ICMPWLDR_HDRLEN) - -#define HICN_V4_TCP_AH_HDRLEN (HICN_V4_TCP_HDRLEN + AH_HDRLEN) -#define HICN_V4_ICMP_AH_HDRLEN (HICN_V4_ICMP_HDRLEN + AH_HDRLEN) - -#define HICN_DEFAULT_PORT 9695 - -#endif /* HICN_HEADER_H */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/lib/includes/hicn/hicn.h b/lib/includes/hicn/hicn.h index 4a5b4dd56..5e67d83a0 100644 --- a/lib/includes/hicn/hicn.h +++ b/lib/includes/hicn/hicn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -29,6 +29,14 @@ * Recovery (WLDR) [2], Anchorless Mobility Management (hICN-AMM) [3], * including MAP-Me producer mobility mechanisms [4]. * + * Other hICN constructs such as faces, policies and stategies are not included + * in this header, but available separately in : + * - hicn/face.h + * - hicn/policy.h + * - hicn/strategy.h + * + * REFERENCES + * * [1] Hybrid Information-Centric Networking * L. Muscariello, G. Carofiglio, J. Augé, M. Papalini * IETF draft (intarea) @ @@ -52,22 +60,21 @@ #ifndef HICN__H #define HICN__H -#ifdef HICN_VPP_PLUGIN +/* Base data structures */ +#include <hicn/base.h> -#include <hicn/header.h> +/* Names */ #include <hicn/name.h> -#include <hicn/ops.h> -#include <hicn/mapme.h> -#else +/* Packet operations */ +#include <hicn/packet.h> -#include <hicn/error.h> -#include <hicn/header.h> -#include <hicn/name.h> -#include <hicn/ops.h> +/* MAP-Me : mobility management operations */ #include <hicn/mapme.h> -#include <hicn/compat.h> +/* Error management */ +#ifndef HICN_VPP_PLUGIN +#include <hicn/error.h> #endif #endif /* HICN__H */ diff --git a/lib/includes/hicn/interest_manifest.h b/lib/includes/hicn/interest_manifest.h new file mode 100644 index 000000000..2b4cd57a2 --- /dev/null +++ b/lib/includes/hicn/interest_manifest.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HICNLIGHT_INTEREST_MANIFEST_H +#define HICNLIGHT_INTEREST_MANIFEST_H + +#include <string.h> +#include <stdbool.h> + +#include <hicn/util/bitmap.h> +#include <hicn/base.h> +#include <hicn/name.h> +#include <hicn/common.h> + +typedef enum +{ + INT_MANIFEST_SPLIT_STRATEGY_NONE, + INT_MANIFEST_SPLIT_STRATEGY_MAX_N_SUFFIXES, + INT_MANIFEST_SPLIT_N_STRATEGIES, +} int_manifest_split_strategy_t; + +#define MAX_SUFFIXES_IN_MANIFEST 256 + +#define DEFAULT_DISAGGREGATION_STRATEGY \ + INT_MANIFEST_SPLIT_STRATEGY_MAX_N_SUFFIXES +#define DEFAULT_N_SUFFIXES_PER_SPLIT MAX_SUFFIXES_IN_MANIFEST + +#define BITMAP_SIZE (MAX_SUFFIXES_IN_MANIFEST / WORD_WIDTH) + +typedef struct +{ + /* This can be 16 bits, but we use 32 bits for alignment */ + uint32_t n_suffixes; + + /* Align to 64 bits */ + uint32_t padding; + + hicn_uword request_bitmap[BITMAP_SIZE]; + + /* Followed by the list of prefixes to ask */ + /* ... */ +} interest_manifest_header_t; + +static_assert (sizeof (interest_manifest_header_t) == 32 + 4 + 4, + "interest_manifest_header_t size must be exactly 40 bytes"); + +#define _interest_manifest_serialize_deserialize(manifest, first, second, \ + size, serialize) \ + do \ + { \ + u32 n_suffixes = 0; \ + if (serialize) \ + n_suffixes = int_manifest_header->n_suffixes; \ + \ + int_manifest_header->n_suffixes = \ + hicn_##first##_to_##second##_32 (int_manifest_header->n_suffixes); \ + int_manifest_header->padding = \ + hicn_##first##_to_##second##_32 (int_manifest_header->padding); \ + \ + for (unsigned i = 0; i < BITMAP_SIZE; i++) \ + { \ + int_manifest_header->request_bitmap[i] = \ + hicn_##first##_to_##second##_##size ( \ + int_manifest_header->request_bitmap[i]); \ + } \ + \ + hicn_name_suffix_t *suffix = \ + (hicn_name_suffix_t *) (int_manifest_header + 1); \ + if (!serialize) \ + n_suffixes = int_manifest_header->n_suffixes; \ + for (unsigned i = 0; i < n_suffixes; i++) \ + { \ + *(suffix + i) = hicn_##first##_to_##second##_32 (*(suffix + i)); \ + } \ + } \ + while (0) + +#define _interest_manifest_serialize(manifest, size) \ + _interest_manifest_serialize_deserialize (manifest, host, net, size, 1) + +#define _interest_manifest_deserialize(manifest, size) \ + _interest_manifest_serialize_deserialize (manifest, net, host, size, 0) + +static inline void +interest_manifest_serialize (interest_manifest_header_t *int_manifest_header) +{ + _interest_manifest_serialize (int_manifest_header, hicn_uword_bits); +} + +static inline void +interest_manifest_deserialize (interest_manifest_header_t *int_manifest_header) +{ + _interest_manifest_deserialize (int_manifest_header, hicn_uword_bits); +} + +static inline bool +interest_manifest_is_valid (interest_manifest_header_t *int_manifest_header, + size_t payload_length) +{ + if (int_manifest_header->n_suffixes == 0 || + int_manifest_header->n_suffixes > MAX_SUFFIXES_IN_MANIFEST) + { + return false; + } + + hicn_uword empty_bitmap[BITMAP_SIZE] = { 0 }; + if (memcmp (empty_bitmap, int_manifest_header->request_bitmap, + sizeof (empty_bitmap)) == 0) + { + return false; + } + + if (payload_length - sizeof (interest_manifest_header_t) != + int_manifest_header->n_suffixes * sizeof (u32)) + { + return false; + } + + return true; +} + +static inline void +interest_manifest_init (interest_manifest_header_t *int_manifest_header) +{ + int_manifest_header->n_suffixes = 0; + int_manifest_header->padding = 0; + memset (int_manifest_header->request_bitmap, 0, + sizeof (int_manifest_header->request_bitmap)); +} + +static inline void +interest_manifest_add_suffix (interest_manifest_header_t *int_manifest_header, + hicn_name_suffix_t suffix) +{ + hicn_name_suffix_t *start = (hicn_name_suffix_t *) (int_manifest_header + 1); + *(start + int_manifest_header->n_suffixes) = suffix; + hicn_uword *request_bitmap = int_manifest_header->request_bitmap; + bitmap_set_no_check (request_bitmap, int_manifest_header->n_suffixes); + int_manifest_header->n_suffixes++; +} + +static inline void +interest_manifest_del_suffix (interest_manifest_header_t *int_manifest_header, + hicn_uword pos) +{ + bitmap_unset_no_check (int_manifest_header->request_bitmap, pos); +} + +static inline size_t +interest_manifest_update_bitmap (const hicn_uword *initial_bitmap, + hicn_uword *bitmap_to_update, size_t start, + size_t n, size_t max_suffixes) +{ + size_t i = start, n_ones = 0; + while (i < n) + { + if (bitmap_is_set_no_check (initial_bitmap, i)) + { + bitmap_set_no_check (bitmap_to_update, i); + n_ones++; + } + i++; + + if (n_ones == max_suffixes) + break; + } + + return i; +} + +#define _FIRST(h) (hicn_name_suffix_t *) (h + 1) + +#define interest_manifest_foreach_suffix(header, suffix) \ + for (suffix = _FIRST (header) + bitmap_first_set_no_check ( \ + header->request_bitmap, BITMAP_SIZE); \ + suffix - _FIRST (header) < header->n_suffixes; \ + suffix = _FIRST (header) + \ + bitmap_next_set_no_check (header->request_bitmap, \ + suffix - _FIRST (header) + 1, \ + BITMAP_SIZE)) + +#endif /* HICNLIGHT_INTEREST_MANIFEST_H */ diff --git a/lib/includes/hicn/mapme.h b/lib/includes/hicn/mapme.h index 63a5cd77e..b452a5dde 100644 --- a/lib/includes/hicn/mapme.h +++ b/lib/includes/hicn/mapme.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -23,9 +23,9 @@ #include <stdint.h> // u32 #include <stdbool.h> +#include <hicn/name.h> + #include "common.h" -#include "protocol.h" -#include "ops.h" /** * @brief MAP-Me configuration options @@ -114,51 +114,11 @@ int hicn_mapme_parse_packet (const u8 *packet, hicn_prefix_t *prefix, /* Default TTL */ #define HICN_MAPME_TTL 255 // typical for redirect (ref?) -/* - * The length of the MAPME4 header struct must be 120 bytes. - */ -#define EXPECTED_MAPME_V4_HDRLEN 120 - -/** @brief MAP-Me packet header for IPv4 */ -typedef struct -{ - _ipv4_header_t ip; - _icmprd4_header_t icmp_rd; - seq_t seq; - u8 len; - u8 _pad[3]; -} hicn_mapme_v4_header_t; +/* Should be moved to mapme.c, but header size still in use in VPP */ -/* - * The length of the MAPME4 header struct must be bytes. - */ +#define EXPECTED_MAPME_V4_HDRLEN 120 #define EXPECTED_MAPME_V6_HDRLEN 88 -/** @brief MAP-Me packet header for IPv6 */ -typedef struct -{ - _ipv6_header_t ip; - _icmprd_header_t icmp_rd; - seq_t seq; - u8 len; - u8 _pad[3]; -} hicn_mapme_v6_header_t; - -/** @brief MAP-Me packet header (IP version agnostic) */ -typedef union -{ - hicn_mapme_v4_header_t v4; - hicn_mapme_v6_header_t v6; -} hicn_mapme_header_t; - -#define HICN_MAPME_V4_HDRLEN sizeof (hicn_mapme_v4_header_t) -#define HICN_MAPME_V6_HDRLEN sizeof (hicn_mapme_v6_header_t) - -static_assert (EXPECTED_MAPME_V4_HDRLEN == HICN_MAPME_V4_HDRLEN, - "Size of MAPME_V4 struct does not match its expected size."); -static_assert (EXPECTED_MAPME_V6_HDRLEN == HICN_MAPME_V6_HDRLEN, - "Size of MAPME_V6 struct does not match its expected size."); - #endif /* HICN_MAPME_H */ /* diff --git a/lib/includes/hicn/name.h b/lib/includes/hicn/name.h index f85b0bc3f..895b86341 100644 --- a/lib/includes/hicn/name.h +++ b/lib/includes/hicn/name.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -24,12 +24,14 @@ #ifndef HICN_NAME_H #define HICN_NAME_H +#include <assert.h> #include <stdbool.h> +#include <stddef.h> #ifndef _WIN32 #include <netinet/in.h> // struct sockadd #endif +#include <hicn/common.h> #include <hicn/util/ip_address.h> -#include "common.h" /****************************************************************************** * hICN names @@ -38,40 +40,92 @@ #define TCP_SEQNO_LEN 4 /* bytes */ #define HICN_V4_PREFIX_LEN IPV4_ADDR_LEN #define HICN_V6_PREFIX_LEN IPV6_ADDR_LEN -#define HICN_SEGMENT_LEN TCP_SEQNO_LEN + +#if 0 +#define HICN_SEGMENT_LEN TCP_SEQNO_LEN + #define HICN_V6_NAME_LEN \ (HICN_V6_PREFIX_LEN + HICN_SEGMENT_LEN) /* 20 bytes \ */ #define HICN_V4_NAME_LEN \ (HICN_V4_PREFIX_LEN + HICN_SEGMENT_LEN) /* 8 bytes \ */ +#endif + +#define HICN_INVALID_SUFFIX ((uint32_t) (~0)) /* Prefix */ -typedef u32 hicn_name_suffix_t; +#define HICN_PREFIX_MAX_LEN IP_ADDRESS_MAX_LEN typedef struct { - ip_address_t name; + hicn_ip_address_t name; u8 len; } hicn_prefix_t; +#define HICN_PREFIX_EMPTY \ + (hicn_prefix_t) { .name = IP_ADDRESS_EMPTY, .len = 0 } + +static inline const hicn_ip_address_t * +hicn_prefix_get_ip_address (const hicn_prefix_t *prefix) +{ + return &prefix->name; +} + +static inline u8 +hicn_prefix_get_len (const hicn_prefix_t *prefix) +{ + return prefix->len; +} + +int hicn_prefix_get_ip_prefix (const hicn_prefix_t *prefix, + hicn_ip_prefix_t *ip_prefix); /* * Name * * A name is a prefix + a segment name (suffix) */ +typedef hicn_ip_address_t hicn_name_prefix_t; +typedef uint32_t hicn_name_suffix_t; + +#define hicn_name_prefix_cmp hicn_ip_address_cmp +#define hicn_name_prefix_equals hicn_ip_address_equals +#define hicn_name_prefix_get_len_bits hicn_ip_address_get_len_bits +#define hicn_name_prefix_get_hash hicn_ip_address_get_hash +#define hicn_name_prefix_snprintf hicn_ip_address_snprintf +#define HICN_NAME_PREFIX_EMPTY IP_ADDRESS_EMPTY + typedef struct { - ip_address_t prefix; + hicn_name_prefix_t prefix; hicn_name_suffix_t suffix; } hicn_name_t; +static_assert (offsetof (hicn_name_t, prefix) == 0, ""); +static_assert (offsetof (hicn_name_t, suffix) == 16, ""); +static_assert (sizeof (hicn_name_t) == 20, ""); + +#define HICN_NAME_EMPTY \ + (hicn_name_t) { .prefix = HICN_NAME_PREFIX_EMPTY, .suffix = 0, } + +static inline const hicn_name_prefix_t * +hicn_name_get_prefix (const hicn_name_t *name) +{ + return &name->prefix; +} + +static inline const hicn_name_suffix_t +hicn_name_get_suffix (const hicn_name_t *name) +{ + return name->suffix; +} + #define _is_unspec(name) \ (((name)->prefix.pad[0] | (name)->prefix.pad[1] | (name)->prefix.pad[2] | \ (name)->prefix.v4.as_u32) == 0) -#define _is_inet4(name) (ip_address_is_v4 (&name->prefix)) +#define _is_inet4(name) (hicn_ip_address_is_v4 (&name->prefix)) #define _is_inet6(name) (!_is_inet4 (name)) /** @@ -86,11 +140,21 @@ int hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name); /** * @brief Create an hICN name from IP address * @param [in] ip_address - IP address - * @param [in] id Segment - identifier + * @param [in] suffix - Name suffix * @param [out] Resulting - hICN name * @return hICN error code */ -int hicn_name_create_from_ip_prefix (const ip_prefix_t *prefix, u32 id, +int hicn_name_create_from_ip_address (const hicn_ip_address_t ip_address, + u32 suffix, hicn_name_t *name); + +/** + * @brief Create an hICN name from IP prefix + * @param [in] prefix - IP prefix + * @param [in] suffix - Name suffix + * @param [out] Resulting - hICN name + * @return hICN error code + */ +int hicn_name_create_from_ip_prefix (const hicn_ip_prefix_t *prefix, u32 id, hicn_name_t *name); /** @@ -113,7 +177,10 @@ int hicn_name_compare (const hicn_name_t *name_1, const hicn_name_t *name_2, * @param [in] consider_suffix - Consider the suffix in the hash computation * @return hICN error code */ -int hicn_name_hash (const hicn_name_t *name, u32 *hash, bool consider_suffix); +uint32_t _hicn_name_get_hash (const hicn_name_t *name, bool consider_suffix); + +#define hicn_name_get_hash(NAME) _hicn_name_get_hash (NAME, true) +#define hicn_name_get_prefix_hash(NAME) _hicn_name_get_hash (NAME, false) /** * @brief Test whether an hICN name is empty @@ -146,7 +213,7 @@ int hicn_name_copy_prefix_to_destination (u8 *dst, const hicn_name_t *src); * @param [in] seq_number - Segment identifier * @return hICN error code */ -int hicn_name_set_seq_number (hicn_name_t *name, u32 seq_number); +int hicn_name_set_suffix (hicn_name_t *name, hicn_name_suffix_t suffix); /** * @brief Retrieves the segment part of an hICN name @@ -171,7 +238,8 @@ int hicn_name_to_sockaddr_address (const hicn_name_t *name, * @param [out] ip_address - Resulting IP address * @return hICN error code */ -int hicn_name_to_ip_prefix (const hicn_name_t *name, ip_prefix_t *ip_prefix); +int hicn_name_to_hicn_ip_prefix (const hicn_name_t *name, + hicn_ip_prefix_t *hicn_ip_prefix); /** * @brief Convert an hICN name to presentation format @@ -198,15 +266,50 @@ int hicn_name_pton (const char *src, hicn_name_t *dst); */ int hicn_name_get_family (const hicn_name_t *name, int *family); +bool hicn_name_is_v4 (const hicn_name_t *name); + +int hicn_name_snprintf (char *s, size_t size, const hicn_name_t *name); + +int hicn_name_cmp (const hicn_name_t *n1, const hicn_name_t *n2); +bool hicn_name_equals (const hicn_name_t *n1, const hicn_name_t *n2); + +#define MAXSZ_HICN_NAME MAXSZ_IP_ADDRESS + /** * @brief Creates an hICN prefix from an IP address * @param [in] ip_address - Input IP address * @param [out] prefix - Resulting prefix * @return hICN error code */ -int hicn_prefix_create_from_ip_prefix (const ip_prefix_t *ip_prefix, +int hicn_prefix_create_from_ip_prefix (const hicn_ip_prefix_t *hicn_ip_prefix, hicn_prefix_t *prefix); +int +hicn_prefix_create_from_ip_address_len (const hicn_ip_address_t *ip_address, + uint8_t len, hicn_prefix_t *prefix); + +hicn_prefix_t *hicn_prefix_dup (const hicn_prefix_t *prefix); + +int hicn_prefix_copy (hicn_prefix_t *dst, const hicn_prefix_t *src); + +bool hicn_prefix_is_v4 (const hicn_prefix_t *prefix); + +uint32_t hicn_prefix_lpm (const hicn_prefix_t *p1, const hicn_prefix_t *p2); + +void hicn_prefix_clear (hicn_prefix_t *prefix, uint8_t start_from); + +void hicn_prefix_truncate (hicn_prefix_t *prefix, uint8_t len); + +int hicn_prefix_cmp (const hicn_prefix_t *p1, const hicn_prefix_t *p2); + +bool hicn_prefix_equals (const hicn_prefix_t *p1, const hicn_prefix_t *p2); + +int hicn_prefix_snprintf (char *s, size_t size, const hicn_prefix_t *prefix); + +uint8_t hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos); + +#define MAXSZ_HICN_PREFIX MAXSZ_IP_PREFIX + #endif /* HICN_NAME_H */ /* diff --git a/lib/includes/hicn/ops.h b/lib/includes/hicn/ops.h deleted file mode 100644 index 4efef6523..000000000 --- a/lib/includes/hicn/ops.h +++ /dev/null @@ -1,1029 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file base.h - * @brief Protocol-independent packet operations - */ - -#ifndef HICN_OPS_H -#define HICN_OPS_H - -#include <stdlib.h> - -#include "common.h" -#include "error.h" -#include "header.h" -#include "name.h" - -/* - * hICN operations on packets - * - * All prototypes take an hicn_type_t parameter as their first argument, as - * this decides the sequence of protocols that are being used by the different - * operations. - */ - -typedef struct hicn_ops_s -{ - /** - * @brief Initialize the headers of the hicn packet - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the packet - */ - int (*init_packet_header) (hicn_type_t type, hicn_protocol_t *h); - - /** - * @brief Retrieves an Interest locator - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest packet - * @param [out] ip_address - Retrieved locator - * @return hICN error code - */ - int (*get_interest_locator) (hicn_type_t type, const hicn_protocol_t *h, - ip_address_t *ip_address); - - /** - * @brief Sets an Interest locator - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest packet - * @param [in] ip_address - Locator to set - * @return hICN error code - */ - int (*set_interest_locator) (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *ip_address); - - /** - * @brief Retrieves an Interest name - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest packet - * @param [out] name - Retrieved name - * @return hICN error code - */ - int (*get_interest_name) (hicn_type_t type, const hicn_protocol_t *h, - hicn_name_t *name); - - /** - * @brief Sets an Interest name - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest packet - * @param [in] name - Name to set - * @return hICN error code - */ - int (*set_interest_name) (hicn_type_t type, hicn_protocol_t *h, - const hicn_name_t *name); - - /** - * @brief Retrieves an Interest name suffix - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest packet - * @param [out] suffix - Retrieved name suffix - * @return hICN error code - */ - int (*get_interest_name_suffix) (hicn_type_t type, const hicn_protocol_t *h, - hicn_name_suffix_t *suffix); - - /** - * @brief Sets an Interest name suffix - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest packet - * @param [in] suffix - Name suffix to set - * @return hICN error code - */ - int (*set_interest_name_suffix) (hicn_type_t type, hicn_protocol_t *h, - const hicn_name_suffix_t *suffix); - - /** - * @brief Check if packet is an interest - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest packet - * @param [out] h - 1 if interest, 0 otherwise - * @return hICN error code - */ - int (*is_interest) (hicn_type_t type, const hicn_protocol_t *h, int *ret); - - /** - * @brief Set flag to mark current packet as interest - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest packet - * @return hICN error code - */ - int (*mark_packet_as_interest) (hicn_type_t type, hicn_protocol_t *h); - - /** - * @brief Set flag to mark current packet as data - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest packet - * @return hICN error code - */ - int (*mark_packet_as_data) (hicn_type_t type, hicn_protocol_t *h); - - /** - * @brief Clear the necessary Interest fields in order to hash it - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest packet - * @return hICN error code - */ - int (*reset_interest_for_hash) (hicn_type_t type, hicn_protocol_t *h); - - /** - * @brief Retrieves a Data locator - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Data packet - * @param [out] ip_address - Retrieved locator - * @return hICN error code - */ - int (*get_data_locator) (hicn_type_t type, const hicn_protocol_t *h, - ip_address_t *ip_address); - - /** - * @brief Sets a Data locator - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Data packet - * @param [in] ip_address - Locator to set - * @return hICN error code - */ - int (*set_data_locator) (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *ip_address); - - /** - * @brief Retrieves a Data name - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Data packet - * @param [out] name - Retrieved name - * @return hICN error code - */ - int (*get_data_name) (hicn_type_t type, const hicn_protocol_t *h, - hicn_name_t *name); - - /** - * @brief Sets a Data name - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Data packet - * @param [in] name - Name to set - * @return hICN error code - */ - int (*set_data_name) (hicn_type_t type, hicn_protocol_t *h, - const hicn_name_t *name); - - /** - * @brief Retrieves a Data name suffix - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Data packet - * @param [out] suffix - Retrieved name suffix - * @return hICN error code - */ - int (*get_data_name_suffix) (hicn_type_t type, const hicn_protocol_t *h, - hicn_name_suffix_t *suffix); - - /** - * @brief Sets a Data name suffix - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Data packet - * @param [in] suffix - Name suffix to set - * @return hICN error code - */ - int (*set_data_name_suffix) (hicn_type_t type, hicn_protocol_t *h, - const hicn_name_suffix_t *suffix); - - /** - * @brief Retrieves a Data pathlabel - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Data packet - * @param [out] pathlabel - Retrieved pathlabel - * @return hICN error code - */ - int (*get_data_pathlabel) (hicn_type_t type, const hicn_protocol_t *h, - u32 *pathlabel); - - /** - * @brief Sets a Data pathlabel - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Data packet - * @param [in] pathlabel - Pathlabel to set - * @return hICN error code - */ - int (*set_data_pathlabel) (hicn_type_t type, hicn_protocol_t *h, - const u32 pathlabel); - - /** - * @brief Update a Data pathlabel with a new face identifier - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Data packet - * @param [in] pathlabel - Face identifier used to update pathlabel - * @return hICN error code - */ - int (*update_data_pathlabel) (hicn_type_t type, hicn_protocol_t *h, - const hicn_faceid_t face_id); - - /** - * @brief Clear the necessary Data fields in order to hash it - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Data packet - * @return hICN error code - */ - int (*reset_data_for_hash) (hicn_type_t type, hicn_protocol_t *h); - - /** - * @brief Retrieves an Interest or Data lifetime - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest or Data packet - * @param [out] pathlabel - Retrieved lifetime - * @return hICN error code - */ - int (*get_lifetime) (hicn_type_t type, const hicn_protocol_t *h, - hicn_lifetime_t *lifetime); - - /** - * @brief Sets an Interest or Data lifetime - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [in] pathlabel - Lifetime to set - * @return hICN error code - */ - int (*set_lifetime) (hicn_type_t type, hicn_protocol_t *h, - const hicn_lifetime_t lifetime); - - /** - * @brief Get the source port of the hicn packet. - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest or Data packet - * @param [out] source_port - Retrieved source port - * @return hICN error code - */ - int (*get_source_port) (hicn_type_t type, const hicn_protocol_t *h, - u16 *source_port); - - /** - * @brief Get the destination port of the hicn packet. - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest or Data packet - * @param [out] source_port - Retrieved destination port - * @return hICN error code - */ - int (*get_dest_port) (hicn_type_t type, const hicn_protocol_t *h, - u16 *dest_port); - - /** - * @brief Set the source port of the hicn packet. - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest or Data packet - * @param [out] source_port - Source port to set - * @return hICN error code - */ - int (*set_source_port) (hicn_type_t type, hicn_protocol_t *h, - u16 source_port); - - /** - * @brief Set the destination port of the hicn packet. - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest or Data packet - * @param [out] source_port - Destination port to set - * @return hICN error code - */ - int (*set_dest_port) (hicn_type_t type, hicn_protocol_t *h, u16 dest_port); - - /** - * @brief Update all checksums in packet headers - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the packet - * @param [in] partial_csum - Partial checksum (set to 0, used internally to - * carry intermediate values from IP pseudo-header) - * @param [in] payload_length - Payload length (can be set to ~0, retrieved - * and used internally to carry payload length across protocol headers) - * @return hICN error code - */ - int (*update_checksums) (hicn_type_t type, hicn_protocol_t *h, - u16 partial_csum, size_t payload_length); - - /** - * @brief Validate all checksums in packet headers - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the packet - * @param [in] partial_csum - Partial checksum, or zero if no partial - * checksum available - * @param [in] payload_length - Payload length (can be set to ~0, retrieved - * and used internally to carry payload length across protocol headers) - * @return hICN error code - */ - int (*verify_checksums) (hicn_type_t type, hicn_protocol_t *h, - u16 partial_csum, size_t payload_length); - - /** - * @brief Rewrite an Interest packet header (locator) - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest packet - * @param [in] addr_new - New locator - * @param [in] addr_old - Old locator (set to NULL, used internally to - * compute incremental checksums) - * @return hICN error code - */ - int (*rewrite_interest) (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, - ip_address_t *addr_old); - - /** - * @brief Rewrite a Data packet header (locator + pathlabel) - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Data packet - * @param [in] addr_new - New locator - * @param [in] addr_old - Old locator (set to NULL, used internally to - * compute incremental checksums) - * @param [in] face_id - Face identifier used to update pathlabel - * @param [in] reset_pl - If not zero, reset the current pathlabel - * before update it - * @return hICN error code - */ - int (*rewrite_data) (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old, - const hicn_faceid_t face_id, u8 reset_pl); - - /** - * @brief Return the packet length - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the packet - * @parma [out] length - Returned packet length - * @return hICN error code - */ - int (*get_length) (hicn_type_t type, const hicn_protocol_t *h, - size_t *length); - - /** - * @brief Return the current packet header length - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the packet - * @parma [out] header_length - Returned packet current header length - * @return hICN error code - */ - int (*get_current_header_length) (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length); - - /** - * @brief Return the packet header length - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the packet - * @parma [out] header_length - Returned packet header length - * @return hICN error code - */ - int (*get_header_length) (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length); - - /** - * @brief Return the packet payload length - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the packet - * @parma [out] payload_length - Returned packet payload length - * @return hICN error code - */ - int (*get_payload_length) (hicn_type_t type, const hicn_protocol_t *h, - size_t *payload_length); - - /** - * @brief Sets the packet paylaod length - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the packet - * @parma [out] payload_length - Payload length to set - * @return hICN error code - */ - int (*set_payload_length) (hicn_type_t type, hicn_protocol_t *h, - size_t payload_length); - - /** - * @brief Retrieves an Interest or Data signature size - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest or Data packet - * @param [out] signature_size - Retrieved signature size - * @return hICN error code - */ - int (*get_signature_size) (hicn_type_t type, const hicn_protocol_t *h, - size_t *signature_size); - - /** - * @brief Sets an Interest or Data signature size - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [in] signature_size - Signature size to set - * @return hICN error code - */ - int (*set_signature_size) (hicn_type_t type, hicn_protocol_t *h, - size_t signature_size); - - /** - * @brief Sets an Interest or Data signature padding between maximum size and - * real size - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [in] signature_size - Signature size to set - * @return hICN error code - */ - int (*set_signature_padding) (hicn_type_t type, hicn_protocol_t *h, - size_t signature_padding); - - /** - * @brief gets an Interest or Data signature padding between maximum size and - * real size - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [in] signature_size - retrieve the padding between maximum size and - * real size - * @return hICN error code - */ - int (*get_signature_padding) (hicn_type_t type, const hicn_protocol_t *h, - size_t *signature_padding); - - /** - * @brief Gets the signature timestamp - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [out] signature_timestamp - Retrieved signature timestamp - * @return hICN error code - */ - int (*get_signature_timestamp) (hicn_type_t type, const hicn_protocol_t *h, - uint64_t *signature_timestamp); - - /** - * @brief Sets the signature timestamp - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [in] signature_timestamp - Signature timestamp to set - * @return hICN error code - */ - int (*set_signature_timestamp) (hicn_type_t type, hicn_protocol_t *h, - uint64_t signature_timestamp); - - /** - * @brief Gets the signature validation algorithm - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [out] validation_algorithm - Retrieved validation_algorithm - * @return hICN error code - */ - int (*get_validation_algorithm) (hicn_type_t type, const hicn_protocol_t *h, - uint8_t *validation_algorithm); - - /** - * @brief Sets the signature validation algorithm - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [in] validation_algorithm - Validation algorithm enumeration - * @return hICN error code - */ - int (*set_validation_algorithm) (hicn_type_t type, hicn_protocol_t *h, - uint8_t validation_algorithm); - - /** - * @brief Gets the key id - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [out] key_id - Retrieved key id first byte address - * @return hICN error code - */ - int (*get_key_id) (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id, - uint8_t *key_id_size); - - /** - * @brief Sets the key id - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [in] key_id - Key id first byte address - * @return hICN error code - */ - int (*set_key_id) (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id); - - /** - * @brief Get a pointer to the signature field in the packet - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [out] signature - Pointer to the memory region holding the - * signature - * @return hICN error code - */ - int (*get_signature) (hicn_type_t type, hicn_protocol_t *h, - uint8_t **signature); - - /** - * @brief Set payload type of the packet - * @param [in] type - hICN packet type - * @param [in,out] h - Buffer holding the Interest or Data packet - * @param [in] payload_type - The payload type of this packet - * @return hICN error code - */ - int (*set_payload_type) (hicn_type_t type, hicn_protocol_t *h, - hicn_payload_type_t payload_type); - - /** - * @brief Get payload type from the packet - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest or Data packet - * @param [out] payload_type - The payload type of this packet - * @return hICN error code - */ - int (*get_payload_type) (hicn_type_t type, const hicn_protocol_t *h, - hicn_payload_type_t *payload_type); - - /** - * @brief Check if data packet is last one. - * @param [in] type - hICN packet type - * @param [in] h - Buffer holding the Interest or Data packet - * @param [out] is_last - 1 if last data, 0 otherwise - * @return hICN error code - */ - int (*is_last_data) (hicn_type_t type, const hicn_protocol_t *h, - int *is_last); - - /** - * @brief Mark data packet as last - * @param [in] type - hICN packet type - * @param [in, out] h - Buffer holding the Interest or Data packet - * @return hICN error code - */ - int (*set_last_data) (hicn_type_t type, hicn_protocol_t *h); -} hicn_ops_t; - -#define DECLARE_HICN_OPS(protocol) \ - const hicn_ops_t hicn_ops_##protocol = { \ - ATTR_INIT (init_packet_header, protocol##_init_packet_header), \ - ATTR_INIT (get_interest_locator, protocol##_get_interest_locator), \ - ATTR_INIT (set_interest_locator, protocol##_set_interest_locator), \ - ATTR_INIT (get_interest_name, protocol##_get_interest_name), \ - ATTR_INIT (set_interest_name, protocol##_set_interest_name), \ - ATTR_INIT (get_interest_name_suffix, \ - protocol##_get_interest_name_suffix), \ - ATTR_INIT (set_interest_name_suffix, \ - protocol##_set_interest_name_suffix), \ - ATTR_INIT (is_interest, protocol##_is_interest), \ - ATTR_INIT (mark_packet_as_interest, protocol##_mark_packet_as_interest), \ - ATTR_INIT (mark_packet_as_data, protocol##_mark_packet_as_data), \ - ATTR_INIT (reset_interest_for_hash, protocol##_reset_interest_for_hash), \ - ATTR_INIT (get_data_locator, protocol##_get_data_locator), \ - ATTR_INIT (set_data_locator, protocol##_set_data_locator), \ - ATTR_INIT (get_data_name, protocol##_get_data_name), \ - ATTR_INIT (set_data_name, protocol##_set_data_name), \ - ATTR_INIT (get_data_name_suffix, protocol##_get_data_name_suffix), \ - ATTR_INIT (set_data_name_suffix, protocol##_set_data_name_suffix), \ - ATTR_INIT (get_data_pathlabel, protocol##_get_data_pathlabel), \ - ATTR_INIT (set_data_pathlabel, protocol##_set_data_pathlabel), \ - ATTR_INIT (update_data_pathlabel, protocol##_update_data_pathlabel), \ - ATTR_INIT (reset_data_for_hash, protocol##_reset_data_for_hash), \ - ATTR_INIT (get_lifetime, protocol##_get_lifetime), \ - ATTR_INIT (set_lifetime, protocol##_set_lifetime), \ - ATTR_INIT (get_source_port, protocol##_get_source_port), \ - ATTR_INIT (get_dest_port, protocol##_get_dest_port), \ - ATTR_INIT (set_source_port, protocol##_set_source_port), \ - ATTR_INIT (set_dest_port, protocol##_set_dest_port), \ - ATTR_INIT (update_checksums, protocol##_update_checksums), \ - ATTR_INIT (verify_checksums, protocol##_verify_checksums), \ - ATTR_INIT (rewrite_interest, protocol##_rewrite_interest), \ - ATTR_INIT (rewrite_data, protocol##_rewrite_data), \ - ATTR_INIT (get_length, protocol##_get_length), \ - ATTR_INIT (get_current_header_length, \ - protocol##_get_current_header_length), \ - ATTR_INIT (get_header_length, protocol##_get_header_length), \ - ATTR_INIT (get_payload_length, protocol##_get_payload_length), \ - ATTR_INIT (set_payload_length, protocol##_set_payload_length), \ - ATTR_INIT (get_payload_type, protocol##_get_payload_type), \ - ATTR_INIT (set_payload_type, protocol##_set_payload_type), \ - ATTR_INIT (get_signature_size, protocol##_get_signature_size), \ - ATTR_INIT (get_signature_timestamp, protocol##_get_signature_timestamp), \ - ATTR_INIT (set_signature_timestamp, protocol##_set_signature_timestamp), \ - ATTR_INIT (get_validation_algorithm, \ - protocol##_get_validation_algorithm), \ - ATTR_INIT (set_validation_algorithm, \ - protocol##_set_validation_algorithm), \ - ATTR_INIT (get_key_id, protocol##_get_key_id), \ - ATTR_INIT (set_key_id, protocol##_set_key_id), \ - ATTR_INIT (get_signature, protocol##_get_signature), \ - ATTR_INIT (set_signature_padding, protocol##_set_signature_padding), \ - ATTR_INIT (set_signature_size, protocol##_set_signature_size), \ - ATTR_INIT (get_signature_padding, protocol##_get_signature_padding), \ - ATTR_INIT (is_last_data, protocol##_is_last_data), \ - ATTR_INIT (set_last_data, protocol##_set_last_data), \ - } - -/** - * @brief Protocol-independent packet operations VFT - * NOTE: The following declarations should be kept in order - */ -extern const hicn_ops_t *const hicn_ops_vft[]; - -/* - * Helpers for writing recursive protocol operations on packet headers - * - * NOTE : we cannot use a shift operation as IPPROTO_NONE != 0 (and 0 is - * IPv4...) - */ -static inline hicn_type_t -TYPE_POP (hicn_type_t type) -{ -#ifndef _WIN32 - return HICN_TYPE (type.l2, type.l3, type.l4, IPPROTO_NONE); -#else - hicn_type_t new_type; - new_type.l1 = type.l2; - new_type.l2 = type.l3; - new_type.l3 = type.l4; - new_type.l4 = IPPROTO_NONE; - return new_type; -#endif -} - -static inline hicn_protocol_t * -PAYLOAD (hicn_type_t type, const hicn_protocol_t *h) -{ - size_t header_length; - int rc = - hicn_ops_vft[type.l1]->get_current_header_length (type, h, &header_length); - if (rc < 0) - return NULL; - return (hicn_protocol_t *) ((u8 *) h + header_length); -} - -#define CHILD_OPS(f, type, h, ...) \ - (hicn_ops_vft[type.l2]->f (TYPE_POP (type), PAYLOAD (type, h), \ - ##__VA_ARGS__)) - -/** Shortcuts to entry points in VFT */ -#define HICN_OPS4 hicn_ops_vft[IPPROTO_IP] -#define HICN_OPS6 hicn_ops_vft[IPPROTO_IPV6] - -/* Helpers for simple declarations */ - -#define DECLARE_init_packet_header(protocol, error) \ - int protocol##_init_packet_header (hicn_type_t type, hicn_protocol_t *h) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_interest_locator(protocol, error) \ - int protocol##_get_interest_locator ( \ - hicn_type_t type, const hicn_protocol_t *h, ip_address_t *ip_address) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_interest_locator(protocol, error) \ - int protocol##_set_interest_locator (hicn_type_t type, hicn_protocol_t *h, \ - const ip_address_t *ip_address) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_interest_name(protocol, error) \ - int protocol##_get_interest_name ( \ - hicn_type_t type, const hicn_protocol_t *h, hicn_name_t *name) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_interest_name(protocol, error) \ - int protocol##_set_interest_name (hicn_type_t type, hicn_protocol_t *h, \ - const hicn_name_t *name) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_interest_name_suffix(protocol, error) \ - int protocol##_get_interest_name_suffix ( \ - hicn_type_t type, const hicn_protocol_t *h, hicn_name_suffix_t *suffix) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_interest_name_suffix(protocol, error) \ - int protocol##_set_interest_name_suffix ( \ - hicn_type_t type, hicn_protocol_t *h, const hicn_name_suffix_t *suffix) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_is_interest(protocol, error) \ - int protocol##_is_interest (hicn_type_t type, const hicn_protocol_t *h, \ - int *ret) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_mark_packet_as_interest(protocol, error) \ - int protocol##_mark_packet_as_interest (hicn_type_t type, \ - hicn_protocol_t *h) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_mark_packet_as_data(protocol, error) \ - int protocol##_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_reset_interest_for_hash(protocol, error) \ - int protocol##_reset_interest_for_hash (hicn_type_t type, \ - hicn_protocol_t *h) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_data_locator(protocol, error) \ - int protocol##_get_data_locator ( \ - hicn_type_t type, const hicn_protocol_t *h, ip_address_t *ip_address) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_data_locator(protocol, error) \ - int protocol##_set_data_locator (hicn_type_t type, hicn_protocol_t *h, \ - const ip_address_t *ip_address) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_data_name(protocol, error) \ - int protocol##_get_data_name (hicn_type_t type, const hicn_protocol_t *h, \ - hicn_name_t *name) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_data_name(protocol, error) \ - int protocol##_set_data_name (hicn_type_t type, hicn_protocol_t *h, \ - const hicn_name_t *name) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_data_name_suffix(protocol, error) \ - int protocol##_get_data_name_suffix ( \ - hicn_type_t type, const hicn_protocol_t *h, hicn_name_suffix_t *suffix) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_data_name_suffix(protocol, error) \ - int protocol##_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h, \ - const hicn_name_suffix_t *suffix) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_data_pathlabel(protocol, error) \ - int protocol##_get_data_pathlabel ( \ - hicn_type_t type, const hicn_protocol_t *h, u32 *pathlabel) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_data_pathlabel(protocol, error) \ - int protocol##_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, \ - const u32 pathlabel) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_update_data_pathlabel(protocol, error) \ - int protocol##_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, \ - const hicn_faceid_t face_id) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_reset_data_for_hash(protocol, error) \ - int protocol##_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_lifetime(protocol, error) \ - int protocol##_get_lifetime (hicn_type_t type, const hicn_protocol_t *h, \ - hicn_lifetime_t *lifetime) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_lifetime(protocol, error) \ - int protocol##_set_lifetime (hicn_type_t type, hicn_protocol_t *h, \ - const hicn_lifetime_t lifetime) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_source_port(protocol, error) \ - int protocol##_get_source_port (hicn_type_t type, const hicn_protocol_t *h, \ - u16 *source_port) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_dest_port(protocol, error) \ - int protocol##_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, \ - u16 *dest_port) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_source_port(protocol, error) \ - int protocol##_set_source_port (hicn_type_t type, hicn_protocol_t *h, \ - u16 source_port) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_dest_port(protocol, error) \ - int protocol##_set_dest_port (hicn_type_t type, hicn_protocol_t *h, \ - u16 dest_port) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_update_checksums(protocol, error) \ - int protocol##_update_checksums (hicn_type_t type, hicn_protocol_t *h, \ - u16 partial_csum, size_t payload_length) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_verify_checksums(protocol, error) \ - int protocol##_verify_checksums (hicn_type_t type, hicn_protocol_t *h, \ - u16 partial_csum, size_t payload_length) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_rewrite_interest(protocol, error) \ - int protocol##_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, \ - const ip_address_t *addr_new, \ - ip_address_t *addr_old) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_rewrite_data(protocol, error) \ - int protocol##_rewrite_data ( \ - hicn_type_t type, hicn_protocol_t *h, const ip_address_t *addr_new, \ - ip_address_t *addr_old, const hicn_faceid_t face_id, u8 reset_pl) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_length(protocol, error) \ - int protocol##_get_length (hicn_type_t type, const hicn_protocol_t *h, \ - size_t *length) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_current_header_length(protocol, error) \ - int protocol##_get_current_header_length ( \ - hicn_type_t type, const hicn_protocol_t *h, size_t *header_length) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_header_length(protocol, error) \ - int protocol##_get_header_length ( \ - hicn_type_t type, const hicn_protocol_t *h, size_t *header_length) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_payload_length(protocol, error) \ - int protocol##_get_payload_length ( \ - hicn_type_t type, const hicn_protocol_t *h, size_t *payload_length) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_payload_length(protocol, error) \ - int protocol##_set_payload_length (hicn_type_t type, hicn_protocol_t *h, \ - size_t payload_length) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_payload_type(protocol, error) \ - int protocol##_get_payload_type (hicn_type_t type, \ - const hicn_protocol_t *h, \ - hicn_payload_type_t *payload_type) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_payload_type(protocol, error) \ - int protocol##_set_payload_type (hicn_type_t type, hicn_protocol_t *h, \ - hicn_payload_type_t payload_type) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_signature_size(protocol, error) \ - int protocol##_get_signature_size ( \ - hicn_type_t type, const hicn_protocol_t *h, size_t *signature_size) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_signature_size(protocol, error) \ - int protocol##_set_signature_size (hicn_type_t type, hicn_protocol_t *h, \ - size_t signature_size) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_signature_padding(protocol, error) \ - int protocol##_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, \ - size_t padding) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_signature_padding(protocol, error) \ - int protocol##_get_signature_padding ( \ - hicn_type_t type, const hicn_protocol_t *h, size_t *padding) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_signature_timestamp(protocol, error) \ - int protocol##_set_signature_timestamp ( \ - hicn_type_t type, hicn_protocol_t *h, uint64_t signature_timestamp) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_signature_timestamp(protocol, error) \ - int protocol##_get_signature_timestamp (hicn_type_t type, \ - const hicn_protocol_t *h, \ - uint64_t *signature_timestamp) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_validation_algorithm(protocol, error) \ - int protocol##_set_validation_algorithm ( \ - hicn_type_t type, hicn_protocol_t *h, uint8_t validation_algorithm) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_validation_algorithm(protocol, error) \ - int protocol##_get_validation_algorithm (hicn_type_t type, \ - const hicn_protocol_t *h, \ - uint8_t *validation_algorithm) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_key_id(protocol, error) \ - int protocol##_set_key_id (hicn_type_t type, hicn_protocol_t *h, \ - uint8_t *key_id) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_key_id(protocol, error) \ - int protocol##_get_key_id (hicn_type_t type, hicn_protocol_t *h, \ - uint8_t **key_id, uint8_t *key_id_size) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_get_signature(protocol, error) \ - int protocol##_get_signature (hicn_type_t type, hicn_protocol_t *h, \ - uint8_t **signature) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_is_last_data(protocol, error) \ - int protocol##_is_last_data (hicn_type_t type, const hicn_protocol_t *h, \ - int *is_last) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#define DECLARE_set_last_data(protocol, error) \ - int protocol##_set_last_data (hicn_type_t type, hicn_protocol_t *h) \ - { \ - return HICN_LIB_ERROR_##error; \ - } - -#endif /* HICN_OPS_H */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/lib/includes/hicn/packet.h b/lib/includes/hicn/packet.h new file mode 100644 index 000000000..c64014fe6 --- /dev/null +++ b/lib/includes/hicn/packet.h @@ -0,0 +1,697 @@ +/* + * Copyright (c) 2017-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file compat.h + * @brief Implementation of the compatibility layer. + * + * The structure of the core API has evolved to support operations of a variety + * of packet formats in addition to IPv4/TCP and IPv6/TCP, namely with the use + * of ICMP for signalization and AH headers for integrity. The new API format + * has been designed to scale better with the multiplicity of packet formats, + * and provide a unified interface on top. We maintain an interface for the + * former API in this file, which mainly acts as a wrapper on top of new calls. + * + */ +#ifndef HICN_PACKET_H +#define HICN_PACKET_H + +#include <limits.h> + +#include <hicn/base.h> +#include <hicn/common.h> +#include <hicn/name.h> + +/* Packet buffer definition */ + +typedef struct __attribute__ ((packed)) +{ + /* Packet format */ + hicn_packet_format_t format; + + /* Packet type */ + hicn_packet_type_t type; + + /* + * We store an offset to the packet header. + * + * NOTE: This is a signed value. + * + * In most implementations, the buffer located closeby to the current packet + * buffer (eg msgbuf in hicn-light, and vlib buffer in VPP), and an int16_t + * would be sufficient. This is not the case in transport though and we have + * to use a full integer. + */ + int64_t header; + + /* Packet len */ + uint16_t len; + +#ifdef OPAQUE_IP + /* Interest or data packet */ + union + { + uint16_t ipv4; + uint16_t ipv6; + }; +#endif /* OPAQUE_IP */ + union + { + uint16_t tcp; + uint16_t udp; + uint16_t icmp; + }; + uint16_t newhdr; + uint16_t ah; + uint16_t payload; + + uint16_t buffer_size; + // uint16_t len; + + /* Contiguous copy of the name */ + // hicn_name_t *name; + +} hicn_packet_buffer_t; + +static_assert (sizeof (hicn_packet_buffer_t) == 28, ""); + +static inline uint8_t * +_pkbuf_get_ipv4 (const hicn_packet_buffer_t *pkbuf) +{ +#ifdef OPAQUE_IP + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->ipv4; +#else + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header; +#endif + _ASSERT (header); + return header; +} +#define pkbuf_get_ipv4(pkbuf) ((_ipv4_header_t *) (_pkbuf_get_ipv4 (pkbuf))) + +static inline uint8_t * +_pkbuf_get_ipv6 (const hicn_packet_buffer_t *pkbuf) +{ +#ifdef OPAQUE_IP + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->ipv6; +#else + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header; +#endif + assert (header); + return header; +} +#define pkbuf_get_ipv6(pkbuf) ((_ipv6_header_t *) (_pkbuf_get_ipv6 (pkbuf))) + +static inline uint8_t * +_pkbuf_get_tcp (const hicn_packet_buffer_t *pkbuf) +{ + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->tcp; + assert (header); + return header; +} +#define pkbuf_get_tcp(pkbuf) ((_tcp_header_t *) (_pkbuf_get_tcp (pkbuf))) + +static inline uint8_t * +_pkbuf_get_udp (const hicn_packet_buffer_t *pkbuf) +{ + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->udp; + assert (header); + return header; +} +#define pkbuf_get_udp(pkbuf) ((_udp_header_t *) (_pkbuf_get_udp (pkbuf))) + +static inline uint8_t * +_pkbuf_get_icmp (const hicn_packet_buffer_t *pkbuf) +{ + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->icmp; + assert (header); + return header; +} +#define pkbuf_get_icmp(pkbuf) ((_icmp_header_t *) (_pkbuf_get_icmp (pkbuf))) + +static inline uint8_t * +_pkbuf_get_ah (const hicn_packet_buffer_t *pkbuf) +{ + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->ah; + assert (header); + return header; +} +#define pkbuf_get_ah(pkbuf) ((_ah_header_t *) (_pkbuf_get_ah (pkbuf))) + +static inline uint8_t * +_pkbuf_get_new (const hicn_packet_buffer_t *pkbuf) +{ + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header + pkbuf->newhdr; + assert (header); + return header; +} +#define pkbuf_get_new(pkbuf) ((_new_header_t *) (_pkbuf_get_new (pkbuf))) + +static inline uint8_t * +pkbuf_get_header (const hicn_packet_buffer_t *pkbuf) +{ + uint8_t *header = (uint8_t *) pkbuf + pkbuf->header; + assert (header); + return header; +} + +static inline void +pkbuf_set_header (hicn_packet_buffer_t *pkbuf, uint8_t *header) +{ + ssize_t offset = header - (uint8_t *) pkbuf; + assert (offset < INT64_MAX); + assert (offset > INT64_MIN); + pkbuf->header = (int64_t) offset; +} + +/* + * Packet buffer operations + * + * A packet buffer can either be initialized either: + * + * 1) from an empty buffer (packet crafting). + * + * #define MTU 1500 + * size_t size = MTU; + * u8 buffer[MTU]; + * + * hicn_packet_t pkbuf; + * hicn_packet_set_format(&pkbuf, HICN_PACKET_FORMAT_NEW); + * hicn_packet_set_buffer(&pkbuf, &buffer, size); + * hicn_packet_init_header(&pkbuf, 0); + * + * An empty (but correct) packet is not available in the buffer, ready to be + * modified and/or sent. + * + * 2) from an existing buffer (packet reception): + * + * hicn_packet_t pkbuf; + * hicn_packet_set_buffer(&pkbuf, &buffer, size); + * hicn_packet_analyze(&pkbuf); + * + * It is then possible to retrieve properties of the packet such as format and + * type (interest, data, etc.). + * + * hicn_packet_get_format(&pkbuf); + * hicn_packet_get_type(&pkbuf); + * + * */ + +hicn_packet_format_t +hicn_packet_get_format (const hicn_packet_buffer_t *pkbuf); + +void hicn_packet_set_format (hicn_packet_buffer_t *pkbuf, + hicn_packet_format_t format); + +hicn_packet_type_t hicn_packet_get_type (const hicn_packet_buffer_t *pkbuf); +void hicn_packet_set_type (hicn_packet_buffer_t *pkbuf, + hicn_packet_type_t type); + +bool hicn_packet_is_interest (const hicn_packet_buffer_t *pkbuf); + +bool hicn_packet_is_data (const hicn_packet_buffer_t *pkbuf); + +bool hicn_packet_is_undefined (const hicn_packet_buffer_t *pkbuf); + +/** + * @brief Initialize the buffer from packet buffer metadata (builds a valid + * packet). + * @param [in] pkbuf - hICN packet buffer + * @return hICN error code + * + * Packet type, format, and a buffer are required. + */ +int hicn_packet_init_header (hicn_packet_buffer_t *pkbuf, + size_t additional_header_size); + +/** + * @brief Reset information stored in the packet header. + * @param [in] pkbuf - hICN packet buffer + * @return hICN error code + */ +int hicn_packet_reset (hicn_packet_buffer_t *pkbuf); + +/** + * @brief Analyze buffer to populate metadata in packet buffer. + * @param [in] pkbuf - hICN packet buffer + * @return hICN error code + */ +int hicn_packet_analyze (hicn_packet_buffer_t *pkbuf); + +/** + * @brief Initialize hicn packet storage space with a buffer + * @param [in] pkbuf - hICN packet buffer + * @param [in] buffer - Packet storage buffer + * @param [in] analyze - Flag indicating whether to analyze the buffer + * content to populate packet format, header's offsets, etc. + * @return hICN error code + */ +int hicn_packet_set_buffer (hicn_packet_buffer_t *pkbuf, u8 *buffer, + uint16_t buffer_size, uint16_t len); + +/** + * @brief Retrieve the storage buffer. + * @param [in] pkbuf - hICN packet buffer + * @param [out] buffer - Packet buffer + * @param [out] buffer_size - Packet buffer size + * @return Pointer to storage buffer (this only returns the pointer; no copy is + * made) + */ +int hicn_packet_get_buffer (const hicn_packet_buffer_t *pkbuf, u8 **buffer, + uint16_t *buffer_size, uint16_t *len); + +/** + * @brief Retrieve the packet length + * @param [in] pkbuf - hICN packet buffer + * @return Length of the stored packet + */ +size_t hicn_packet_get_len (const hicn_packet_buffer_t *pkbuf); + +/** + * @brief Set the packet length + * @param [in] pkbuf - hICN packet buffer + * @param [in] len - hICN packet length + * @return None + */ +int hicn_packet_set_len (hicn_packet_buffer_t *pkbuf, size_t len); + +/** + * @brief Return total length of hicn headers (before payload) + * @param [in] pkbuf - hICN packet buffer + * @param [out] len - Total headers length + * @return Headers' len + */ +int hicn_packet_get_header_len (const hicn_packet_buffer_t *pkbuf, + size_t *len); + +/** + * @brief Return the length of hICN payload in the packet. + * @param [in] pkbuf - hICN packet buffer + * @param [out] len - hICN payload length + * @return Payload len + */ +int hicn_packet_get_payload_len (const hicn_packet_buffer_t *pkbuf, + size_t *len); + +/** + * @brief Sets the payload of a packet + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] packet - packet header + * @param [in] payload - payload to set + * @param [in] payload_length - size of the payload to set + * @return hICN error code + * + * NOTE: + * - The buffer holding payload is assumed sufficiently large + * - This function updates header fields with the new length, but no checksum. + */ +int hicn_packet_set_payload (const hicn_packet_buffer_t *pkbuf, + const u8 *payload, u16 payload_length); + +/** + * @brief Retrieves the payload of a packet + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [out] payload - pointer to buffer for storing the result + * @param [out] payload_length - size of the retreived payload + * @param [in] hard_copy - Flag : if true (eg. 1), a copy of the payload is + * made into the payload buffer, otherwise (0) the pointer is changed to point + * to the payload offset in the packet. + * @return hICN error code + * + * NOTE: + * - The buffer holding payload is assumed sufficiently large + */ +int hicn_packet_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload, + size_t *payload_size, bool hard_copy); + +/* Header fields manipulation */ + +/** + * @brief Return total length of hicn headers (but signature payload) + * @param [in] pkbuf - hICN packet buffer + * @param [out] header_length - Total length of headers + * @return hICN error code + */ +int hicn_packet_get_header_length_from_format (hicn_packet_format_t format, + size_t *header_length); + +/** + * @brief Sets payload length + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] packet - packet header + * @param [in] payload_length - payload length + * @return hICN error code + */ +int hicn_packet_set_payload_length (const hicn_packet_buffer_t *pkbuf, + const size_t payload_length); + +/** + * @brief Compare two hICN packets + * @param [in] packet_1 - First packet + * @param [in] packet_2 - Second packet + * @return 0 if both packets are considered equal, any other value otherwise. + */ +int hicn_packet_compare (const hicn_packet_buffer_t *pkbuf11, + const hicn_packet_buffer_t *pkbuf22); + +/** + * @brief Retrieve the name of an interest/data packet + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [out] name - name holding the result + * @return hICN error code + */ +int hicn_packet_get_name (const hicn_packet_buffer_t *pkbuf, + hicn_name_t *name); + +/** + * @brief Sets the name of an interest/data packet + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] packet - packet header + * @param [in] name - name to set into packet + * @return hICN error code + */ +int hicn_packet_set_name (const hicn_packet_buffer_t *pkbuf, + const hicn_name_t *name); + +/** + * @brief Retrieve the locator of an interest / data packet + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [out] ip_address - retrieved locator + * @return hICN error code + */ +int hicn_packet_get_locator (const hicn_packet_buffer_t *pkbuf, + hicn_ip_address_t *prefix); + +/** + * @brief Sets the locator of an interest / data packet + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] packet - packet header + * @param [out] ip_address - retrieved locator + * @return hICN error code + */ +int hicn_packet_set_locator (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *prefix); + +int hicn_packet_save_header (const hicn_packet_buffer_t *pkbuf, u8 *header, + size_t *header_len, bool copy_ah); + +int hicn_packet_load_header (const hicn_packet_buffer_t *pkbuf, + const u8 *header, size_t header_len); + +int hicn_packet_get_lifetime (const hicn_packet_buffer_t *pkbuf, + u32 *lifetime); +int hicn_packet_set_lifetime (const hicn_packet_buffer_t *pkbuf, u32 lifetime); + +/* Interest */ +int hicn_interest_get_name (const hicn_packet_buffer_t *pkbuf, + hicn_name_t *name); +int hicn_interest_set_name (const hicn_packet_buffer_t *pkbuf, + const hicn_name_t *name); +int hicn_interest_get_locator (const hicn_packet_buffer_t *pkbuf, + hicn_ip_address_t *prefix); +int hicn_interest_set_locator (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *prefix); +int hicn_interest_compare (const hicn_packet_buffer_t *pkbuf11, + const hicn_packet_buffer_t *pkbuf2); +int hicn_interest_set_lifetime (const hicn_packet_buffer_t *pkbuf, + u32 lifetime); +int hicn_interest_get_lifetime (const hicn_packet_buffer_t *pkbuf, + u32 *lifetime); +int hicn_interest_get_header_length (const hicn_packet_buffer_t *pkbuf, + size_t *header_length); +int hicn_interest_get_payload_length (const hicn_packet_buffer_t *pkbuf, + size_t *payload_length); +int hicn_interest_set_payload (const hicn_packet_buffer_t *pkbuf, + const u8 *payload, size_t payload_length); +int hicn_interest_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload, + size_t *payload_size, bool hard_copy); +int hicn_interest_reset_for_hash (hicn_packet_buffer_t *pkbuf); + +/* Data */ + +int hicn_data_get_name (const hicn_packet_buffer_t *pkbuf, hicn_name_t *name); +int hicn_data_set_name (const hicn_packet_buffer_t *pkbuf, + const hicn_name_t *name); +int hicn_data_get_locator (const hicn_packet_buffer_t *pkbuf, + hicn_ip_address_t *prefix); +int hicn_data_set_locator (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *prefix); +int hicn_data_compare (const hicn_packet_buffer_t *pkbuf11, + const hicn_packet_buffer_t *pkbuf22); +int hicn_data_get_expiry_time (const hicn_packet_buffer_t *pkbuf, + u32 *expiry_time); +int hicn_data_set_expiry_time (const hicn_packet_buffer_t *pkbuf, + u32 expiry_time); +int hicn_data_get_header_length (const hicn_packet_buffer_t *pkbuf, + size_t *header_length); +int hicn_data_get_payload_length (const hicn_packet_buffer_t *pkbuf, + size_t *payload_length); + +/* Path label */ + +/** + * @brief Returns the path label from a data packet + * @param [in] pkbuf - packet buffer + * @param [in] hdr - packet header + * @param [in] path_label - pointer in which to store the path label value + * @return hICN error code + */ +int hicn_data_get_path_label (const hicn_packet_buffer_t *pkbufdr, + hicn_path_label_t *path_label); + +/** + * @brief Returns the path label from a packet + * @param [in] pkbuf - packet buffer + * @param [in] hdr - packet header + * @param [in] path_label - pointer in which to store the path label value + * @return hICN error code + */ +int hicn_get_path_label (const hicn_packet_buffer_t *pkbufdr, + hicn_path_label_t *path_label); + +int hicn_data_set_path_label (const hicn_packet_buffer_t *pkbuf, + hicn_path_label_t path_label); + +/* Data specific flags */ + +int hicn_packet_get_payload_type (const hicn_packet_buffer_t *pkbuf, + + hicn_payload_type_t *payload_type); +int hicn_packet_set_payload_type (const hicn_packet_buffer_t *pkbuf, + + const hicn_payload_type_t payload_type); + +int hicn_data_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload, + size_t *payload_size, bool hard_copy); +int hicn_data_set_payload (const hicn_packet_buffer_t *pkbuf, + const u8 *payload, size_t payload_length); +int hicn_data_get_payload_type (hicn_payload_type_t *payload_type); +int hicn_data_set_payload_type (hicn_payload_type_t payload_type); +int hicn_data_reset_for_hash (hicn_packet_buffer_t *pkbuf); +int hicn_data_is_last (const hicn_packet_buffer_t *pkbuf, int *is_last); +int hicn_data_set_last (const hicn_packet_buffer_t *pkbuf); + +/* Security */ + +/** + * @brief Retrieves the signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [out] bytes - Retrieved signature size + * @return hICN error code + */ +int hicn_packet_get_signature_size (const hicn_packet_buffer_t *pkbuf, + size_t *bytes); + +/** + * @brief Sets the signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [in] bytes - Retrieved signature size + * @return hICN error code + */ +int hicn_packet_set_signature_size (const hicn_packet_buffer_t *pkbuf, + size_t bytes); + +/** + * @brief Sets the signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [in] signature_timestamp - Signature timestamp to set + * @return hICN error code + */ +int hicn_packet_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, + uint64_t signature_timestamp); + +/** + * @brief Sets the signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [out] signature_timestamp - Retrieved signature timestamp + * @return hICN error code + */ +int hicn_packet_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, + uint64_t *signature_timestamp); + +/** + * @brief Sets the signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [in] validation_algorithm - Validation algorithm to set + * @return hICN error code + */ +int hicn_packet_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, + uint8_t validation_algorithm); + +/** + * @brief Sets the signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [out] validation_algorithm - Retrieved validation algorithm + * @return hICN error code + */ +int hicn_packet_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, + uint8_t *validation_algorithm); + +/** + * @brief Sets the signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [in] key_id - Key id to set + * @param [in] key_len - Key length + * @return hICN error code + */ +int hicn_packet_set_key_id (const hicn_packet_buffer_t *pkbuf, uint8_t *key_id, + size_t key_len); + +/** + * @brief Sets the signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] packet - packet header + * @param [out] key_id - Retrieved key id + * @return hICN error code + */ +int hicn_packet_get_key_id (const hicn_packet_buffer_t *pkbuf, + uint8_t **key_id, uint8_t *key_id_length); + +int hicn_packet_get_signature (const hicn_packet_buffer_t *pkbuf, + uint8_t **sign_buf); + +int hicn_packet_get_signature_padding (const hicn_packet_buffer_t *pkbuf, + size_t *bytes); +int hicn_packet_set_signature_padding (const hicn_packet_buffer_t *pkbuf, + size_t bytes); + +/* Checksums */ + +/** + * @brief Update checksums in packet headers + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] packet - packet header + * @return hICN error code + */ +int hicn_packet_compute_checksum (const hicn_packet_buffer_t *pkbuf); + +/** + * @brief compute the checksum of the packet header, adding init_sum to the + * final value + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] packet - packet header + * @param [in] init_sum - value to add to the final checksum + * @return hICN error code + */ +int hicn_packet_compute_header_checksum (const hicn_packet_buffer_t *pkbuf, + u16 init_sum); + +/** + * @brief Verify checksums in packet headers + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] packet - packet header + * @return hICN error code + */ +int hicn_packet_check_integrity_no_payload (const hicn_packet_buffer_t *pkbuf, + u16 init_sum); + +/** + * @brief Returns the packet TTL + * @param [in] pkbuf - hICN packet buffer + * @param [out] hops - Pointer to the variable receiving the TTL value + * @return hICN error code + */ +int hicn_packet_get_ttl (const hicn_packet_buffer_t *pkbuf, u8 *hops); + +/** + * @brief Returns the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [in, out] pos - Current position in the sequence of headers while + * @param [out] hops - The TTL value to set + * @return hICN error code + */ +int hicn_packet_set_ttl (const hicn_packet_buffer_t *pkbuf, u8 hops); + +/** + * @brief Returns the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [out] port - Pointer to the variable that will receive the port + * number + * @return hICN error code + */ +int hicn_packet_get_src_port (const hicn_packet_buffer_t *pkbuf, u16 *port); + +/** + * @brief Sets the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [out] port - The port number to set + * @return hICN error code + */ +int hicn_packet_set_src_port (const hicn_packet_buffer_t *pkbuf, u16 port); + +/** + * @brief Returns the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [out] port - Pointer to the variable that will receive the port + * number + * @return hICN error code + */ +int hicn_packet_get_dst_port (const hicn_packet_buffer_t *pkbuf, u16 *port); + +/** + * @brief Sets the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [out] port - The port number to set + * @return hICN error code + */ +int hicn_packet_set_dst_port (const hicn_packet_buffer_t *pkbuf, u16 port); + +int hicn_interest_rewrite (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old); + +int hicn_data_rewrite (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, + const hicn_faceid_t face_id, u8 reset_pl); + +#endif /* HICN_PACKET_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/includes/hicn/policy.h b/lib/includes/hicn/policy.h index f39fa9272..50b771537 100644 --- a/lib/includes/hicn/policy.h +++ b/lib/includes/hicn/policy.h @@ -151,7 +151,7 @@ policy_state_t policy_state_from_str (const char *str); /* POLICY TAG STATE */ -typedef struct +typedef struct __attribute__ ((packed, aligned (1))) { policy_state_t state; uint8_t disabled; diff --git a/lib/includes/hicn/protocol/icmprd.h b/lib/includes/hicn/protocol/icmprd.h index 897e7969e..17088c22a 100644 --- a/lib/includes/hicn/protocol/icmprd.h +++ b/lib/includes/hicn/protocol/icmprd.h @@ -33,7 +33,7 @@ typedef struct u8 type; u8 code; u16 csum; - ip4_address_t ip; + ipv4_address_t ip; _ipv4_header_t iph; u8 data[64]; } _icmprd4_header_t; @@ -53,8 +53,8 @@ typedef struct u8 code; u16 csum; u32 res; - ip6_address_t tgt; - ip6_address_t dst; + ipv6_address_t tgt; + ipv6_address_t dst; } _icmprd_header_t; #define ICMPRD_HDRLEN sizeof (_icmprd_header_t) diff --git a/lib/includes/hicn/protocol/ipv4.h b/lib/includes/hicn/protocol/ipv4.h index 44e95c1e3..89435b516 100644 --- a/lib/includes/hicn/protocol/ipv4.h +++ b/lib/includes/hicn/protocol/ipv4.h @@ -54,8 +54,8 @@ typedef struct u8 ttl; u8 protocol; u16 csum; - ip4_address_t saddr; - ip4_address_t daddr; + ipv4_address_t saddr; + ipv4_address_t daddr; } _ipv4_header_t; #define ipv4_header_bytes(ipv4_header) \ @@ -72,8 +72,8 @@ static_assert (EXPECTED_IPV4_HDRLEN == IPV4_HDRLEN, typedef struct { - ip4_address_t ip_src; - ip4_address_t ip_dst; + ipv4_address_t ip_src; + ipv4_address_t ip_dst; u8 zero; u8 protocol; u16 size; diff --git a/lib/includes/hicn/protocol/ipv6.h b/lib/includes/hicn/protocol/ipv6.h index 86301e7d1..6e8e30af3 100644 --- a/lib/includes/hicn/protocol/ipv6.h +++ b/lib/includes/hicn/protocol/ipv6.h @@ -42,8 +42,8 @@ typedef struct u8 vfc; /* 4 bits version, top 4 bits class */ }; #endif - ip6_address_t saddr; /* source address */ - ip6_address_t daddr; /* destination address */ + ipv6_address_t saddr; /* source address */ + ipv6_address_t daddr; /* destination address */ } _ipv6_header_t; #define IPV6_HDRLEN sizeof (_ipv6_header_t) @@ -57,8 +57,8 @@ static_assert (EXPECTED_IPV6_HDRLEN == IPV6_HDRLEN, typedef struct { - ip6_address_t ip_src; - ip6_address_t ip_dst; + ipv6_address_t ip_src; + ipv6_address_t ip_dst; u32 size; u16 zeros; u8 zero; diff --git a/lib/includes/hicn/protocol/new.h b/lib/includes/hicn/protocol/new.h index 47f7758d2..e688bef21 100644 --- a/lib/includes/hicn/protocol/new.h +++ b/lib/includes/hicn/protocol/new.h @@ -34,7 +34,7 @@ typedef struct u8 flags; u16 payload_length; u32 lifetime; - ip_address_t prefix; + hicn_ip_address_t prefix; u32 suffix; u32 path_label; } _new_header_t; diff --git a/lib/includes/hicn/util/bitmap.h b/lib/includes/hicn/util/bitmap.h index 11eb7870b..68541bc28 100644 --- a/lib/includes/hicn/util/bitmap.h +++ b/lib/includes/hicn/util/bitmap.h @@ -24,17 +24,26 @@ #define UTIL_BITMAP_H #include <assert.h> +#include <stdio.h> #include <string.h> #include <sys/param.h> // MIN, MAX -#include <hicn/util/log.h> - #include <hicn/common.h> #include <hicn/util/vector.h> -typedef uint_fast32_t bitmap_t; +typedef hicn_uword bitmap_t; + +#define WORD_WIDTH (sizeof (bitmap_t) * 8) +#define WORD_WIDTH (sizeof (bitmap_t) * 8) #define BITMAP_WIDTH(bitmap) (sizeof ((bitmap)[0]) * 8) +#define BITMAP_INVALID_INDEX ((uint32_t) (~0)) + +static inline int +get_lowest_set_bit_index (hicn_uword w) +{ + return hicn_uword_bits > 32 ? __builtin_ctzll (w) : __builtin_ctz (w); +} /** * @brief Allocate and initialize a bitmap @@ -79,13 +88,27 @@ bitmap_ensure_pos (bitmap_t **bitmap, off_t pos) * @param[in] i The bit position. */ static inline int -bitmap_get (const bitmap_t *bitmap, off_t i) +_bitmap_get (const bitmap_t *bitmap, off_t i) { size_t offset = i / BITMAP_WIDTH (bitmap); assert (offset < bitmap_get_alloc_size (bitmap)); size_t pos = i % BITMAP_WIDTH (bitmap); - size_t shift = BITMAP_WIDTH (bitmap) - pos - 1; - return (bitmap[offset] >> shift) & 1; + return (bitmap[offset] >> pos) & 1; +} + +/** + * @brief Retrieve the state of the i-th bit in the bitmap. + * Does not sanity check the position. + * + * @param[in] bitmap The bitmap to access. + * @param[in] i The bit position. + */ +static inline int +_bitmap_get_no_check (const bitmap_t *bitmap, off_t i) +{ + size_t offset = i / BITMAP_WIDTH (bitmap); + size_t pos = i % BITMAP_WIDTH (bitmap); + return (bitmap[offset] >> pos) & 1; } /* @@ -96,11 +119,36 @@ bitmap_get (const bitmap_t *bitmap, off_t i) * * @return bool */ -#define bitmap_is_set(bitmap, i) (bitmap_get ((bitmap), (i)) == 1) -#define bitmap_is_unset(bitmap, i) (bitmap_get ((bitmap), (i)) == 0) +#define bitmap_is_set(bitmap, i) (_bitmap_get ((bitmap), (i)) == 1) +#define bitmap_is_unset(bitmap, i) (_bitmap_get ((bitmap), (i)) == 0) + +#define bitmap_is_set_no_check(bitmap, i) \ + (_bitmap_get_no_check ((bitmap), (i)) == 1) +#define bitmap_is_unset_no_check(bitmap, i) \ + (_bitmap_get_no_check ((bitmap), (i)) == 0) + +static inline int +_bitmap_set_no_check (bitmap_t *bitmap, off_t i) +{ + size_t offset = i / BITMAP_WIDTH (bitmap); + size_t pos = i % BITMAP_WIDTH (bitmap); + bitmap[offset] |= (bitmap_t) 1 << pos; + return 0; +} + +static inline int +_bitmap_set (bitmap_t **bitmap_ptr, off_t i) +{ + if (bitmap_ensure_pos (bitmap_ptr, i) < 0) + return -1; + + bitmap_t *bitmap = *bitmap_ptr; + return _bitmap_set_no_check (bitmap, i); +} /* - * @brief Returns whether the i-th bit is unset (equal to 0) in a bitmap. + * @brief Set i-th bit to 1 in a bitmap. Reallocate the vector if the bit + * position is greater than the vector length. * * @param[in] bitmap The bitmap to access. * @param[in] i The bit position. @@ -110,38 +158,27 @@ bitmap_get (const bitmap_t *bitmap, off_t i) #define bitmap_set(bitmap, i) _bitmap_set ((bitmap_t **) &bitmap, i) /* - * @brief Returns whether the i-th bit is unset (equal to 0) in a bitmap - * (helper). + * @brief Set i-th bit to 1 in a bitmap. Unsafe version, does not check + * boundaries. * * @param[in] bitmap The bitmap to access. * @param[in] i The bit position. * * @return bool */ -static inline int -_bitmap_set (bitmap_t **bitmap_ptr, off_t i) -{ - if (bitmap_ensure_pos (bitmap_ptr, i) < 0) - return -1; - - bitmap_t *bitmap = *bitmap_ptr; - size_t offset = i / BITMAP_WIDTH (bitmap); - size_t pos = i % BITMAP_WIDTH (bitmap); - size_t shift = BITMAP_WIDTH (bitmap) - pos - 1; +#define bitmap_set_no_check(bitmap, i) _bitmap_set_no_check (bitmap, i) - bitmap[offset] |= (bitmap_t) 1 << shift; - return 0; -} +#define bitmap_unset(bitmap, i) _bitmap_unset (bitmap, i, 1) +#define bitmap_unset_no_check(bitmap, i) _bitmap_unset (bitmap, i, 0) static inline int -bitmap_unset (bitmap_t *bitmap, off_t i) +_bitmap_unset (bitmap_t *bitmap, off_t i, int check) { - if (bitmap_ensure_pos (&bitmap, i) < 0) + if (check && bitmap_ensure_pos (&bitmap, i) < 0) return -1; size_t offset = i / BITMAP_WIDTH (bitmap); size_t pos = i % BITMAP_WIDTH (bitmap); - size_t shift = BITMAP_WIDTH (bitmap) - pos - 1; - bitmap[offset] &= ~(1ul << shift); + bitmap[offset] &= ~(1ul << pos); return 0; } @@ -201,7 +238,6 @@ bitmap_set_range (bitmap_t *bitmap, off_t from, off_t to) return 0; END: - ERROR ("Error setting bitmap range\n"); return -1; } @@ -209,4 +245,88 @@ END: #define bitmap_free(bitmap) vector_free (bitmap) +static inline hicn_uword +bitmap_next_set_no_check (const bitmap_t *bitmap, hicn_uword i, size_t length) +{ + hicn_uword pos = i / WORD_WIDTH; + hicn_uword offset = i % WORD_WIDTH; + hicn_uword tmp; + hicn_uword mask = ~((1ULL << offset) - 1); + + if (pos < length) + { + // This will zeroes all bits < i + tmp = bitmap[pos] & mask; + if (tmp) + return get_lowest_set_bit_index (tmp) + pos * WORD_WIDTH; + + for (pos += 1; pos < length; pos++) + { + tmp = bitmap[pos]; + if (tmp) + return get_lowest_set_bit_index (tmp) + pos * WORD_WIDTH; + } + } + + return BITMAP_INVALID_INDEX; +} + +static inline hicn_uword +bitmap_next_set (const bitmap_t *bitmap, hicn_uword i) +{ + return bitmap_next_set_no_check (bitmap, i, vector_get_alloc_size (bitmap)); +} + +static inline hicn_uword +bitmap_next_unset_no_check (const bitmap_t *bitmap, hicn_uword i, + size_t length) +{ + hicn_uword pos = i / WORD_WIDTH; + hicn_uword offset = i % WORD_WIDTH; + hicn_uword tmp; + hicn_uword mask = ~((1ULL << offset) - 1); + + if (pos < length) + { + // This will zeroes all bits < i + tmp = ~bitmap[pos] & mask; + if (tmp) + return get_lowest_set_bit_index (tmp) + pos * WORD_WIDTH; + + for (pos += 1; pos < length; pos++) + { + tmp = ~bitmap[pos]; + if (tmp) + return get_lowest_set_bit_index (tmp) + pos * WORD_WIDTH; + } + } + return BITMAP_INVALID_INDEX; +} + +static inline hicn_uword +bitmap_next_unset (const bitmap_t *bitmap, hicn_uword i) +{ + return bitmap_next_unset_no_check (bitmap, i, + vector_get_alloc_size (bitmap)); +} + +#define bitmap_first_set(bitmap) bitmap_next_set (bitmap, 0) +#define bitmap_first_set_no_check(bitmap, size) \ + bitmap_next_set_no_check (bitmap, 0, size) + +#define bitmap_first_unset(bitmap) bitmap_next_unset (bitmap, 0) +#define bitmap_first_unset_no_check(bitmap, size) \ + bitmap_next_unset_no_check (bitmap, 0, size) + +static inline void +bitmap_print (const bitmap_t *bitmap, size_t n_words) +{ + for (size_t word = 0; word < n_words; word++) + { + for (int bit = sizeof (hicn_uword) - 1; bit >= 0; bit--) + (bitmap_is_set_no_check (&bitmap[word], bit)) ? printf ("1") : + printf ("0"); + } +} + #endif /* UTIL_BITMAP_H */ diff --git a/lib/includes/hicn/util/hash.h b/lib/includes/hicn/util/hash.h index ded8fc370..8dbe0d680 100644 --- a/lib/includes/hicn/util/hash.h +++ b/lib/includes/hicn/util/hash.h @@ -28,6 +28,7 @@ #define UTIL_HASH_H #include <stdint.h> +#include <stddef.h> // size_t #if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ __BYTE_ORDER == __LITTLE_ENDIAN) || \ diff --git a/lib/includes/hicn/util/ip_address.h b/lib/includes/hicn/util/ip_address.h index 89a4c11e0..55d5f5fc3 100644 --- a/lib/includes/hicn/util/ip_address.h +++ b/lib/includes/hicn/util/ip_address.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,10 +32,11 @@ #endif #include <errno.h> +#include <assert.h> #ifndef _WIN32 #include <netinet/in.h> // struct sockadd -#include <arpa/inet.h> -#include <netdb.h> // struct addrinfo +#include <arpa/inet.h> // inet_ntop +#include <netdb.h> // struct addrinfo #endif #include <stdbool.h> #include <stdlib.h> @@ -61,11 +62,10 @@ #endif //#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN -#define IP_MAX_ADDR_LEN IPV6_ADDR_LEN +#define IP_ADDRESS_MAX_LEN IPV6_ADDR_LEN #define DUMMY_PORT 1234 -#ifndef HICN_VPP_PLUGIN typedef union { struct in_addr as_inaddr; @@ -73,9 +73,11 @@ typedef union u8 as_u8[4]; u16 as_u16[2]; u32 as_u32; -} ip4_address_t; +} ipv4_address_t; -typedef union +static_assert (sizeof (ipv4_address_t) == 4, ""); + +typedef union __attribute__ ((__packed__)) { struct in6_addr as_in6addr; u8 buffer[16]; @@ -83,16 +85,24 @@ typedef union u16 as_u16[8]; u32 as_u32[4]; u64 as_u64[2]; -} ip6_address_t; +} ipv6_address_t; + +static_assert (sizeof (ipv6_address_t) == 16, ""); + +#ifdef HICN_VPP_PLUGIN +#include <vnet/ip/ip46_address.h> +static_assert (sizeof (ipv4_address_t) == sizeof (ip4_address_t), ""); +static_assert (sizeof (ipv6_address_t) == sizeof (ip6_address_t), ""); +#endif typedef union { struct { u32 pad[3]; - ip4_address_t v4; + ipv4_address_t v4; }; - ip6_address_t v6; + ipv6_address_t v6; #if 0 /* removed as prone to error due to IPv4 padding */ u8 buffer[IP_MAX_ADDR_LEN]; u8 as_u8[IP_MAX_ADDR_LEN]; @@ -100,28 +110,14 @@ typedef union u32 as_u32[IP_MAX_ADDR_LEN >> 2]; u64 as_u64[IP_MAX_ADDR_LEN >> 3]; #endif -} ip_address_t; - -#else - -#include <vnet/ip/ip4_packet.h> // ip4_address_t -#include <vnet/ip/ip6_packet.h> // ip6_address_t - -#if __GNUC__ >= 9 -#pragma GCC diagnostic ignored "-Waddress-of-packed-member" -#endif - -#include <vnet/ip/ip46_address.h> - -#if __GNUC__ >= 9 -#pragma GCC diagnostic pop -#endif - -typedef ip46_address_t ip_address_t; - +#ifdef HICN_VPP_PLUGIN + ip46_address_t as_ip46; #endif /* HICN_VPP_PLUGIN */ +} hicn_ip_address_t; + +static_assert (sizeof (hicn_ip_address_t) == 16, ""); -#define ip_address_is_v4(ip) \ +#define hicn_ip_address_is_v4(ip) \ (((ip)->pad[0] | (ip)->pad[1] | (ip)->pad[2]) == 0) #define MAXSZ_IP4_ADDRESS_ INET_ADDRSTRLEN - 1 @@ -131,24 +127,26 @@ typedef ip46_address_t ip_address_t; #define MAXSZ_IP6_ADDRESS MAXSZ_IP6_ADDRESS_ + 1 #define MAXSZ_IP_ADDRESS MAXSZ_IP_ADDRESS_ + 1 +#define IP_ADDRESS_V4_OFFSET_LEN 12 + typedef struct { int family; - ip_address_t address; + hicn_ip_address_t address; u8 len; -} ip_prefix_t; +} hicn_ip_prefix_t; #define MAXSZ_IP_PREFIX_ MAXSZ_IP_ADDRESS_ + 1 + 3 #define MAXSZ_IP_PREFIX MAXSZ_IP_PREFIX_ + 1 -extern const ip_address_t IPV4_LOOPBACK; -extern const ip_address_t IPV6_LOOPBACK; -extern const ip_address_t IPV4_ANY; -extern const ip_address_t IPV6_ANY; +extern const hicn_ip_address_t IPV4_LOOPBACK; +extern const hicn_ip_address_t IPV6_LOOPBACK; +extern const hicn_ip_address_t IPV4_ANY; +extern const hicn_ip_address_t IPV6_ANY; -extern const ip4_address_t IP4_ADDRESS_EMPTY; -extern const ip6_address_t IP6_ADDRESS_EMPTY; -extern const ip_address_t IP_ADDRESS_EMPTY; +extern const ipv4_address_t IP4_ADDRESS_EMPTY; +extern const ipv6_address_t IP6_ADDRESS_EMPTY; +extern const hicn_ip_address_t IP_ADDRESS_EMPTY; #define IP_ANY(family) (family == AF_INET) ? IPV4_ANY : IPV6_ANY @@ -161,32 +159,52 @@ extern const ip_address_t IP_ADDRESS_EMPTY; #define IS_VALID_FAMILY(x) ((x == AF_INET) || (x == AF_INET6)) /* IP address */ - -int ip_address_get_family (const char *ip_address); -int ip_address_len (int family); -const u8 *ip_address_get_buffer (const ip_address_t *ip_address, int family); -int ip_address_ntop (const ip_address_t *ip_address, char *dst, - const size_t len, int family); -int ip_address_pton (const char *ip_address_str, ip_address_t *ip_address); -int ip_address_snprintf (char *s, size_t size, const ip_address_t *ip_address, - int family); -int ip_address_to_sockaddr (const ip_address_t *ip_address, - struct sockaddr *sa, int family); -int ip_address_cmp (const ip_address_t *ip1, const ip_address_t *ip2, - int family); -int ip_address_empty (const ip_address_t *ip); +int hicn_ip_address_get_family (const hicn_ip_address_t *address); +int hicn_ip_address_str_get_family (const char *ip_address); +int hicn_ip_address_len (int family); +int hicn_ip_address_get_len (const hicn_ip_address_t *ip_address); + +int hicn_ip_address_get_len_bits (const hicn_ip_address_t *ip_address); +const u8 *hicn_ip_address_get_buffer (const hicn_ip_address_t *ip_address, + int family); +int hicn_ip_address_ntop (const hicn_ip_address_t *ip_address, char *dst, + const size_t len, int family); +int hicn_ip_address_pton (const char *ip_address_str, + hicn_ip_address_t *ip_address); +int hicn_ip_address_snprintf (char *s, size_t size, + const hicn_ip_address_t *ip_address); +int hicn_ip_address_to_sockaddr (const hicn_ip_address_t *ip_address, + struct sockaddr *sa, int family); +int hicn_ip_address_cmp (const hicn_ip_address_t *ip1, + const hicn_ip_address_t *ip2); +bool hicn_ip_address_equals (const hicn_ip_address_t *ip1, + const hicn_ip_address_t *ip2); +int hicn_ip_address_empty (const hicn_ip_address_t *ip); + +uint8_t hicn_ip_address_get_bit (const hicn_ip_address_t *address, + uint8_t pos); + +bool hicn_ip_address_match_family (const hicn_ip_address_t *address, + int family); + +uint32_t hicn_ip_address_get_hash (const hicn_ip_address_t *address); /* Prefix */ -int ip_prefix_pton (const char *ip_address_str, ip_prefix_t *ip_prefix); -int ip_prefix_ntop_short (const ip_prefix_t *ip_prefix, char *dst, - size_t size); -int ip_prefix_ntop (const ip_prefix_t *ip_prefix, char *dst, size_t size); -int ip_prefix_snprintf (char *s, size_t size, const ip_prefix_t *prefix); -int ip_prefix_len (const ip_prefix_t *prefix); -bool ip_prefix_empty (const ip_prefix_t *prefix); -int ip_prefix_to_sockaddr (const ip_prefix_t *prefix, struct sockaddr *sa); -int ip_prefix_cmp (const ip_prefix_t *prefix1, const ip_prefix_t *prefix2); +int hicn_ip_prefix_pton (const char *ip_address_str, + hicn_ip_prefix_t *hicn_ip_prefix); +int hicn_ip_prefix_ntop_short (const hicn_ip_prefix_t *hicn_ip_prefix, + char *dst, size_t size); +int hicn_ip_prefix_ntop (const hicn_ip_prefix_t *hicn_ip_prefix, char *dst, + size_t size); +int hicn_ip_prefix_snprintf (char *s, size_t size, + const hicn_ip_prefix_t *prefix); +int hicn_ip_prefix_len (const hicn_ip_prefix_t *prefix); +bool hicn_ip_prefix_empty (const hicn_ip_prefix_t *prefix); +int hicn_ip_prefix_to_sockaddr (const hicn_ip_prefix_t *prefix, + struct sockaddr *sa); +int hicn_ip_prefix_cmp (const hicn_ip_prefix_t *prefix1, + const hicn_ip_prefix_t *prefix2); /* URL */ @@ -200,7 +218,7 @@ int ip_prefix_cmp (const ip_prefix_t *prefix1, const ip_prefix_t *prefix2); #define MAXSZ_URL6 MAXSZ_URL6_ + NULLTERM #define MAXSZ_URL MAXSZ_URL_ + NULLTERM -int url_snprintf (char *s, size_t size, int family, - const ip_address_t *ip_address, u16 port); +int url_snprintf (char *s, size_t size, const hicn_ip_address_t *ip_address, + u16 port); #endif /* UTIL_IP_ADDRESS_H */ diff --git a/lib/includes/hicn/util/pool.h b/lib/includes/hicn/util/pool.h index 7488e08fd..b8acadc44 100644 --- a/lib/includes/hicn/util/pool.h +++ b/lib/includes/hicn/util/pool.h @@ -234,6 +234,26 @@ bool _pool_validate_id (void **pool_ptr, off_t id); } \ while (0) +#define pool_enumerate_typed(pool, i, TYPE, ELTP, BODY) \ + do \ + { \ + pool_hdr_t *_pool_var (ph) = pool_hdr (pool); \ + bitmap_t *_pool_var (fb) = _pool_var (ph)->free_bitmap; \ + TYPE ELTP = NULL; \ + for ((i) = 0; (i) < _pool_var (ph)->alloc_size; (i)++) \ + { \ + if (bitmap_is_set (_pool_var (fb), (i))) \ + continue; \ + ELTP = (pool) + (i); \ + do \ + { \ + BODY; \ + } \ + while (0); \ + } \ + } \ + while (0) + /** * @brief Iterate over elements in a pool. * @@ -256,6 +276,14 @@ bool _pool_validate_id (void **pool_ptr, off_t id); #define pool_get_alloc_size(pool) pool_hdr (pool)->alloc_size +#define pool_foreach_typed(pool, TYPE, ELTP, BODY) \ + do \ + { \ + unsigned _pool_var (i); \ + pool_enumerate_typed ((pool), _pool_var (i), TYPE, ELTP, BODY); \ + } \ + while (0) + #ifdef WITH_TESTS #define pool_get_free_indices(pool) pool_hdr (pool)->free_indices #define pool_get_free_bitmap(pool) pool_hdr (pool)->free_bitmap diff --git a/lib/includes/hicn/util/sstrncpy.h b/lib/includes/hicn/util/sstrncpy.h index b316201be..81427be6b 100644 --- a/lib/includes/hicn/util/sstrncpy.h +++ b/lib/includes/hicn/util/sstrncpy.h @@ -16,7 +16,10 @@ #ifndef UTIL_SSTRNCPY_H #define UTIL_SSTRNCPY_H +#ifndef __STDC_WANT_LIB_EXT1__ #define __STDC_WANT_LIB_EXT1__ 1 +#endif + #include <string.h> #ifdef __STDC_LIB_EXT1__ @@ -30,6 +33,9 @@ typedef int errno_t; #define EOK 0 +#ifndef HICN_VPP_PLUGIN +/* This function is already defined in vppinfra/string.h */ + /** * @brief This function assures a null byte at the end of the buffer. */ @@ -63,6 +69,7 @@ strnlen_s (const char *s, size_t maxlen) return strnlen (s, maxlen); } +#endif /* HICN_VPP_PLUGIN */ #endif /* __STDC_LIB_EXT1__ */ #endif /* UTIL_SSTRNCPY_H */ diff --git a/lib/includes/hicn/util/types.h b/lib/includes/hicn/util/types.h index 50c5362d3..a883b8220 100644 --- a/lib/includes/hicn/util/types.h +++ b/lib/includes/hicn/util/types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,11 +19,46 @@ #include <hicn/util/windows/windows_Utils.h> #endif +/* Standard types. */ +#include <stdint.h> + typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef double f64; +typedef float f32; + +/* Architecture-dependent uword size */ +#if INTPTR_MAX == INT64_MAX +#define hicn_log2_uword_bits 6 +#elif INTPTR_MAX == INT32_MAX +#define hicn_log2_uword_bits 5 +#else +#error "Impossible to detect architecture" +#endif + +#define _hicn_uword_bits (1 << hicn_log2_uword_bits) + +/* Word types. */ +#if _hicn_uword_bits == 64 +/* 64 bit word machines. */ +typedef u64 hicn_uword; +#define hicn_uword_bits 64 +#else +/* 32 bit word machines. */ +typedef u32 hicn_uword; +#define hicn_uword_bits 32 +#endif + +typedef hicn_uword hicn_ip_csum_t; + /* Helper for avoiding warnings about type-punning */ #define UNION_CAST(x, destType) \ (((union { \ @@ -32,12 +67,15 @@ typedef uint64_t u64; }) x) \ .b) -// typedef unsigned int hash_t; - typedef int (*cmp_t) (const void *, const void *); /* Enums */ #define IS_VALID_ENUM_TYPE(NAME, x) ((x > NAME##_UNDEFINED) && (x < NAME##_N)) +/* Float */ + +uint32_t htonf (float f); +float ntohf (uint32_t i); + #endif /* UTIL_TYPES */ diff --git a/lib/includes/hicn/util/vector.h b/lib/includes/hicn/util/vector.h index 46f195c6d..e693df9e3 100644 --- a/lib/includes/hicn/util/vector.h +++ b/lib/includes/hicn/util/vector.h @@ -209,7 +209,7 @@ static inline int _vector_get (void *vector, off_t pos, size_t elt_size, void *elt) { vector_hdr_t *vh = vector_hdr (vector); - if (pos >= vh->alloc_size) + if ((size_t) pos >= vh->alloc_size) return -1; memcpy (elt, (uint8_t *) vector + pos * elt_size, elt_size); @@ -228,7 +228,7 @@ _vector_get (void *vector, off_t pos, size_t elt_size, void *elt) static inline bool _vector_contains (void *vector, size_t elt_size, void *elt) { - for (int i = 0; i < vector_hdr (vector)->cur_size; i++) + for (size_t i = 0; i < vector_hdr (vector)->cur_size; i++) { if (memcmp ((uint8_t *) vector + i * elt_size, elt, elt_size) == 0) return true; @@ -251,7 +251,7 @@ static inline int _vector_remove_at (void **vector_ptr, size_t elt_size, off_t pos) { vector_hdr_t *vh = vector_hdr (*vector_ptr); - if (pos >= vh->cur_size) + if ((size_t) pos >= vh->cur_size) return -1; // Shift backward by one position all the elements after the one specified @@ -342,7 +342,7 @@ _vector_remove_at (void **vector_ptr, size_t elt_size, off_t pos) #define vector_at(vector, pos) \ ({ \ - assert (pos < vector_hdr (vector)->cur_size); \ + assert ((size_t) pos < vector_hdr (vector)->cur_size); \ (vector)[(pos)]; \ }) diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt index 8e81aa442..10c39fae2 100644 --- a/lib/src/CMakeLists.txt +++ b/lib/src/CMakeLists.txt @@ -15,13 +15,14 @@ # Source and Header files ############################################################## list(APPEND LIBHICN_SOURCE_FILES + base.c common.c - compat.c error.c face.c mapme.c name.c ops.c + packet.c policy.c strategy.c protocol/ah.c @@ -35,6 +36,7 @@ list(APPEND LIBHICN_SOURCE_FILES util/log.c util/pool.c util/ring.c + util/types.c util/vector.c ) @@ -72,6 +74,7 @@ endif() ############################################################## set(COMPILER_OPTIONS ${DEFAULT_COMPILER_OPTIONS} + PRIVATE "-Wno-address-of-packed-member" ) diff --git a/lib/src/base.c b/lib/src/base.c new file mode 100644 index 000000000..a15d55938 --- /dev/null +++ b/lib/src/base.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file base.c + * @brief Implementation of base hICN definitions. + */ + +#include <hicn/base.h> +#include "ops.h" + +const char *_hicn_packet_type_str[] = { +#define _(x) [HICN_PACKET_TYPE_##x] = #x, + foreach_packet_type +#undef _ +}; + +int +hicn_packet_format_snprintf (char *s, size_t size, hicn_packet_format_t format) +{ + char *cur = s; + int rc; + for (unsigned i = 0; i < 4; i++) + { + if (i > 0) + { + rc = snprintf (cur, size - (cur - s), " %s ", "/"); + if (rc < 0 || rc >= size - (cur - s)) + return rc; + cur += rc; + } + + rc = snprintf (cur, size - (cur - s), "%s", + hicn_ops_vft[format.as_u8[i]]->name); + if (rc < 0 || rc >= size - (cur - s)) + return rc; + cur += rc; + } + return (int) (cur - s); +} diff --git a/lib/src/compat.c b/lib/src/compat.c deleted file mode 100644 index cb771dbdd..000000000 --- a/lib/src/compat.c +++ /dev/null @@ -1,1268 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file compat.c - * @brief Implementation of the compatibility layer. - */ -#ifndef _WIN32 -#include <netinet/in.h> -#endif -#include <string.h> // memset -#include <stddef.h> // offsetof - -#include <hicn/common.h> -#include <hicn/compat.h> -#include <hicn/error.h> -#include <hicn/header.h> -#include <hicn/name.h> -#include <hicn/ops.h> - -#define member_size(type, member) sizeof (((type *) 0)->member) -#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a))) - -#define HICN_NAME_COMPONENT_SIZE 2 - -int -hicn_packet_get_format (const hicn_header_t *h, hicn_format_t *format) -{ - *format = HF_UNSPEC; - - switch (HICN_IP_VERSION (h)) - { - case 4: - switch (h->v4.ip.protocol) - { - case IPPROTO_TCP: - if (h->v4.tcp.flags & AH_FLAG) - *format = HF_INET_TCP_AH; - else - *format = HF_INET_TCP; - break; - case IPPROTO_UDP: - if (h->v4.newhdr.flags & HICN_NEW_FLAG_SIG) - *format = HF_INET_UDP_AH; - else - *format = HF_INET_UDP; - break; - case IPPROTO_ICMP: - *format = HF_INET_ICMP; - break; - default: - return HICN_LIB_ERROR_NOT_HICN; - } - break; - case 6: - switch (h->v6.ip.nxt) - { - case IPPROTO_TCP: - if (h->v6.tcp.flags & AH_FLAG) - *format = HF_INET6_TCP_AH; - else - *format = HF_INET6_TCP; - break; - case IPPROTO_UDP: - if (h->v6.newhdr.flags & HICN_NEW_FLAG_SIG) - *format = HF_INET6_UDP_AH; - else - *format = HF_INET6_UDP; - break; - case IPPROTO_ICMPV6: - *format = HF_INET6_ICMP; - break; - default: - return HICN_LIB_ERROR_NOT_HICN; - } - break; - case 9: - { - uint8_t ah = (HICN_NEW_FLAG_SIG & h->protocol.newhdr.flags); - *format = HF_NEW_AH * ah + (1 - ah) * HF_NEW; - break; - } - default: - return HICN_LIB_ERROR_NOT_HICN; - } - - return HICN_LIB_ERROR_NONE; -} - -/** - * @brief Convert (former) hICN format into (newer) hICN type - * @param [in] format - hICN format - * @return hICN type, all zero'ed if type is unknown - */ -hicn_type_t -hicn_format_to_type (hicn_format_t format) -{ - switch (format) - { - case HF_INET_TCP: - return HICN_TYPE_IPV4_TCP; - case HF_INET_UDP: - return HICN_TYPE_IPV4_UDP; - case HF_INET6_TCP: - return HICN_TYPE_IPV6_TCP; - case HF_INET6_UDP: - return HICN_TYPE_IPV6_UDP; - case HF_INET_ICMP: - return HICN_TYPE_IPV4_ICMP; - case HF_INET6_ICMP: - return HICN_TYPE_IPV6_ICMP; - case HF_NEW: - return HICN_TYPE_NEW; - case HF_INET_TCP_AH: - return HICN_TYPE_IPV4_TCP_AH; - case HF_INET_UDP_AH: - return HICN_TYPE_IPV4_UDP_AH; - case HF_INET6_TCP_AH: - return HICN_TYPE_IPV6_TCP_AH; - case HF_INET6_UDP_AH: - return HICN_TYPE_IPV6_UDP_AH; - case HF_INET_ICMP_AH: - return HICN_TYPE_IPV4_ICMP_AH; - case HF_INET6_ICMP_AH: - return HICN_TYPE_IPV6_ICMP_AH; - case HF_NEW_AH: - return HICN_TYPE_NEW_AH; - default: - break; - } - return HICN_TYPE_NONE; -} - -/** - * @brief Parse hICN header and return hICN type - * @param [in] h - hICN header - * @param [out] format - hICN type - * @return hICN error code - * - * This function is used to wrap old API calls to new ones - */ -hicn_type_t -hicn_header_to_type (const hicn_header_t *h) -{ - hicn_format_t format; - hicn_packet_get_format (h, &format); - return hicn_format_to_type (format); -} - -int -hicn_packet_init_header (hicn_format_t format, hicn_header_t *packet) -{ - hicn_type_t type = hicn_format_to_type (format); - - if (hicn_type_is_none (type)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - return hicn_ops_vft[type.l1]->init_packet_header (type, &packet->protocol); -} - -int -hicn_packet_compute_checksum (hicn_format_t format, hicn_header_t *h) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol, 0, ~0); -} - -int -hicn_packet_compute_header_checksum (hicn_format_t format, hicn_header_t *h, - u16 init_sum) -{ - hicn_type_t type = hicn_format_to_type (format); - /* payload_length == 0: ignore payload */ - return hicn_ops_vft[type.l1]->update_checksums (type, &h->protocol, init_sum, - 0); -} - -int -hicn_packet_check_integrity_no_payload (hicn_format_t format, hicn_header_t *h, - u16 init_sum) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->verify_checksums (type, &h->protocol, init_sum, - 0); -} - -int -hicn_packet_get_header_length_from_format (hicn_format_t format, - size_t *header_length) -{ - *header_length = _is_ipv4 (format) * IPV4_HDRLEN; - *header_length += _is_ipv6 (format) * IPV6_HDRLEN; - *header_length += _is_icmp (format) * ICMP_HDRLEN; - *header_length += _is_tcp (format) * TCP_HDRLEN; - *header_length += _is_udp (format) * UDP_HDRLEN; - *header_length += _is_cmpr (format) * NEW_HDRLEN; - *header_length += _is_ah (format) * AH_HDRLEN; - - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_get_header_length (hicn_format_t format, const hicn_header_t *h, - size_t *header_length) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol, - header_length); -} - -int -hicn_packet_get_payload_length (hicn_format_t format, const hicn_header_t *h, - size_t *payload_length) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol, - payload_length); -} - -int -hicn_packet_set_payload_length (hicn_format_t format, hicn_header_t *h, - const size_t payload_length) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->set_payload_length (type, &h->protocol, - payload_length); -} - -int -hicn_packet_compare (const hicn_header_t *packet1, - const hicn_header_t *packet2) -{ - hicn_type_t type1 = hicn_header_to_type (packet1); - hicn_type_t type2 = hicn_header_to_type (packet2); - - size_t len1, len2; - int rc; - - if (type1.as_u32 != type2.as_u32) - return HICN_LIB_ERROR_UNEXPECTED; - - rc = hicn_ops_vft[type1.l1]->get_length (type1, &packet1->protocol, &len1); - if (PREDICT_FALSE (rc < 0)) - return HICN_LIB_ERROR_UNEXPECTED; - - rc = hicn_ops_vft[type2.l1]->get_length (type2, &packet2->protocol, &len2); - if (PREDICT_FALSE (rc < 0)) - return HICN_LIB_ERROR_UNEXPECTED; - - if (len1 != len2) - return HICN_LIB_ERROR_UNEXPECTED; - - return memcmp ((u8 *) packet1, (u8 *) packet2, len1); -} - -int -hicn_packet_get_name (hicn_format_t format, const hicn_header_t *h, - hicn_name_t *name, u8 is_interest) -{ - hicn_type_t type = hicn_format_to_type (format); - - if (is_interest) - return hicn_ops_vft[type.l1]->get_interest_name (type, &h->protocol, name); - else - return hicn_ops_vft[type.l1]->get_data_name (type, &h->protocol, name); -} - -int -hicn_packet_set_name (hicn_format_t format, hicn_header_t *h, - const hicn_name_t *name, u8 is_interest) -{ - hicn_type_t type = hicn_format_to_type (format); - - if (is_interest) - return hicn_ops_vft[type.l1]->set_interest_name (type, &h->protocol, name); - else - return hicn_ops_vft[type.l1]->set_data_name (type, &h->protocol, name); -} - -int -hicn_packet_set_payload (hicn_format_t format, hicn_header_t *h, - const u8 *payload, u16 payload_length) -{ - hicn_type_t type = hicn_format_to_type (format); - size_t header_length; - int rc; - - rc = hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol, - &header_length); - if (rc < 0) - return rc; - - memcpy ((u8 *) h + header_length, payload, payload_length); - - return hicn_ops_vft[type.l1]->set_payload_length (type, &h->protocol, - payload_length); -} - -int -hicn_packet_get_payload (hicn_format_t format, const hicn_header_t *h, - u8 **payload, size_t *payload_size, bool hard_copy) -{ - size_t header_length, payload_length; - int rc; - hicn_type_t type = hicn_format_to_type (format); - - rc = hicn_ops_vft[type.l1]->get_header_length (type, &h->protocol, - &header_length); - if (rc < 0) - return rc; - - rc = hicn_ops_vft[type.l1]->get_payload_length (type, &h->protocol, - &payload_length); - if (rc < 0) - return rc; - - if (hard_copy) - { - memcpy (payload, (u8 *) h + header_length, payload_length); - } - else - { - *payload = (u8 *) h + header_length; - } - - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_get_locator (hicn_format_t format, const hicn_header_t *h, - ip_address_t *address, bool is_interest) -{ - hicn_type_t type = hicn_format_to_type (format); - if (is_interest) - return hicn_ops_vft[type.l1]->get_interest_locator (type, &h->protocol, - address); - else - return hicn_ops_vft[type.l1]->get_data_locator (type, &h->protocol, - address); -} - -int -hicn_packet_set_locator (hicn_format_t format, hicn_header_t *h, - const ip_address_t *address, bool is_interest) -{ - hicn_type_t type = hicn_format_to_type (format); - if (is_interest) - return hicn_ops_vft[type.l1]->set_interest_locator (type, &h->protocol, - address); - else - return hicn_ops_vft[type.l1]->set_data_locator (type, &h->protocol, - address); -} - -int -hicn_packet_get_signature_size (hicn_format_t format, const hicn_header_t *h, - size_t *bytes) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->get_signature_size (type, &h->protocol, bytes); -} - -int -hicn_packet_set_signature_size (hicn_format_t format, hicn_header_t *h, - size_t bytes) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->set_signature_size (type, &h->protocol, bytes); -} - -int -hicn_packet_get_signature_padding (hicn_format_t format, - const hicn_header_t *h, size_t *bytes) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->get_signature_padding (type, &h->protocol, - bytes); -} - -int -hicn_packet_set_signature_padding (hicn_format_t format, hicn_header_t *h, - size_t bytes) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->set_signature_padding (type, &h->protocol, - bytes); -} - -int -hicn_packet_set_signature_timestamp (hicn_format_t format, hicn_header_t *h, - uint64_t signature_timestamp) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->set_signature_timestamp (type, &h->protocol, - signature_timestamp); -} - -int -hicn_packet_get_signature_timestamp (hicn_format_t format, - const hicn_header_t *h, - uint64_t *signature_timestamp) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->get_signature_timestamp (type, &h->protocol, - signature_timestamp); -} - -int -hicn_packet_set_validation_algorithm (hicn_format_t format, hicn_header_t *h, - uint8_t validation_algorithm) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->set_validation_algorithm ( - type, &h->protocol, validation_algorithm); -} - -int -hicn_packet_get_validation_algorithm (hicn_format_t format, - const hicn_header_t *h, - uint8_t *validation_algorithm) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->get_validation_algorithm ( - type, &h->protocol, validation_algorithm); -} - -int -hicn_packet_set_key_id (hicn_format_t format, hicn_header_t *h, - uint8_t *key_id) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->set_key_id (type, &h->protocol, key_id); -} - -int -hicn_packet_get_key_id (hicn_format_t format, hicn_header_t *h, - uint8_t **key_id, uint8_t *key_id_length) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->get_key_id (type, &h->protocol, key_id, - key_id_length); -} - -int -hicn_packet_get_hoplimit (const hicn_header_t *h, u8 *hops) -{ - switch (HICN_IP_VERSION (h)) - { - case 6: - *hops = h->v6.ip.hlim; - break; - case 4: - *hops = h->v4.ip.ttl; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_set_hoplimit (hicn_header_t *h, u8 hops) -{ - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.ip.hlim = hops; - break; - case 4: - h->v4.ip.ttl = hops; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_is_interest (hicn_format_t format, const hicn_header_t *h, - int *ret) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->is_interest (type, &h->protocol, ret); -} - -int -hicn_packet_set_interest (hicn_format_t format, hicn_header_t *h) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->mark_packet_as_interest (type, &h->protocol); -} - -int -hicn_packet_set_data (hicn_format_t format, hicn_header_t *h) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->mark_packet_as_data (type, &h->protocol); -} - -int -hicn_packet_get_lifetime (hicn_format_t format, const hicn_header_t *h, - u32 *lifetime) -{ - hicn_type_t type = hicn_header_to_type (h); - return hicn_ops_vft[type.l1]->get_lifetime (type, &h->protocol, - (hicn_lifetime_t *) lifetime); -} - -int -hicn_packet_set_lifetime (hicn_format_t format, hicn_header_t *h, u32 lifetime) -{ - hicn_type_t type = hicn_header_to_type (h); - return hicn_ops_vft[type.l1]->set_lifetime (type, &h->protocol, - (hicn_lifetime_t) lifetime); -} - -int -hicn_packet_get_reserved_bits (const hicn_header_t *h, u8 *reserved_bits) -{ - switch (HICN_IP_VERSION (h)) - { - case 6: - *reserved_bits = (u8) (h->v6.tcp.reserved); - break; - case 4: - *reserved_bits = (u8) (h->v4.tcp.reserved); - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_set_reserved_bits (hicn_header_t *h, const u8 reserved_bits) -{ - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.reserved = reserved_bits; - break; - case 4: - h->v4.tcp.reserved = reserved_bits; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_get_payload_type (hicn_format_t format, const hicn_header_t *h, - hicn_payload_type_t *payload_type) -{ - hicn_type_t type = hicn_header_to_type (h); - return hicn_ops_vft[type.l1]->get_payload_type (type, &h->protocol, - payload_type); -} - -int -hicn_packet_set_payload_type (hicn_format_t format, hicn_header_t *h, - hicn_payload_type_t payload_type) -{ - hicn_type_t type = hicn_header_to_type (h); - return hicn_ops_vft[type.l1]->set_payload_type (type, &h->protocol, - payload_type); -} - -int -hicn_packet_set_syn (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_SYN; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_SYN; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_reset_syn (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_SYN; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_SYN; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_test_syn (hicn_format_t format, const hicn_header_t *h, bool *flag) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - *flag = h->v6.tcp.flags & HICN_TCP_FLAG_SYN; - break; - case 4: - *flag = h->v4.tcp.flags & HICN_TCP_FLAG_SYN; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_set_ack (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_ACK; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_ACK; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_reset_ack (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_ACK; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_ACK; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_test_ack (hicn_format_t format, const hicn_header_t *h, bool *flag) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - *flag = h->v6.tcp.flags & HICN_TCP_FLAG_ACK; - break; - case 4: - *flag = h->v4.tcp.flags & HICN_TCP_FLAG_ACK; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_set_rst (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_RST; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_RST; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_reset_rst (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_RST; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_RST; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_test_rst (hicn_format_t format, const hicn_header_t *h, bool *flag) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - *flag = h->v6.tcp.flags & HICN_TCP_FLAG_RST; - break; - case 4: - *flag = h->v4.tcp.flags & HICN_TCP_FLAG_RST; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_set_fin (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_FIN; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_FIN; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_reset_fin (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_FIN; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_FIN; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_test_fin (hicn_format_t format, const hicn_header_t *h, bool *flag) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - *flag = h->v6.tcp.flags & HICN_TCP_FLAG_FIN; - break; - case 4: - *flag = h->v4.tcp.flags & HICN_TCP_FLAG_FIN; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_set_ece (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags | HICN_TCP_FLAG_ECE; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags | HICN_TCP_FLAG_ECE; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_reset_ece (hicn_format_t format, hicn_header_t *h) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.flags = h->v6.tcp.flags & ~HICN_TCP_FLAG_ECE; - break; - case 4: - h->v4.tcp.flags = h->v4.tcp.flags & ~HICN_TCP_FLAG_ECE; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_test_ece (hicn_format_t format, const hicn_header_t *h, bool *flag) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - *flag = h->v6.tcp.flags & HICN_TCP_FLAG_ECE; - break; - case 4: - *flag = h->v4.tcp.flags & HICN_TCP_FLAG_ECE; - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_set_src_port (hicn_format_t format, hicn_header_t *h, u16 src_port) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.sport = htons (src_port); - break; - case 4: - h->v4.tcp.sport = htons (src_port); - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_get_src_port (hicn_format_t format, const hicn_header_t *h, - u16 *src_port) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - *src_port = ntohs (h->v6.tcp.sport); - break; - case 4: - *src_port = ntohs (h->v4.tcp.sport); - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_set_dst_port (hicn_format_t format, hicn_header_t *h, u16 dst_port) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - h->v6.tcp.dport = htons (dst_port); - break; - case 4: - h->v4.tcp.dport = htons (dst_port); - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_get_dst_port (hicn_format_t format, const hicn_header_t *h, - u16 *dst_port) -{ - if (!_is_tcp (format)) - { - return HICN_LIB_ERROR_UNEXPECTED; - } - - switch (HICN_IP_VERSION (h)) - { - case 6: - *dst_port = ntohs (h->v6.tcp.dport); - break; - case 4: - *dst_port = ntohs (h->v4.tcp.dport); - break; - default: - return HICN_LIB_ERROR_UNEXPECTED; - } - return HICN_LIB_ERROR_NONE; -} - -int -hicn_packet_copy_header (hicn_format_t format, const hicn_header_t *packet, - hicn_header_t *destination, bool copy_ah) -{ - size_t header_length = _is_ipv4 (format) * IPV4_HDRLEN; - header_length += _is_ipv6 (format) * IPV6_HDRLEN; - header_length += _is_icmp (format) * ICMP_HDRLEN; - header_length += _is_tcp (format) * TCP_HDRLEN; - header_length += _is_ah (format) * copy_ah * AH_HDRLEN; - - memcpy (destination, packet, header_length); - - return HICN_LIB_ERROR_NONE; -} - -#define _INTEREST 1 -#define _DATA 0 - -/* Interest */ - -int -hicn_interest_get_name (hicn_format_t format, const hicn_header_t *interest, - hicn_name_t *name) -{ - return hicn_packet_get_name (format, interest, name, _INTEREST); -} - -int -hicn_interest_set_name (hicn_format_t format, hicn_header_t *interest, - const hicn_name_t *name) -{ - return hicn_packet_set_name (format, interest, name, _INTEREST); -} - -int -hicn_interest_get_locator (hicn_format_t format, const hicn_header_t *interest, - ip_address_t *address) -{ - return hicn_packet_get_locator (format, interest, address, _INTEREST); -} - -int -hicn_interest_set_locator (hicn_format_t format, hicn_header_t *interest, - const ip_address_t *address) -{ - return hicn_packet_set_locator (format, interest, address, _INTEREST); -} - -int -hicn_interest_compare (const hicn_header_t *interest_1, - const hicn_header_t *interest_2) -{ - return hicn_packet_compare (interest_1, interest_2); -} - -int -hicn_interest_get_lifetime (const hicn_header_t *interest, u32 *lifetime) -{ - hicn_format_t format; - int rc = hicn_packet_get_format (interest, &format); - - if (rc) - return rc; - - return hicn_packet_get_lifetime (format, interest, lifetime); -} - -int -hicn_interest_set_lifetime (hicn_header_t *interest, u32 lifetime) -{ - hicn_format_t format; - int rc = hicn_packet_get_format (interest, &format); - - if (rc) - return rc; - - return hicn_packet_set_lifetime (format, interest, lifetime); -} - -int -hicn_interest_get_header_length (hicn_format_t format, - const hicn_header_t *interest, - size_t *header_length) -{ - return hicn_packet_get_header_length (format, interest, header_length); -} - -int -hicn_interest_get_payload_length (hicn_format_t format, - const hicn_header_t *interest, - size_t *payload_length) -{ - return hicn_packet_get_payload_length (format, interest, payload_length); -} - -int -hicn_interest_get_payload (hicn_format_t format, const hicn_header_t *interest, - u8 **payload, size_t *payload_size, bool hard_copy) -{ - return hicn_packet_get_payload (format, interest, payload, payload_size, - hard_copy); -} - -int -hicn_interest_set_payload (hicn_format_t format, hicn_header_t *interest, - const u8 *payload, size_t payload_length) -{ - return hicn_packet_set_payload (format, interest, payload, - (u16) payload_length); -} - -int -hicn_interest_reset_for_hash (hicn_format_t format, hicn_header_t *packet) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->reset_interest_for_hash (type, - &packet->protocol); -} - -/* Data */ - -int -hicn_data_get_name (hicn_format_t format, const hicn_header_t *data, - hicn_name_t *name) -{ - return hicn_packet_get_name (format, data, name, _DATA); -} - -int -hicn_data_set_name (hicn_format_t format, hicn_header_t *data, - const hicn_name_t *name) -{ - return hicn_packet_set_name (format, data, name, _DATA); -} - -int -hicn_data_get_locator (hicn_format_t format, const hicn_header_t *data, - ip_address_t *address) -{ - return hicn_packet_get_locator (format, data, address, _DATA); -} - -int -hicn_data_set_locator (hicn_format_t format, hicn_header_t *data, - const ip_address_t *address) -{ - return hicn_packet_set_locator (format, data, address, _DATA); -} - -int -hicn_data_compare (const hicn_header_t *data_1, const hicn_header_t *data_2) -{ - return hicn_packet_compare (data_1, data_2); -} - -int -hicn_data_get_expiry_time (const hicn_header_t *data, u32 *expiry_time) -{ - hicn_format_t format; - int rc = hicn_packet_get_format (data, &format); - - if (rc) - return rc; - - return hicn_packet_get_lifetime (format, data, expiry_time); -} - -int -hicn_data_set_expiry_time (hicn_header_t *data, u32 expiry_time) -{ - hicn_format_t format; - int rc = hicn_packet_get_format (data, &format); - - if (rc) - return rc; - - return hicn_packet_set_lifetime (format, data, - (hicn_lifetime_t) expiry_time); -} - -int -hicn_data_get_header_length (hicn_format_t format, hicn_header_t *data, - size_t *header_length) -{ - return hicn_packet_get_header_length (format, data, header_length); -} - -int -hicn_data_get_payload_length (hicn_format_t format, const hicn_header_t *data, - size_t *payload_length) -{ - return hicn_packet_get_payload_length (format, data, payload_length); -} - -int -hicn_data_get_path_label (const hicn_header_t *data, u32 *path_label) -{ - hicn_type_t type = hicn_header_to_type (data); - return hicn_ops_vft[type.l1]->get_data_pathlabel (type, &data->protocol, - path_label); -} - -int -hicn_data_set_path_label (hicn_header_t *data, u32 path_label) -{ - hicn_type_t type = hicn_header_to_type (data); - return hicn_ops_vft[type.l1]->set_data_pathlabel (type, &data->protocol, - path_label); -} - -int -hicn_data_set_payload (hicn_format_t format, hicn_header_t *data, - const u8 *payload, size_t payload_length) -{ - return hicn_packet_set_payload (format, data, payload, (u16) payload_length); -} - -int -hicn_data_get_payload (hicn_format_t format, const hicn_header_t *data, - u8 **payload, size_t *payload_size, bool hard_copy) -{ - return hicn_packet_get_payload (format, data, payload, payload_size, - hard_copy); -} - -int -hicn_data_reset_for_hash (hicn_format_t format, hicn_header_t *packet) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->reset_data_for_hash (type, &packet->protocol); -} - -int -hicn_data_is_last (hicn_format_t format, hicn_header_t *h, int *is_last) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->is_last_data (type, &h->protocol, is_last); -} - -int -hicn_data_set_last (hicn_format_t format, hicn_header_t *h) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->set_last_data (type, &h->protocol); -} - -int -hicn_packet_get_signature (hicn_format_t format, hicn_header_t *packet, - uint8_t **sign_buf) -{ - hicn_type_t type = hicn_format_to_type (format); - return hicn_ops_vft[type.l1]->get_signature (type, &packet->protocol, - sign_buf); -} - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/lib/src/face.c b/lib/src/face.c index 46b36e8cd..832cd0936 100644 --- a/lib/src/face.c +++ b/lib/src/face.c @@ -142,6 +142,12 @@ netdevice_cmp (const netdevice_t *nd1, const netdevice_t *nd2) return (nd1->index - nd2->index); } +bool +netdevice_is_empty (const netdevice_t *netdevice) +{ + return (netdevice->index != 0) || (netdevice->name[0] != '\0'); +} + /* Face state */ const char *_face_state_str[] = { @@ -181,8 +187,8 @@ face_initialize (face_t *face) int face_initialize_udp (face_t *face, const char *interface_name, - const ip_address_t *local_addr, u16 local_port, - const ip_address_t *remote_addr, u16 remote_port, + const hicn_ip_address_t *local_addr, u16 local_port, + const hicn_ip_address_t *remote_addr, u16 remote_port, int family) { if (!local_addr) @@ -264,9 +270,10 @@ face_create () } face_t * -face_create_udp (const char *interface_name, const ip_address_t *local_addr, - u16 local_port, const ip_address_t *remote_addr, - u16 remote_port, int family) +face_create_udp (const char *interface_name, + const hicn_ip_address_t *local_addr, u16 local_port, + const hicn_ip_address_t *remote_addr, u16 remote_port, + int family) { face_t *face = face_create (); if (face_initialize_udp (face, interface_name, local_addr, local_port, @@ -336,11 +343,11 @@ face_cmp (const face_t *f1, const face_t *f2) switch (f1->type) { case FACE_TYPE_HICN: - ret = ip_address_cmp (&f1->local_addr, &f2->local_addr, f1->family); + ret = hicn_ip_address_cmp (&f1->local_addr, &f2->local_addr); if (ret != 0) return ret; - ret = ip_address_cmp (&f1->remote_addr, &f2->remote_addr, f1->family); + ret = hicn_ip_address_cmp (&f1->remote_addr, &f2->remote_addr); if (ret != 0) return ret; @@ -348,7 +355,7 @@ face_cmp (const face_t *f1, const face_t *f2) case FACE_TYPE_TCP: case FACE_TYPE_UDP: - ret = ip_address_cmp (&f1->local_addr, &f2->local_addr, f1->family); + ret = hicn_ip_address_cmp (&f1->local_addr, &f2->local_addr); if (ret != 0) return ret; @@ -356,7 +363,7 @@ face_cmp (const face_t *f1, const face_t *f2) if (ret != 0) return ret; - ret = ip_address_cmp (&f1->remote_addr, &f2->remote_addr, f1->family); + ret = hicn_ip_address_cmp (&f1->remote_addr, &f2->remote_addr); if (ret != 0) return ret; @@ -376,19 +383,24 @@ face_cmp (const face_t *f1, const face_t *f2) size_t face_snprintf (char *s, size_t size, const face_t *face) { + char local[MAXSZ_IP_ADDRESS]; + char remote[MAXSZ_IP_ADDRESS]; + char tags[MAXSZ_POLICY_TAGS]; + + if (!hicn_ip_address_match_family (&face->local_addr, face->family)) + return 0; + if (!hicn_ip_address_match_family (&face->remote_addr, face->family)) + return 0; + + hicn_ip_address_snprintf (local, MAXSZ_IP_ADDRESS, &face->local_addr); + hicn_ip_address_snprintf (remote, MAXSZ_IP_ADDRESS, &face->remote_addr); + policy_tags_snprintf (tags, MAXSZ_POLICY_TAGS, face->tags); + switch (face->type) { case FACE_TYPE_HICN: { - char local[MAXSZ_IP_ADDRESS]; - char remote[MAXSZ_IP_ADDRESS]; - char tags[MAXSZ_POLICY_TAGS]; - - ip_address_snprintf (local, MAXSZ_IP_ADDRESS, &face->local_addr, - face->family); - ip_address_snprintf (remote, MAXSZ_IP_ADDRESS, &face->remote_addr, - face->family); - policy_tags_snprintf (tags, MAXSZ_POLICY_TAGS, face->tags); + return snprintf (s, size, "%s [%s -> %s] [%s]", face_type_str (face->type), local, remote, tags); } @@ -396,16 +408,6 @@ face_snprintf (char *s, size_t size, const face_t *face) case FACE_TYPE_TCP: case FACE_TYPE_UDP: { - char local[MAXSZ_IP_ADDRESS]; - char remote[MAXSZ_IP_ADDRESS]; - char tags[MAXSZ_POLICY_TAGS]; - - ip_address_snprintf (local, MAXSZ_IP_ADDRESS, &face->local_addr, - face->family); - ip_address_snprintf (remote, MAXSZ_IP_ADDRESS, &face->remote_addr, - face->family); - policy_tags_snprintf (tags, MAXSZ_POLICY_TAGS, face->tags); - return snprintf (s, size, "%s [%s:%d -> %s:%d] [%s]", face_type_str (face->type), local, face->local_port, remote, face->remote_port, tags); diff --git a/lib/src/mapme.c b/lib/src/mapme.c index b8e8eaed2..3f864e768 100644 --- a/lib/src/mapme.c +++ b/lib/src/mapme.c @@ -22,8 +22,44 @@ #include <hicn/common.h> #include <hicn/error.h> -#include <hicn/protocol/ipv4.h> -#include <hicn/protocol/ipv6.h> +#include "protocol/ipv4.h" +#include "protocol/ipv6.h" +#include "protocol/icmprd.h" + +/** @brief MAP-Me packet header for IPv4 */ +typedef struct +{ + _ipv4_header_t ip; + _icmprd4_header_t icmp_rd; + seq_t seq; + u8 len; + u8 _pad[3]; +} hicn_mapme_v4_header_t; + +/** @brief MAP-Me packet header for IPv6 */ +typedef struct +{ + _ipv6_header_t ip; + _icmprd_header_t icmp_rd; + seq_t seq; + u8 len; + u8 _pad[3]; +} hicn_mapme_v6_header_t; + +/** @brief MAP-Me packet header (IP version agnostic) */ +typedef union +{ + hicn_mapme_v4_header_t v4; + hicn_mapme_v6_header_t v6; +} hicn_mapme_header_t; + +#define HICN_MAPME_V4_HDRLEN sizeof (hicn_mapme_v4_header_t) +#define HICN_MAPME_V6_HDRLEN sizeof (hicn_mapme_v6_header_t) + +static_assert (EXPECTED_MAPME_V4_HDRLEN == HICN_MAPME_V4_HDRLEN, + "Size of MAPME_V4 struct does not match its expected size."); +static_assert (EXPECTED_MAPME_V6_HDRLEN == HICN_MAPME_V6_HDRLEN, + "Size of MAPME_V6 struct does not match its expected size."); size_t hicn_mapme_v4_create_packet (u8 *buf, const hicn_prefix_t *prefix, @@ -96,7 +132,7 @@ hicn_mapme_create_packet (u8 *buf, const hicn_prefix_t *prefix, const mapme_params_t *params) { /* We currently ignore subsequent protocol definitions */ - if (PREDICT_TRUE (params->protocol == IPPROTO_IPV6)) + if (HICN_EXPECT_TRUE (params->protocol == IPPROTO_IPV6)) return hicn_mapme_v6_create_packet (buf, prefix, params); else return hicn_mapme_v4_create_packet (buf, prefix, params); @@ -105,7 +141,7 @@ hicn_mapme_create_packet (u8 *buf, const hicn_prefix_t *prefix, size_t hicn_mapme_v4_create_ack (u8 *buf, const mapme_params_t *params) { - ip4_address_t tmp; // tmp storage for swapping IP addresses for ACK + ipv4_address_t tmp; // tmp storage for swapping IP addresses for ACK hicn_mapme_v4_header_t *mh = (hicn_mapme_v4_header_t *) buf; tmp = mh->ip.daddr; @@ -121,7 +157,7 @@ hicn_mapme_v4_create_ack (u8 *buf, const mapme_params_t *params) size_t hicn_mapme_v6_create_ack (u8 *buf, const mapme_params_t *params) { - ip6_address_t tmp; // tmp storage for swapping IP addresses for ACK + ipv6_address_t tmp; // tmp storage for swapping IP addresses for ACK hicn_mapme_v6_header_t *mh = (hicn_mapme_v6_header_t *) buf; tmp = mh->ip.daddr; @@ -138,7 +174,7 @@ size_t hicn_mapme_create_ack (u8 *buf, const mapme_params_t *params) { /* We currently ignore subsequent protocol definitions */ - if (PREDICT_TRUE (params->protocol == IPPROTO_IPV6)) + if (HICN_EXPECT_TRUE (params->protocol == IPPROTO_IPV6)) return hicn_mapme_v6_create_ack (buf, params); else return hicn_mapme_v4_create_ack (buf, params); @@ -205,8 +241,9 @@ hicn_mapme_parse_packet (const u8 *packet, hicn_prefix_t *prefix, case 6: return hicn_mapme_v6_parse_packet (packet, prefix, params); default: - return HICN_LIB_ERROR_UNEXPECTED; + break; } + return HICN_LIB_ERROR_UNEXPECTED; } /* diff --git a/lib/src/name.c b/lib/src/name.c index 3bdcbbdb4..04c48cb4d 100644 --- a/lib/src/name.c +++ b/lib/src/name.c @@ -31,6 +31,8 @@ #include <hicn/name.h> #include <hicn/util/sstrncpy.h> +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + int hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name) { @@ -55,11 +57,20 @@ hicn_name_create (const char *ip_address, u32 id, hicn_name_t *name) } int -hicn_name_create_from_ip_prefix (const ip_prefix_t *prefix, u32 id, +hicn_name_create_from_ip_address (const hicn_ip_address_t ip_address, + u32 suffix, hicn_name_t *name) +{ + name->prefix = ip_address; + name->suffix = suffix; + + return HICN_LIB_ERROR_NONE; +} + +int +hicn_name_create_from_ip_prefix (const hicn_ip_prefix_t *prefix, u32 id, hicn_name_t *name) { - name->prefix.v6.as_u64[0] = prefix->address.v6.as_u64[0]; - name->prefix.v6.as_u64[1] = prefix->address.v6.as_u64[1]; + name->prefix = prefix->address; name->suffix = id; return HICN_LIB_ERROR_NONE; @@ -79,15 +90,15 @@ hicn_name_compare (const hicn_name_t *name_1, const hicn_name_t *name_2, return ret; } -int -hicn_name_hash (const hicn_name_t *name, u32 *hash, bool consider_suffix) +uint32_t +_hicn_name_get_hash (const hicn_name_t *name, bool consider_suffix) { - *hash = hash32 (&name->prefix, sizeof (name->prefix)); + uint32_t hash = hash32 (&name->prefix, sizeof (name->prefix)); if (consider_suffix) - *hash = cumulative_hash32 (&name->suffix, sizeof (name->suffix), *hash); + hash = cumulative_hash32 (&name->suffix, sizeof (name->suffix), hash); - return HICN_LIB_ERROR_NONE; + return hash; } int @@ -116,9 +127,9 @@ hicn_name_copy_prefix_to_destination (u8 *dst, const hicn_name_t *name) } int -hicn_name_set_seq_number (hicn_name_t *name, u32 seq_number) +hicn_name_set_suffix (hicn_name_t *name, hicn_name_suffix_t suffix) { - name->suffix = seq_number; + name->suffix = suffix; return HICN_LIB_ERROR_NONE; } @@ -149,7 +160,7 @@ hicn_name_to_sockaddr_address (const hicn_name_t *name, } int -hicn_name_to_ip_prefix (const hicn_name_t *name, ip_prefix_t *prefix) +hicn_name_to_hicn_ip_prefix (const hicn_name_t *name, hicn_ip_prefix_t *prefix) { int family, rc; rc = hicn_name_get_family (name, &family); @@ -211,24 +222,247 @@ hicn_name_get_family (const hicn_name_t *name, int *family) return HICN_LIB_ERROR_NONE; } +bool +hicn_name_is_v4 (const hicn_name_t *name) +{ + return _is_inet4 (name); +} + int -hicn_prefix_create_from_ip_prefix (const ip_prefix_t *ip_prefix, +hicn_name_snprintf (char *s, size_t size, const hicn_name_t *name) +{ + int n, rc; + n = hicn_ip_address_snprintf (s, size, &name->prefix); + if (n < 0 || n >= size) + return n; + rc = snprintf (s + n, size - n, "|%d", name->suffix); + if (rc < 0) + return rc; + return rc + n; +} + +int +hicn_prefix_create_from_ip_prefix (const hicn_ip_prefix_t *hicn_ip_prefix, hicn_prefix_t *prefix) { - switch (ip_prefix->family) + if (hicn_ip_prefix->family != AF_INET || hicn_ip_prefix->family != AF_INET6) + return HICN_LIB_ERROR_INVALID_IP_ADDRESS; + prefix->name = hicn_ip_prefix->address; + prefix->len = (u8) (hicn_ip_prefix->len); + + return HICN_LIB_ERROR_NONE; +} + +int +hicn_name_cmp (const hicn_name_t *n1, const hicn_name_t *n2) +{ + int rc = hicn_ip_address_cmp (&n1->prefix, &n2->prefix); + if (rc != 0) + return rc; + return n2->suffix - n1->suffix; +} + +bool +hicn_name_equals (const hicn_name_t *n1, const hicn_name_t *n2) +{ + return (hicn_name_cmp (n1, n2) == 0); +} + +int +hicn_prefix_create_from_ip_address_len (const hicn_ip_address_t *ip_address, + uint8_t len, hicn_prefix_t *prefix) +{ + prefix->name = *ip_address; + prefix->len = len; + + return HICN_LIB_ERROR_NONE; +} + +hicn_prefix_t * +hicn_prefix_dup (const hicn_prefix_t *prefix) +{ + hicn_prefix_t *copy = malloc (sizeof (hicn_prefix_t)); + if (!copy) + goto ERR_MALLOC; + if (hicn_prefix_copy (copy, prefix) < 0) + goto ERR_COPY; + return copy; + +ERR_COPY: + free (copy); +ERR_MALLOC: + return NULL; +} + +int +hicn_prefix_copy (hicn_prefix_t *dst, const hicn_prefix_t *src) +{ + dst->name = src->name; + dst->len = src->len; + return 0; +} + +bool +hicn_prefix_is_v4 (const hicn_prefix_t *prefix) +{ + return hicn_ip_address_is_v4 (&prefix->name); +} + +/* + * The ip address is in network byte order (big endian, msb last) in + * hicn_{prefix,name}_t, as in ip_address_t which builds upon struct in*_addr, + * But the bits are in host order... so we cannot use builtin functions to get + * the position of the first 1 unless we swap bytes as was done previously, + * which is costly and non-essential. + */ + +uint64_t +_log2_nbo (uint64_t val) +{ + assert (val != 0); /* There is at least 1 bit set (network byte order) */ + + uint64_t result = 0; + + if (val & 0xFFFFFFFF00000000) + val = val >> 32; + else + /* The first 32 bits of val are 0 */ + result = result | 32; + + if (val & 0xFFFF0000) + val = val >> 16; + else + result = result | 16; + + if (val & 0xFF00) + val = val >> 8; + else + result = result | 8; + + /* Val now contains the byte with at last 1 bit set (host bit order) */ + if (val & 0xF0) { - case AF_INET: - prefix->name.v4.as_u32 = ip_prefix->address.v4.as_u32; - break; - case AF_INET6: - prefix->name.v6.as_u64[0] = ip_prefix->address.v6.as_u64[0]; - prefix->name.v6.as_u64[1] = ip_prefix->address.v6.as_u64[1]; - break; - default: - return HICN_LIB_ERROR_INVALID_IP_ADDRESS; + val = val >> 4; + result = result | 4; } - prefix->len = (u8) (ip_prefix->len); + if (val & 0xC) + { + val = val >> 2; + result = result | 2; + } + if (val & 0x2) + { + val = val >> 1; + result = result | 1; + } + + return result; +} + +uint32_t +hicn_prefix_lpm (const hicn_prefix_t *p1, const hicn_prefix_t *p2) +{ + uint32_t prefix_len = 0; + /* Test each block of 64 bits as a whole */ + for (unsigned i = 0; i < 2; i++) + { + + /* Check for differences in the two u64 */ + uint64_t diff = p1->name.v6.as_u64[i] ^ p2->name.v6.as_u64[i]; + if (diff) + { + /* + * As the ip_address_t mimics in*_addr and has network byte order + * (and host bit order, we cannot directly use 64-bit operations: + * + * Example: + * + * bits | 7 .. 0 | 15 14 13 12 11 10 9 8 | .. | 127 .. 120 | + * diff | | 1 0 1 0 0 0 0 0 | .. | | + * ^ + * bit of interest ---------+ + */ + prefix_len += _log2_nbo (diff); + break; + } + prefix_len += 8 * sizeof (uint64_t); + } + + /* Bound the returned prefix length by the length of all input */ + return MIN (prefix_len, + MIN (hicn_prefix_get_len (p1), hicn_prefix_get_len (p2))); +} + +void +hicn_prefix_clear (hicn_prefix_t *prefix, uint8_t start_from) +{ + uint8_t *buffer = prefix->name.v6.as_u8; + + /* Compute the offset of the byte from which to clear the name... */ + uint8_t offset = start_from / 8; + if (hicn_prefix_is_v4 (prefix)) + offset += IP_ADDRESS_V4_OFFSET_LEN; /* Ignore padding */ + /* ... and the position of the first bit to clear */ + uint8_t pos = start_from % 8; + + /* Mask to clear specific bits at offset... + * pos 7 6 5 4 3 2 1 0 (eg. start_from = 19, pos = 3) + * mask 0 0 0 0 0 1 1 1 (= 1<<pos - 1) + * */ + buffer[offset] &= 1 << (pos - 1); + /* ... then fully clear remaining bytes */ + for (uint8_t i = offset + 1; i < HICN_PREFIX_MAX_LEN; i++) + buffer[i] = 0; +} + +void +hicn_prefix_truncate (hicn_prefix_t *prefix, uint8_t len) +{ + hicn_prefix_clear (prefix, len); + prefix->len = len; +} + +int +hicn_prefix_cmp (const hicn_prefix_t *p1, const hicn_prefix_t *p2) +{ + if (p1->len != p2->len) + return p2->len - p1->len; + return hicn_ip_address_cmp (&p1->name, &p2->name); +} + +bool +hicn_prefix_equals (const hicn_prefix_t *p1, const hicn_prefix_t *p2) +{ + return hicn_prefix_cmp (p1, p2) == 0; +} + +int +hicn_prefix_snprintf (char *s, size_t size, const hicn_prefix_t *prefix) +{ + hicn_ip_prefix_t ip_prefix = { .family = + hicn_ip_address_get_family (&prefix->name), + .address = prefix->name, + .len = prefix->len }; + return hicn_ip_prefix_snprintf (s, size, &ip_prefix); +} + +uint8_t +hicn_prefix_get_bit (const hicn_prefix_t *prefix, uint8_t pos) +{ + assert (pos <= hicn_prefix_get_len (prefix)); + const hicn_ip_address_t *address = hicn_prefix_get_ip_address (prefix); + return hicn_ip_address_get_bit (address, pos); +} + +int +hicn_prefix_get_ip_prefix (const hicn_prefix_t *prefix, + hicn_ip_prefix_t *ip_prefix) +{ + *ip_prefix = + (hicn_ip_prefix_t){ .family = hicn_ip_address_get_family (&prefix->name), + .address = prefix->name, + .len = prefix->len }; return HICN_LIB_ERROR_NONE; } diff --git a/lib/src/ops.c b/lib/src/ops.c index 20362d69d..0174a3902 100644 --- a/lib/src/ops.c +++ b/lib/src/ops.c @@ -22,8 +22,9 @@ #include <netinet/in.h> #endif #include <stdlib.h> -#include <hicn/ops.h> -#include <hicn/header.h> + +#include "ops.h" +#include "protocol.h" extern const hicn_ops_t hicn_ops_ipv4; extern const hicn_ops_t hicn_ops_icmp; @@ -34,16 +35,22 @@ extern const hicn_ops_t hicn_ops_new; extern const hicn_ops_t hicn_ops_ah; /* Declare empty operations (terminates recursion on protocol layers) */ -DECLARE_init_packet_header (none, NONE); + +int +none_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) +{ + pkbuf->payload = pkbuf->len; + return HICN_LIB_ERROR_NONE; +} + DECLARE_get_interest_locator (none, NONE); DECLARE_set_interest_locator (none, NONE); DECLARE_get_interest_name (none, NONE); DECLARE_set_interest_name (none, NONE); DECLARE_get_interest_name_suffix (none, NONE); DECLARE_set_interest_name_suffix (none, NONE); -DECLARE_is_interest (none, NONE); -DECLARE_mark_packet_as_interest (none, NONE); -DECLARE_mark_packet_as_data (none, NONE); +DECLARE_get_type (none, NONE); +DECLARE_set_type (none, NONE); DECLARE_reset_interest_for_hash (none, NONE); DECLARE_get_data_locator (none, NONE); DECLARE_set_data_locator (none, NONE); @@ -51,25 +58,18 @@ DECLARE_get_data_name (none, NONE); DECLARE_set_data_name (none, NONE); DECLARE_get_data_name_suffix (none, NONE); DECLARE_set_data_name_suffix (none, NONE); -DECLARE_get_data_pathlabel (none, NONE); -DECLARE_set_data_pathlabel (none, NONE); -DECLARE_update_data_pathlabel (none, NONE); +DECLARE_get_data_path_label (none, NONE); +DECLARE_set_data_path_label (none, NONE); +DECLARE_update_data_path_label (none, NONE); DECLARE_reset_data_for_hash (none, NONE); DECLARE_get_lifetime (none, NONE); DECLARE_set_lifetime (none, NONE); -DECLARE_get_source_port (none, NONE); -DECLARE_get_dest_port (none, NONE); -DECLARE_set_source_port (none, NONE); -DECLARE_set_dest_port (none, NONE); DECLARE_update_checksums (none, NONE); +DECLARE_update_checksums_incremental (none, NONE); DECLARE_verify_checksums (none, NONE); DECLARE_rewrite_interest (none, NONE); DECLARE_rewrite_data (none, NONE); -DECLARE_get_length (none, NONE); -DECLARE_get_header_length (none, NONE); -DECLARE_get_current_header_length (none, NONE); -DECLARE_get_payload_length (none, NONE); -DECLARE_set_payload_length (none, NONE); +DECLARE_set_payload_len (none, NONE); DECLARE_get_payload_type (none, NONE); DECLARE_set_payload_type (none, NONE); DECLARE_get_signature_size (none, NONE); @@ -81,11 +81,18 @@ DECLARE_get_validation_algorithm (none, NONE); DECLARE_set_key_id (none, NONE); DECLARE_get_key_id (none, NONE); DECLARE_get_signature (none, NONE); +DECLARE_has_signature (none, NONE); DECLARE_get_signature_padding (none, NONE); DECLARE_set_signature_padding (none, NONE); DECLARE_is_last_data (none, NONE); DECLARE_set_last_data (none, NONE); -DECLARE_HICN_OPS (none); +DECLARE_get_ttl (none, NONE); +DECLARE_set_ttl (none, NONE); +DECLARE_get_src_port (none, NONE); +DECLARE_set_src_port (none, NONE); +DECLARE_get_dst_port (none, NONE); +DECLARE_set_dst_port (none, NONE); +DECLARE_HICN_OPS (none, 0); /** * @brief Virtual function table for packet operations @@ -99,8 +106,8 @@ const hicn_ops_t *const hicn_ops_vft[] = { /* 41 */[IPPROTO_IPV6] = &hicn_ops_ipv6, /* 51 */[IPPROTO_AH] = &hicn_ops_ah, /* 58 */[IPPROTO_ICMPV6] = &hicn_ops_icmp, + /* 59 */[IPPROTO_NONE] = &hicn_ops_none, /* 98 */[IPPROTO_ENCAP] = &hicn_ops_new, - [IPPROTO_NONE] = &hicn_ops_none, }; /* diff --git a/lib/src/ops.h b/lib/src/ops.h new file mode 100644 index 000000000..886d75cd5 --- /dev/null +++ b/lib/src/ops.h @@ -0,0 +1,1082 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file base.h + * @brief Protocol-independent packet operations + */ + +#ifndef HICN_OPS_H +#define HICN_OPS_H + +#include <assert.h> +#include <stdlib.h> + +#include <hicn/base.h> +#include <hicn/error.h> +#include <hicn/name.h> +#include <hicn/packet.h> // HICN_OPAQUE_LEN +#include <hicn/util/ip_address.h> + +#include "protocol.h" + +/* + * In order to provide fast lookup and accelerate packet operations, we allow + * ourselves to use a header cache structure under the responsibility of the + * caller, and that can be associated to each packet. This structure is exposed + * as a opaque pointer. + */ + +/* + * hICN operations on packets + * + * All prototypes take an hicn_type_t parameter as their first argument, as + * this decides the sequence of protocols that are being used by the different + * operations. + */ + +typedef struct hicn_ops_s +{ + const char *name; + + size_t header_len; + + /** + * @brief Initialize the headers of the hicn packet + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + */ + int (*init_packet_header) (hicn_packet_buffer_t *pkbuf, size_t pos); + + /** + * @brief Retrieves an Interest locator + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [out] ip_address - Retrieved locator + * @return hICN error code + */ + int (*get_interest_locator) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, + hicn_ip_address_t *ip_address); + + /** + * @brief Sets an Interest locator + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] ip_address - Locator to set + * @return hICN error code + */ + int (*set_interest_locator) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *ip_address); + + /** + * @brief Retrieves an Interest name + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [out] name - Retrieved name + * @return hICN error code + */ + int (*get_interest_name) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, hicn_name_t *name); + + /** + * @brief Sets an Interest name + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] name - Name to set + * @return hICN error code + */ + int (*set_interest_name) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_name_t *name); + + /** + * @brief Retrieves an Interest name suffix + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [out] suffix - Retrieved name suffix + * @return hICN error code + */ + int (*get_interest_name_suffix) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, + hicn_name_suffix_t *suffix); + + /** + * @brief Sets an Interest name suffix + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] suffix - Name suffix to set + * @return hICN error code + */ + int (*set_interest_name_suffix) (const hicn_packet_buffer_t *pkbuf, + size_t pos, + const hicn_name_suffix_t *suffix); + + /** + * @brief Get packet type + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Position within the network layers + * @param [out] type - Packet type + * @return hICN error code + */ + int (*get_type) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_packet_type_t *type); + + /** + * @brief Set flag to mark current packet as interest + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Position within the network layers + * @param [in] type - Packet type + * @return hICN error code + */ + int (*set_type) (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_packet_type_t type); + + /** + * @brief Clear the necessary Interest fields in order to hash it + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @return hICN error code + */ + int (*reset_interest_for_hash) (hicn_packet_buffer_t *pkbuf, size_t pos); + + /** + * @brief Retrieves a Data locator + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [out] ip_address - Retrieved locator + * @return hICN error code + */ + int (*get_data_locator) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_ip_address_t *ip_address); + + /** + * @brief Sets a Data locator + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] ip_address - Locator to set + * @return hICN error code + */ + int (*set_data_locator) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *ip_address); + + /** + * @brief Retrieves a Data name + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [out] name - Retrieved name + * @return hICN error code + */ + int (*get_data_name) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_name_t *name); + + /** + * @brief Sets a Data name + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] name - Name to set + * @return hICN error code + */ + int (*set_data_name) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_name_t *name); + + /** + * @brief Retrieves a Data name suffix + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [out] suffix - Retrieved name suffix + * @return hICN error code + */ + int (*get_data_name_suffix) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, hicn_name_suffix_t *suffix); + + /** + * @brief Sets a Data name suffix + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] suffix - Name suffix to set + * @return hICN error code + */ + int (*set_data_name_suffix) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_name_suffix_t *suffix); + + /** + * @brief Retrieves a Data path_label + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [out] path_label - Retrieved path_label + * @return hICN error code + */ + int (*get_data_path_label) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, hicn_path_label_t *path_label); + + /** + * @brief Sets a Data path_label + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] path_label - Pathlabel to set + * @return hICN error code + */ + int (*set_data_path_label) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_path_label_t path_label); + + /** + * @brief Update a Data path_label with a new face identifier + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] path_label - Face identifier used to update path_label + * @return hICN error code + */ + int (*update_data_path_label) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_faceid_t face_id); + + /** + * @brief Clear the necessary Data fields in order to hash it + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @return hICN error code + */ + int (*reset_data_for_hash) (hicn_packet_buffer_t *pkbuf, size_t pos); + + /** + * @brief Retrieves an Interest or Data lifetime + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Current position in the sequence of headers while + * executing command + * @param [out] path_label - Retrieved lifetime + * @return hICN error code + */ + int (*get_lifetime) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_lifetime_t *lifetime); + + /** + * @brief Sets an Interest or Data lifetime + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [in] path_label - Lifetime to set + * @return hICN error code + */ + int (*set_lifetime) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_lifetime_t lifetime); + + /** + * @brief Update all checksums in packet headers + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] partial_csum - Partial checksum (set to 0, used internally to + * carry intermediate values from IP pseudo-header) + * @param [in] payload_len - Payload len (can be set to ~0, retrieved + * and used internally to carry payload len across protocol headers) + * @return hICN error code + * + * Payload len is initialized during the initial steps (eg. IP) if not + * provided (value is ~0), and not ignored (value is 0). + */ + int (*update_checksums) (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len); + + /** + * @brief Update all checksums in packet headers + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] old_val - Pointer to the old value + * @param [in] new_val - Pointer to the new value + * @param [in] size - Size of the changed value + * @param [in] skip_first - Skip the first protocol (ignore IP checksum) + * @return hICN error code + */ + int (*update_checksums_incremental) (const hicn_packet_buffer_t *pkbuf, + size_t pos, u16 *old_val, u16 *new_val, + u8 size, bool skip_first); + + /** + * @brief Validate all checksums in packet headers + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] partial_csum - Partial checksum, or zero if no partial + * checksum available + * @param [in] payload_len - Payload len (can be set to ~0, retrieved + * and used internally to carry payload len across protocol headers) + * @return hICN error code + */ + int (*verify_checksums) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + u16 partial_csum, size_t payload_len); + + /** + * @brief Rewrite an Interest packet header (locator) + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] addr_new - New locator + * @param [in] addr_old - Old locator (set to NULL, used internally to + * compute incremental checksums) + * @return hICN error code + */ + int (*rewrite_interest) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old); + + /** + * @brief Rewrite a Data packet header (locator + path_label) + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @param [in] addr_new - New locator + * @param [in] addr_old - Old locator (set to NULL, used internally to + * compute incremental checksums) + * @param [in] face_id - Face identifier used to update path_label + * @param [in] reset_pl - If not zero, reset the current path_label + * before update it + * @return hICN error code + */ + int (*rewrite_data) (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, + const hicn_faceid_t face_id, u8 reset_pl); + + /** + * @brief Return the packet len + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @parma [out] len - Returned packet len + * @return hICN error code + */ + int (*get_len) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + size_t *len); + + /** + * @brief Return the current packet header len + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @parma [out] header_len - Returned packet current header len + * @return hICN error code + */ + int (*get_current_header_len) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, size_t *header_len); + + /** + * @brief Sets the packet paylaod len + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Depth in the header stack + * @parma [out] payload_len - Payload len to set + * @return hICN error code + */ + int (*set_payload_len) (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t payload_len); + + /** + * @brief Retrieves an Interest or Data signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Current position in the sequence of headers while + * executing command + * @param [out] signature_size - Retrieved signature size + * @return hICN error code + */ + int (*get_signature_size) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, size_t *signature_size); + + /** + * @brief Sets an Interest or Data signature size + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [in] signature_size - Signature size to set + * @return hICN error code + */ + int (*set_signature_size) (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t signature_size); + + /** + * @brief Sets an Interest or Data signature padding between maximum size and + * real size + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [in] signature_size - Signature size to set + * @return hICN error code + */ + int (*set_signature_padding) (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t signature_padding); + + /** + * @brief gets an Interest or Data signature padding between maximum size and + * real size + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [in] signature_size - retrieve the padding between maximum size and + * real size + * @return hICN error code + */ + int (*get_signature_padding) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, size_t *signature_padding); + + /** + * @brief Gets the signature timestamp + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [out] signature_timestamp - Retrieved signature timestamp + * @return hICN error code + */ + int (*get_signature_timestamp) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, + uint64_t *signature_timestamp); + + /** + * @brief Sets the signature timestamp + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [in] signature_timestamp - Signature timestamp to set + * @return hICN error code + */ + int (*set_signature_timestamp) (const hicn_packet_buffer_t *pkbuf, + size_t pos, uint64_t signature_timestamp); + + /** + * @brief Gets the signature validation algorithm + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [out] validation_algorithm - Retrieved validation_algorithm + * @return hICN error code + */ + int (*get_validation_algorithm) (const hicn_packet_buffer_t *pkbuf, + const size_t pos, + uint8_t *validation_algorithm); + + /** + * @brief Sets the signature validation algorithm + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [in] validation_algorithm - Validation algorithm enumeration + * @return hICN error code + */ + int (*set_validation_algorithm) (const hicn_packet_buffer_t *pkbuf, + size_t pos, uint8_t validation_algorithm); + + /** + * @brief Gets the key id + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [out] key_id - Retrieved key id first byte address + * @return hICN error code + */ + int (*get_key_id) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + uint8_t **key_id, uint8_t *key_id_size); + + /** + * @brief Sets the key id + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [in] key_id - Key id first byte address + * @return hICN error code + */ + int (*set_key_id) (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t *key_id, size_t size); + + /** + * @brief Get a pointer to the signature field in the packet + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [out] signature - Pointer to the memory region holding the + * signature + * @return hICN error code + */ + int (*get_signature) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + uint8_t **signature); + + /** + * @brief Returns whether the packet holds a signature. + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [out] flag - Boolean indicating whether the packet has a signature. + * @return hICN error code + */ + int (*has_signature) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + bool *flag); + + /** + * @brief Set payload type of the packet + * @param [in] pkbuf - hICN packet buffer + * @param [in,out] pos - Current position in the sequence of headers while + * executing command + * @param [in] payload_type - The payload type of this packet + * @return hICN error code + */ + int (*set_payload_type) (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_payload_type_t payload_type); + + /** + * @brief Get payload type from the packet + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Current position in the sequence of headers while + * executing command + * @param [out] payload_type - The payload type of this packet + * @return hICN error code + */ + int (*get_payload_type) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_payload_type_t *payload_type); + + /** + * @brief Check if data packet is last one. + * @param [in] pkbuf - hICN packet buffer + * @param [in] pos - Current position in the sequence of headers while + * executing command + * @param [out] is_last - 1 if last data, 0 otherwise + * @return hICN error code + */ + int (*is_last_data) (const hicn_packet_buffer_t *pkbuf, const size_t pos, + int *is_last); + + /** + * @brief Mark data packet as last + * @param [in] pkbuf - hICN packet buffer + * @param [in, out] pos - Current position in the sequence of headers while + * executing command + * @return hICN error code + */ + int (*set_last_data) (const hicn_packet_buffer_t *pkbuf, size_t pos); + + /** + * @brief Returns the packet TTL + * @param [in] pkbuf - hICN packet buffer + * @param [in, out] pos - Current position in the sequence of headers while + * @param [out] hops - Pointer to the variable receiving the TTL value + * @return hICN error code + */ + int (*get_ttl) (const hicn_packet_buffer_t *pkbuf, size_t pos, u8 *hops); + + /** + * @brief Returns the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [in, out] pos - Current position in the sequence of headers while + * @param [out] hops - The TTL value to set + * @return hICN error code + */ + int (*set_ttl) (const hicn_packet_buffer_t *pkbuf, size_t pos, u8 hops); + + /** + * @brief Returns the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [in, out] pos - Current position in the sequence of headers while + * @param [out] port - Pointer to the variable that will receive the port + * number + * @return hICN error code + */ + int (*get_src_port) (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 *port); + + /** + * @brief Sets the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [in, out] pos - Current position in the sequence of headers while + * @param [out] port - The port number to set + * @return hICN error code + */ + int (*set_src_port) (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 port); + + /** + * @brief Returns the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [in, out] pos - Current position in the sequence of headers while + * @param [out] port - Pointer to the variable that will receive the port + * number + * @return hICN error code + */ + int (*get_dst_port) (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 *port); + + /** + * @brief Sets the packet source port + * @param [in] pkbuf - hICN packet buffer + * @param [in, out] pos - Current position in the sequence of headers while + * @param [out] port - The port number to set + * @return hICN error code + */ + int (*set_dst_port) (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 port); +} hicn_ops_t; + +#define DECLARE_HICN_OPS(protocol, len) \ + const hicn_ops_t hicn_ops_##protocol = { \ + ATTR_INIT (name, #protocol), \ + ATTR_INIT (header_len, len), \ + ATTR_INIT (init_packet_header, protocol##_init_packet_header), \ + ATTR_INIT (get_interest_locator, protocol##_get_interest_locator), \ + ATTR_INIT (set_interest_locator, protocol##_set_interest_locator), \ + ATTR_INIT (get_interest_name, protocol##_get_interest_name), \ + ATTR_INIT (set_interest_name, protocol##_set_interest_name), \ + ATTR_INIT (get_interest_name_suffix, \ + protocol##_get_interest_name_suffix), \ + ATTR_INIT (set_interest_name_suffix, \ + protocol##_set_interest_name_suffix), \ + ATTR_INIT (get_type, protocol##_get_type), \ + ATTR_INIT (set_type, protocol##_set_type), \ + ATTR_INIT (reset_interest_for_hash, protocol##_reset_interest_for_hash), \ + ATTR_INIT (get_data_locator, protocol##_get_data_locator), \ + ATTR_INIT (set_data_locator, protocol##_set_data_locator), \ + ATTR_INIT (get_data_name, protocol##_get_data_name), \ + ATTR_INIT (set_data_name, protocol##_set_data_name), \ + ATTR_INIT (get_data_name_suffix, protocol##_get_data_name_suffix), \ + ATTR_INIT (set_data_name_suffix, protocol##_set_data_name_suffix), \ + ATTR_INIT (get_data_path_label, protocol##_get_data_path_label), \ + ATTR_INIT (set_data_path_label, protocol##_set_data_path_label), \ + ATTR_INIT (update_data_path_label, protocol##_update_data_path_label), \ + ATTR_INIT (reset_data_for_hash, protocol##_reset_data_for_hash), \ + ATTR_INIT (get_lifetime, protocol##_get_lifetime), \ + ATTR_INIT (set_lifetime, protocol##_set_lifetime), \ + ATTR_INIT (update_checksums, protocol##_update_checksums), \ + ATTR_INIT (update_checksums_incremental, \ + protocol##_update_checksums_incremental), \ + ATTR_INIT (verify_checksums, protocol##_verify_checksums), \ + ATTR_INIT (rewrite_interest, protocol##_rewrite_interest), \ + ATTR_INIT (rewrite_data, protocol##_rewrite_data), \ + ATTR_INIT (set_payload_len, protocol##_set_payload_len), \ + ATTR_INIT (get_payload_type, protocol##_get_payload_type), \ + ATTR_INIT (set_payload_type, protocol##_set_payload_type), \ + ATTR_INIT (get_signature_size, protocol##_get_signature_size), \ + ATTR_INIT (get_signature_timestamp, protocol##_get_signature_timestamp), \ + ATTR_INIT (set_signature_timestamp, protocol##_set_signature_timestamp), \ + ATTR_INIT (get_validation_algorithm, \ + protocol##_get_validation_algorithm), \ + ATTR_INIT (set_validation_algorithm, \ + protocol##_set_validation_algorithm), \ + ATTR_INIT (get_key_id, protocol##_get_key_id), \ + ATTR_INIT (set_key_id, protocol##_set_key_id), \ + ATTR_INIT (get_signature, protocol##_get_signature), \ + ATTR_INIT (has_signature, protocol##_has_signature), \ + ATTR_INIT (set_signature_padding, protocol##_set_signature_padding), \ + ATTR_INIT (set_signature_size, protocol##_set_signature_size), \ + ATTR_INIT (get_signature_padding, protocol##_get_signature_padding), \ + ATTR_INIT (is_last_data, protocol##_is_last_data), \ + ATTR_INIT (get_ttl, protocol##_get_ttl), \ + ATTR_INIT (set_ttl, protocol##_set_ttl), \ + ATTR_INIT (get_src_port, protocol##_get_src_port), \ + ATTR_INIT (set_src_port, protocol##_set_src_port), \ + ATTR_INIT (get_dst_port, protocol##_get_dst_port), \ + ATTR_INIT (set_dst_port, protocol##_set_dst_port), \ + } + +/** + * @brief Protocol-independent packet operations VFT + * NOTE: The following declarations should be kept in order + */ +extern const hicn_ops_t *const hicn_ops_vft[]; + +#define PROT(pkbuf, pos) \ + ((pos < (HICN_FORMAT_LEN - 1)) ? \ + hicn_packet_get_format (pkbuf).as_u8[(pos) + 1] : \ + IPPROTO_NONE) + +#define CALL_CHILD(method, pkbuf, pos, ...) \ + hicn_ops_vft[PROT (pkbuf, (pos))]->method (pkbuf, (pos) + 1, ##__VA_ARGS__); + +#define CALL(method, pkbuf, ...) CALL_CHILD (method, pkbuf, -1, ##__VA_ARGS__) + +/** Shortcuts to entry points in VFT */ +#define HICN_OPS4 hicn_ops_vft[IPPROTO_IP] +#define HICN_OPS6 hicn_ops_vft[IPPROTO_IPV6] + +/* Helpers for simple declarations */ + +#define DECLARE_init_packet_header(protocol, error) \ + int protocol##_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_interest_locator(protocol, error) \ + int protocol##_get_interest_locator (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + hicn_ip_address_t *ip_address) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_interest_locator(protocol, error) \ + int protocol##_set_interest_locator (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + const hicn_ip_address_t *ip_address) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_interest_name(protocol, error) \ + int protocol##_get_interest_name (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, hicn_name_t *name) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_interest_name(protocol, error) \ + int protocol##_set_interest_name (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, const hicn_name_t *name) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_interest_name_suffix(protocol, error) \ + int protocol##_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + hicn_name_suffix_t *suffix) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_interest_name_suffix(protocol, error) \ + int protocol##_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + const hicn_name_suffix_t *suffix) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_type(protocol, error) \ + int protocol##_get_type (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, hicn_packet_type_t *type) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_type(protocol, error) \ + int protocol##_set_type (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, hicn_packet_type_t type) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_reset_interest_for_hash(protocol, error) \ + int protocol##_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, \ + size_t pos) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_data_locator(protocol, error) \ + int protocol##_get_data_locator (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + hicn_ip_address_t *ip_address) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_data_locator(protocol, error) \ + int protocol##_set_data_locator (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + const hicn_ip_address_t *ip_address) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_data_name(protocol, error) \ + int protocol##_get_data_name (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, hicn_name_t *name) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_data_name(protocol, error) \ + int protocol##_set_data_name (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, const hicn_name_t *name) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_data_name_suffix(protocol, error) \ + int protocol##_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + hicn_name_suffix_t *suffix) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_data_name_suffix(protocol, error) \ + int protocol##_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + const hicn_name_suffix_t *suffix) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_data_path_label(protocol, error) \ + int protocol##_get_data_path_label (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + hicn_path_label_t *path_label) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_data_path_label(protocol, error) \ + int protocol##_set_data_path_label (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + const hicn_path_label_t path_label) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_update_data_path_label(protocol, error) \ + int protocol##_update_data_path_label (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + const hicn_faceid_t face_id) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_reset_data_for_hash(protocol, error) \ + int protocol##_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, \ + size_t pos) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_lifetime(protocol, error) \ + int protocol##_get_lifetime (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, hicn_lifetime_t *lifetime) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_lifetime(protocol, error) \ + int protocol##_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + const hicn_lifetime_t lifetime) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_update_checksums(protocol, error) \ + int protocol##_update_checksums (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, u16 partial_csum, \ + size_t payload_len) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_update_checksums_incremental(protocol, error) \ + int protocol##_update_checksums_incremental ( \ + const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *old_val, \ + u16 *new_val, u8 size, bool skip_first) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_verify_checksums(protocol, error) \ + int protocol##_verify_checksums (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, u16 partial_csum, \ + size_t payload_len) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_rewrite_interest(protocol, error) \ + int protocol##_rewrite_interest ( \ + const hicn_packet_buffer_t *pkbuf, size_t pos, \ + const hicn_ip_address_t *addr_new, hicn_ip_address_t *addr_old) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_rewrite_data(protocol, error) \ + int protocol##_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + const hicn_ip_address_t *addr_new, \ + hicn_ip_address_t *addr_old, \ + const hicn_faceid_t face_id, u8 reset_pl) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_payload_len(protocol, error) \ + int protocol##_set_payload_len (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, size_t payload_len) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_payload_type(protocol, error) \ + int protocol##_get_payload_type (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + hicn_payload_type_t *payload_type) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_payload_type(protocol, error) \ + int protocol##_set_payload_type (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + hicn_payload_type_t payload_type) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_signature_size(protocol, error) \ + int protocol##_get_signature_size (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + size_t *signature_size) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_signature_size(protocol, error) \ + int protocol##_set_signature_size (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, size_t signature_size) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_signature_padding(protocol, error) \ + int protocol##_set_signature_padding (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, size_t padding) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_signature_padding(protocol, error) \ + int protocol##_get_signature_padding (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, size_t *padding) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_signature_timestamp(protocol, error) \ + int protocol##_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + uint64_t signature_timestamp) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_signature_timestamp(protocol, error) \ + int protocol##_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + uint64_t *signature_timestamp) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_validation_algorithm(protocol, error) \ + int protocol##_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, \ + size_t pos, \ + uint8_t validation_algorithm) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_validation_algorithm(protocol, error) \ + int protocol##_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, \ + uint8_t *validation_algorithm) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_key_id(protocol, error) \ + int protocol##_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + uint8_t *key_id, size_t size) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_key_id(protocol, error) \ + int protocol##_get_key_id (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, uint8_t **key_id, \ + uint8_t *key_id_size) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_signature(protocol, error) \ + int protocol##_get_signature (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, uint8_t **signature) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_has_signature(protocol, error) \ + int protocol##_has_signature (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, bool *flag) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_is_last_data(protocol, error) \ + int protocol##_is_last_data (const hicn_packet_buffer_t *pkbuf, \ + const size_t pos, int *is_last) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_last_data(protocol, error) \ + int protocol##_set_last_data (const hicn_packet_buffer_t *pkbuf, \ + size_t pos) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_ttl(protocol, error) \ + int protocol##_get_ttl (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + u8 *hops) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_ttl(protocol, error) \ + int protocol##_set_ttl (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + u8 hops) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_src_port(protocol, error) \ + int protocol##_get_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + u16 *port) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_src_port(protocol, error) \ + int protocol##_set_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + u16 port) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_get_dst_port(protocol, error) \ + int protocol##_get_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + u16 *port) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#define DECLARE_set_dst_port(protocol, error) \ + int protocol##_set_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, \ + u16 port) \ + { \ + return HICN_LIB_ERROR_##error; \ + } + +#endif /* HICN_OPS_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/packet.c b/lib/src/packet.c new file mode 100644 index 000000000..ccef568cd --- /dev/null +++ b/lib/src/packet.c @@ -0,0 +1,833 @@ +/* + * Copyright (c) 2017-2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file packet.c + * @brief Implementation of the compatibility layer. + */ +#ifndef _WIN32 +#include <netinet/in.h> +#endif +#include <string.h> // memset +#include <stddef.h> // offsetof + +#include <hicn/common.h> +#include <hicn/packet.h> +#include <hicn/error.h> +#include <hicn/name.h> +#include <hicn/util/log.h> +#include "ops.h" + +#define member_size(type, member) sizeof (((type *) 0)->member) +#define ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a))) + +#define HICN_NAME_COMPONENT_SIZE 2 + +hicn_packet_format_t +hicn_packet_get_format (const hicn_packet_buffer_t *pkbuf) +{ + return pkbuf->format; +} + +void +hicn_packet_set_format (hicn_packet_buffer_t *pkbuf, + hicn_packet_format_t format) +{ + pkbuf->format = format; +} + +hicn_packet_type_t +hicn_packet_get_type (const hicn_packet_buffer_t *pkbuf) +{ + return pkbuf->type; +} + +void +hicn_packet_set_type (hicn_packet_buffer_t *pkbuf, hicn_packet_type_t type) +{ + pkbuf->type = type; +} + +bool +hicn_packet_is_interest (const hicn_packet_buffer_t *pkbuf) +{ + return pkbuf->type == HICN_PACKET_TYPE_INTEREST; +} + +bool +hicn_packet_is_data (const hicn_packet_buffer_t *pkbuf) +{ + return pkbuf->type == HICN_PACKET_TYPE_DATA; +} + +bool +hicn_packet_is_undefined (const hicn_packet_buffer_t *pkbuf) +{ + return pkbuf->type == HICN_PACKET_TYPE_UNDEFINED; +} + +int +hicn_packet_init_header (hicn_packet_buffer_t *pkbuf, + size_t additional_header_size) +{ + if (hicn_packet_is_undefined (pkbuf)) + return HICN_LIB_ERROR_UNEXPECTED; + if (hicn_packet_get_format (pkbuf).as_u32 == HICN_PACKET_FORMAT_NONE.as_u32) + return HICN_LIB_ERROR_UNEXPECTED; + if (!pkbuf_get_header (pkbuf)) + return HICN_LIB_ERROR_UNEXPECTED; + pkbuf->len = 0; + pkbuf->payload = 0; + + int rc = CALL (init_packet_header, pkbuf); + + /* + * Additional header size is there for the signature, and assumes the AH + * header is always located at the end... + */ + pkbuf->len += additional_header_size; + pkbuf->payload += additional_header_size; + + return rc; +} + +int +hicn_packet_reset (hicn_packet_buffer_t *pkbuf) +{ + memset (pkbuf, 0, sizeof (hicn_packet_buffer_t)); + hicn_packet_set_format (pkbuf, HICN_PACKET_FORMAT_NONE); + hicn_packet_set_type (pkbuf, HICN_PACKET_TYPE_UNDEFINED); + hicn_packet_set_len (pkbuf, 0); + + return HICN_LIB_ERROR_NONE; +} + +int +hicn_packet_analyze (hicn_packet_buffer_t *pkbuf) +{ + u8 *header = pkbuf_get_header (pkbuf); + u8 protocol; + u16 offset = 0; + bool has_signature; + size_t signature_size; + int rc; + + hicn_packet_format_t *format = &pkbuf->format; + + /* Bootstrap: assume IP packet, and get version from header */ + switch (HICN_IP_VERSION (pkbuf_get_header (pkbuf))) + { + case 4: + protocol = IPPROTO_IP; + break; + case 6: + protocol = IPPROTO_IPV6; + break; + default: + goto ERR; + } + + format->as_u32 = 0; + for (unsigned i = 0; i < HICN_FORMAT_LEN; i++) + { + format->as_u8[i] = protocol; + + /* Next protocol + increment offset */ + switch (protocol) + { + + /* + * All packets either start with IPv4 or IPv6, so we take the + * opportunity to update packet length there + */ + case IPPROTO_IP: + { + if (i > 0) + goto ERR; +#ifdef OPAQUE_IP + pkbuf->ipv4 = offset; +#else + assert (offset == 0); +#endif /* OPAQUE_IP */ + _ipv4_header_t *ipv4 = (_ipv4_header_t *) (header + offset); + protocol = ipv4->protocol; + offset += IPV4_HDRLEN; + + // hicn_packet_set_len (pkbuf, htons (ipv4->len)); + if (hicn_packet_get_len (pkbuf) != htons (ipv4->len)) + { + ERROR ("Invalid packet size in IPv4 header %d != %d", + htons (ipv4->len), hicn_packet_get_len (pkbuf)); + goto ERR; + } + break; + } + case IPPROTO_IPV6: + { + if (i > 0) + goto ERR; +#ifdef OPAQUE_IP + pkbuf->ipv6 = offset; +#else + assert (offset == 0); +#endif /* OPAQUE_IP */ + _ipv6_header_t *ipv6 = (_ipv6_header_t *) (header + offset); + protocol = ipv6->nxt; + offset += IPV6_HDRLEN; + // hicn_packet_set_len (pkbuf, IPV6_HDRLEN + htons (ipv6->len)); + if (hicn_packet_get_len (pkbuf) != IPV6_HDRLEN + htons (ipv6->len)) + { + ERROR ("Invalid packet size in IPv6 header %d != %d", + IPV6_HDRLEN + htons (ipv6->len), + hicn_packet_get_len (pkbuf)); + goto ERR; + } + break; + } + case IPPROTO_TCP: + pkbuf->tcp = offset; + /* After TCP, we might eventually have a AH header */ + rc = CALL_CHILD (has_signature, pkbuf, i - 1, &has_signature); + if (rc < 0) + goto ERR; + protocol = has_signature ? IPPROTO_AH : IPPROTO_NONE; + offset += TCP_HDRLEN; + break; + case IPPROTO_UDP: + pkbuf->udp = offset; + protocol = IPPROTO_ENCAP; + offset += UDP_HDRLEN; + break; + case IPPROTO_ICMP: + case IPPROTO_ICMPV6: + pkbuf->icmp = offset; + /* After ICMP, we might eventually have a AH header */ + // CALL_CHILD (has_signature, pkbuf, i - 1, &has_signature); + protocol = /* has_signature ? IPPROTO_AH : */ IPPROTO_NONE; + offset += ICMP_HDRLEN; + break; + + case IPPROTO_ENCAP: + pkbuf->newhdr = offset; + /* After ENCAP, we might eventually have a AH header */ + rc = CALL_CHILD (has_signature, pkbuf, i - 1, &has_signature); + if (rc < 0) + goto ERR; + protocol = has_signature ? IPPROTO_AH : IPPROTO_NONE; + offset += NEW_HDRLEN; + break; + + case IPPROTO_AH: + pkbuf->ah = offset; + protocol = IPPROTO_NONE; + offset += AH_HDRLEN; + + rc = CALL_CHILD (get_signature_size, pkbuf, i - 1, &signature_size); + if (rc < 0) + goto ERR; + offset += signature_size; + break; + + case IPPROTO_NONE: + /* NONE until we terminate the list of protocols */ + break; + + default: + goto ERR; + } + } + pkbuf->payload = offset; + + rc = CALL (get_type, pkbuf, &pkbuf->type); + if (rc < 0) + goto ERR; + + return HICN_LIB_ERROR_NONE; + +ERR: + *format = HICN_PACKET_FORMAT_NONE; + pkbuf->type = HICN_PACKET_TYPE_UNDEFINED; + return HICN_LIB_ERROR_UNEXPECTED; +} + +int +hicn_packet_set_buffer (hicn_packet_buffer_t *pkbuf, u8 *buffer, + uint16_t buffer_size, uint16_t len) +{ + pkbuf_set_header (pkbuf, buffer); + pkbuf->buffer_size = buffer_size; + pkbuf->len = len; + + return HICN_LIB_ERROR_NONE; +} + +int +hicn_packet_get_buffer (const hicn_packet_buffer_t *pkbuf, u8 **buffer, + uint16_t *buffer_size, uint16_t *len) +{ + *buffer = pkbuf_get_header (pkbuf); + *buffer_size = pkbuf->buffer_size; + *len = pkbuf->len; + return HICN_LIB_ERROR_NONE; +} + +size_t +hicn_packet_get_len (const hicn_packet_buffer_t *pkbuf) +{ + return pkbuf->len; +} + +int +hicn_packet_set_len (hicn_packet_buffer_t *pkbuf, size_t len) +{ + pkbuf->len = len; + return HICN_LIB_ERROR_NONE; +} + +int +hicn_packet_get_header_len (const hicn_packet_buffer_t *pkbuf, size_t *len) +{ + *len = pkbuf->payload; + return HICN_LIB_ERROR_NONE; +} + +int +hicn_packet_get_payload_len (const hicn_packet_buffer_t *pkbuf, size_t *len) +{ + *len = hicn_packet_get_len (pkbuf) - pkbuf->payload; + return HICN_LIB_ERROR_NONE; +} + +// XXX this fails with chained membufs in libtransport +int +hicn_packet_set_payload (const hicn_packet_buffer_t *pkbuf, const u8 *payload, + u16 payload_len) +{ + memcpy (pkbuf_get_header (pkbuf) + pkbuf->payload, payload, payload_len); + + return CALL (set_payload_len, pkbuf, payload_len); +} + +int +hicn_packet_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload, + size_t *payload_size, bool hard_copy) +{ + size_t payload_len = hicn_packet_get_len (pkbuf) - pkbuf->payload; + + if (hard_copy) + { + memcpy (payload, pkbuf_get_header (pkbuf) + pkbuf->payload, payload_len); + } + else + { + *payload = pkbuf_get_header (pkbuf) + pkbuf->payload; + } + + return HICN_LIB_ERROR_NONE; +} + +/* Header fields manipulation */ + +int +hicn_packet_get_header_length_from_format (hicn_packet_format_t format, + size_t *header_length) +{ + *header_length = 0; + for (unsigned i = 0; i < HICN_FORMAT_LEN; i++) + { + *header_length += hicn_ops_vft[format.as_u8[i]]->header_len; + } + return HICN_LIB_ERROR_NONE; +} + +int +hicn_packet_compute_checksum (const hicn_packet_buffer_t *pkbuf) +{ + return CALL (update_checksums, pkbuf, 0, ~0); +} + +int +hicn_packet_compute_header_checksum (const hicn_packet_buffer_t *pkbuf, + u16 init_sum) +{ + /* payload_len == 0: ignore payload */ + return CALL (update_checksums, pkbuf, init_sum, 0); +} + +int +hicn_packet_check_integrity_no_payload (const hicn_packet_buffer_t *pkbuf, + u16 init_sum) +{ + return CALL (verify_checksums, pkbuf, init_sum, 0); +} + +int +hicn_packet_set_payload_length (const hicn_packet_buffer_t *pkbuf, + const size_t payload_len) +{ + return CALL (set_payload_len, pkbuf, payload_len); +} + +int +hicn_packet_compare (const hicn_packet_buffer_t *pkbuf1, + const hicn_packet_buffer_t *pkbuf2) +{ + + hicn_packet_format_t format1 = hicn_packet_get_format (pkbuf1); + hicn_packet_format_t format2 = hicn_packet_get_format (pkbuf2); + + if (format1.as_u32 != format2.as_u32) + return HICN_LIB_ERROR_UNEXPECTED; + + size_t len1 = hicn_packet_get_len (pkbuf1); + size_t len2 = hicn_packet_get_len (pkbuf2); + + if (len1 != len2) + return HICN_LIB_ERROR_UNEXPECTED; + + return memcmp (pkbuf_get_header (pkbuf1), pkbuf_get_header (pkbuf2), len1); +} + +int +hicn_packet_get_name (const hicn_packet_buffer_t *pkbuf, hicn_name_t *name) +{ + switch (pkbuf->type) + { + case HICN_PACKET_TYPE_INTEREST: + return hicn_interest_get_name (pkbuf, name); + case HICN_PACKET_TYPE_DATA: + return hicn_data_get_name (pkbuf, name); + default: + return HICN_LIB_ERROR_UNEXPECTED; + } +} + +int +hicn_packet_set_name (const hicn_packet_buffer_t *pkbuf, + const hicn_name_t *name) +{ + switch (pkbuf->type) + { + case HICN_PACKET_TYPE_INTEREST: + return hicn_interest_set_name (pkbuf, name); + case HICN_PACKET_TYPE_DATA: + return hicn_data_set_name (pkbuf, name); + default: + return HICN_LIB_ERROR_UNEXPECTED; + } +} + +int +hicn_packet_get_locator (const hicn_packet_buffer_t *pkbuf, + hicn_ip_address_t *address) +{ + switch (pkbuf->type) + { + case HICN_PACKET_TYPE_INTEREST: + return hicn_interest_get_locator (pkbuf, address); + case HICN_PACKET_TYPE_DATA: + return hicn_data_get_locator (pkbuf, address); + default: + return HICN_LIB_ERROR_UNEXPECTED; + } +} + +int +hicn_packet_set_locator (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *address) +{ + switch (pkbuf->type) + { + case HICN_PACKET_TYPE_INTEREST: + return hicn_interest_set_locator (pkbuf, address); + case HICN_PACKET_TYPE_DATA: + return hicn_data_set_locator (pkbuf, address); + default: + return HICN_LIB_ERROR_UNEXPECTED; + } +} + +int +hicn_packet_get_signature_size (const hicn_packet_buffer_t *pkbuf, + size_t *bytes) +{ + return CALL (get_signature_size, pkbuf, bytes); +} + +int +hicn_packet_set_signature_size (const hicn_packet_buffer_t *pkbuf, + size_t bytes) +{ + return CALL (set_signature_size, pkbuf, bytes); +} + +int +hicn_packet_get_signature_padding (const hicn_packet_buffer_t *pkbuf, + size_t *bytes) +{ + return CALL (get_signature_padding, pkbuf, bytes); +} + +int +hicn_packet_set_signature_padding (const hicn_packet_buffer_t *pkbuf, + size_t bytes) +{ + return CALL (set_signature_padding, pkbuf, bytes); +} + +int +hicn_packet_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, + uint64_t signature_timestamp) +{ + return CALL (set_signature_timestamp, pkbuf, signature_timestamp); +} + +int +hicn_packet_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, + uint64_t *signature_timestamp) +{ + return CALL (get_signature_timestamp, pkbuf, signature_timestamp); +} + +int +hicn_packet_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, + uint8_t validation_algorithm) +{ + return CALL (set_validation_algorithm, pkbuf, validation_algorithm); +} + +int +hicn_packet_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, + uint8_t *validation_algorithm) +{ + return CALL (get_validation_algorithm, pkbuf, validation_algorithm); +} + +int +hicn_packet_set_key_id (const hicn_packet_buffer_t *pkbuf, uint8_t *key_id, + size_t key_len) +{ + return CALL (set_key_id, pkbuf, key_id, key_len); +} + +int +hicn_packet_get_key_id (const hicn_packet_buffer_t *pkbuf, uint8_t **key_id, + uint8_t *key_id_len) +{ + return CALL (get_key_id, pkbuf, key_id, key_id_len); +} + +int +hicn_packet_get_lifetime (const hicn_packet_buffer_t *pkbuf, + hicn_lifetime_t *lifetime) +{ + return CALL (get_lifetime, pkbuf, lifetime); +} + +int +hicn_packet_set_lifetime (const hicn_packet_buffer_t *pkbuf, + hicn_lifetime_t lifetime) +{ + return CALL (set_lifetime, pkbuf, lifetime); +} + +int +hicn_packet_get_payload_type (const hicn_packet_buffer_t *pkbuf, + hicn_payload_type_t *payload_type) +{ + return CALL (get_payload_type, pkbuf, payload_type); +} + +int +hicn_packet_set_payload_type (const hicn_packet_buffer_t *pkbuf, + hicn_payload_type_t payload_type) +{ + return CALL (set_payload_type, pkbuf, payload_type); +} + +int +hicn_packet_save_header (const hicn_packet_buffer_t *pkbuf, u8 *header, + size_t *header_len, bool copy_ah) +{ + hicn_packet_format_t format = hicn_packet_get_format (pkbuf); + if (copy_ah || !_is_ah (format)) + { + int rc = hicn_packet_get_header_len (pkbuf, header_len); + if (HICN_LIB_IS_ERROR (rc)) + return rc; + } + else + { + /* Copy up until the ah header (which we assume is last) */ + *header_len = pkbuf->ah; + } + + memcpy (header, pkbuf_get_header (pkbuf), *header_len); + + return HICN_LIB_ERROR_NONE; +} + +int +hicn_packet_load_header (const hicn_packet_buffer_t *pkbuf, const u8 *header, + size_t header_len) +{ + memcpy (pkbuf_get_header (pkbuf), header, header_len); + + return HICN_LIB_ERROR_NONE; +} + +/* Interest */ + +int +hicn_interest_get_name (const hicn_packet_buffer_t *pkbuf, hicn_name_t *name) +{ + return CALL (get_interest_name, pkbuf, name); +} + +int +hicn_interest_set_name (const hicn_packet_buffer_t *pkbuf, + const hicn_name_t *name) +{ + return CALL (set_interest_name, pkbuf, name); +} + +int +hicn_interest_get_locator (const hicn_packet_buffer_t *pkbuf, + hicn_ip_address_t *address) +{ + return CALL (get_interest_locator, pkbuf, address); +} + +int +hicn_interest_set_locator (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *address) +{ + return CALL (set_interest_locator, pkbuf, address); +} + +int +hicn_interest_compare (const hicn_packet_buffer_t *pkbuf1, + const hicn_packet_buffer_t *pkbuf2) +{ + return hicn_packet_compare (pkbuf1, pkbuf2); +} + +int +hicn_interest_get_lifetime (const hicn_packet_buffer_t *pkbuf, + hicn_lifetime_t *lifetime) +{ + return hicn_packet_get_lifetime (pkbuf, lifetime); +} + +int +hicn_interest_set_lifetime (const hicn_packet_buffer_t *pkbuf, + hicn_lifetime_t lifetime) +{ + return hicn_packet_set_lifetime (pkbuf, lifetime); +} + +int +hicn_interest_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload, + size_t *payload_size, bool hard_copy) +{ + return hicn_packet_get_payload (pkbuf, payload, payload_size, hard_copy); +} + +int +hicn_interest_set_payload (const hicn_packet_buffer_t *pkbuf, + const u8 *payload, size_t payload_len) +{ + return hicn_packet_set_payload (pkbuf, payload, (u16) payload_len); +} + +int +hicn_interest_reset_for_hash (hicn_packet_buffer_t *pkbuf) +{ + return CALL (reset_interest_for_hash, pkbuf); +} + +/* Data */ + +int +hicn_data_get_name (const hicn_packet_buffer_t *pkbuf, hicn_name_t *name) +{ + return CALL (get_data_name, pkbuf, name); +} + +int +hicn_data_set_name (const hicn_packet_buffer_t *pkbuf, const hicn_name_t *name) +{ + return CALL (set_data_name, pkbuf, name); +} + +int +hicn_data_get_locator (const hicn_packet_buffer_t *pkbuf, + hicn_ip_address_t *address) +{ + return CALL (get_data_locator, pkbuf, address); +} + +int +hicn_data_set_locator (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *address) +{ + return CALL (set_data_locator, pkbuf, address); +} + +int +hicn_data_compare (const hicn_packet_buffer_t *pkbuf1, + const hicn_packet_buffer_t *pkbuf2) +{ + return hicn_packet_compare (pkbuf1, pkbuf2); +} + +int +hicn_data_get_expiry_time (const hicn_packet_buffer_t *pkbuf, + hicn_lifetime_t *expiry_time) +{ + return hicn_packet_get_lifetime (pkbuf, expiry_time); +} + +int +hicn_data_set_expiry_time (const hicn_packet_buffer_t *pkbuf, + hicn_lifetime_t expiry_time) +{ + return hicn_packet_set_lifetime (pkbuf, expiry_time); +} + +/* Path label */ + +int +hicn_data_get_path_label (const hicn_packet_buffer_t *pkbuf, + hicn_path_label_t *path_label) +{ + return CALL (get_data_path_label, pkbuf, path_label); +} + +int +hicn_get_path_label (const hicn_packet_buffer_t *pkbuf, + hicn_path_label_t *path_label) +{ + if (!hicn_packet_is_data (pkbuf)) + return INVALID_PATH_LABEL; + return hicn_data_get_path_label (pkbuf, path_label); +} + +int +hicn_data_set_path_label (const hicn_packet_buffer_t *pkbuf, + hicn_path_label_t path_label) +{ + return CALL (set_data_path_label, pkbuf, path_label); +} + +int +hicn_data_set_payload (const hicn_packet_buffer_t *pkbuf, const u8 *payload, + size_t payload_len) +{ + return hicn_packet_set_payload (pkbuf, payload, (u16) payload_len); +} + +int +hicn_data_get_payload (const hicn_packet_buffer_t *pkbuf, u8 **payload, + size_t *payload_size, bool hard_copy) +{ + return hicn_packet_get_payload (pkbuf, payload, payload_size, hard_copy); +} + +int +hicn_data_reset_for_hash (hicn_packet_buffer_t *pkbuf) +{ + return CALL (reset_data_for_hash, pkbuf); +} + +int +hicn_data_is_last (const hicn_packet_buffer_t *pkbuf, int *is_last) +{ + return CALL (is_last_data, pkbuf, is_last); +} + +int +hicn_data_set_last (const hicn_packet_buffer_t *pkbuf) +{ + return CALL (set_last_data, pkbuf); +} + +int +hicn_packet_get_signature (const hicn_packet_buffer_t *pkbuf, + uint8_t **sign_buf) +{ + return CALL (get_signature, pkbuf, sign_buf); +} + +int +hicn_packet_get_ttl (const hicn_packet_buffer_t *pkbuf, u8 *hops) +{ + return CALL (get_ttl, pkbuf, hops); +} + +int +hicn_packet_set_ttl (const hicn_packet_buffer_t *pkbuf, u8 hops) +{ + return CALL (set_ttl, pkbuf, hops); +} + +int +hicn_packet_get_src_port (const hicn_packet_buffer_t *pkbuf, u16 *port) +{ + return CALL (get_src_port, pkbuf, port); +} + +int +hicn_packet_set_src_port (const hicn_packet_buffer_t *pkbuf, u16 port) +{ + return CALL (set_src_port, pkbuf, port); +} + +int +hicn_packet_get_dst_port (const hicn_packet_buffer_t *pkbuf, u16 *port) +{ + return CALL (get_dst_port, pkbuf, port); +} + +int +hicn_packet_set_dst_port (const hicn_packet_buffer_t *pkbuf, u16 port) +{ + return CALL (set_dst_port, pkbuf, port); +} + +int +hicn_interest_rewrite (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old) +{ + return CALL (rewrite_interest, pkbuf, addr_new, addr_old); +} + +int +hicn_data_rewrite (const hicn_packet_buffer_t *pkbuf, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, const hicn_faceid_t face_id, + u8 reset_pl) +{ + return CALL (rewrite_data, pkbuf, addr_new, addr_old, face_id, reset_pl); +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/includes/hicn/protocol.h b/lib/src/protocol.h index fb142e4c3..58bbb2ac2 100644 --- a/lib/includes/hicn/protocol.h +++ b/lib/src/protocol.h @@ -29,19 +29,6 @@ #include "protocol/udp.h" #include "protocol/new.h" -typedef union -{ - _new_header_t newhdr; - _ipv4_header_t ipv4; - _ipv6_header_t ipv6; - _tcp_header_t tcp; - _udp_header_t udp; - _icmp_header_t icmp; - _icmprd_header_t icmprd; - _ah_header_t ah; - void *bytes; -} hicn_protocol_t; - #endif /* HICN_PROTOCOL_H */ /* diff --git a/lib/src/protocol/ah.c b/lib/src/protocol/ah.c index c9ed40179..645b0482b 100644 --- a/lib/src/protocol/ah.c +++ b/lib/src/protocol/ah.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -18,12 +18,12 @@ * @brief hICN operations for AH header */ -#include <string.h> // memcpy #include <hicn/common.h> #include <hicn/error.h> -#include <hicn/header.h> -#include <hicn/ops.h> -#include <hicn/protocol/ah.h> +#include <string.h> // memcpy + +#include "../ops.h" +#include "ah.h" DECLARE_get_interest_locator (ah, UNEXPECTED); DECLARE_set_interest_locator (ah, UNEXPECTED); @@ -31,218 +31,248 @@ DECLARE_get_interest_name (ah, UNEXPECTED); DECLARE_set_interest_name (ah, UNEXPECTED); DECLARE_get_interest_name_suffix (ah, UNEXPECTED); DECLARE_set_interest_name_suffix (ah, UNEXPECTED); -DECLARE_is_interest (ah, UNEXPECTED); -DECLARE_mark_packet_as_interest (ah, UNEXPECTED); -DECLARE_mark_packet_as_data (ah, UNEXPECTED); +DECLARE_get_type (ah, UNEXPECTED); +DECLARE_set_type (ah, UNEXPECTED); DECLARE_get_data_locator (ah, UNEXPECTED); DECLARE_set_data_locator (ah, UNEXPECTED); DECLARE_get_data_name (ah, UNEXPECTED); DECLARE_set_data_name (ah, UNEXPECTED); DECLARE_get_data_name_suffix (ah, UNEXPECTED); DECLARE_set_data_name_suffix (ah, UNEXPECTED); -DECLARE_get_data_pathlabel (ah, UNEXPECTED); -DECLARE_set_data_pathlabel (ah, UNEXPECTED); -DECLARE_update_data_pathlabel (ah, UNEXPECTED); +DECLARE_get_data_path_label (ah, UNEXPECTED); +DECLARE_set_data_path_label (ah, UNEXPECTED); +DECLARE_update_data_path_label (ah, UNEXPECTED); DECLARE_get_lifetime (ah, UNEXPECTED); DECLARE_set_lifetime (ah, UNEXPECTED); -DECLARE_get_source_port (ah, UNEXPECTED); -DECLARE_get_dest_port (ah, UNEXPECTED); -DECLARE_set_source_port (ah, UNEXPECTED); -DECLARE_set_dest_port (ah, UNEXPECTED); -DECLARE_get_payload_length (ah, UNEXPECTED); -DECLARE_set_payload_length (ah, UNEXPECTED); +// DECLARE_get_payload_len (ah, UNEXPECTED); +DECLARE_set_payload_len (ah, UNEXPECTED); DECLARE_get_payload_type (ah, UNEXPECTED); DECLARE_set_payload_type (ah, UNEXPECTED); DECLARE_is_last_data (ah, UNEXPECTED); DECLARE_set_last_data (ah, UNEXPECTED); +DECLARE_get_ttl (ah, UNEXPECTED); +DECLARE_set_ttl (ah, UNEXPECTED); +DECLARE_get_src_port (ah, UNEXPECTED); +DECLARE_set_src_port (ah, UNEXPECTED); +DECLARE_get_dst_port (ah, UNEXPECTED); +DECLARE_set_dst_port (ah, UNEXPECTED); int -ah_init_packet_header (hicn_type_t type, hicn_protocol_t *h) +ah_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) { - /* *INDENT-OFF* */ - h->ah = (_ah_header_t){ + pkbuf->ah = pkbuf->len; + if (AH_HDRLEN > pkbuf->buffer_size - pkbuf->len) + return -1; + pkbuf->len += AH_HDRLEN; + + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + /* clang-format off */ + *ah = (_ah_header_t){ .nh = (u8) 0, .payloadlen = (u8) 0, .reserved = (u16) 0, }; - /* *INDENT-ON* */ - return CHILD_OPS (init_packet_header, type, h); + /* clang-format on */ + return CALL_CHILD (init_packet_header, pkbuf, pos); } int -ah_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h) +ah_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + size_t signature_size; - int rc = - hicn_ops_vft[type.l1]->get_signature_size (type, h, &signature_size); + int rc = CALL (get_signature_size, pkbuf, &signature_size); if (rc < 0) return rc; - memset (&(h->ah.validationPayload), 0, signature_size); - h->ah.signaturePadding = 0; - return CHILD_OPS (reset_interest_for_hash, type, h); + memset (&(ah->validationPayload), 0, signature_size); + ah->signaturePadding = 0; + return CALL_CHILD (reset_interest_for_hash, pkbuf, pos); } int -ah_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) +ah_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + size_t signature_size; - int rc = - hicn_ops_vft[type.l1]->get_signature_size (type, h, &signature_size); + int rc = CALL (get_signature_size, pkbuf, &signature_size); if (rc < 0) return rc; - memset (&(h->ah.validationPayload), 0, signature_size); - h->ah.signaturePadding = 0; - return CHILD_OPS (reset_interest_for_hash, type, h); + memset (&(ah->validationPayload), 0, signature_size); + ah->signaturePadding = 0; + return CALL_CHILD (reset_interest_for_hash, pkbuf, pos); } int -ah_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +ah_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { /* Nothing to do as there is no checksum in AH */ return HICN_LIB_ERROR_NONE; } int -ah_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +ah_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 *old_val, u16 *new_val, u8 size, + bool skip_first) { - /* Nothing to do as there is no checksum in AH */ - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val, + new_val, size, false); } int -ah_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old) +ah_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { - /* Nothing to do on signature */ + /* Nothing to do as there is no checksum in AH */ return HICN_LIB_ERROR_NONE; } int -ah_rewrite_data (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old, - const hicn_faceid_t face_id, u8 reset_pl) +ah_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old) { /* Nothing to do on signature */ return HICN_LIB_ERROR_NONE; } int -ah_get_length (hicn_type_t type, const hicn_protocol_t *h, size_t *length) -{ - return HICN_LIB_ERROR_NOT_IMPLEMENTED; -} - -int -ah_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ah_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, const hicn_faceid_t face_id, + u8 reset_pl) { - *header_length = AH_HDRLEN + (h->ah.payloadlen << 2); + /* Nothing to do on signature */ return HICN_LIB_ERROR_NONE; } int -ah_get_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ah_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **signature) { - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - *header_length = AH_HDRLEN + (h->ah.payloadlen << 2) + child_header_length; + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + *signature = ah->validationPayload; return HICN_LIB_ERROR_NONE; } int -ah_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature) +ah_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag) { - *signature = h->ah.validationPayload; + *flag = true; return HICN_LIB_ERROR_NONE; } int -ah_get_signature_size (hicn_type_t type, const hicn_protocol_t *h, +ah_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t *signature_size) { - *signature_size = h->ah.payloadlen << 2; + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + *signature_size = ah->payloadlen << 2; return HICN_LIB_ERROR_NONE; } int -ah_set_signature_size (hicn_type_t type, hicn_protocol_t *h, - const size_t signature_size) +ah_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t signature_size) { - h->ah.payloadlen = signature_size >> 2; + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + ah->payloadlen = signature_size >> 2; return HICN_LIB_ERROR_NONE; } int -ah_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h, +ah_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, uint64_t signature_timestamp) { - uint64_t netwok_order_timestamp = htonll (signature_timestamp); - memcpy (h->ah.timestamp_as_u8, &netwok_order_timestamp, sizeof (uint64_t)); + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + uint64_t netwok_order_timestamp = hicn_net_to_host_64 (signature_timestamp); + memcpy (ah->timestamp_as_u8, &netwok_order_timestamp, sizeof (uint64_t)); return HICN_LIB_ERROR_NONE; } int -ah_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h, +ah_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, uint64_t *signature_timestamp) { - memcpy (signature_timestamp, h->ah.timestamp_as_u8, sizeof (uint64_t)); - *signature_timestamp = ntohll (*signature_timestamp); + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + memcpy (signature_timestamp, ah->timestamp_as_u8, sizeof (uint64_t)); + *signature_timestamp = hicn_host_to_net_64 (*signature_timestamp); return HICN_LIB_ERROR_NONE; } int -ah_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h, +ah_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t validation_algorithm) { - h->ah.validationAlgorithm = validation_algorithm; + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + ah->validationAlgorithm = validation_algorithm; return HICN_LIB_ERROR_NONE; } int -ah_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h, +ah_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *validation_algorithm) { - *validation_algorithm = h->ah.validationAlgorithm; + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + *validation_algorithm = ah->validationAlgorithm; return HICN_LIB_ERROR_NONE; } int -ah_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, size_t padding) +ah_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t padding) { - h->ah.signaturePadding = padding; + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + ah->signaturePadding = padding; return HICN_LIB_ERROR_NONE; } int -ah_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h, +ah_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t *padding) { - *padding = h->ah.signaturePadding; + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + *padding = ah->signaturePadding; return HICN_LIB_ERROR_NONE; } int -ah_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id) +ah_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *key_id, + size_t size) { - memcpy (h->ah.keyId, key_id, sizeof (h->ah.keyId)); + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + if (size != sizeof (ah->keyId)) + return HICN_LIB_ERROR_INVALID_PARAMETER; + + memcpy (ah->keyId, key_id, sizeof (ah->keyId)); return HICN_LIB_ERROR_NONE; } int -ah_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id, +ah_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t **key_id, uint8_t *key_id_size) { - *key_id = h->ah.keyId; - *key_id_size = sizeof (h->ah.keyId); + _ah_header_t *ah = pkbuf_get_ah (pkbuf); + + *key_id = ah->keyId; + *key_id_size = sizeof (ah->keyId); return HICN_LIB_ERROR_NONE; } -DECLARE_HICN_OPS (ah); +DECLARE_HICN_OPS (ah, AH_HDRLEN); /* * fd.io coding-style-patch-verification: ON diff --git a/lib/src/protocol/ah.h b/lib/src/protocol/ah.h new file mode 100644 index 000000000..ee124f92a --- /dev/null +++ b/lib/src/protocol/ah.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file protocol/ah.h + * @brief AH packet header + */ +#ifndef HICN_PROTOCOL_AH_H +#define HICN_PROTOCOL_AH_H + +#include <hicn/common.h> + +/* + * The TCP PSH flag is set to indicate TCP payload in fact contains a AH header + * with signature information for the packet + */ +#define AH_FLAG 0x10 + +/* + * The length of the AH struct must be 44 bytes. + */ +#define EXPECTED_AH_HDRLEN 44 + +typedef struct +{ + u8 nh; // To match with reserved in IPSEC AH + // Length of the signature field. Note that the signature might be smaller + // than the field: the actual size is computed from the field size and + // signaturePadding. + u8 payloadlen; + union + { + u16 reserved; + + struct + { + u8 validationAlgorithm; + u8 signaturePadding; + }; + }; + union + { + struct + { + u32 spi; + u32 seq; + }; + // Unix timestamp indicating when the signature has been calculated + u8 timestamp_as_u8[8]; + u16 timestamp_as_u16[4]; + u32 timestamp_as_u32[2]; + }; + // ICV would follow + u8 keyId[32]; // Hash of pub key + /* 44 B + validationPayload */ + u8 validationPayload[0]; // Holds the signature +} _ah_header_t; + +#define AH_HDRLEN sizeof (_ah_header_t) +static_assert (EXPECTED_AH_HDRLEN == AH_HDRLEN, + "Size of AH Struct does not match its expected size."); + +#endif /* HICN_PROTOCOL_AH_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/protocol/icmp.c b/lib/src/protocol/icmp.c index 1fc6c7d2f..71417a4e0 100644 --- a/lib/src/protocol/icmp.c +++ b/lib/src/protocol/icmp.c @@ -13,10 +13,11 @@ * limitations under the License. */ -#include <string.h> -#include <hicn/protocol/icmp.h> #include <hicn/error.h> -#include <hicn/ops.h> +#include <string.h> + +#include "icmp.h" +#include "../ops.h" DECLARE_get_interest_locator (icmp, UNEXPECTED); DECLARE_set_interest_locator (icmp, UNEXPECTED); @@ -24,89 +25,110 @@ DECLARE_get_interest_name (icmp, UNEXPECTED); DECLARE_set_interest_name (icmp, UNEXPECTED); DECLARE_get_interest_name_suffix (icmp, UNEXPECTED); DECLARE_set_interest_name_suffix (icmp, UNEXPECTED); -DECLARE_is_interest (icmp, UNEXPECTED); -DECLARE_mark_packet_as_interest (icmp, UNEXPECTED); -DECLARE_mark_packet_as_data (icmp, UNEXPECTED); DECLARE_get_data_locator (icmp, UNEXPECTED); DECLARE_set_data_locator (icmp, UNEXPECTED); DECLARE_get_data_name (icmp, UNEXPECTED); DECLARE_set_data_name (icmp, UNEXPECTED); DECLARE_get_data_name_suffix (icmp, UNEXPECTED); DECLARE_set_data_name_suffix (icmp, UNEXPECTED); -DECLARE_get_data_pathlabel (icmp, UNEXPECTED); -DECLARE_set_data_pathlabel (icmp, UNEXPECTED); -DECLARE_update_data_pathlabel (icmp, UNEXPECTED); +DECLARE_get_data_path_label (icmp, UNEXPECTED); +DECLARE_set_data_path_label (icmp, UNEXPECTED); +DECLARE_update_data_path_label (icmp, UNEXPECTED); DECLARE_get_lifetime (icmp, UNEXPECTED); DECLARE_set_lifetime (icmp, UNEXPECTED); -DECLARE_get_source_port (icmp, UNEXPECTED); -DECLARE_get_dest_port (icmp, UNEXPECTED); -DECLARE_set_source_port (icmp, UNEXPECTED); -DECLARE_set_dest_port (icmp, UNEXPECTED); -DECLARE_get_length (icmp, UNEXPECTED); -DECLARE_get_payload_length (icmp, UNEXPECTED); -DECLARE_set_payload_length (icmp, UNEXPECTED); +// DECLARE_get_payload_len (icmp, UNEXPECTED); +DECLARE_set_payload_len (icmp, UNEXPECTED); DECLARE_get_payload_type (icmp, UNEXPECTED); DECLARE_set_payload_type (icmp, UNEXPECTED); DECLARE_get_signature (icmp, UNEXPECTED); +DECLARE_has_signature (icmp, UNEXPECTED); DECLARE_is_last_data (icmp, UNEXPECTED); DECLARE_set_last_data (icmp, UNEXPECTED); +DECLARE_get_ttl (icmp, UNEXPECTED); +DECLARE_set_ttl (icmp, UNEXPECTED); +DECLARE_get_src_port (icmp, UNEXPECTED); +DECLARE_set_src_port (icmp, UNEXPECTED); +DECLARE_get_dst_port (icmp, UNEXPECTED); +DECLARE_set_dst_port (icmp, UNEXPECTED); int -icmp_init_packet_header (hicn_type_t type, hicn_protocol_t *h) +icmp_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) { - h->icmp = (_icmp_header_t){ + pkbuf->icmp = pkbuf->len; + if (ICMP_HDRLEN > pkbuf->buffer_size - pkbuf->len) + return -1; + pkbuf->len += ICMP_HDRLEN; + + _icmp_header_t *icmp = pkbuf_get_icmp (pkbuf); + + *icmp = (_icmp_header_t){ .type = 0, .code = 0, .csum = 0, }; - return HICN_LIB_ERROR_NONE; // CHILD_OPS(init_packet_header, type, h->icmp); + return CALL_CHILD (init_packet_header, pkbuf, pos); } int -icmp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h) +icmp_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - h->icmp.csum = 0; + _icmp_header_t *icmp = pkbuf_get_icmp (pkbuf); + + icmp->csum = 0; - return CHILD_OPS (reset_interest_for_hash, type, h); + return CALL_CHILD (reset_interest_for_hash, pkbuf, pos); } int -icmp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) +icmp_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - h->icmp.csum = 0; + _icmp_header_t *icmp = pkbuf_get_icmp (pkbuf); + + icmp->csum = 0; - return CHILD_OPS (reset_data_for_hash, type, h); + return CALL_CHILD (reset_data_for_hash, pkbuf, pos); } int -icmp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +icmp_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { return HICN_LIB_ERROR_NOT_IMPLEMENTED; - // h->icmp.csum = 0; - // h->icmp.csum = csum(h->bytes, TCP_HDRLEN + payload_length, + // icmp->csum = 0; + // icmp->csum = csum(h->bytes, TCP_HDRLEN + payload_len, // ~partial_csum); // - // return CHILD_OPS(update_checksums, type, h->icmp, 0, payload_length); + // return CALL_CHILD(update_checksums, pkbuf, pos->icmp, 0, + // payload_len); } int -icmp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +icmp_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, + size_t pos, u16 *old_val, u16 *new_val, + u8 size, bool skip_first) { return HICN_LIB_ERROR_NOT_IMPLEMENTED; - // if (csum(h->bytes, TCP_HDRLEN + payload_length, ~partial_csum) != 0) +} + +int +icmp_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) +{ + return HICN_LIB_ERROR_NOT_IMPLEMENTED; + // if (csum(h->bytes, TCP_HDRLEN + payload_len, ~partial_csum) != 0) // return HICN_LIB_ERROR_CORRUPTED_PACKET; - // return CHILD_OPS(verify_checksums, type, h->icmp, 0, payload_length); + // return CALL_CHILD(verify_checksums, pkbuf, pos->icmp, 0, + // payload_len); } int -icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old) +icmp_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old) { return HICN_LIB_ERROR_NOT_IMPLEMENTED; - // u16 *icmp_checksum = &(h->icmp.csum); + // u16 *icmp_checksum = &(icmp->csum); // // /* // * Padding fields are set to zero so we can apply checksum on the @@ -127,12 +149,13 @@ icmp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, } int -icmp_rewrite_data (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old, - const hicn_faceid_t face_id, u8 reset_pl) +icmp_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, const hicn_faceid_t face_id, + u8 reset_pl) { return HICN_LIB_ERROR_NOT_IMPLEMENTED; - // u16 *icmp_checksum = &(h->icmp.csum); + // u16 *icmp_checksum = &(icmp->csum); // // /* // * Padding fields are set to zero so we can apply checksum on the @@ -147,9 +170,9 @@ icmp_rewrite_data (hicn_type_t type, hicn_protocol_t *h, // csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[0]); // csum = ip_csum_add_even (csum, addr_new->ip6.as_u64[1]); // - // csum = ip_csum_sub_even (csum, h->icmp.pathlabel); - // icmp_update_data_pathlabel(type, h, face_id); - // csum = ip_csum_add_even (csum, h->icmp.pathlabel); + // csum = ip_csum_sub_even (csum, icmp->path_label); + // icmp_update_data_path_label(pkbuf, pos, face_id); + // csum = ip_csum_add_even (csum, icmp->path_label); // // *icmp_checksum = ip_csum_fold (csum); // @@ -157,96 +180,92 @@ icmp_rewrite_data (hicn_type_t type, hicn_protocol_t *h, } int -icmp_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +icmp_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_packet_type_t *type) { - *header_length = ICMP_HDRLEN; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (get_type, pkbuf, pos, type); } int -icmp_get_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +icmp_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_packet_type_t type) { - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - - *header_length = ICMP_HDRLEN + child_header_length; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (set_type, pkbuf, pos, type); } int -icmp_get_signature_size (hicn_type_t type, const hicn_protocol_t *h, +icmp_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t *signature_size) { - return CHILD_OPS (get_signature_size, type, h, signature_size); + return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size); } int -icmp_set_signature_size (hicn_type_t type, hicn_protocol_t *h, +icmp_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t signature_size) { - return CHILD_OPS (set_signature_size, type, h, signature_size); + return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size); } int -icmp_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, +icmp_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t padding) { - return CHILD_OPS (set_signature_padding, type, h, padding); + return CALL_CHILD (set_signature_padding, pkbuf, pos, padding); } int -icmp_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h, +icmp_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t *padding) { - return CHILD_OPS (get_signature_padding, type, h, padding); + return CALL_CHILD (get_signature_padding, pkbuf, pos, padding); } int -icmp_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h, +icmp_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, uint64_t signature_timestamp) { - return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp); } int -icmp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h, +icmp_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, uint64_t *signature_timestamp) { - return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp); } int -icmp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h, +icmp_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t validation_algorithm) { - return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (set_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -icmp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h, +icmp_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *validation_algorithm) { - return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (get_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -icmp_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id) +icmp_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t *key_id, size_t key_len) { - return CHILD_OPS (set_key_id, type, h, key_id); + return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len); } int -icmp_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id, - uint8_t *key_id_size) +icmp_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **key_id, uint8_t *key_id_size) { - return CHILD_OPS (get_key_id, type, h, key_id, key_id_size); + return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size); } -DECLARE_HICN_OPS (icmp); +DECLARE_HICN_OPS (icmp, ICMP_HDRLEN); /* * fd.io coding-style-patch-verification: ON diff --git a/lib/src/protocol/icmp.h b/lib/src/protocol/icmp.h new file mode 100644 index 000000000..6cbba6398 --- /dev/null +++ b/lib/src/protocol/icmp.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file protocol/icmp.h + * @brief ICMP packet header + */ +#ifndef HICN_PROTOCOL_ICMP_H +#define HICN_PROTOCOL_ICMP_H + +#include <hicn/common.h> + +/* + * The length of the ICMP header struct must be 4 bytes. + */ +#define EXPECTED_ICMP_HDRLEN 4 + +typedef struct +{ + u8 type; + u8 code; + u16 csum; +} _icmp_header_t; + +#define ICMP_HDRLEN sizeof (_icmp_header_t) +static_assert (EXPECTED_ICMP_HDRLEN == ICMP_HDRLEN, + "Size of ICMP struct does not match its expected size."); + +/* + * The length of the ICMPWLDR header struct must be 4 bytes. + */ +#define EXPECTED_ICMPWLDR_HDRLEN 8 + +typedef struct +{ + u8 type; + u8 code; + u16 csum; + union + { + struct + { + u16 id; + u16 sequence; + } echo; /* echo datagram */ + u32 gateway; /* gateway address */ + struct + { + u16 _unused; + u16 mtu; + } frag; /* path mtu discovery */ + struct + { + u16 expected_lbl; + u16 received_lbl; + } wldr_notification_lbl; + }; +} _icmp_wldr_header_t; + +#define ICMPWLDR_HDRLEN sizeof (_icmp_wldr_header_t) +static_assert (EXPECTED_ICMPWLDR_HDRLEN == ICMPWLDR_HDRLEN, + "Size of ICMPWLDR struct does not match its expected size."); + +#endif /* HICN_PROTOCOL_ICMP_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/protocol/icmprd.h b/lib/src/protocol/icmprd.h new file mode 100644 index 000000000..7edff8111 --- /dev/null +++ b/lib/src/protocol/icmprd.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file protocol/icmp-rd.c + * @brief hICN operations for ICMP Redirect header + */ +#ifndef HICN_PROTOCOL_ICMPRD_H +#define HICN_PROTOCOL_ICMPRD_H + +#include <hicn/common.h> +#include "ipv4.h" + +/* + * The length of the ICMPRD4 header struct must be 92 bytes. + */ +#define EXPECTED_ICMPRD4_HDRLEN 92 + +typedef struct +{ + u8 type; + u8 code; + u16 csum; + ipv4_address_t ip; + _ipv4_header_t iph; + u8 data[64]; +} _icmprd4_header_t; + +#define ICMPRD4_HDRLEN sizeof (_icmprd4_header_t) +static_assert (EXPECTED_ICMPRD4_HDRLEN == ICMPRD4_HDRLEN, + "Size of ICMPWLDR struct does not match its expected size."); + +/* + * The length of the ICMPRD header struct must be 40 bytes. + */ +#define EXPECTED_ICMPRD_HDRLEN 40 + +typedef struct +{ + u8 type; + u8 code; + u16 csum; + u32 res; + ipv6_address_t tgt; + ipv6_address_t dst; +} _icmprd_header_t; + +#define ICMPRD_HDRLEN sizeof (_icmprd_header_t) +static_assert (EXPECTED_ICMPRD_HDRLEN == ICMPRD_HDRLEN, + "Size of ICMPWLDR struct does not match its expected size."); + +#endif /* HICN_PROTOCOL_ICMPRD_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/protocol/ipv4.c b/lib/src/protocol/ipv4.c index 840fbe34b..a13728d04 100644 --- a/lib/src/protocol/ipv4.c +++ b/lib/src/protocol/ipv4.c @@ -14,7 +14,7 @@ */ /** - * @file protocol/ipv4.c + * @file protocol/ipv4->c * @brief hICN operations for IPv4 header * * NOTE: IPv4 options (affecting the header size) are currently not supported. @@ -28,264 +28,262 @@ #include <string.h> #include <hicn/error.h> -#include <hicn/ops.h> #include <hicn/common.h> -#include <hicn/header.h> -#include <hicn/protocol/ipv4.h> -typedef unsigned short u_short; -int ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *payload_length); +#include "../ops.h" +#include "ipv4.h" + +#define UINT16_T_MASK 0x0000ffff // 1111 1111 1111 1111 + +#define ipv4_get_payload_len(pkbuf, ipv4) htons (ipv4->len - pkbuf->payload) int -ipv4_init_packet_header (hicn_type_t type, hicn_protocol_t *h) +ipv4_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) { - size_t total_header_length; - int rc = - hicn_ops_vft[type.l1]->get_header_length (type, h, &total_header_length); - if (rc < 0) - return rc; + assert (pkbuf->len == 0); + if (IPV4_HDRLEN > pkbuf->buffer_size - pkbuf->len) + return -1; + pkbuf->len += IPV4_HDRLEN; + + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + hicn_packet_format_t format = hicn_packet_get_format (pkbuf); - h->ipv4 = (_ipv4_header_t){ + size_t header_len; + hicn_packet_get_header_length_from_format (pkbuf->format, &header_len); + + /* We initialize the len considering an empty payload */ + *ipv4 = (_ipv4_header_t){ .version_ihl = (IPV4_DEFAULT_VERSION << 4) | (0x0f & IPV4_DEFAULT_IHL), .tos = IPV4_DEFAULT_TOS, - .len = htons ((u16) total_header_length), + .len = htons (header_len), .id = htons (IPV4_DEFAULT_ID), .frag_off = htons (IPV4_DEFAULT_FRAG_OFF), .ttl = HICN_DEFAULT_TTL, - .protocol = type.l2, + .protocol = format.as_u8[pos + 1], .csum = 0, .saddr.as_u32 = 0, .daddr.as_u32 = 0, }; - return CHILD_OPS (init_packet_header, type, h); + return CALL_CHILD (init_packet_header, pkbuf, pos); } int -ipv4_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h, - ip_address_t *ip_address) +ipv4_get_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_ip_address_t *ip_address) { - ip_address->v4 = h->ipv4.saddr; + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + ip_address->v4 = ipv4->saddr; return HICN_LIB_ERROR_NONE; } int -ipv4_set_interest_locator (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *ip_address) +ipv4_set_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *ip_address) { - h->ipv4.saddr = ip_address->v4; + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + ipv4->saddr = ip_address->v4; return HICN_LIB_ERROR_NONE; } int -ipv4_get_interest_name (hicn_type_t type, const hicn_protocol_t *h, +ipv4_get_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_t *name) { - name->prefix.v4 = h->ipv4.daddr; - return CHILD_OPS (get_interest_name_suffix, type, h, &(name->suffix)); + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + name->prefix.v4 = ipv4->daddr; + return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, &(name->suffix)); } int -ipv4_set_interest_name (hicn_type_t type, hicn_protocol_t *h, +ipv4_set_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_t *name) { - h->ipv4.daddr = name->prefix.v4; - return CHILD_OPS (set_interest_name_suffix, type, h, &(name->suffix)); + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + ipv4->daddr = name->prefix.v4; + return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, &(name->suffix)); } int -ipv4_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +ipv4_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - return CHILD_OPS (get_interest_name_suffix, type, h, suffix); + return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, suffix); } int -ipv4_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h, +ipv4_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - return CHILD_OPS (set_interest_name_suffix, type, h, suffix); + return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, suffix); } int -ipv4_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest) +ipv4_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_packet_type_t *type) { - return CHILD_OPS (is_interest, type, h, is_interest); + return CALL_CHILD (get_type, pkbuf, pos, type); } int -ipv4_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h) +ipv4_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_packet_type_t type) { - return CHILD_OPS (mark_packet_as_interest, type, h); + return CALL_CHILD (set_type, pkbuf, pos, type); } int -ipv4_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h) +ipv4_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - return CHILD_OPS (mark_packet_as_data, type, h); -} + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); -int -ipv4_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h) -{ /* Sets everything to 0 up to IP destination address */ - memset (&(h->ipv4), 0, 16); + memset (ipv4, 0, 16); - return CHILD_OPS (reset_interest_for_hash, type, h); + return CALL_CHILD (reset_interest_for_hash, pkbuf, pos); } int -ipv4_get_data_locator (hicn_type_t type, const hicn_protocol_t *h, - ip_address_t *ip_address) +ipv4_get_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_ip_address_t *ip_address) { - ip_address->v4 = h->ipv4.daddr; + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + ip_address->v4 = ipv4->daddr; return HICN_LIB_ERROR_NONE; } int -ipv4_set_data_locator (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *ip_address) +ipv4_set_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *ip_address) { - h->ipv4.daddr = ip_address->v4; + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + ipv4->daddr = ip_address->v4; return HICN_LIB_ERROR_NONE; } int -ipv4_get_data_name (hicn_type_t type, const hicn_protocol_t *h, +ipv4_get_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_t *name) { - name->prefix.v4 = h->ipv4.saddr; - return CHILD_OPS (get_data_name_suffix, type, h, &(name->suffix)); + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + name->prefix.v4 = ipv4->saddr; + return CALL_CHILD (get_data_name_suffix, pkbuf, pos, &(name->suffix)); } int -ipv4_set_data_name (hicn_type_t type, hicn_protocol_t *h, +ipv4_set_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_t *name) { - h->ipv4.saddr = name->prefix.v4; - return CHILD_OPS (set_data_name_suffix, type, h, &(name->suffix)); + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + ipv4->saddr = name->prefix.v4; + return CALL_CHILD (set_data_name_suffix, pkbuf, pos, &(name->suffix)); } int -ipv4_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +ipv4_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - return CHILD_OPS (get_data_name_suffix, type, h, suffix); + return CALL_CHILD (get_data_name_suffix, pkbuf, pos, suffix); } int -ipv4_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h, +ipv4_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - return CHILD_OPS (set_data_name_suffix, type, h, suffix); + return CALL_CHILD (set_data_name_suffix, pkbuf, pos, suffix); } int -ipv4_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h, - u32 *pathlabel) +ipv4_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t *path_label) { - return CHILD_OPS (get_data_pathlabel, type, h, pathlabel); + return CALL_CHILD (get_data_path_label, pkbuf, pos, path_label); } int -ipv4_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const u32 pathlabel) +ipv4_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t path_label) { - return CHILD_OPS (set_data_pathlabel, type, h, pathlabel); + return CALL_CHILD (set_data_path_label, pkbuf, pos, path_label); } int -ipv4_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const hicn_faceid_t face_id) +ipv4_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_faceid_t face_id) { - return CHILD_OPS (update_data_pathlabel, type, h, face_id); + return CALL_CHILD (update_data_path_label, pkbuf, pos, face_id); } int -ipv4_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) +ipv4_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + /* Sets everything to 0 up to source address */ - memset (&h->ipv4, 0, 12); + memset (ipv4, 0, 12); /* Clears destination address */ - memset (&(h->ipv4.daddr), 0, 4); + memset (&(ipv4->daddr), 0, 4); - return CHILD_OPS (reset_data_for_hash, type, h); + return CALL_CHILD (reset_data_for_hash, pkbuf, pos); } int -ipv4_get_lifetime (hicn_type_t type, const hicn_protocol_t *h, +ipv4_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_lifetime_t *lifetime) { - return CHILD_OPS (get_lifetime, type, h, lifetime); + return CALL_CHILD (get_lifetime, pkbuf, pos, lifetime); } int -ipv4_set_lifetime (hicn_type_t type, hicn_protocol_t *h, +ipv4_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_lifetime_t lifetime) { - return CHILD_OPS (set_lifetime, type, h, lifetime); -} - -int -ipv4_get_source_port (hicn_type_t type, const hicn_protocol_t *h, - u16 *source_port) -{ - return CHILD_OPS (get_source_port, type, h, source_port); -} - -int -ipv4_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port) -{ - return CHILD_OPS (get_dest_port, type, h, dest_port); -} - -int -ipv4_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port) -{ - return CHILD_OPS (set_source_port, type, h, source_port); + return CALL_CHILD (set_lifetime, pkbuf, pos, lifetime); } int -ipv4_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port) +ipv4_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { - return CHILD_OPS (set_dest_port, type, h, dest_port); -} + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); -int -ipv4_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) -{ /* * Checksum field is not accounted for in lower layers, so we can compute * them in any order. Note that it is only a header checksum. */ - h->ipv4.csum = 0; - h->ipv4.csum = csum (h, IPV4_HDRLEN, 0); + ipv4->csum = 0; + ipv4->csum = csum (pkbuf_get_header (pkbuf), IPV4_HDRLEN, 0); - /* Retrieve payload length if not specified, as it is not available later */ - if (payload_length == 0) + /* Retrieve payload len if not specified, as it is not available later */ + if (payload_len == 0) { - int rc = ipv4_get_payload_length (type, h, &payload_length); - if (rc < 0) - return rc; + payload_len = ipv4_get_payload_len (pkbuf, ipv4); } - /* Ignore the payload if payload_length = ~0 */ - if (payload_length == ~0) + /* Ignore the payload if payload_len = ~0 */ + if (payload_len == ~0) { - payload_length = 0; + payload_len = 0; } /* Build pseudo-header */ ipv4_pseudo_header_t psh; - psh.ip_src = h->ipv4.saddr; - psh.ip_dst = h->ipv4.daddr; + psh.ip_src = ipv4->saddr; + psh.ip_dst = ipv4->daddr; /* Size is u32 and not u16, we cannot copy and need to care about endianness */ - psh.size = htons (ntohs (h->ipv4.len) - (u16) IPV4_HDRLEN); + psh.size = htons (ntohs (ipv4->len) - (u16) IPV4_HDRLEN); psh.zero = 0; - psh.protocol = (u8) h->ipv4.protocol; + psh.protocol = (u8) ipv4->protocol; /* Compute partial checksum based on pseudo-header */ if (partial_csum != 0) @@ -294,243 +292,289 @@ ipv4_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, } partial_csum = csum (&psh, IPV4_PSHDRLEN, partial_csum); - return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length); + return CALL_CHILD (update_checksums, pkbuf, pos, partial_csum, payload_len); +} + +int +ipv4_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, + size_t pos, u16 *old_val, u16 *new_val, + u8 size, bool skip_first) +{ + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + /* We update the child first */ + int rc = CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val, + new_val, size, false); + if (rc < 0) + return rc; + + if (!skip_first) + { + for (uint8_t i = 0; i < size; i++) + { + uint16_t old_csum = ~ipv4->csum; + uint16_t not_old_val = ~(*old_val); + uint32_t sum = (uint32_t) old_csum + not_old_val + *new_val; + + while (sum >> 16) + { + sum = (sum >> 16) + (sum & UINT16_T_MASK); + } + + ipv4->csum = ~sum; + ++old_val; + ++new_val; + } + } + + return HICN_LIB_ERROR_NONE; } int -ipv4_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +ipv4_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + /* * Checksum field is not accounted for in lower layers, so we can compute * them in any order. Note that it is only a header checksum. */ - if (csum (h, IPV4_HDRLEN, 0) != 0) + if (csum (pkbuf_get_header (pkbuf), IPV4_HDRLEN, 0) != 0) return HICN_LIB_ERROR_CORRUPTED_PACKET; - /* Retrieve payload length if not specified, as it is not available later */ - if (payload_length == 0) + /* Retrieve payload len if not specified, as it is not available later */ + if (payload_len == 0) { - int rc = ipv4_get_payload_length (type, h, &payload_length); - if (rc < 0) - return rc; + payload_len = ipv4_get_payload_len (pkbuf, ipv4); } /* Build pseudo-header */ ipv4_pseudo_header_t psh; - psh.ip_src = h->ipv4.saddr; - psh.ip_dst = h->ipv4.daddr; + psh.ip_src = ipv4->saddr; + psh.ip_dst = ipv4->daddr; /* Size is u32 and not u16, we cannot copy and need to care about endianness */ - psh.size = htons (ntohs (h->ipv4.len) - (u16) IPV4_HDRLEN); + psh.size = htons (ntohs (ipv4->len) - (u16) IPV4_HDRLEN); psh.zero = 0; - psh.protocol = (u8) h->ipv4.protocol; + psh.protocol = (u8) ipv4->protocol; /* Compute partial checksum based on pseudo-header */ partial_csum = csum (&psh, IPV4_PSHDRLEN, 0); - return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length); + return CALL_CHILD (verify_checksums, pkbuf, pos, partial_csum, payload_len); } int -ipv4_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old) +ipv4_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old) { + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + // ASSERT(addr_old == NULL); - addr_old->v4 = h->ipv4.saddr; + addr_old->v4 = ipv4->saddr; addr_old->pad[0] = 0; addr_old->pad[1] = 0; addr_old->pad[2] = 0; - h->ipv4.saddr = addr_new->v4; - h->ipv4.csum = 0; - h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0); + ipv4->saddr = addr_new->v4; + ipv4->csum = 0; + ipv4->csum = csum (&ipv4, IPV4_HDRLEN, 0); - return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old); + return CALL_CHILD (rewrite_interest, pkbuf, pos, addr_new, addr_old); } int -ipv4_rewrite_data (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old, - const hicn_faceid_t face_id, u8 reset_pl) +ipv4_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, const hicn_faceid_t face_id, + u8 reset_pl) { + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + // ASSERT(addr_old == NULL); - addr_old->v4 = h->ipv4.daddr; + addr_old->v4 = ipv4->daddr; addr_old->pad[0] = 0; addr_old->pad[1] = 0; addr_old->pad[2] = 0; - h->ipv4.daddr = addr_new->v4; - h->ipv4.csum = 0; - h->ipv4.csum = csum (&h->ipv4, IPV4_HDRLEN, 0); + ipv4->daddr = addr_new->v4; + ipv4->csum = 0; + ipv4->csum = csum (&ipv4, IPV4_HDRLEN, 0); - return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id, - reset_pl); + return CALL_CHILD (rewrite_data, pkbuf, pos, addr_new, addr_old, face_id, + reset_pl); } int -ipv4_get_current_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ipv4_set_payload_len (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t payload_len) { - *header_length = IPV4_HDRLEN; + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + size_t child_header_len = hicn_ops_vft[pos + 1]->header_len; + + ipv4->len = htons ((u16) (payload_len + IPV4_HDRLEN + child_header_len)); return HICN_LIB_ERROR_NONE; } int -ipv4_get_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ipv4_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_payload_type_t *payload_type) { - *header_length = h->ipv4.len; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (get_payload_type, pkbuf, pos, payload_type); } int -ipv4_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ipv4_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_payload_type_t payload_type) { - *header_length = IPV4_HDRLEN; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (set_payload_type, pkbuf, pos, payload_type); } int -ipv4_get_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ipv4_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t *signature_size) { - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - *header_length = IPV4_HDRLEN + child_header_length; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size); } int -ipv4_get_payload_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *payload_length) +ipv4_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t signature_size) { - size_t child_header_length; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - *payload_length = htons (h->ipv4.len) - IPV4_HDRLEN - child_header_length; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size); } int -ipv4_set_payload_length (hicn_type_t type, hicn_protocol_t *h, - size_t payload_length) +ipv4_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t padding) { - size_t child_header_length; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - h->ipv4.len = - htons ((u_short) (payload_length + IPV4_HDRLEN + child_header_length)); - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (set_signature_padding, pkbuf, pos, padding); } int -ipv4_get_payload_type (hicn_type_t type, const hicn_protocol_t *h, - hicn_payload_type_t *payload_type) +ipv4_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t *padding) { - return CHILD_OPS (get_payload_type, type, h, payload_type); + return CALL_CHILD (get_signature_padding, pkbuf, pos, padding); } int -ipv4_set_payload_type (hicn_type_t type, hicn_protocol_t *h, - hicn_payload_type_t payload_type) +ipv4_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint64_t signature_timestamp) { - return CHILD_OPS (set_payload_type, type, h, payload_type); + return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp); } int -ipv4_get_signature_size (hicn_type_t type, const hicn_protocol_t *h, - size_t *signature_size) +ipv4_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint64_t *signature_timestamp) { - return CHILD_OPS (get_signature_size, type, h, signature_size); + return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp); } int -ipv4_set_signature_size (hicn_type_t type, hicn_protocol_t *h, - size_t signature_size) +ipv4_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t validation_algorithm) { - return CHILD_OPS (set_signature_size, type, h, signature_size); + return CALL_CHILD (set_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -ipv4_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, - size_t padding) +ipv4_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t *validation_algorithm) { - return CHILD_OPS (set_signature_padding, type, h, padding); + return CALL_CHILD (get_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -ipv4_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h, - size_t *padding) +ipv4_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t *key_id, size_t key_len) { - return CHILD_OPS (get_signature_padding, type, h, padding); + return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len); } int -ipv4_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h, - uint64_t signature_timestamp) +ipv4_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **key_id, uint8_t *key_id_size) { - return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size); } int -ipv4_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h, - uint64_t *signature_timestamp) +ipv4_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **signature) { - return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (get_signature, pkbuf, pos, signature); } int -ipv4_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h, - uint8_t validation_algorithm) +ipv4_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag) { - return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (has_signature, pkbuf, pos, flag); } int -ipv4_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h, - uint8_t *validation_algorithm) +ipv4_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last) +{ + return CALL_CHILD (is_last_data, pkbuf, pos, is_last); +} + +int +ipv4_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos) +{ + return CALL_CHILD (set_last_data, pkbuf, pos); +} + +int +ipv4_get_ttl (const hicn_packet_buffer_t *pkbuf, size_t pos, u8 *hops) { - return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm); + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + *hops = ipv4->ttl; + + return HICN_LIB_ERROR_NONE; } int -ipv4_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id) +ipv4_set_ttl (const hicn_packet_buffer_t *pkbuf, size_t pos, u8 hops) { - return CHILD_OPS (set_key_id, type, h, key_id); + _ipv4_header_t *ipv4 = pkbuf_get_ipv4 (pkbuf); + + ipv4->ttl = hops; + + return HICN_LIB_ERROR_NONE; } int -ipv4_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id, - uint8_t *key_id_size) +ipv4_get_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *port) { - return CHILD_OPS (get_key_id, type, h, key_id, key_id_size); + return CALL_CHILD (get_src_port, pkbuf, pos, port); } int -ipv4_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature) +ipv4_set_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 port) { - return CHILD_OPS (get_signature, type, h, signature); + return CALL_CHILD (set_src_port, pkbuf, pos, port); } int -ipv4_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last) +ipv4_get_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *port) { - return CHILD_OPS (is_last_data, type, h, is_last); + return CALL_CHILD (get_dst_port, pkbuf, pos, port); } int -ipv4_set_last_data (hicn_type_t type, hicn_protocol_t *h) +ipv4_set_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 port) { - return CHILD_OPS (set_last_data, type, h); + return CALL_CHILD (set_dst_port, pkbuf, pos, port); } -DECLARE_HICN_OPS (ipv4); +DECLARE_HICN_OPS (ipv4, IPV4_HDRLEN); /* * fd.io coding-style-patch-verification: ON diff --git a/lib/src/protocol/ipv4.h b/lib/src/protocol/ipv4.h new file mode 100644 index 000000000..5d729b955 --- /dev/null +++ b/lib/src/protocol/ipv4.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HICN_PROTOCOL_IPV4 +#define HICN_PROTOCOL_IPV4 + +#include <hicn/util/ip_address.h> + +#include <hicn/base.h> +#include <hicn/common.h> + +/* Headers were adapted from linux' definitions in netinet/ip.h */ + +/* + * The length of the IPV4 header struct must be 20 bytes. + */ +#define EXPECTED_IPV4_HDRLEN 20 + +typedef struct +{ + union + { + struct + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + u8 ihl : 4; + u8 version : 4; +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 version : 4; + u8 ihl : 4; +#else +#error "Unsupported endianness" +#endif + }; + + u8 version_ihl; + }; + u8 tos; + + /* + * This is the total length of the IP packet, including the IP header. + * NOTE: vriable len header size is currently not supported by the lib. + */ + u16 len; + + u16 id; + u16 frag_off; + u8 ttl; + u8 protocol; + u16 csum; + ipv4_address_t saddr; + ipv4_address_t daddr; +} _ipv4_header_t; + +#define ipv4_header_bytes(ipv4_header) \ + (sizeof (u32) * (ipv4_header->version_ihl & 0xf)) + +#define IPV4_HDRLEN sizeof (_ipv4_header_t) +static_assert (EXPECTED_IPV4_HDRLEN == IPV4_HDRLEN, + "Size of IPV4 struct does not match its expected size."); + +/* + * The length of the IPV4 pseudo header struct must be 12 bytes. + */ +#define EXPECTED_IPV4_PSHDRLEN 12 + +typedef struct +{ + ipv4_address_t ip_src; + ipv4_address_t ip_dst; + u8 zero; + u8 protocol; + u16 size; +} ipv4_pseudo_header_t; + +#define IPV4_PSHDRLEN sizeof (ipv4_pseudo_header_t) +static_assert (EXPECTED_IPV4_PSHDRLEN == IPV4_PSHDRLEN, + "Size of IPV4_PSHDR struct does not match its expected size."); + +/* Default field values */ +#define IPV4_DEFAULT_VERSION 4 +#define IPV4_DEFAULT_IHL 5 +#define IPV4_DEFAULT_TOS 0 +#define IPV4_DEFAULT_PAYLOAD_LENGTH 0 +#define IPV4_DEFAULT_ID 300 +#define IPV4_DEFAULT_FRAG_OFF 0x000 +#define IPV4_DEFAULT_TTL 64 +#define IPV4_DEFAULT_PROTOCOL IPPROTO_TCP +#define IPV4_DEFAULT_SRC_IP 0, 0, 0, 0 +#define IPV4_DEFAULT_DST_IP 0, 0, 0, 0 + +#endif /* HICN_PROTOCOL_IPV4 */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/protocol/ipv6.c b/lib/src/protocol/ipv6.c index b3c543249..aec521afc 100644 --- a/lib/src/protocol/ipv6.c +++ b/lib/src/protocol/ipv6.c @@ -17,247 +17,252 @@ #include <string.h> #include <hicn/common.h> #include <hicn/error.h> -#include <hicn/ops.h> + +#include "ipv6.h" +#include "../ops.h" typedef unsigned short u_short; -int ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *payload_length); + +#ifdef OPAQUE_IP +#define GET_IPV6_HEADER(pkbuf) \ + (_ipv6_header_t *) ((pkbuf)->header + (pkbuf)->ipv6) +#else +#define GET_IPV6_HEADER(pkbuf) (_ipv6_header_t *) ((pkbuf)->header) +#endif /* OPAQUE_IP */ int -ipv6_init_packet_header (hicn_type_t type, hicn_protocol_t *h) +ipv6_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) { - size_t total_header_length; - int rc = CHILD_OPS (get_header_length, type, h, &total_header_length); - if (rc < 0) - return rc; + assert (pkbuf->len == 0); + if (IPV6_HDRLEN > pkbuf->buffer_size - pkbuf->len) + return -1; + pkbuf->len += IPV6_HDRLEN; + + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); - /* *INDENT-OFF* */ - h->ipv6 = (_ipv6_header_t){ + hicn_packet_format_t format = hicn_packet_get_format (pkbuf); + + size_t header_len; + hicn_packet_get_header_length_from_format (pkbuf->format, &header_len); + + /* clang-format off */ + *ipv6 = (_ipv6_header_t){ .saddr = IP6_ADDRESS_EMPTY, .daddr = IP6_ADDRESS_EMPTY, .version_class_flow = htonl ((IPV6_DEFAULT_VERSION << 28) | (IPV6_DEFAULT_TRAFFIC_CLASS << 20) | (IPV6_DEFAULT_FLOW_LABEL & 0xfffff)), - .len = htons ((u16) total_header_length), - .nxt = type.l2, + .len = htons(header_len - IPV6_HDRLEN), + .nxt = format.as_u8[pos + 1], .hlim = HICN_DEFAULT_TTL, }; - /* *INDENT-ON* */ - return CHILD_OPS (init_packet_header, type, h); + /* clang-format on */ + return CALL_CHILD (init_packet_header, pkbuf, pos); } int -ipv6_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h, - ip_address_t *ip_address) +ipv6_get_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_ip_address_t *ip_address) { - ip_address->v6 = h->ipv6.saddr; + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + ip_address->v6 = ipv6->saddr; return HICN_LIB_ERROR_NONE; } int -ipv6_set_interest_locator (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *ip_address) +ipv6_set_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *ip_address) { - h->ipv6.saddr = ip_address->v6; + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + ipv6->saddr = ip_address->v6; return HICN_LIB_ERROR_NONE; } int -ipv6_get_interest_name (hicn_type_t type, const hicn_protocol_t *h, +ipv6_get_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_t *name) { - name->prefix.v6 = h->ipv6.daddr; - return CHILD_OPS (get_interest_name_suffix, type, h, &(name->suffix)); + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + name->prefix.v6 = ipv6->daddr; + return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, &(name->suffix)); } int -ipv6_set_interest_name (hicn_type_t type, hicn_protocol_t *h, +ipv6_set_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_t *name) { - h->ipv6.daddr = name->prefix.v6; - return CHILD_OPS (set_interest_name_suffix, type, h, &(name->suffix)); + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + ipv6->daddr = name->prefix.v6; + return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, &(name->suffix)); } int -ipv6_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +ipv6_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - return CHILD_OPS (get_interest_name_suffix, type, h, suffix); + return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, suffix); } int -ipv6_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h, +ipv6_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - return CHILD_OPS (set_interest_name_suffix, type, h, suffix); + return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, suffix); } int -ipv6_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest) +ipv6_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_packet_type_t *type) { - return CHILD_OPS (is_interest, type, h, is_interest); + return CALL_CHILD (get_type, pkbuf, pos, type); } int -ipv6_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h) +ipv6_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_packet_type_t type) { - return CHILD_OPS (mark_packet_as_interest, type, h); + return CALL_CHILD (set_type, pkbuf, pos, type); } int -ipv6_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h) +ipv6_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - return CHILD_OPS (mark_packet_as_data, type, h); -} + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); -int -ipv6_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h) -{ /* Sets everything to 0 up to IP destination address */ - memset (&(h->ipv6), 0, 24); + memset (ipv6, 0, 24); - return CHILD_OPS (reset_interest_for_hash, type, h); + return CALL_CHILD (reset_interest_for_hash, pkbuf, pos); } int -ipv6_get_data_locator (hicn_type_t type, const hicn_protocol_t *h, - ip_address_t *ip_address) +ipv6_get_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_ip_address_t *ip_address) { - ip_address->v6 = h->ipv6.daddr; + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + ip_address->v6 = ipv6->daddr; return HICN_LIB_ERROR_NONE; } int -ipv6_set_data_locator (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *ip_address) +ipv6_set_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *ip_address) { - h->ipv6.daddr = ip_address->v6; + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + ipv6->daddr = ip_address->v6; return HICN_LIB_ERROR_NONE; } int -ipv6_get_data_name (hicn_type_t type, const hicn_protocol_t *h, +ipv6_get_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_t *name) { - name->prefix.v6 = h->ipv6.saddr; - return CHILD_OPS (get_data_name_suffix, type, h, &(name->suffix)); + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + name->prefix.v6 = ipv6->saddr; + return CALL_CHILD (get_data_name_suffix, pkbuf, pos, &(name->suffix)); } int -ipv6_set_data_name (hicn_type_t type, hicn_protocol_t *h, +ipv6_set_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_t *name) { - h->ipv6.saddr = name->prefix.v6; - return CHILD_OPS (set_data_name_suffix, type, h, &(name->suffix)); + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + ipv6->saddr = name->prefix.v6; + return CALL_CHILD (set_data_name_suffix, pkbuf, pos, &(name->suffix)); } int -ipv6_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +ipv6_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - return CHILD_OPS (get_data_name_suffix, type, h, suffix); + return CALL_CHILD (get_data_name_suffix, pkbuf, pos, suffix); } int -ipv6_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h, +ipv6_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - return CHILD_OPS (set_data_name_suffix, type, h, suffix); + return CALL_CHILD (set_data_name_suffix, pkbuf, pos, suffix); } int -ipv6_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h, - u32 *pathlabel) +ipv6_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t *path_label) { - return CHILD_OPS (get_data_pathlabel, type, h, pathlabel); + return CALL_CHILD (get_data_path_label, pkbuf, pos, path_label); } int -ipv6_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const u32 pathlabel) +ipv6_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t path_label) { - return CHILD_OPS (set_data_pathlabel, type, h, pathlabel); + return CALL_CHILD (set_data_path_label, pkbuf, pos, path_label); } int -ipv6_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const hicn_faceid_t face_id) +ipv6_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_faceid_t face_id) { - return CHILD_OPS (update_data_pathlabel, type, h, face_id); + return CALL_CHILD (update_data_path_label, pkbuf, pos, face_id); } int -ipv6_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) +ipv6_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + /* IP: Set everithing to 0 up to destination address */ - memset (&h->ipv6, 0, 8); + memset (ipv6, 0, 8); /* Clears destination address */ - memset (&(h->ipv6.daddr), 0, 16); + memset (&(ipv6->daddr), 0, 16); - return CHILD_OPS (reset_data_for_hash, type, h); + return CALL_CHILD (reset_data_for_hash, pkbuf, pos); } int -ipv6_get_lifetime (hicn_type_t type, const hicn_protocol_t *h, +ipv6_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_lifetime_t *lifetime) { - return CHILD_OPS (get_lifetime, type, h, lifetime); + return CALL_CHILD (get_lifetime, pkbuf, pos, lifetime); } int -ipv6_set_lifetime (hicn_type_t type, hicn_protocol_t *h, +ipv6_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_lifetime_t lifetime) { - return CHILD_OPS (set_lifetime, type, h, lifetime); -} - -int -ipv6_get_source_port (hicn_type_t type, const hicn_protocol_t *h, - u16 *source_port) -{ - return CHILD_OPS (get_source_port, type, h, source_port); + return CALL_CHILD (set_lifetime, pkbuf, pos, lifetime); } int -ipv6_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port) +ipv6_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { - return CHILD_OPS (get_dest_port, type, h, dest_port); -} - -int -ipv6_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port) -{ - return CHILD_OPS (set_source_port, type, h, source_port); -} + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); -int -ipv6_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port) -{ - return CHILD_OPS (set_dest_port, type, h, dest_port); -} - -int -ipv6_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) -{ - /* Retrieve payload length if not specified */ - if (payload_length == ~0) + /* Retrieve payload len if not specified */ + if (payload_len == ~0) { - int rc = ipv6_get_payload_length (type, h, &payload_length); - if (rc < 0) - return rc; + payload_len = hicn_packet_get_len (pkbuf) - pkbuf->payload; } /* Build pseudo-header */ ipv6_pseudo_header_t psh; - psh.ip_src = h->ipv6.saddr; - psh.ip_dst = h->ipv6.daddr; + psh.ip_src = ipv6->saddr; + psh.ip_dst = ipv6->daddr; /* Size is u32 and not u16, we cannot copy and need to care about endianness */ - psh.size = htonl (ntohs (h->ipv6.len)); + psh.size = htonl (ntohs (ipv6->len)); psh.zeros = 0; psh.zero = 0; - psh.protocol = h->ipv6.nxt; + psh.protocol = ipv6->nxt; /* Compute partial checksum based on pseudo-header */ if (partial_csum != 0) @@ -266,31 +271,41 @@ ipv6_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, } partial_csum = csum (&psh, IPV6_PSHDRLEN, partial_csum); - return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length); + return CALL_CHILD (update_checksums, pkbuf, pos, partial_csum, payload_len); } int -ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +ipv6_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, + size_t pos, u16 *old_val, u16 *new_val, + u8 size, bool skip_first) { - /* Retrieve payload length if not specified */ - if (payload_length == ~0) + /* We update the child only */ + return CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val, + new_val, size, false); +} + +int +ipv6_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) +{ + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + /* Retrieve payload len if not specified */ + if (payload_len == ~0) { - int rc = ipv6_get_payload_length (type, h, &payload_length); - if (rc < 0) - return rc; + payload_len = hicn_packet_get_len (pkbuf) - pkbuf->payload; } /* Build pseudo-header */ ipv6_pseudo_header_t pseudo; - pseudo.ip_src = h->ipv6.saddr; - pseudo.ip_dst = h->ipv6.daddr; + pseudo.ip_src = ipv6->saddr; + pseudo.ip_dst = ipv6->daddr; /* Size is u32 and not u16, we cannot copy and need to care about endianness */ - pseudo.size = htonl (ntohs (h->ipv6.len)); + pseudo.size = htonl (ntohs (ipv6->len)); pseudo.zeros = 0; pseudo.zero = 0; - pseudo.protocol = h->ipv6.nxt; + pseudo.protocol = ipv6->nxt; /* Compute partial checksum based on pseudo-header */ if (partial_csum != 0) @@ -299,187 +314,206 @@ ipv6_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, } partial_csum = csum (&pseudo, IPV6_PSHDRLEN, partial_csum); - return CHILD_OPS (verify_checksums, type, h, partial_csum, payload_length); + return CALL_CHILD (verify_checksums, pkbuf, pos, partial_csum, payload_len); } int -ipv6_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old) +ipv6_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old) { + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + // ASSERT(addr_old == NULL); - addr_old->v6 = h->ipv6.saddr; - h->ipv6.saddr = addr_new->v6; + addr_old->v6 = ipv6->saddr; + ipv6->saddr = addr_new->v6; - return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old); + return CALL_CHILD (rewrite_interest, pkbuf, pos, addr_new, addr_old); } int -ipv6_rewrite_data (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old, - const hicn_faceid_t face_id, u8 reset_pl) +ipv6_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, const hicn_faceid_t face_id, + u8 reset_pl) { + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + // ASSERT(addr_old == NULL); - addr_old->v6 = h->ipv6.daddr; - h->ipv6.daddr = addr_new->v6; + addr_old->v6 = ipv6->daddr; + ipv6->daddr = addr_new->v6; - return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id, - reset_pl); + return CALL_CHILD (rewrite_data, pkbuf, pos, addr_new, addr_old, face_id, + reset_pl); } int -ipv6_get_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ipv6_set_payload_len (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t payload_len) { - *header_length = IPV6_HDRLEN + ntohs (h->ipv6.len); + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + ipv6->len = htons ((u_short) (payload_len + pkbuf->payload - IPV6_HDRLEN)); return HICN_LIB_ERROR_NONE; } int -ipv6_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ipv6_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_payload_type_t *payload_type) { - *header_length = IPV6_HDRLEN; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (get_payload_type, pkbuf, pos, payload_type); } int -ipv6_get_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +ipv6_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_payload_type_t payload_type) { - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - *header_length = IPV6_HDRLEN + child_header_length; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (set_payload_type, pkbuf, pos, payload_type); } int -ipv6_get_payload_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *payload_length) +ipv6_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t *signature_size) { - size_t child_header_length; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - *payload_length = ntohs (h->ipv6.len) - child_header_length; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size); } int -ipv6_set_payload_length (hicn_type_t type, hicn_protocol_t *h, - size_t payload_length) +ipv6_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t signature_size) { - size_t child_header_length; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - h->ipv6.len = htons ((u_short) (payload_length + child_header_length)); - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size); } int -ipv6_get_payload_type (hicn_type_t type, const hicn_protocol_t *h, - hicn_payload_type_t *payload_type) +ipv6_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t padding) { - return CHILD_OPS (get_payload_type, type, h, payload_type); + return CALL_CHILD (set_signature_padding, pkbuf, pos, padding); } int -ipv6_set_payload_type (hicn_type_t type, hicn_protocol_t *h, - hicn_payload_type_t payload_type) +ipv6_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t *padding) { - return CHILD_OPS (set_payload_type, type, h, payload_type); + return CALL_CHILD (get_signature_padding, pkbuf, pos, padding); } int -ipv6_get_signature_size (hicn_type_t type, const hicn_protocol_t *h, - size_t *signature_size) +ipv6_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint64_t signature_timestamp) { - return CHILD_OPS (get_signature_size, type, h, signature_size); + return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp); } int -ipv6_set_signature_size (hicn_type_t type, hicn_protocol_t *h, - size_t signature_size) +ipv6_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint64_t *signature_timestamp) { - return CHILD_OPS (set_signature_size, type, h, signature_size); + return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp); } int -ipv6_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, - size_t padding) +ipv6_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t validation_algorithm) { - return CHILD_OPS (set_signature_padding, type, h, padding); + return CALL_CHILD (set_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -ipv6_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h, - size_t *padding) +ipv6_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t *validation_algorithm) { - return CHILD_OPS (get_signature_padding, type, h, padding); + return CALL_CHILD (get_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -ipv6_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h, - uint64_t signature_timestamp) +ipv6_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t *key_id, size_t key_len) { - return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len); } int -ipv6_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h, - uint64_t *signature_timestamp) +ipv6_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **key_id, uint8_t *key_id_size) { - return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size); } int -ipv6_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h, - uint8_t validation_algorithm) +ipv6_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **signature) { - return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (get_signature, pkbuf, pos, signature); } int -ipv6_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h, - uint8_t *validation_algorithm) +ipv6_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag) +{ + return CALL_CHILD (has_signature, pkbuf, pos, flag); +} + +int +ipv6_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last) +{ + return CALL_CHILD (is_last_data, pkbuf, pos, is_last); +} + +int +ipv6_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos) +{ + return CALL_CHILD (set_last_data, pkbuf, pos); +} + +int +ipv6_get_ttl (const hicn_packet_buffer_t *pkbuf, size_t pos, u8 *hops) { - return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm); + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + *hops = ipv6->hlim; + + return HICN_LIB_ERROR_NONE; } int -ipv6_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id) +ipv6_set_ttl (const hicn_packet_buffer_t *pkbuf, size_t pos, u8 hops) { - return CHILD_OPS (set_key_id, type, h, key_id); + + _ipv6_header_t *ipv6 = pkbuf_get_ipv6 (pkbuf); + + ipv6->hlim = hops; + + return HICN_LIB_ERROR_NONE; } int -ipv6_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id, - uint8_t *key_id_size) +ipv6_get_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *port) { - return CHILD_OPS (get_key_id, type, h, key_id, key_id_size); + return CALL_CHILD (get_src_port, pkbuf, pos, port); } int -ipv6_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature) +ipv6_set_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 port) { - return CHILD_OPS (get_signature, type, h, signature); + return CALL_CHILD (set_src_port, pkbuf, pos, port); } int -ipv6_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last) +ipv6_get_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *port) { - return CHILD_OPS (is_last_data, type, h, is_last); + return CALL_CHILD (get_dst_port, pkbuf, pos, port); } int -ipv6_set_last_data (hicn_type_t type, hicn_protocol_t *h) +ipv6_set_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 port) { - return CHILD_OPS (set_last_data, type, h); + return CALL_CHILD (set_dst_port, pkbuf, pos, port); } -DECLARE_HICN_OPS (ipv6); +DECLARE_HICN_OPS (ipv6, IPV6_HDRLEN); /* * fd.io coding-style-patch-verification: ON diff --git a/lib/src/protocol/ipv6.h b/lib/src/protocol/ipv6.h new file mode 100644 index 000000000..9a51096a0 --- /dev/null +++ b/lib/src/protocol/ipv6.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HICN_PROTOCOL_IPV6_H +#define HICN_PROTOCOL_IPV6_H + +#include <hicn/util/ip_address.h> + +#include <hicn/common.h> + +/* + * The length of the IPV6 header struct must be 40 bytes. + */ +#define EXPECTED_IPV6_HDRLEN 40 + +typedef struct +{ +#if 0 // TEMPORARY FIX + union + { + struct + { +#endif + u32 version_class_flow; /* version, traffic class and 20 bits of flow-ID */ + u16 len; /* payload length */ + u8 nxt; /* next header */ + u8 hlim; /* hop limit */ +#if 0 + }; + u8 vfc; /* 4 bits version, top 4 bits class */ + }; +#endif + ipv6_address_t saddr; /* source address */ + ipv6_address_t daddr; /* destination address */ +} _ipv6_header_t; + +#define IPV6_HDRLEN sizeof (_ipv6_header_t) +static_assert (EXPECTED_IPV6_HDRLEN == IPV6_HDRLEN, + "Size of IPV6 struct does not match its expected size."); + +/* + * The length of the IPV6 pseudo header struct must be 40 bytes. + */ +#define EXPECTED_IPV6_PSHDRLEN 40 + +typedef struct +{ + ipv6_address_t ip_src; + ipv6_address_t ip_dst; + u32 size; + u16 zeros; + u8 zero; + u8 protocol; +} ipv6_pseudo_header_t; + +#define IPV6_PSHDRLEN sizeof (ipv6_pseudo_header_t) +static_assert (EXPECTED_IPV6_PSHDRLEN == IPV6_PSHDRLEN, + "Size of IPV6_PSHDR struct does not match its expected size."); + +/* Default field values */ +#define IPV6_DEFAULT_VERSION 6 +#define IPV6_DEFAULT_TRAFFIC_CLASS 0 +#define IPV6_DEFAULT_FLOW_LABEL 0 +#define IPV6_DEFAULT_PAYLOAD_LENGTH 0 + +#endif + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/protocol/new.c b/lib/src/protocol/new.c index 07c1d0d76..5308e8c0a 100644 --- a/lib/src/protocol/new.c +++ b/lib/src/protocol/new.c @@ -17,423 +17,544 @@ #include <string.h> #include <hicn/common.h> #include <hicn/error.h> -#include <hicn/ops.h> + +#include "udp.h" +#include "../ops.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" -DECLARE_get_source_port (new, UNEXPECTED); -DECLARE_get_dest_port (new, UNEXPECTED); -DECLARE_set_source_port (new, UNEXPECTED); -DECLARE_set_dest_port (new, UNEXPECTED); - -static int -is_interest (u8 flags) -{ - return flags & HICN_NEW_FLAG_INT; -} +DECLARE_get_ttl (new, UNEXPECTED); +DECLARE_set_ttl (new, UNEXPECTED); +DECLARE_get_src_port (new, UNEXPECTED); +DECLARE_set_src_port (new, UNEXPECTED); +DECLARE_get_dst_port (new, UNEXPECTED); +DECLARE_set_dst_port (new, UNEXPECTED); int -new_init_packet_header (hicn_type_t type, hicn_protocol_t *h) +new_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) { - memset (&h->newhdr, 0, sizeof (h->newhdr)); - _set_new_header_version (&h->newhdr); - uint8_t ah_flag = type.l2 == IPPROTO_AH ? HICN_NEW_FLAG_SIG : 0; - h->newhdr.flags |= ah_flag; + pkbuf->newhdr = pkbuf->len; + if (NEW_HDRLEN > pkbuf->buffer_size - pkbuf->len) + return -1; + pkbuf->len += NEW_HDRLEN; - return CHILD_OPS (init_packet_header, type, h); -} + _new_header_t *new = pkbuf_get_new (pkbuf); -int -new_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest) -{ - *is_interest = (h->newhdr.flags & HICN_NEW_FLAG_INT) != 0; - return HICN_LIB_ERROR_NONE; + hicn_packet_format_t format = hicn_packet_get_format (pkbuf); + + memset (new, 0, sizeof (_new_header_t)); + _set_new_header_version (new); + uint8_t ah_flag = + format.as_u8[pos + 1] == IPPROTO_AH ? HICN_NEW_FLAG_SIG : 0; + new->flags |= ah_flag; + + return CALL_CHILD (init_packet_header, pkbuf, pos); } int -new_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h) +new_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_packet_type_t *type) { - h->newhdr.flags |= HICN_NEW_FLAG_INT; + _new_header_t *new = pkbuf_get_new (pkbuf); + + /* Interest packets have the INT bit set */ + if (new->flags & HICN_NEW_FLAG_INT) + *type = HICN_PACKET_TYPE_INTEREST; + else + *type = HICN_PACKET_TYPE_DATA; return HICN_LIB_ERROR_NONE; } int -new_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h) +new_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_packet_type_t type) { - h->newhdr.flags &= ~HICN_NEW_FLAG_INT; + _new_header_t *new = pkbuf_get_new (pkbuf); + + switch (type) + { + case HICN_PACKET_TYPE_INTEREST: + new->flags |= HICN_NEW_FLAG_INT; + break; + case HICN_PACKET_TYPE_DATA: + new->flags &= ~HICN_NEW_FLAG_INT; + break; + default: + return -1; + } return HICN_LIB_ERROR_NONE; } int -new_get_interest_locator (hicn_type_t type, const hicn_protocol_t *h, - ip_address_t *ip_address) +new_get_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_ip_address_t *ip_address) { - assert (is_interest (h->newhdr.flags)); + _new_header_t *new = pkbuf_get_new (pkbuf); + _unused (new); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); return HICN_LIB_ERROR_NONE; } int -new_set_interest_locator (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *ip_address) +new_set_interest_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *ip_address) { - assert (is_interest (h->newhdr.flags)); + _new_header_t *new = pkbuf_get_new (pkbuf); + _unused (new); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); + return HICN_LIB_ERROR_NONE; } int -new_get_interest_name (hicn_type_t type, const hicn_protocol_t *h, +new_get_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_t *name) { - assert (is_interest (h->newhdr.flags)); - name->prefix = h->newhdr.prefix; - name->suffix = ntohl (h->newhdr.suffix); + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); + + name->prefix = new->prefix; + name->suffix = ntohl (new->suffix); return HICN_LIB_ERROR_NONE; } int -new_set_interest_name (hicn_type_t type, hicn_protocol_t *h, +new_set_interest_name (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_t *name) { - int rc = new_mark_packet_as_interest (type, h); + _new_header_t *new = pkbuf_get_new (pkbuf); + + int rc = new_set_type (pkbuf, pos, HICN_PACKET_TYPE_INTEREST); if (rc) return rc; - assert (is_interest (h->newhdr.flags)); - h->newhdr.prefix = name->prefix; - h->newhdr.suffix = htonl (name->suffix); + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); + + new->prefix = name->prefix; + new->suffix = htonl (name->suffix); return HICN_LIB_ERROR_NONE; } int -new_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +new_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - assert (is_interest (h->newhdr.flags)); - *suffix = ntohl (h->newhdr.suffix); + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); + + *suffix = ntohl (new->suffix); return HICN_LIB_ERROR_NONE; } int -new_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h, +new_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - assert (is_interest (h->newhdr.flags)); - h->newhdr.suffix = htonl (*suffix); + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); + + new->suffix = htonl (*suffix); return HICN_LIB_ERROR_NONE; } int -new_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h) +new_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - assert (is_interest (h->newhdr.flags)); - return CHILD_OPS (init_packet_header, type, h); + _new_header_t *new = pkbuf_get_new (pkbuf); + _unused (new); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); + + return CALL_CHILD (init_packet_header, pkbuf, pos); } int -new_get_data_locator (hicn_type_t type, const hicn_protocol_t *h, - ip_address_t *ip_address) +new_get_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_ip_address_t *ip_address) { - assert (!is_interest (h->newhdr.flags)); + _new_header_t *new = pkbuf_get_new (pkbuf); + _unused (new); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); + return HICN_LIB_ERROR_NONE; } int -new_set_data_locator (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *ip_address) +new_set_data_locator (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *ip_address) { - assert (!is_interest (h->newhdr.flags)); + _new_header_t *new = pkbuf_get_new (pkbuf); + _unused (new); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + return HICN_LIB_ERROR_NONE; } int -new_get_data_name (hicn_type_t type, const hicn_protocol_t *h, +new_get_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_t *name) { - assert (!is_interest (h->newhdr.flags)); - name->prefix = h->newhdr.prefix; - name->suffix = ntohl (h->newhdr.suffix); + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + + name->prefix = new->prefix; + name->suffix = ntohl (new->suffix); return HICN_LIB_ERROR_NONE; } int -new_set_data_name (hicn_type_t type, hicn_protocol_t *h, +new_set_data_name (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_t *name) { - new_mark_packet_as_data (type, h); - assert (!is_interest (h->newhdr.flags)); - h->newhdr.prefix = name->prefix; - h->newhdr.suffix = htonl (name->suffix); + _new_header_t *new = pkbuf_get_new (pkbuf); + + int rc = new_set_type (pkbuf, pos, HICN_PACKET_TYPE_DATA); + if (rc) + return rc; + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + + new->prefix = name->prefix; + new->suffix = htonl (name->suffix); return HICN_LIB_ERROR_NONE; } int -new_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +new_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - assert (!is_interest (h->newhdr.flags)); - *suffix = ntohl (h->newhdr.suffix); + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + + *suffix = ntohl (new->suffix); return HICN_LIB_ERROR_NONE; } int -new_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h, +new_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - assert (!is_interest (h->newhdr.flags)); - h->newhdr.suffix = htonl (*suffix); + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + + new->suffix = htonl (*suffix); return HICN_LIB_ERROR_NONE; } int -new_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h, - u32 *pathlabel) +new_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t *path_label) { - assert (!is_interest (h->newhdr.flags)); - *pathlabel = h->newhdr.path_label; + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + + *path_label = ntohl (new->path_label); return HICN_LIB_ERROR_NONE; } int -new_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const u32 pathlabel) +new_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t path_label) { - assert (!is_interest (h->newhdr.flags)); - h->newhdr.path_label = pathlabel; + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + + new->path_label = htonl (path_label); return HICN_LIB_ERROR_NONE; } int -new_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const hicn_faceid_t face_id) +new_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_faceid_t face_id) { - hicn_pathlabel_t new_pl; - update_pathlabel (h->newhdr.path_label, face_id, &new_pl); - h->newhdr.path_label = new_pl; + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_path_label_t new_pl; + update_path_label (new->path_label, face_id, &new_pl); + new->path_label = new_pl; return HICN_LIB_ERROR_NONE; } int -new_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) +new_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - return CHILD_OPS (reset_data_for_hash, type, h); + return CALL_CHILD (reset_data_for_hash, pkbuf, pos); } int -new_get_lifetime (hicn_type_t type, const hicn_protocol_t *h, +new_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_lifetime_t *lifetime) { - *lifetime = ntohl (h->newhdr.lifetime); + _new_header_t *new = pkbuf_get_new (pkbuf); + + *lifetime = ntohl (new->lifetime); return HICN_LIB_ERROR_NONE; } int -new_set_lifetime (hicn_type_t type, hicn_protocol_t *h, +new_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_lifetime_t lifetime) { - h->newhdr.lifetime = htonl (lifetime); - return HICN_LIB_ERROR_NONE; -} + _new_header_t *new = pkbuf_get_new (pkbuf); -int -new_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) -{ + new->lifetime = htonl (lifetime); return HICN_LIB_ERROR_NONE; } int -new_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +new_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { return HICN_LIB_ERROR_NONE; } int -new_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old) +new_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, + size_t pos, u16 *old_val, u16 *new_val, + u8 size, bool skip_first) { - assert (is_interest (h->newhdr.flags)); return HICN_LIB_ERROR_NONE; } int -new_rewrite_data (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old, - const hicn_faceid_t face_id, u8 reset_pl) +new_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { - assert (!is_interest (h->newhdr.flags)); return HICN_LIB_ERROR_NONE; } int -new_get_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +new_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old) { - *header_length = NEW_HDRLEN + ntohs (h->newhdr.payload_length); - return HICN_LIB_ERROR_NONE; -} + _new_header_t *new = pkbuf_get_new (pkbuf); + _unused (new); -int -new_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) -{ - *header_length = NEW_HDRLEN; - return HICN_LIB_ERROR_NONE; -} + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_INTEREST); -int -new_get_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) -{ - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - *header_length = NEW_HDRLEN + child_header_length; return HICN_LIB_ERROR_NONE; } int -new_get_payload_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *payload_length) +new_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, const hicn_faceid_t face_id, + u8 reset_pl) { - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - *payload_length = ntohs (h->newhdr.payload_length) - child_header_length; + _new_header_t *new = pkbuf_get_new (pkbuf); + _unused (new); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + return HICN_LIB_ERROR_NONE; } int -new_set_payload_length (hicn_type_t type, hicn_protocol_t *h, - size_t payload_length) +new_set_payload_len (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t payload_len) { - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - h->newhdr.payload_length = - htons ((u_short) (payload_length + child_header_length)); + _new_header_t *new = pkbuf_get_new (pkbuf); + + /* + * The value we have to store in the header is the sum of headers following + * the current header + the new payload size + */ + + size_t child_header_len = + (pkbuf->payload - pkbuf->newhdr) - sizeof (_new_header_t); + new->payload_len = htons ((u16) child_header_len + payload_len); return HICN_LIB_ERROR_NONE; } int -new_get_signature_size (hicn_type_t type, const hicn_protocol_t *h, +new_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t *signature_size) { - return CHILD_OPS (get_signature_size, type, h, signature_size); + return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size); } int -new_set_signature_size (hicn_type_t type, hicn_protocol_t *h, +new_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t signature_size) { - return CHILD_OPS (set_signature_size, type, h, signature_size); + return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size); } int -new_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, +new_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t padding) { - return CHILD_OPS (set_signature_padding, type, h, padding); + return CALL_CHILD (set_signature_padding, pkbuf, pos, padding); } int -new_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h, +new_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t *padding) { - return CHILD_OPS (get_signature_padding, type, h, padding); + return CALL_CHILD (get_signature_padding, pkbuf, pos, padding); } int -new_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h, +new_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, uint64_t signature_timestamp) { - return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp); } int -new_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h, +new_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, uint64_t *signature_timestamp) { - return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp); } int -new_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h, +new_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t validation_algorithm) { - return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (set_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -new_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h, +new_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *validation_algorithm) { - return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (get_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -new_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id) +new_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *key_id, + size_t key_len) { - return CHILD_OPS (set_key_id, type, h, key_id); + return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len); } int -new_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id, - uint8_t *key_id_size) +new_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **key_id, uint8_t *key_id_size) { - return CHILD_OPS (get_key_id, type, h, key_id, key_id_size); + return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size); } int -new_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature) +new_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **signature) { - return CHILD_OPS (get_signature, type, h, signature); + return CALL_CHILD (get_signature, pkbuf, pos, signature); } int -new_get_payload_type (hicn_type_t type, const hicn_protocol_t *h, +new_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag) +{ + _new_header_t *new = pkbuf_get_new (pkbuf); + + return new->flags &HICN_NEW_FLAG_SIG; +} + +int +new_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_payload_type_t *payload_type) { - *payload_type = ((h->newhdr.flags & HICN_NEW_FLAG_MAN) == HICN_NEW_FLAG_MAN); + _new_header_t *new = pkbuf_get_new (pkbuf); + + *payload_type = ((new->flags &HICN_NEW_FLAG_MAN) == HICN_NEW_FLAG_MAN); return HICN_LIB_ERROR_NONE; } int -new_set_payload_type (hicn_type_t type, hicn_protocol_t *h, +new_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_payload_type_t payload_type) { + _new_header_t *new = pkbuf_get_new (pkbuf); + if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST) return HICN_LIB_ERROR_INVALID_PARAMETER; if (payload_type) - h->newhdr.flags |= HICN_NEW_FLAG_MAN; + new->flags |= HICN_NEW_FLAG_MAN; else - h->newhdr.flags &= ~HICN_NEW_FLAG_MAN; + new->flags &= ~HICN_NEW_FLAG_MAN; return HICN_LIB_ERROR_NONE; } int -new_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last) +new_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last) { - assert (!is_interest (h->newhdr.flags)); - *is_last = h->newhdr.flags & HICN_NEW_FLAG_LST; + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + + *is_last = new->flags &HICN_NEW_FLAG_LST; return HICN_LIB_ERROR_NONE; } int -new_set_last_data (hicn_type_t type, hicn_protocol_t *h) +new_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos) { - assert (!is_interest (h->newhdr.flags)); - h->newhdr.flags |= HICN_NEW_FLAG_LST; + _new_header_t *new = pkbuf_get_new (pkbuf); + + hicn_packet_type_t type; + _ASSERT (new_get_type (pkbuf, pos, &type) == 0); + _ASSERT (type == HICN_PACKET_TYPE_DATA); + + new->flags |= HICN_NEW_FLAG_LST; return HICN_LIB_ERROR_NONE; } -DECLARE_HICN_OPS (new); +DECLARE_HICN_OPS (new, NEW_HDRLEN); #pragma GCC diagnostic pop diff --git a/lib/src/protocol/new.h b/lib/src/protocol/new.h new file mode 100644 index 000000000..7679910f4 --- /dev/null +++ b/lib/src/protocol/new.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file protocol/ah.h + * @brief AH packet header + */ +#ifndef HICN_PROTOCOL_NEW_H +#define HICN_PROTOCOL_NEW_H + +#include <hicn/common.h> +#include <hicn/name.h> + +/* + * The length of the new header struct must be 28 bytes. + */ +#define EXPECTED_NEW_HDRLEN 32 + +typedef struct +{ + u8 version_reserved; + u8 flags; + + /* Size of the payload direcly after the new header */ + u16 payload_len; + + u32 lifetime; + + /* Name prefix and suffix */ + hicn_ip_address_t prefix; + u32 suffix; + + /* We reserve 32 bits for the path label */ + u32 path_label; +} _new_header_t; + +#define NEW_HDRLEN sizeof (_new_header_t) +static_assert (EXPECTED_NEW_HDRLEN == NEW_HDRLEN, + "Size of new_header Struct does not match its expected size."); + +/* TCP flags bit 0 first. */ +#define foreach_hicn_new_flag \ + _ (SIG) /**< Signature header after. */ \ + _ (MAN) /**< Payload type is manifest. */ \ + _ (INT) /**< Packet is interest. */ \ + _ (LST) /**< Last data. */ + +enum +{ +#define _(f) HICN_NEW_FLAG_BIT_##f, + foreach_hicn_new_flag +#undef _ + HICN_NEW_N_FLAG_BITS, +}; + +enum +{ +#define _(f) HICN_NEW_FLAG_##f = 1 << HICN_NEW_FLAG_BIT_##f, + foreach_hicn_new_flag +#undef _ +}; + +static inline int +_get_new_header_version (const _new_header_t *new_hdr) +{ + return ((new_hdr->version_reserved >> 4) & 0x0F); +} + +static inline void +_set_new_header_version (_new_header_t *new_hdr) +{ + new_hdr->version_reserved = (0x9 << 4) & 0xF0; +} + +#endif /* HICN_PROTOCOL_NEW_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/protocol/tcp.c b/lib/src/protocol/tcp.c index 82fc461ea..822bd3e0c 100644 --- a/lib/src/protocol/tcp.c +++ b/lib/src/protocol/tcp.c @@ -14,9 +14,12 @@ */ #include <string.h> -#include <hicn/protocol/tcp.h> + +#include <hicn/base.h> #include <hicn/error.h> -#include <hicn/ops.h> + +#include "tcp.h" +#include "../ops.h" #define TCP_DEFAULT_SRC_PORT 0x8000 #define TCP_DEFAULT_DST_PORT 0x0080 @@ -32,6 +35,8 @@ #define TCP_DEFAULT_SYN 1 #define TCP_DEFAULT_FIN 0 +#define UINT16_T_MASK 0x0000ffff // 1111 1111 1111 1111 + DECLARE_get_interest_locator (tcp, UNEXPECTED); DECLARE_set_interest_locator (tcp, UNEXPECTED); DECLARE_get_interest_name (tcp, UNEXPECTED); @@ -40,21 +45,26 @@ DECLARE_get_data_locator (tcp, UNEXPECTED); DECLARE_set_data_locator (tcp, UNEXPECTED); DECLARE_get_data_name (tcp, UNEXPECTED); DECLARE_set_data_name (tcp, UNEXPECTED); -DECLARE_get_length (tcp, UNEXPECTED); -DECLARE_get_payload_length (tcp, UNEXPECTED); -DECLARE_set_payload_length (tcp, UNEXPECTED); +DECLARE_set_payload_len (tcp, UNEXPECTED); +DECLARE_get_ttl (tcp, UNEXPECTED); +DECLARE_set_ttl (tcp, UNEXPECTED); + +int tcp_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, + size_t pos, u16 *old_val, u16 *new_val, + u8 size, bool skip_first); static inline void -reset_for_hash (hicn_protocol_t *h) +reset_for_hash (hicn_packet_buffer_t *pkbuf) { - h->tcp.sport = 0; - h->tcp.dport = 0; - h->tcp.seq_ack = 0; - h->tcp.data_offset_and_reserved = 0; - h->tcp.flags = 0; - h->tcp.window = 0; - h->tcp.csum = 0; - h->tcp.urg_ptr = 0; + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + tcp->sport = 0; + tcp->dport = 0; + tcp->seq_ack = 0; + tcp->data_offset_and_reserved = 0; + tcp->flags = 0; + tcp->window = 0; + tcp->csum = 0; + tcp->urg_ptr = 0; } static inline int @@ -80,9 +90,17 @@ check_tcp_checksum (u16 csum) } int -tcp_init_packet_header (hicn_type_t type, hicn_protocol_t *h) +tcp_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) { - h->tcp = (_tcp_header_t){ + pkbuf->tcp = pkbuf->len; + if (TCP_HDRLEN > pkbuf->buffer_size - pkbuf->len) + return -1; + pkbuf->len += TCP_HDRLEN; + + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + hicn_packet_format_t format = hicn_packet_get_format (pkbuf); + + *tcp = (_tcp_header_t){ .sport = htons (TCP_DEFAULT_SRC_PORT), .dport = htons (TCP_DEFAULT_DST_PORT), .seq = 0, @@ -97,142 +115,169 @@ tcp_init_packet_header (hicn_type_t type, hicn_protocol_t *h) .urg_ptr = 65000, }; - uint8_t ah_flag = type.l2 == IPPROTO_AH ? AH_FLAG : 0; + uint8_t ah_flag = ((format.as_u8[pos + 1] == IPPROTO_AH) ? AH_FLAG : 0); - h->tcp.flags |= ah_flag; + tcp->flags |= ah_flag; - return CHILD_OPS (init_packet_header, type, h); + return CALL_CHILD (init_packet_header, pkbuf, pos); } int -tcp_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest) +tcp_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_packet_type_t *type) { - *is_interest = (h->tcp.flags & HICN_TCP_FLAG_ECE) == 0; + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + /* Data packets have the ECE bit set */ + if (tcp->flags & HICN_TCP_FLAG_ECE) + *type = HICN_PACKET_TYPE_DATA; + else + *type = HICN_PACKET_TYPE_INTEREST; return HICN_LIB_ERROR_NONE; } int -tcp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h) +tcp_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_packet_type_t type) { - h->tcp.flags &= ~HICN_TCP_FLAG_ECE; + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + switch (type) + { + case HICN_PACKET_TYPE_INTEREST: + tcp->flags &= ~HICN_TCP_FLAG_ECE; + break; + case HICN_PACKET_TYPE_DATA: + tcp->flags |= HICN_TCP_FLAG_ECE; + break; + default: + return HICN_LIB_ERROR_INVALID_PARAMETER; + } return HICN_LIB_ERROR_NONE; } int -tcp_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +tcp_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - *suffix = ntohl (h->tcp.name_suffix); + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *suffix = ntohl (tcp->name_suffix); return HICN_LIB_ERROR_NONE; } int -tcp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h, +tcp_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - int rc = tcp_mark_packet_as_interest (type, h); + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + int rc = tcp_set_type (pkbuf, pos, HICN_PACKET_TYPE_INTEREST); if (rc) return rc; - h->tcp.name_suffix = htonl (*suffix); + tcp->name_suffix = htonl (*suffix); return HICN_LIB_ERROR_NONE; } int -tcp_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h) +tcp_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - h->tcp.flags |= HICN_TCP_FLAG_ECE; - return HICN_LIB_ERROR_NONE; + reset_for_hash (pkbuf); + return CALL_CHILD (reset_interest_for_hash, pkbuf, pos); } int -tcp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h) -{ - reset_for_hash (h); - return CHILD_OPS (reset_interest_for_hash, type, h); -} - -int -tcp_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +tcp_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - *suffix = ntohl (h->tcp.name_suffix); + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *suffix = ntohl (tcp->name_suffix); return HICN_LIB_ERROR_NONE; } int -tcp_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h, +tcp_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - int rc = tcp_mark_packet_as_data (type, h); + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + int rc = tcp_set_type (pkbuf, pos, HICN_PACKET_TYPE_DATA); if (rc) return rc; - h->tcp.name_suffix = htonl (*suffix); + tcp->name_suffix = htonl (*suffix); return HICN_LIB_ERROR_NONE; } int -tcp_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h, - u32 *pathlabel) +tcp_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t *path_label) { - *pathlabel = h->tcp.seq_ack; + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *path_label = + (hicn_path_label_t) (tcp->seq_ack >> (32 - HICN_PATH_LABEL_SIZE_BITS)); return HICN_LIB_ERROR_NONE; } int -tcp_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const u32 pathlabel) +tcp_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t path_label) { - h->tcp.seq_ack = pathlabel; + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + hicn_path_label_t old_path_label; + tcp_get_data_path_label (pkbuf, pos, &old_path_label); + + tcp->seq_ack = (path_label << (32 - HICN_PATH_LABEL_SIZE_BITS)); + + tcp_update_checksums_incremental ( + pkbuf, pos, (uint16_t *) &old_path_label, (uint16_t *) &path_label, + sizeof (hicn_path_label_t) / sizeof (uint16_t), true); + return HICN_LIB_ERROR_NONE; } int -tcp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const hicn_faceid_t face_id) +tcp_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_faceid_t face_id) { - hicn_pathlabel_t pl = - (hicn_pathlabel_t) (h->tcp.seq_ack >> (32 - HICN_PATH_LABEL_SIZE)); + assert (sizeof (hicn_path_label_t) == 1); - hicn_pathlabel_t new_pl; + hicn_path_label_t old_path_label; + hicn_path_label_t new_path_label; - update_pathlabel (pl, face_id, &new_pl); - h->tcp.seq_ack = (new_pl << (32 - HICN_PATH_LABEL_SIZE)); + tcp_get_data_path_label (pkbuf, pos, &old_path_label); + update_path_label (old_path_label, face_id, &new_path_label); + tcp_set_data_path_label (pkbuf, pos, new_path_label); return HICN_LIB_ERROR_NONE; } int -tcp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) +tcp_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - reset_for_hash (h); - return CHILD_OPS (reset_data_for_hash, type, h); + reset_for_hash (pkbuf); + return CALL_CHILD (reset_data_for_hash, pkbuf, pos); } int -tcp_get_lifetime (hicn_type_t type, const hicn_protocol_t *h, +tcp_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_lifetime_t *lifetime) { - *lifetime = ntohs (h->tcp.urg_ptr) - << (h->tcp.data_offset_and_reserved & 0xF); + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *lifetime = ntohs (tcp->urg_ptr) << (tcp->data_offset_and_reserved & 0xF); return HICN_LIB_ERROR_NONE; } int -tcp_set_lifetime (hicn_type_t type, hicn_protocol_t *h, +tcp_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_lifetime_t lifetime) { + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); u8 multiplier = 0; u32 lifetime_scaled = lifetime; - if (PREDICT_FALSE (lifetime >= HICN_MAX_LIFETIME)) + if (HICN_EXPECT_FALSE (lifetime >= HICN_MAX_LIFETIME)) { - h->tcp.urg_ptr = htons (HICN_MAX_LIFETIME_SCALED); - h->tcp.data_offset_and_reserved = - (h->tcp.data_offset_and_reserved & ~0x0F) | - HICN_MAX_LIFETIME_MULTIPLIER; + tcp->urg_ptr = htons (HICN_MAX_LIFETIME_SCALED); + tcp->data_offset_and_reserved = + (tcp->data_offset_and_reserved & ~0x0F) | HICN_MAX_LIFETIME_MULTIPLIER; return HICN_LIB_ERROR_NONE; } @@ -243,70 +288,76 @@ tcp_set_lifetime (hicn_type_t type, hicn_protocol_t *h, lifetime_scaled = lifetime_scaled >> 1; } - h->tcp.urg_ptr = htons (lifetime_scaled); - h->tcp.data_offset_and_reserved = - (h->tcp.data_offset_and_reserved & ~0x0F) | multiplier; + tcp->urg_ptr = htons (lifetime_scaled); + tcp->data_offset_and_reserved = + (tcp->data_offset_and_reserved & ~0x0F) | multiplier; return HICN_LIB_ERROR_NONE; } int -tcp_get_source_port (hicn_type_t type, const hicn_protocol_t *h, - u16 *source_port) +tcp_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { - *source_port = ntohs (h->tcp.sport); - return HICN_LIB_ERROR_NONE; -} + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + /* TODO bound checks for payload_len based on pkbuf size */ + assert (payload_len != ~0); -int -tcp_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port) -{ - *dest_port = ntohs (h->tcp.dport); - return HICN_LIB_ERROR_NONE; -} + tcp->csum = 0; -int -tcp_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port) -{ - h->tcp.sport = htons (source_port); - return HICN_LIB_ERROR_NONE; -} + if (HICN_EXPECT_TRUE (partial_csum != 0)) + { + partial_csum = ~partial_csum; + } -int -tcp_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port) -{ - h->tcp.dport = htons (dest_port); - return HICN_LIB_ERROR_NONE; + tcp->csum = + csum (pkbuf_get_header (pkbuf), TCP_HDRLEN + payload_len, partial_csum); + + return CALL_CHILD (update_checksums, pkbuf, pos, 0, payload_len); } int -tcp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +tcp_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, + size_t pos, u16 *old_val, u16 *new_val, + u8 size, bool skip_first) { - h->tcp.csum = 0; + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + if (skip_first) + return HICN_LIB_ERROR_INVALID_PARAMETER; - if (PREDICT_TRUE (partial_csum != 0)) + for (uint8_t i = 0; i < size; i++) { - partial_csum = ~partial_csum; + uint16_t old_csum = ~tcp->csum; + uint16_t not_old_val = ~(*old_val); + uint32_t sum = (uint32_t) old_csum + not_old_val + *new_val; + + while (sum >> 16) + { + sum = (sum >> 16) + (sum & UINT16_T_MASK); + } + + tcp->csum = ~sum; + ++old_val; + ++new_val; } - h->tcp.csum = csum (h, TCP_HDRLEN + payload_length, partial_csum); - - return CHILD_OPS (update_checksums, type, h, 0, payload_length); + return CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val, + new_val, size, false); } int -tcp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +tcp_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { - if (PREDICT_TRUE (partial_csum != 0)) + if (HICN_EXPECT_TRUE (partial_csum != 0)) { partial_csum = ~partial_csum; } - if (csum (h, TCP_HDRLEN + payload_length, partial_csum) != 0) + if (csum (pkbuf_get_header (pkbuf), TCP_HDRLEN + payload_len, + partial_csum) != 0) return HICN_LIB_ERROR_CORRUPTED_PACKET; - return CHILD_OPS (verify_checksums, type, h, 0, payload_length); + return CALL_CHILD (verify_checksums, pkbuf, pos, 0, payload_len); } #define TCP_OFFSET_MASK 13 @@ -331,10 +382,14 @@ tcp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, #define TCP_DEFAULT_FIN 0 int -tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old) +tcp_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old) { - u16 *tcp_checksum = &(h->tcp.csum); + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + _ipv6_header_t *ip6 = pkbuf_get_ipv6 (pkbuf); + + u16 *tcp_checksum = &(tcp->csum); int ret = check_tcp_checksum (*tcp_checksum); if (ret) @@ -347,14 +402,14 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, * whole struct by interpreting it as IPv6 in all cases * * v4 code would be: - * csum = ip_csum_sub_even (*tcp_checksum, h->ipv4.saddr.as_u32); - * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32); + * csum = ip_csum_sub_even (*tcp_checksum, h->tcp.saddr.as_u32); + * csum = ip_csum_add_even (csum, h->tcp.saddr.as_u32); */ - ip_csum_t csum = - ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (h->ipv6.saddr.as_u64[0])); - csum = ip_csum_sub_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[1])); - csum = ip_csum_add_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[0])); - csum = ip_csum_add_even (csum, (ip_csum_t) (h->ipv6.saddr.as_u64[1])); + hicn_ip_csum_t csum = + ip_csum_sub_even (*tcp_checksum, (hicn_ip_csum_t) (ip6->saddr.as_u64[0])); + csum = ip_csum_sub_even (csum, (hicn_ip_csum_t) (ip6->saddr.as_u64[1])); + csum = ip_csum_add_even (csum, (hicn_ip_csum_t) (ip6->saddr.as_u64[0])); + csum = ip_csum_add_even (csum, (hicn_ip_csum_t) (ip6->saddr.as_u64[1])); *tcp_checksum = ip_csum_fold (csum); @@ -362,21 +417,22 @@ tcp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, } int -tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old, - const hicn_faceid_t face_id, u8 reset_pl) +tcp_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, const hicn_faceid_t face_id, + u8 reset_pl) { - - u16 *tcp_checksum = &(h->tcp.csum); + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + u16 *tcp_checksum = &(tcp->csum); int ret = check_tcp_checksum (*tcp_checksum); /* * update path label */ - u16 old_pl = h->tcp.seq_ack; + u16 old_pl = tcp->seq_ack; if (reset_pl) - h->tcp.seq_ack = 0; - tcp_update_data_pathlabel (type, h, face_id); + tcp->seq_ack = 0; + tcp_update_data_path_label (pkbuf, pos, face_id); if (ret) { @@ -388,18 +444,18 @@ tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h, * whole struct by interpreting it as IPv6 in all cases * * v4 code would be: - * csum = ip_csum_sub_even (*tcp_checksum, h->ipv4.saddr.as_u32); - * csum = ip_csum_add_even (csum, h->ipv4.saddr.as_u32); + * csum = ip_csum_sub_even (*tcp_checksum, h->tcp.saddr.as_u32); + * csum = ip_csum_add_even (csum, h->tcp.saddr.as_u32); */ - ip_csum_t csum = - ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->v6.as_u64[0])); - csum = - ip_csum_sub_even (*tcp_checksum, (ip_csum_t) (addr_old->v6.as_u64[1])); - csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->v6.as_u64[0])); - csum = ip_csum_add_even (csum, (ip_csum_t) (addr_new->v6.as_u64[1])); + hicn_ip_csum_t csum = ip_csum_sub_even ( + *tcp_checksum, (hicn_ip_csum_t) (addr_old->v6.as_u64[0])); + csum = ip_csum_sub_even (*tcp_checksum, + (hicn_ip_csum_t) (addr_old->v6.as_u64[1])); + csum = ip_csum_add_even (csum, (hicn_ip_csum_t) (addr_new->v6.as_u64[0])); + csum = ip_csum_add_even (csum, (hicn_ip_csum_t) (addr_new->v6.as_u64[1])); csum = ip_csum_sub_even (csum, old_pl); - csum = ip_csum_add_even (csum, h->tcp.seq_ack); + csum = ip_csum_add_even (csum, tcp->seq_ack); *tcp_checksum = ip_csum_fold (csum); @@ -407,139 +463,166 @@ tcp_rewrite_data (hicn_type_t type, hicn_protocol_t *h, } int -tcp_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) -{ - *header_length = TCP_HDRLEN; - return HICN_LIB_ERROR_NONE; -} - -int -tcp_get_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) -{ - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - - *header_length = TCP_HDRLEN + child_header_length; - return HICN_LIB_ERROR_NONE; -} - -int -tcp_get_signature_size (hicn_type_t type, const hicn_protocol_t *h, +tcp_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t *signature_size) { - return CHILD_OPS (get_signature_size, type, h, signature_size); + return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size); } int -tcp_set_signature_size (hicn_type_t type, hicn_protocol_t *h, +tcp_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t signature_size) { - return CHILD_OPS (set_signature_size, type, h, signature_size); + return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size); } int -tcp_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, +tcp_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t padding) { - return CHILD_OPS (set_signature_padding, type, h, padding); + return CALL_CHILD (set_signature_padding, pkbuf, pos, padding); } int -tcp_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h, +tcp_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, size_t *padding) { - return CHILD_OPS (get_signature_padding, type, h, padding); + return CALL_CHILD (get_signature_padding, pkbuf, pos, padding); } int -tcp_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h, +tcp_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, uint64_t signature_timestamp) { - return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp); } int -tcp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h, +tcp_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, uint64_t *signature_timestamp) { - return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp); } int -tcp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h, +tcp_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t validation_algorithm) { - return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (set_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -tcp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h, +tcp_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *validation_algorithm) { - return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (get_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -tcp_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id) +tcp_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *key_id, + size_t key_len) { - return CHILD_OPS (set_key_id, type, h, key_id); + return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len); } int -tcp_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id, - uint8_t *key_id_size) +tcp_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **key_id, uint8_t *key_id_size) { - return CHILD_OPS (get_key_id, type, h, key_id, key_id_size); + return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size); } int -tcp_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature) +tcp_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **signature) { - return CHILD_OPS (get_signature, type, h, signature); + return CALL_CHILD (get_signature, pkbuf, pos, signature); } int -tcp_get_payload_type (hicn_type_t type, const hicn_protocol_t *h, +tcp_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag) +{ + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *flag = tcp->flags & AH_FLAG; + return HICN_LIB_ERROR_NONE; +} + +int +tcp_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_payload_type_t *payload_type) { - *payload_type = ((h->tcp.flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG); + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *payload_type = ((tcp->flags & HICN_TCP_FLAG_URG) == HICN_TCP_FLAG_URG); return HICN_LIB_ERROR_NONE; } int -tcp_set_payload_type (hicn_type_t type, hicn_protocol_t *h, +tcp_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_payload_type_t payload_type) { + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); if (payload_type != HPT_DATA && payload_type != HPT_MANIFEST) return HICN_LIB_ERROR_INVALID_PARAMETER; if (payload_type) - h->tcp.flags |= HICN_TCP_FLAG_URG; + tcp->flags |= HICN_TCP_FLAG_URG; else - h->tcp.flags &= ~HICN_TCP_FLAG_URG; + tcp->flags &= ~HICN_TCP_FLAG_URG; + + return HICN_LIB_ERROR_NONE; +} + +int +tcp_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last) +{ + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *is_last = (tcp->flags & HICN_TCP_FLAG_RST) == HICN_TCP_FLAG_RST; + return HICN_LIB_ERROR_NONE; +} +int +tcp_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos) +{ + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + tcp->flags |= HICN_TCP_FLAG_RST; + return HICN_LIB_ERROR_NONE; +} + +int +tcp_get_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *port) +{ + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *port = ntohs (tcp->sport); + return HICN_LIB_ERROR_NONE; +} + +int +tcp_set_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 port) +{ + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + tcp->sport = htons (port); return HICN_LIB_ERROR_NONE; } int -tcp_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last) +tcp_get_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *port) { - *is_last = (h->tcp.flags & HICN_TCP_FLAG_RST) == HICN_TCP_FLAG_RST; + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + *port = ntohs (tcp->dport); return HICN_LIB_ERROR_NONE; } int -tcp_set_last_data (hicn_type_t type, hicn_protocol_t *h) +tcp_set_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 port) { - h->tcp.flags |= HICN_TCP_FLAG_RST; + _tcp_header_t *tcp = pkbuf_get_tcp (pkbuf); + tcp->dport = htons (port); return HICN_LIB_ERROR_NONE; } -DECLARE_HICN_OPS (tcp); +DECLARE_HICN_OPS (tcp, TCP_HDRLEN); /* * fd.io coding-style-patch-verification: ON diff --git a/lib/src/protocol/tcp.h b/lib/src/protocol/tcp.h new file mode 100644 index 000000000..e563372d0 --- /dev/null +++ b/lib/src/protocol/tcp.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HICN_PROTOCOL_TCP_H +#define HICN_PROTOCOL_TCP_H + +#include <hicn/base.h> +#include <hicn/common.h> +#include <hicn/name.h> + +/* + * The length of the TCP header struct must be 20 bytes. + */ +#define EXPECTED_TCP_HDRLEN 20 + +/* + * NOTE: bitfields are problematic for portability reasons. There are provided + * here for reference and documentation purposes, we might just provide a macro + * to disable and use it instead of __BYTE_ORDER__. + */ +typedef struct +{ + u16 sport; + u16 dport; + union + { + u32 seq; + hicn_name_suffix_t name_suffix; + }; + union + { + u32 seq_ack; + struct + { + hicn_path_label_t pathlabel; + u8 pad[3]; + }; + }; + + union + { + struct + { + u8 data_offset_and_reserved; + u8 flags; + }; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + struct + { + u16 reserved : 4; + u16 doff : 4; + u16 fin : 1; + u16 syn : 1; + u16 rst : 1; + u16 psh : 1; + u16 ack : 1; + u16 urg : 1; + u16 ece : 1; + u16 cwr : 1; + }; + struct + { /* __ denotes unchanged bitfields */ + u16 timescale : 4; + u16 __doff : 4; + u16 __fin : 1; + u16 __syn : 1; + u16 __rst : 1; + u16 sig : 1; + u16 __ack : 1; + u16 man : 1; + u16 id : 1; + u16 __cwr : 1; + }; +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + struct + { + u16 doff : 4; + u16 reserved : 4; + u16 cwr : 1; + u16 ece : 1; + u16 urg : 1; + u16 ack : 1; + u16 psh : 1; + u16 rst : 1; + u16 syn : 1; + u16 fin : 1; + }; + struct + { + u16 __doff : 4; + u16 timescale : 4; + u16 __cwr : 1; + u16 id : 1 u16 man : 1; + u16 __ack : 1; + u16 sig : 1; + u16 __rst : 1; + u16 __syn : 1; + u16 __fin : 1; + }; +#endif + }; + union + { + u16 window; + u16 ldr; + }; + u16 csum; + union + { + u16 urg_ptr; + u16 lifetime; + }; +} _tcp_header_t; + +#define TCP_HDRLEN sizeof (_tcp_header_t) +static_assert (EXPECTED_TCP_HDRLEN == TCP_HDRLEN, + "Size of TCP struct does not match its expected size."); + +/* TCP flags bit 0 first. */ +#define foreach_tcp_flag \ + _ (FIN) /**< No more data from sender. */ \ + _ (SYN) /**< Synchronize sequence numbers. */ \ + _ (RST) /**< Reset the connection. */ \ + _ (PSH) /**< Push function. */ \ + _ (ACK) /**< Ack field significant. */ \ + _ (URG) /**< Urgent pointer field significant. */ \ + _ (ECE) /**< ECN-echo. Receiver got CE packet */ \ + _ (CWR) /**< Sender reduced congestion window */ + +enum +{ +#define _(f) HICN_TCP_FLAG_BIT_##f, + foreach_tcp_flag +#undef _ + HICN_TCP_N_FLAG_BITS, +}; + +enum +{ +#define _(f) HICN_TCP_FLAG_##f = 1 << HICN_TCP_FLAG_BIT_##f, + foreach_tcp_flag +#undef _ +}; + +#endif /* HICN_PROTOCOL_TCP_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/protocol/udp.c b/lib/src/protocol/udp.c index 7a14b09c2..ff2355b0c 100644 --- a/lib/src/protocol/udp.c +++ b/lib/src/protocol/udp.c @@ -17,9 +17,9 @@ #include <string.h> #include <hicn/common.h> #include <hicn/error.h> -#include <hicn/ops.h> -#include <hicn/protocol/udp.h> +#include "udp.h" +#include "../ops.h" DECLARE_get_interest_locator (udp, UNEXPECTED); DECLARE_set_interest_locator (udp, UNEXPECTED); @@ -29,308 +29,313 @@ DECLARE_get_data_locator (udp, UNEXPECTED); DECLARE_set_data_locator (udp, UNEXPECTED); DECLARE_get_data_name (udp, UNEXPECTED); DECLARE_set_data_name (udp, UNEXPECTED); -DECLARE_get_payload_length (udp, UNEXPECTED); -DECLARE_set_payload_length (udp, UNEXPECTED); +DECLARE_set_payload_len (udp, UNEXPECTED); +DECLARE_get_ttl (udp, UNEXPECTED); +DECLARE_set_ttl (udp, UNEXPECTED); int -udp_init_packet_header (hicn_type_t type, hicn_protocol_t *h) +udp_init_packet_header (hicn_packet_buffer_t *pkbuf, size_t pos) { - size_t total_header_length; - int rc = CHILD_OPS (get_header_length, type, h, &total_header_length); - if (rc < 0) - return rc; + pkbuf->udp = pkbuf->len; + if (UDP_HDRLEN > pkbuf->buffer_size - pkbuf->len) + return -1; + pkbuf->len += UDP_HDRLEN; - /* *INDENT-OFF* */ - h->udp = (_udp_header_t){ .src_port = 0, - .dst_port = 0, - .length = htons ((u16) total_header_length), - .checksum = 0 }; - /* *INDENT-ON* */ - return CHILD_OPS (init_packet_header, type, h); + _udp_header_t *udp = pkbuf_get_udp (pkbuf); + + size_t len = hicn_packet_get_len (pkbuf) - + ((u8 *) udp - pkbuf_get_header (pkbuf)) - + sizeof (_udp_header_t); + + // clang-format off + *udp = (_udp_header_t){ + .src_port = 0, + .dst_port = 0, + .len = htons ((u16) len), + .checksum = 0 + }; + // clang-format on + return CALL_CHILD (init_packet_header, pkbuf, pos); } int -udp_get_interest_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +udp_get_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - return CHILD_OPS (get_interest_name_suffix, type, h, suffix); + return CALL_CHILD (get_interest_name_suffix, pkbuf, pos, suffix); } int -udp_set_interest_name_suffix (hicn_type_t type, hicn_protocol_t *h, +udp_set_interest_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - return CHILD_OPS (set_interest_name_suffix, type, h, suffix); -} - -int -udp_is_interest (hicn_type_t type, const hicn_protocol_t *h, int *is_interest) -{ - return CHILD_OPS (is_interest, type, h, is_interest); + return CALL_CHILD (set_interest_name_suffix, pkbuf, pos, suffix); } int -udp_mark_packet_as_interest (hicn_type_t type, hicn_protocol_t *h) +udp_get_type (const hicn_packet_buffer_t *pkbuf, const size_t pos, + hicn_packet_type_t *type) { - return CHILD_OPS (mark_packet_as_interest, type, h); + return CALL_CHILD (get_type, pkbuf, pos, type); } int -udp_mark_packet_as_data (hicn_type_t type, hicn_protocol_t *h) +udp_set_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_packet_type_t type) { - return CHILD_OPS (mark_packet_as_data, type, h); + return CALL_CHILD (set_type, pkbuf, pos, type); } int -udp_reset_interest_for_hash (hicn_type_t type, hicn_protocol_t *h) +udp_reset_interest_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - return CHILD_OPS (reset_interest_for_hash, type, h); + return CALL_CHILD (reset_interest_for_hash, pkbuf, pos); } int -udp_get_data_name_suffix (hicn_type_t type, const hicn_protocol_t *h, +udp_get_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_name_suffix_t *suffix) { - return CHILD_OPS (get_data_name_suffix, type, h, suffix); + return CALL_CHILD (get_data_name_suffix, pkbuf, pos, suffix); } int -udp_set_data_name_suffix (hicn_type_t type, hicn_protocol_t *h, +udp_set_data_name_suffix (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_name_suffix_t *suffix) { - return CHILD_OPS (set_data_name_suffix, type, h, suffix); + return CALL_CHILD (set_data_name_suffix, pkbuf, pos, suffix); } int -udp_get_data_pathlabel (hicn_type_t type, const hicn_protocol_t *h, - u32 *pathlabel) +udp_get_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t *path_label) { - return CHILD_OPS (get_data_pathlabel, type, h, pathlabel); + return CALL_CHILD (get_data_path_label, pkbuf, pos, path_label); } int -udp_set_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const u32 pathlabel) +udp_set_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_path_label_t path_label) { - return CHILD_OPS (set_data_pathlabel, type, h, pathlabel); + return CALL_CHILD (set_data_path_label, pkbuf, pos, path_label); } int -udp_update_data_pathlabel (hicn_type_t type, hicn_protocol_t *h, - const hicn_faceid_t face_id) +udp_update_data_path_label (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_faceid_t face_id) { - return CHILD_OPS (update_data_pathlabel, type, h, face_id); + return CALL_CHILD (update_data_path_label, pkbuf, pos, face_id); } int -udp_reset_data_for_hash (hicn_type_t type, hicn_protocol_t *h) +udp_reset_data_for_hash (hicn_packet_buffer_t *pkbuf, size_t pos) { - return CHILD_OPS (reset_data_for_hash, type, h); + return CALL_CHILD (reset_data_for_hash, pkbuf, pos); } int -udp_get_lifetime (hicn_type_t type, const hicn_protocol_t *h, +udp_get_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, hicn_lifetime_t *lifetime) { - return CHILD_OPS (get_lifetime, type, h, lifetime); + return CALL_CHILD (get_lifetime, pkbuf, pos, lifetime); } int -udp_set_lifetime (hicn_type_t type, hicn_protocol_t *h, +udp_set_lifetime (const hicn_packet_buffer_t *pkbuf, size_t pos, const hicn_lifetime_t lifetime) { - return CHILD_OPS (set_lifetime, type, h, lifetime); + return CALL_CHILD (set_lifetime, pkbuf, pos, lifetime); } int -udp_get_source_port (hicn_type_t type, const hicn_protocol_t *h, - u16 *source_port) +udp_update_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { - *source_port = ntohs (h->udp.src_port); - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (update_checksums, pkbuf, pos, partial_csum, payload_len); } int -udp_get_dest_port (hicn_type_t type, const hicn_protocol_t *h, u16 *dest_port) +udp_update_checksums_incremental (const hicn_packet_buffer_t *pkbuf, + size_t pos, u16 *old_val, u16 *new_val, + u8 size, bool skip_first) { - *dest_port = ntohs (h->udp.dst_port); - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (update_checksums_incremental, pkbuf, pos, old_val, + new_val, size, false); } int -udp_set_source_port (hicn_type_t type, hicn_protocol_t *h, u16 source_port) +udp_verify_checksums (const hicn_packet_buffer_t *pkbuf, size_t pos, + u16 partial_csum, size_t payload_len) { - h->udp.src_port = htons (source_port); - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (verify_checksums, pkbuf, pos, partial_csum, payload_len); } int -udp_set_dest_port (hicn_type_t type, hicn_protocol_t *h, u16 dest_port) +udp_rewrite_interest (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old) { - h->udp.dst_port = htons (dest_port); - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (rewrite_interest, pkbuf, pos, addr_new, addr_old); } int -udp_update_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +udp_rewrite_data (const hicn_packet_buffer_t *pkbuf, size_t pos, + const hicn_ip_address_t *addr_new, + hicn_ip_address_t *addr_old, const hicn_faceid_t face_id, + u8 reset_pl) { - return CHILD_OPS (update_checksums, type, h, partial_csum, payload_length); + return CALL_CHILD (rewrite_data, pkbuf, pos, addr_new, addr_old, face_id, + reset_pl); } int -udp_verify_checksums (hicn_type_t type, hicn_protocol_t *h, u16 partial_csum, - size_t payload_length) +udp_get_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_payload_type_t *payload_type) { - return CHILD_OPS (verify_checksums, type, h, partial_csum, payload_length); + return CALL_CHILD (get_payload_type, pkbuf, pos, payload_type); } int -udp_rewrite_interest (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old) +udp_set_payload_type (const hicn_packet_buffer_t *pkbuf, size_t pos, + hicn_payload_type_t payload_type) { - return CHILD_OPS (rewrite_interest, type, h, addr_new, addr_old); + return CALL_CHILD (set_payload_type, pkbuf, pos, payload_type); } int -udp_rewrite_data (hicn_type_t type, hicn_protocol_t *h, - const ip_address_t *addr_new, ip_address_t *addr_old, - const hicn_faceid_t face_id, u8 reset_pl) +udp_get_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t *signature_size) { - return CHILD_OPS (rewrite_data, type, h, addr_new, addr_old, face_id, - reset_pl); + return CALL_CHILD (get_signature_size, pkbuf, pos, signature_size); } int -udp_get_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +udp_set_signature_size (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t signature_size) { - *header_length = IPV6_HDRLEN + ntohs (h->ipv6.len); - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (set_signature_size, pkbuf, pos, signature_size); } int -udp_get_current_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +udp_has_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, bool *flag) { - *header_length = UDP_HDRLEN; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (has_signature, pkbuf, pos, flag); } int -udp_get_header_length (hicn_type_t type, const hicn_protocol_t *h, - size_t *header_length) +udp_set_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t padding) { - size_t child_header_length = 0; - int rc = CHILD_OPS (get_header_length, type, h, &child_header_length); - if (rc < 0) - return rc; - *header_length = UDP_HDRLEN + child_header_length; - return HICN_LIB_ERROR_NONE; + return CALL_CHILD (set_signature_padding, pkbuf, pos, padding); } int -udp_get_payload_type (hicn_type_t type, const hicn_protocol_t *h, - hicn_payload_type_t *payload_type) +udp_get_signature_padding (const hicn_packet_buffer_t *pkbuf, size_t pos, + size_t *padding) { - return CHILD_OPS (get_payload_type, type, h, payload_type); + return CALL_CHILD (get_signature_padding, pkbuf, pos, padding); } int -udp_set_payload_type (hicn_type_t type, hicn_protocol_t *h, - hicn_payload_type_t payload_type) +udp_set_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint64_t signature_timestamp) { - return CHILD_OPS (set_payload_type, type, h, payload_type); + return CALL_CHILD (set_signature_timestamp, pkbuf, pos, signature_timestamp); } int -udp_get_signature_size (hicn_type_t type, const hicn_protocol_t *h, - size_t *signature_size) +udp_get_signature_timestamp (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint64_t *signature_timestamp) { - return CHILD_OPS (get_signature_size, type, h, signature_size); + return CALL_CHILD (get_signature_timestamp, pkbuf, pos, signature_timestamp); } int -udp_set_signature_size (hicn_type_t type, hicn_protocol_t *h, - size_t signature_size) +udp_set_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t validation_algorithm) { - return CHILD_OPS (set_signature_size, type, h, signature_size); + return CALL_CHILD (set_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -udp_set_signature_padding (hicn_type_t type, hicn_protocol_t *h, - size_t padding) +udp_get_validation_algorithm (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t *validation_algorithm) { - return CHILD_OPS (set_signature_padding, type, h, padding); + return CALL_CHILD (get_validation_algorithm, pkbuf, pos, + validation_algorithm); } int -udp_get_signature_padding (hicn_type_t type, const hicn_protocol_t *h, - size_t *padding) +udp_set_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, uint8_t *key_id, + size_t key_len) { - return CHILD_OPS (get_signature_padding, type, h, padding); + return CALL_CHILD (set_key_id, pkbuf, pos, key_id, key_len); } int -udp_set_signature_timestamp (hicn_type_t type, hicn_protocol_t *h, - uint64_t signature_timestamp) +udp_get_key_id (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **key_id, uint8_t *key_id_size) { - return CHILD_OPS (set_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (get_key_id, pkbuf, pos, key_id, key_id_size); } int -udp_get_signature_timestamp (hicn_type_t type, const hicn_protocol_t *h, - uint64_t *signature_timestamp) +udp_get_signature (const hicn_packet_buffer_t *pkbuf, size_t pos, + uint8_t **signature) { - return CHILD_OPS (get_signature_timestamp, type, h, signature_timestamp); + return CALL_CHILD (get_signature, pkbuf, pos, signature); } int -udp_set_validation_algorithm (hicn_type_t type, hicn_protocol_t *h, - uint8_t validation_algorithm) +udp_is_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos, int *is_last) { - return CHILD_OPS (set_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (is_last_data, pkbuf, pos, is_last); } int -udp_get_validation_algorithm (hicn_type_t type, const hicn_protocol_t *h, - uint8_t *validation_algorithm) +udp_set_last_data (const hicn_packet_buffer_t *pkbuf, size_t pos) { - return CHILD_OPS (get_validation_algorithm, type, h, validation_algorithm); + return CALL_CHILD (set_last_data, pkbuf, pos); } int -udp_set_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t *key_id) +udp_get_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *port) { - return CHILD_OPS (set_key_id, type, h, key_id); -} + _udp_header_t *udp = pkbuf_get_udp (pkbuf); -int -udp_get_key_id (hicn_type_t type, hicn_protocol_t *h, uint8_t **key_id, - uint8_t *key_id_size) -{ - return CHILD_OPS (get_key_id, type, h, key_id, key_id_size); + *port = udp->src_port; + return HICN_LIB_ERROR_NONE; } int -udp_get_signature (hicn_type_t type, hicn_protocol_t *h, uint8_t **signature) +udp_set_src_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 port) { - return CHILD_OPS (get_signature, type, h, signature); + _udp_header_t *udp = pkbuf_get_udp (pkbuf); + + udp->src_port = port; + return HICN_LIB_ERROR_NONE; } int -udp_is_last_data (hicn_type_t type, const hicn_protocol_t *h, int *is_last) +udp_get_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 *port) { - return CHILD_OPS (is_last_data, type, h, is_last); + _udp_header_t *udp = pkbuf_get_udp (pkbuf); + + *port = udp->dst_port; + return HICN_LIB_ERROR_NONE; } int -udp_set_last_data (hicn_type_t type, hicn_protocol_t *h) +udp_set_dst_port (const hicn_packet_buffer_t *pkbuf, size_t pos, u16 port) { - return CHILD_OPS (set_last_data, type, h); + _udp_header_t *udp = pkbuf_get_udp (pkbuf); + + udp->dst_port = port; + return HICN_LIB_ERROR_NONE; } -DECLARE_HICN_OPS (udp); +DECLARE_HICN_OPS (udp, UDP_HDRLEN); /* * fd.io coding-style-patch-verification: ON diff --git a/lib/src/protocol/udp.h b/lib/src/protocol/udp.h new file mode 100644 index 000000000..23f5317b3 --- /dev/null +++ b/lib/src/protocol/udp.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021-2022 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef HICN_PROTOCOL_UDP_H +#define HICN_PROTOCOL_UDP_H + +/* + * The len of the UDP header struct must be 8 bytes. + */ +#define EXPECTED_UDP_HDRLEN 8 + +typedef struct +{ + u16 src_port; + u16 dst_port; + u16 len; + u16 checksum; +} _udp_header_t; + +#define UDP_HDRLEN sizeof (_udp_header_t) +static_assert (EXPECTED_UDP_HDRLEN == UDP_HDRLEN, + "Size of UDP struct does not match its expected size."); + +#endif /* HICN_PROTOCOL_UDP_H */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/lib/src/test/CMakeLists.txt b/lib/src/test/CMakeLists.txt index 3e3c025c7..17cf835d2 100644 --- a/lib/src/test/CMakeLists.txt +++ b/lib/src/test/CMakeLists.txt @@ -22,6 +22,12 @@ list(APPEND TESTS_SRC test_new_header.cc test_udp_header.cc test_validation.cc + test_bitmap.cc + test_interest_manifest.cc + test_khash.cc + test_pool.cc + test_ring.cc + test_vector.cc ) ############################################################## diff --git a/lib/src/test/test_bitmap.cc b/lib/src/test/test_bitmap.cc new file mode 100644 index 000000000..7fc8eef71 --- /dev/null +++ b/lib/src/test/test_bitmap.cc @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" +{ +#define WITH_TESTS +#include <hicn/util/bitmap.h> +} + +#define DEFAULT_SIZE 10 + +class BitmapTest : public ::testing::Test +{ +protected: + BitmapTest () {} + + virtual ~BitmapTest () {} + + bitmap_t *bitmap; +}; + +/* + * TEST: bitmap allocation + */ +TEST_F (BitmapTest, BitmapAllocation) +{ + int rc; + + /* + * We take a value < 32 on purpose to avoid confusion on the choice of a 32 + * or 64 bit integer for storage + */ + size_t size_not_pow2 = DEFAULT_SIZE; + bitmap_init (bitmap, size_not_pow2, 0); + + /* + * Bitmap should have been allocated with a size rounded to the next power + * of 2 + */ + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + /* By default, no element should be set */ + EXPECT_FALSE (bitmap_is_set (bitmap, 0)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 0)); + + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + EXPECT_FALSE (bitmap_is_set (bitmap, size_not_pow2 - 1)); + EXPECT_TRUE (bitmap_is_unset (bitmap, size_not_pow2 - 1)); + + /* Bitmap should not have been reallocated */ + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + /* After setting a bit after the end, bitmap should have been reallocated */ + bitmap_set (bitmap, sizeof (bitmap[0]) * 8 - 1); + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + /* After setting a bit after the end, bitmap should have been reallocated */ + rc = bitmap_set (bitmap, sizeof (bitmap[0]) * 8); + EXPECT_GE (rc, 0); + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 2UL); + + rc = bitmap_set (bitmap, sizeof (bitmap[0]) * 8 + 1); + EXPECT_GE (rc, 0); + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 2UL); + + bitmap_free (bitmap); + + size_t size_pow2 = 16; + + /* Limiting test for allocation size */ + bitmap_init (bitmap, size_pow2, 0); + EXPECT_EQ (bitmap_get_alloc_size (bitmap), 1UL); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + bitmap_set (bitmap, 20); + EXPECT_TRUE (bitmap_is_set (bitmap, 20)); + EXPECT_FALSE (bitmap_is_unset (bitmap, 20)); + EXPECT_FALSE (bitmap_is_set (bitmap, 19)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 19)); + + // Test edge cases (i.e. start and end of block) + off_t start_position = 0; + bitmap_set (bitmap, start_position); + EXPECT_TRUE (bitmap_is_set (bitmap, start_position)); + EXPECT_FALSE (bitmap_is_unset (bitmap, start_position)); + + off_t end_position = BITMAP_WIDTH (bitmap) - 1; + bitmap_set (bitmap, end_position); + EXPECT_TRUE (bitmap_is_set (bitmap, end_position)); + EXPECT_FALSE (bitmap_is_unset (bitmap, end_position)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapUnSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + bitmap_set (bitmap, 20); + bitmap_set (bitmap, 19); + bitmap_unset (bitmap, 20); + EXPECT_FALSE (bitmap_is_set (bitmap, 20)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 20)); + EXPECT_TRUE (bitmap_is_set (bitmap, 19)); + EXPECT_FALSE (bitmap_is_unset (bitmap, 19)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapSetTo) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + bitmap_set_to (bitmap, 40); + EXPECT_TRUE (bitmap_is_set (bitmap, 20)); + EXPECT_TRUE (bitmap_is_set (bitmap, 21)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 41)); + EXPECT_TRUE (bitmap_is_unset (bitmap, 42)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapFirstSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + // Get first set bit. It should be INVALID_INDEX + EXPECT_EQ (bitmap_first_set (bitmap), BITMAP_INVALID_INDEX); + + // set bit 40 + bitmap_set (bitmap, 40); + EXPECT_TRUE (bitmap_is_set (bitmap, 40)); + + // Get first set bit. It should be bit 40 (surprise):) + EXPECT_EQ (bitmap_first_set (bitmap), hicn_uword (40)); + + // set bit 3 + bitmap_set (bitmap, 3); + EXPECT_TRUE (bitmap_is_set (bitmap, 3)); + + // The first set bit now should be bit #3 + EXPECT_EQ (bitmap_first_set (bitmap), hicn_uword (3)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapFirstUnSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + // Get first unset bit. It should be 0 + EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (0)); + + // set bit 0 + bitmap_set (bitmap, 0); + EXPECT_TRUE (bitmap_is_set (bitmap, 0)); + + // Get first unset bit. It should be bit 1 + EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (1)); + + // set bit 3 + bitmap_set (bitmap, 3); + EXPECT_TRUE (bitmap_is_set (bitmap, 3)); + + // The first set bit now should be still 1 + EXPECT_EQ (bitmap_first_unset (bitmap), hicn_uword (1)); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapNextSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + // Get next unset bit >= 0. It should be INVALID + EXPECT_EQ (bitmap_next_set (bitmap, 0), BITMAP_INVALID_INDEX); + + // set bit 0 + bitmap_set (bitmap, 0); + EXPECT_TRUE (bitmap_is_set (bitmap, 0)); + + // Get next set bit >= 0. It should be bit 0 + EXPECT_EQ (bitmap_next_set (bitmap, 0), hicn_uword (0)); + + // set bit 3 + bitmap_set (bitmap, 3); + EXPECT_TRUE (bitmap_is_set (bitmap, 3)); + + // Get next set bit >= 1. It should be 3 + EXPECT_EQ (bitmap_next_set (bitmap, 1), hicn_uword (3)); + + // set (N-2)th bit + bitmap_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2); + EXPECT_TRUE (bitmap_is_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2)); + EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 3), + DEFAULT_SIZE * WORD_WIDTH - 2); + + // set (N-1)th bit + bitmap_unset (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2); + bitmap_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1); + EXPECT_TRUE (bitmap_is_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1)); + EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 2), + DEFAULT_SIZE * WORD_WIDTH - 1); + EXPECT_EQ (bitmap_next_set (bitmap, DEFAULT_SIZE * WORD_WIDTH - 1), + DEFAULT_SIZE * WORD_WIDTH - 1); + + bitmap_free (bitmap); +} + +TEST_F (BitmapTest, BitmapNextUnSet) +{ + bitmap_init (bitmap, DEFAULT_SIZE, 0); + + // Get next unset bit >= 0. It should be 0 + EXPECT_EQ (bitmap_next_unset (bitmap, 0), hicn_uword (0)); + + // set bit 0 + bitmap_set (bitmap, 0); + EXPECT_TRUE (bitmap_is_set (bitmap, 0)); + + // Get next set bit >= 0. It should be bit 1 + EXPECT_EQ (bitmap_next_unset (bitmap, 0), hicn_uword (1)); + + // set bit 3 + bitmap_set (bitmap, 3); + EXPECT_TRUE (bitmap_is_set (bitmap, 3)); + + // Get next unset bit after 3. It should be 4 + EXPECT_EQ (bitmap_next_unset (bitmap, 3), hicn_uword (4)); + + bitmap_free (bitmap); +} diff --git a/lib/src/test/test_interest_manifest.cc b/lib/src/test/test_interest_manifest.cc new file mode 100644 index 000000000..5df06d6bd --- /dev/null +++ b/lib/src/test/test_interest_manifest.cc @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> +#include <gmock/gmock.h> + +extern "C" +{ +#include <hicn/interest_manifest.h> +} + +static constexpr hicn_uword WORD_SIZE = WORD_WIDTH; + +class InterestManifestTest : public ::testing::Test +{ +protected: + static constexpr u32 n_suffixes = 0x00000014; + static constexpr u32 padding = 0x21232425; + static constexpr hicn_uword bitmap_word = ~0ULL; + static inline std::vector<uint32_t> values = { 10, 22, 23, 43, 54, 65, 66, + 4, 33, 2, 44, 99, 87, 67, + 78, 98, 76, 1, 7, 123 }; + InterestManifestTest () {} + virtual ~InterestManifestTest () {} + + uint8_t buffer[512]; + hicn_uword bitmap_saved[BITMAP_SIZE]; +}; + +TEST_F (InterestManifestTest, OneWordBitmapUpdate) +{ + hicn_uword initial_bitmap[1]; + hicn_uword curr_bitmap[1] = { 0 }; + initial_bitmap[0] = + 0x0000000000000b07; // ...000000000000000000000101100000111 + + // Consume first 4 'one' bits (i.e. suffixes), reaching position 9 + size_t pos = 0, max_suffixes = 4; + pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap, pos, + WORD_SIZE, max_suffixes); + EXPECT_EQ (pos, std::size_t (9)); + EXPECT_EQ (curr_bitmap[0], hicn_uword (0x0000000000000107)); + + // Consume the remaining 2 'one' bits, reaching end of bitmap + hicn_uword curr_bitmap2[1] = { 0 }; + pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap2, pos, + WORD_SIZE, max_suffixes); + EXPECT_EQ (pos, WORD_SIZE); + EXPECT_EQ (curr_bitmap2[0], hicn_uword (0x00000a00)); + + // Consume all suffixes at once + hicn_uword curr_bitmap3[1] = { 0 }; + max_suffixes = 16; + pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap3, 0, + WORD_SIZE, max_suffixes); + EXPECT_EQ (pos, WORD_SIZE); + EXPECT_EQ (curr_bitmap3[0], initial_bitmap[0]); +} + +TEST_F (InterestManifestTest, TwoWordBitmapUpdate) +{ + hicn_uword initial_bitmap[2]; + initial_bitmap[0] = 0x0000000000000b07; + initial_bitmap[1] = 0x0000000000000b07; + // -> 0000000000000000000010110000011100000000000000000000101100000111 + + int expected_pos[] = { WORD_SIZE + 2, 2 * WORD_SIZE }; + u32 expected_bitmap[][2] = { { 0x00000b07, 0x00000003 }, + { 0x0, 0x00000b04 } }; + + // Loop to consume all suffixes + int pos = 0, max_suffixes = 8, i = 0, len = WORD_SIZE * 2; + while (pos != len) + { + hicn_uword curr_bitmap[2] = { 0 }; + pos = interest_manifest_update_bitmap (initial_bitmap, curr_bitmap, pos, + len, max_suffixes); + + EXPECT_EQ (pos, expected_pos[i]); + EXPECT_EQ (curr_bitmap[0], expected_bitmap[i][0]); + EXPECT_EQ (curr_bitmap[1], expected_bitmap[i][1]); + i++; + } +} + +TEST_F (InterestManifestTest, SerializeDeserialize) +{ +#if hicn_uword_bits == 64 +#define F(x) hicn_host_to_net_64 (x) +#elif hicn_uword_bits == 32 +#define F(x) hicn_host_to_net_32 (x) +#else +#error "Unrecognized architecture" +#endif + + auto header = reinterpret_cast<interest_manifest_header_t *> (buffer); + interest_manifest_init (header); + + for (const auto &v : values) + { + interest_manifest_add_suffix (header, v); + } + + EXPECT_EQ (header->n_suffixes, n_suffixes); + + // Save bitmap + memcpy (bitmap_saved, header->request_bitmap, sizeof (bitmap_saved)); + + // Serialize manifest + interest_manifest_serialize (header); + + // If architecture is little endian, bytes should be now swapped + EXPECT_THAT (header->n_suffixes, ::testing::Eq (hicn_host_to_net_32 ( + n_suffixes) /* 0x14000000 */)); + + for (unsigned i = 0; i < BITMAP_SIZE; i++) + { + EXPECT_THAT (header->request_bitmap[i], + ::testing::Eq (F (bitmap_saved[i]))); + } + + hicn_name_suffix_t *suffix = (hicn_name_suffix_t *) (header + 1); + for (unsigned i = 0; i < n_suffixes; i++) + { + EXPECT_THAT (*(suffix + i), + ::testing::Eq (hicn_host_to_net_32 (values[i]))); + } + + // Deserialize manifest + interest_manifest_deserialize (header); + + // Bytes should now be as before + EXPECT_THAT (header->n_suffixes, ::testing::Eq (n_suffixes)); + + int i = 0; + interest_manifest_foreach_suffix (header, suffix) + { + EXPECT_THAT (*suffix, ::testing::Eq (values[i])); + i++; + } +} + +TEST_F (InterestManifestTest, ForEach) +{ + auto header = reinterpret_cast<interest_manifest_header_t *> (buffer); + header->n_suffixes = n_suffixes; + header->padding = padding; + memset (header->request_bitmap, 0xff, BITMAP_SIZE * sizeof (hicn_uword)); + + hicn_name_suffix_t *suffix = (hicn_name_suffix_t *) (header + 1); + for (uint32_t i = 0; i < n_suffixes; i++) + { + *(suffix + i) = values[i]; + } + + // Iterate over interest manifest. As bitmap is all 1, we should be able to + // iterate over all suffixes. + unsigned i = 0; + interest_manifest_foreach_suffix (header, suffix) + { + EXPECT_EQ (*suffix, values[i]); + i++; + } + + std::set<uint32_t> set_values (values.begin (), values.end ()); + + // Unset few bitmap positions + interest_manifest_del_suffix (header, 5); + set_values.erase (values[5]); + + interest_manifest_del_suffix (header, 6); + set_values.erase (values[6]); + + interest_manifest_del_suffix (header, 12); + set_values.erase (values[12]); + + interest_manifest_del_suffix (header, 17); + set_values.erase (values[17]); + + // Iterate over interest manifest and remove elements in manifest from set. + // The set should be empty at the end. + interest_manifest_foreach_suffix (header, suffix) + { + std::cout << suffix - _FIRST (header) << std::endl; + EXPECT_TRUE (set_values.find (*suffix) != set_values.end ()) + << "The value was " << *suffix; + set_values.erase (*suffix); + } + + EXPECT_TRUE (set_values.empty ()); +}
\ No newline at end of file diff --git a/lib/src/test/test_khash.cc b/lib/src/test/test_khash.cc new file mode 100644 index 000000000..b0423ab5d --- /dev/null +++ b/lib/src/test/test_khash.cc @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" +{ +#include <hicn/util/khash.h> +} + +KHASH_MAP_INIT_INT (int, unsigned char) + +typedef struct +{ + unsigned key; + unsigned char val; +} int_unpack_t; + +typedef struct +{ + unsigned key; + unsigned char val; +} __attribute__ ((__packed__)) int_packed_t; + +#define hash_eq(a, b) ((a).key == (b).key) +#define hash_func(a) ((a).key) + +KHASH_INIT (iun, int_unpack_t, char, 0, hash_func, hash_eq) +KHASH_INIT (ipk, int_packed_t, char, 0, hash_func, hash_eq) + +class KHashTest : public ::testing::Test +{ +protected: + KHashTest () {} + + virtual ~KHashTest () + { + // You can do clean-up work that doesn't throw exceptions here. + } + + // If the constructor and destructor are not enough for setting up + // and cleaning up each test, you can define the following methods: + + virtual void + SetUp () + { + khash = kh_init (int); + } + + virtual void + TearDown () + { + kh_destroy (int, khash); + } + khash_t (int) * khash; +}; + +TEST_F (KHashTest, KhashIntSize) +{ + int ret; + int k; + int size = kh_size (khash); + + EXPECT_EQ (size, 0); + k = kh_put (int, khash, 10, &ret); + if (ret == 1) + { + kh_val (khash, k) = 10; + } + size = kh_size (khash); + EXPECT_EQ (size, 1); +} + +TEST_F (KHashTest, KhashIntPut) +{ + int ret; + int k; + k = kh_put (int, khash, 10, &ret); + if (ret == 1) + { + kh_val (khash, k) = 10; + } + int size = kh_size (khash); + EXPECT_EQ (size, 1); + k = kh_put (int, khash, 20, &ret); + if (ret == 1) + { + kh_val (khash, k) = 20; + } + size = kh_size (khash); + EXPECT_EQ (size, 2); +} + +TEST_F (KHashTest, KhashCheckValue) +{ + int ret; + int k; + k = kh_put (int, khash, 10, &ret); + if (ret == 1) + { + kh_val (khash, k) = 100; + } + k = kh_put (int, khash, 20, &ret); + if (ret == 1) + { + kh_val (khash, k) = 200; + } + + k = kh_put (int, khash, 10, &ret); + int val = -1; + if (!ret) + val = kh_val (khash, k); + EXPECT_EQ (val, 100); + + k = kh_put (int, khash, 20, &ret); + val = -1; + if (!ret) + val = kh_val (khash, k); + EXPECT_EQ (val, 200); +} + +// Check that there are no collisions in case of same key hash +typedef struct +{ + int x; +} Key; +#define hash_key(key) 1 // Hash is always 1 to simulate collisions +#define key_hash_eq(a, b) (a->x == b->x) // Function used in case of collisions +KHASH_INIT (test_map, const Key *, unsigned, 1, hash_key, key_hash_eq); + +TEST_F (KHashTest, Collisions) +{ + int ret; + khiter_t k; + + kh_test_map_t *map = kh_init (test_map); + Key key1 = { .x = 10 }; + Key key2 = { .x = 11 }; + + k = kh_put_test_map (map, &key1, &ret); + EXPECT_EQ (ret, 1); + kh_val (map, k) = 15; + + k = kh_put_test_map (map, &key2, &ret); + EXPECT_EQ (ret, 1); + kh_val (map, k) = 27; + + k = kh_get_test_map (map, &key1); + ASSERT_NE (k, kh_end (map)); + unsigned val = kh_val (map, k); + EXPECT_EQ (val, 15u); + + k = kh_get_test_map (map, &key2); + ASSERT_NE (k, kh_end (map)); + val = kh_val (map, k); + EXPECT_EQ (val, 27u); + + kh_destroy_test_map (map); +} diff --git a/lib/src/test/test_name.cc b/lib/src/test/test_name.cc index 207725adb..35e636b63 100644 --- a/lib/src/test/test_name.cc +++ b/lib/src/test/test_name.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -58,32 +58,24 @@ protected: // The hash should be equal, with and without considering the suffix uint32_t hash_a, hash_b; - rc = hicn_name_hash (&name_a, &hash_a, 1); - EXPECT_EQ (rc, 0); - rc = hicn_name_hash (&name_b, &hash_b, 1); - EXPECT_EQ (rc, 0); + hash_a = hicn_name_get_hash (&name_a); + hash_b = hicn_name_get_hash (&name_b); EXPECT_EQ (hash_a, hash_b); - rc = hicn_name_hash (&name_a, &hash_a, 0); - EXPECT_EQ (rc, 0); - rc = hicn_name_hash (&name_b, &hash_b, 0); - EXPECT_EQ (rc, 0); + hash_a = hicn_name_get_prefix_hash (&name_a); + hash_b = hicn_name_get_prefix_hash (&name_b); EXPECT_EQ (hash_a, hash_b); // Now let's change the suffix - rc = hicn_name_set_seq_number (&name_a, 97531); + rc = hicn_name_set_suffix (&name_a, 97531); // They should result equal if we do not consider the suffix - rc = hicn_name_hash (&name_a, &hash_a, 0); - EXPECT_EQ (rc, 0); - rc = hicn_name_hash (&name_b, &hash_b, 0); - EXPECT_EQ (rc, 0); + hash_a = hicn_name_get_prefix_hash (&name_a); + hash_b = hicn_name_get_prefix_hash (&name_b); EXPECT_EQ (hash_a, hash_b); // And different if we consider it - rc = hicn_name_hash (&name_a, &hash_a, 1); - EXPECT_EQ (rc, 0); - rc = hicn_name_hash (&name_b, &hash_b, 1); - EXPECT_EQ (rc, 0); + hash_a = hicn_name_get_hash (&name_a); + hash_b = hicn_name_get_hash (&name_b); EXPECT_NE (hash_a, hash_b); } @@ -120,7 +112,7 @@ protected: EXPECT_EQ (rc, 0); // Now let's change the suffix - rc = hicn_name_set_seq_number (&name_a, 97531); + rc = hicn_name_set_suffix (&name_a, 97531); // They should result equal if we do not consider the suffix rc = hicn_name_compare (&name_a, &name_b, 0); EXPECT_EQ (rc, 0); @@ -130,13 +122,13 @@ protected: } void - nameFromIpPrefixTest (const ip_prefix_t &ip_prefix) + nameFromIpPrefixTest (const hicn_ip_prefix_t &hicn_ip_prefix) { uint32_t suffix = 54321; hicn_name_t name; - int rc = hicn_name_create_from_ip_prefix (&ip_prefix, suffix, &name); + int rc = hicn_name_create_from_ip_prefix (&hicn_ip_prefix, suffix, &name); EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); - rc = memcmp (ip_prefix.address.v6.as_u8, name.prefix.v6.as_u8, + rc = memcmp (hicn_ip_prefix.address.v6.as_u8, name.prefix.v6.as_u8, sizeof (name.prefix.v6)); EXPECT_EQ (rc, 0); EXPECT_EQ (suffix, name.suffix); @@ -154,16 +146,16 @@ protected: int family; rc = hicn_name_get_family (&name, &family); - ip_prefix_t ip_prefix; - rc = hicn_name_to_ip_prefix (&name, &ip_prefix); + hicn_ip_prefix_t hicn_ip_prefix; + rc = hicn_name_to_hicn_ip_prefix (&name, &hicn_ip_prefix); EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); - EXPECT_EQ (ip_prefix.family, family); - rc = ip_address_cmp (&ip_prefix.address, &name.prefix, AF_INET6); + EXPECT_EQ (hicn_ip_prefix.family, family); + rc = hicn_ip_address_cmp (&hicn_ip_prefix.address, &name.prefix); EXPECT_EQ (rc, 0); } hicn_name_t name_, name4_, name6_; - ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; + hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; }; /** @@ -180,7 +172,7 @@ TEST_F (NameTest, NameInitialization) EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); // Check name is correctly created - rc = ip_address_cmp (&name6.prefix, &ipv6_prefix_bytes, AF_INET6); + rc = hicn_ip_address_cmp (&name6.prefix, &ipv6_prefix_bytes); EXPECT_EQ (rc, 0); EXPECT_EQ (name6.suffix, suffix); @@ -190,7 +182,7 @@ TEST_F (NameTest, NameInitialization) EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); // Check name is correctly created - rc = ip_address_cmp (&name4.prefix, &ipv4_prefix_bytes, AF_INET); + rc = hicn_ip_address_cmp (&name4.prefix, &ipv4_prefix_bytes); EXPECT_EQ (name4.prefix.pad[0], 0UL); EXPECT_EQ (name4.prefix.pad[1], 0UL); EXPECT_EQ (name4.prefix.pad[2], 0UL); @@ -202,7 +194,7 @@ TEST_F (NameTest, NameInitialization) EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); // Check name is correctly created - rc = ip_address_cmp (&name6.prefix, &ipv4_prefix_bytes, AF_INET); + rc = hicn_ip_address_cmp (&name6.prefix, &ipv4_prefix_bytes); EXPECT_EQ (name6.prefix.pad[0], 0UL); EXPECT_EQ (name6.prefix.pad[1], 0UL); EXPECT_EQ (name6.prefix.pad[2], 0UL); @@ -215,22 +207,26 @@ TEST_F (NameTest, NameInitialization) */ TEST_F (NameTest, NameFromIpPrefix6) { - ip_prefix_t ip_prefix = { .family = AF_INET6, .address = {}, .len = 64 }; + hicn_ip_prefix_t hicn_ip_prefix = { .family = AF_INET6, + .address = {}, + .len = 64 }; - ip_prefix.address.v6.as_u64[0] = ipv6_prefix_bytes.v6.as_u64[0]; - ip_prefix.address.v6.as_u64[1] = ipv6_prefix_bytes.v6.as_u64[1]; + hicn_ip_prefix.address.v6.as_u64[0] = ipv6_prefix_bytes.v6.as_u64[0]; + hicn_ip_prefix.address.v6.as_u64[1] = ipv6_prefix_bytes.v6.as_u64[1]; - nameFromIpPrefixTest (ip_prefix); + nameFromIpPrefixTest (hicn_ip_prefix); } TEST_F (NameTest, NameFromIpPrefix4) { - ip_prefix_t ip_prefix = { .family = AF_INET, .address = {}, .len = 64 }; - ip_prefix.address.v4.as_u32 = ipv4_prefix_bytes.v4.as_u32; - ip_prefix.address.pad[0] = 0; - ip_prefix.address.pad[1] = 0; - ip_prefix.address.pad[2] = 0; - nameFromIpPrefixTest (ip_prefix); + hicn_ip_prefix_t hicn_ip_prefix = { .family = AF_INET, + .address = {}, + .len = 64 }; + hicn_ip_prefix.address.v4.as_u32 = ipv4_prefix_bytes.v4.as_u32; + hicn_ip_prefix.address.pad[0] = 0; + hicn_ip_prefix.address.pad[1] = 0; + hicn_ip_prefix.address.pad[2] = 0; + nameFromIpPrefixTest (hicn_ip_prefix); } TEST_F (NameTest, NameCompare6) { nameCompareTest (ipv6_prefix); } @@ -257,8 +253,8 @@ TEST_F (NameTest, NameCopy4) { nameCopyTest (ipv4_prefix); } TEST_F (NameTest, NameCopyToDestination) { - ip4_address_t dst4; - ip6_address_t dst6; + ipv4_address_t dst4; + ipv6_address_t dst6; // Copy names to destination int rc = hicn_name_copy_prefix_to_destination (dst4.as_u8, &name4_); @@ -282,7 +278,7 @@ TEST_F (NameTest, SetGetSuffix) EXPECT_EQ (suffix, suffix_ret); // Set new suffix - rc = hicn_name_set_seq_number (&name6_, suffix2); + rc = hicn_name_set_suffix (&name6_, suffix2); EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); // Check suffix was set diff --git a/lib/src/test/test_new_header.cc b/lib/src/test/test_new_header.cc index 33c9e13c9..c936b6910 100644 --- a/lib/src/test/test_new_header.cc +++ b/lib/src/test/test_new_header.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -20,10 +20,10 @@ extern "C" #include <hicn/name.h> #include <hicn/common.h> #include <hicn/error.h> -#include <hicn/protocol/new.h> -#include <hicn/protocol/ah.h> -#include <hicn/header.h> -#include <hicn/compat.h> +#include <hicn/packet.h> + +#include "../protocol/ah.h" +#include "../protocol/new.h" } class NewHeaderTest : public ::testing::Test @@ -33,10 +33,11 @@ protected: const char *ipv4_prefix = "12.13.14.15"; const uint32_t suffix = 12345; - NewHeaderTest (size_t hdr_size, hicn_format_t format) - : buffer_ (new uint8_t[hdr_size]), header_ ((hicn_header_t *) (buffer_)), + NewHeaderTest (hicn_packet_format_t format) + : buffer_ (new uint8_t[NEW_HDRLEN]), format_ (format), name_{}, name4_{}, name6_{} { + int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6); EXPECT_EQ (rc, 1); @@ -49,42 +50,46 @@ protected: EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); } - NewHeaderTest () : NewHeaderTest (NEW_HDRLEN, HF_NEW) {} + NewHeaderTest () : NewHeaderTest (HICN_PACKET_FORMAT_NEW) {} virtual ~NewHeaderTest () { delete[] buffer_; } void - checkCommon (const _new_header_t *new_hdr) + checkCommon () { // Initialize header - int rc = hicn_packet_init_header (format_, header_); + hicn_packet_set_format (&pkbuf_, format_); + // pkbuf_set_type (&pkbuf_, HICN_PACKET_TYPE_UNDEFINED); + int rc = hicn_packet_init_header (&pkbuf_, 0); EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + auto new_hdr = (_new_header_t *) buffer_; + // Check fields EXPECT_EQ (new_hdr->prefix.v6.as_u64[0], 0UL); EXPECT_EQ (new_hdr->prefix.v6.as_u64[1], 0UL); EXPECT_EQ (new_hdr->suffix, 0UL); EXPECT_EQ (new_hdr->lifetime, 0UL); EXPECT_EQ (new_hdr->path_label, 0UL); - EXPECT_EQ (new_hdr->payload_length, 0UL); + EXPECT_EQ (new_hdr->payload_len, 0UL); EXPECT_EQ (_get_new_header_version (new_hdr), 0x9); + EXPECT_EQ (new_hdr->flags, 0); } virtual void SetUp () override { - auto new_hdr = &header_->protocol.newhdr; - checkCommon (new_hdr); - EXPECT_EQ (new_hdr->flags, 0); + checkCommon (); } uint8_t *buffer_; - hicn_header_t *header_; - hicn_format_t format_; + hicn_packet_buffer_t pkbuf_; + hicn_packet_format_t format_; hicn_name_t name_, name4_, name6_; - ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; + hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; }; +#if 0 class NewHeaderAHTest : public NewHeaderTest { protected: @@ -229,7 +234,7 @@ TEST_F (NewHeaderTest, SetGetName) TEST_F (NewHeaderTest, SetGetLocator) { // This function does nothing but it is set for compatibility - ip_address_t locator; + hicn_ip_address_t locator; memset (&locator, 0, sizeof (locator)); locator.v6.as_u8[15] = 1; int rc = hicn_packet_set_interest (format_, header_); @@ -338,3 +343,4 @@ TEST_F (NewHeaderTest, SetGetPayloadType) EXPECT_EQ (payload_type, payload_type_ret); } +#endif diff --git a/lib/src/test/test_pool.cc b/lib/src/test/test_pool.cc new file mode 100644 index 000000000..cbb5ce068 --- /dev/null +++ b/lib/src/test/test_pool.cc @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" +{ +#define WITH_TESTS +#include <hicn/util/pool.h> +} + +/* + * TODO + * - test max_size + */ + +#define DEFAULT_SIZE 10 + +class PoolTest : public ::testing::Test +{ +protected: + PoolTest () {} + virtual ~PoolTest () {} + + int *pool; +}; + +TEST_F (PoolTest, PoolAllocation) +{ + int rc; + + pool_init (pool, DEFAULT_SIZE, 0); + + size_t pool_size = next_pow2 (DEFAULT_SIZE); + + EXPECT_EQ (pool_get_alloc_size (pool), pool_size); + + /* Check that free indices and bitmaps are correctly initialize */ + off_t *fi = pool_get_free_indices (pool); + EXPECT_EQ (vector_len (fi), pool_size); + EXPECT_EQ (fi[0], (long) (pool_size - 1)); + EXPECT_EQ (fi[pool_size - 1], 0); + + /* The allocated size of the underlying vector should be the next power of + * two + */ + EXPECT_EQ (vector_get_alloc_size (fi), pool_size); + + bitmap_t *fb = pool_get_free_bitmap (pool); + EXPECT_TRUE (bitmap_is_set (fb, 0)); + EXPECT_TRUE (bitmap_is_set (fb, pool_size - 2)); + EXPECT_TRUE (bitmap_is_set (fb, pool_size - 1)); + EXPECT_TRUE (bitmap_is_unset (fb, pool_size)); + + /* Getting elements from the pool should correctly update the free indices + * and bitmap */ + int *elt; + + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + EXPECT_EQ (vector_len (fi), pool_size - 1); + EXPECT_TRUE (bitmap_is_unset (fb, 0)); + + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + EXPECT_EQ (vector_len (fi), pool_size - 2); + EXPECT_TRUE (bitmap_is_unset (fb, 1)); + + for (unsigned i = 0; i < pool_size - 4; i++) + { + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + } + + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + EXPECT_EQ (vector_len (fi), 1UL); + EXPECT_TRUE (bitmap_is_unset (fb, pool_size - 2)); + + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + EXPECT_EQ (vector_len (fi), 0UL); + EXPECT_TRUE (bitmap_is_unset (fb, pool_size - 1)); + + /* + * Getting elements within the allocated range should not have triggered a + * resize + */ + EXPECT_EQ (pool_len (pool), pool_size); + + /* + * Getting elements once the allocated range has been exceeded should + * trigger a resize + */ + rc = pool_get (pool, elt); + EXPECT_GE (rc, 0); + + EXPECT_EQ (pool_get_alloc_size (pool), pool_size * 2); + + EXPECT_EQ (pool_len (pool), pool_size + 1); + + /* + * Doubling the size, we should have again pool_size elements free, minus 1 + */ + EXPECT_EQ (pool_get_free_indices_size (pool), pool_size - 1); + + /* + * NOTE: this is wrong as there has been a realloc and the old fi + * pointer is now invalid + */ + // EXPECT_EQ(vector_len(fi), pool_size - 1); + + /* And the bitmap should also be correctly modified */ + fb = pool_get_free_bitmap (pool); + EXPECT_TRUE (bitmap_is_unset (fb, pool_size)); + + /* Check that surrounding values are also correct */ + EXPECT_TRUE (bitmap_is_unset (fb, pool_size - 1)); + EXPECT_TRUE (bitmap_is_set (fb, pool_size + 1)); + + /* Setting elements after should through */ + + /* Check that free indices and bitmaps are correctly updated */ + + pool_free (pool); +} + +TEST_F (PoolTest, PoolPut) +{ + pool_init (pool, DEFAULT_SIZE, 0); + + int *elt; + pool_get (pool, elt); + *elt = 10; + pool_put (pool, elt); + + pool_free (pool); +} + +TEST_F (PoolTest, PoolGetForceBitmapRealloc) +{ + const int N = 64; + int *elts[N]; + int *elt = NULL; + pool_init (pool, N, 0); + + for (int i = 0; i < N; i++) + pool_get (pool, elts[i]); + pool_get (pool, elt); + + pool_free (pool); +} + +TEST_F (PoolTest, PoolGetAfterReleasing) +{ + int *elt1 = NULL, *elt2 = NULL, *tmp = NULL; + pool_init (pool, DEFAULT_SIZE, 0); + + // If two elements are requested... + off_t id1 = pool_get (pool, elt1); + pool_get (pool, tmp); + + // ...and the first one is released... + pool_put (pool, elt1); + + // ...requesting a new one should return + // the first one (that was freed) + off_t id2 = pool_get (pool, elt2); + EXPECT_EQ (id1, id2); + EXPECT_EQ (elt1, elt2); + + pool_free (pool); +} + +TEST_F (PoolTest, PoolGetMultipleElementsAfterReleasing) +{ + const int N = 2; + int *elts[N]; + pool_init (pool, N, 0); + + for (int i = 0; i < N; i++) + pool_get (pool, elts[i]); + for (int i = 0; i < N; i++) + pool_put (pool, elts[i]); + for (int i = 0; i < N; i++) + pool_get (pool, elts[i]); + + pool_free (pool); +} diff --git a/lib/src/test/test_ring.cc b/lib/src/test/test_ring.cc new file mode 100644 index 000000000..f0b0371e8 --- /dev/null +++ b/lib/src/test/test_ring.cc @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <netinet/in.h> + +extern "C" +{ +#define WITH_TESTS +#include <hicn/util/ring.h> +} + +#define DEFAULT_SIZE 10UL + +class RingTest : public ::testing::Test +{ +protected: + RingTest () { ring_init (ring, DEFAULT_SIZE); } + virtual ~RingTest () { ring_free (ring); } + + int *ring = NULL; +}; + +/* TEST: Ring allocation and initialization */ +TEST_F (RingTest, RingAddOne) +{ + int val = -1; + /* Allocated size should be the next power of two */ + EXPECT_EQ (ring_get_size (ring), 0UL); + ring_add_value (ring, 1); + EXPECT_EQ (ring_get_size (ring), 1UL); + ring_get (ring, 0, &val); + EXPECT_EQ (val, 1); + EXPECT_EQ (ring_get_size (ring), 1UL); + ring_advance (ring, 1); + EXPECT_EQ (ring_get_size (ring), 0UL); +} + +TEST_F (RingTest, RingAddMany) +{ + size_t i = 0; + int val = -1; + size_t count = 0; + + /* Allocated size should be the next power of two */ + EXPECT_EQ (ring_get_size (ring), 0UL); + for (unsigned i = 0; i < DEFAULT_SIZE; i++) + ring_add_value (ring, i); + EXPECT_EQ (ring_get_size (ring), DEFAULT_SIZE); + + count = 0; + ring_enumerate_n (ring, i, &val, 1, { + EXPECT_EQ (val, (int) (i)); + count++; + }); + EXPECT_EQ (count, 1UL); + + count = 0; + ring_enumerate_n (ring, i, &val, DEFAULT_SIZE, { + EXPECT_EQ (val, (int) (i)); + count++; + }); + EXPECT_EQ (count, DEFAULT_SIZE); + + count = 0; + ring_enumerate_n (ring, i, &val, DEFAULT_SIZE + 1, { + EXPECT_EQ (val, (int) (i)); + count++; + }); + EXPECT_EQ (count, DEFAULT_SIZE); + + // Drop one + ring_add_value (ring, DEFAULT_SIZE); + EXPECT_EQ (ring_get_size (ring), DEFAULT_SIZE); + + count = 0; + ring_enumerate_n (ring, i, &val, DEFAULT_SIZE, { + EXPECT_EQ (val, (int) (i + 1)); // all values shoud be shifted + count++; + }); + EXPECT_EQ (count, DEFAULT_SIZE); + + ring_advance (ring, DEFAULT_SIZE); + EXPECT_EQ (ring_get_size (ring), 0UL); +} diff --git a/lib/src/test/test_udp_header.cc b/lib/src/test/test_udp_header.cc index 5d9f4d1eb..2853ee31b 100644 --- a/lib/src/test/test_udp_header.cc +++ b/lib/src/test/test_udp_header.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -20,10 +20,12 @@ extern "C" #include <hicn/name.h> #include <hicn/common.h> #include <hicn/error.h> -#include <hicn/protocol/new.h> -#include <hicn/protocol/ah.h> -#include <hicn/header.h> -#include <hicn/compat.h> +#include <hicn/packet.h> + +#include "../protocol/ah.h" +#include "../protocol/ipv6.h" +#include "../protocol/udp.h" +#include "../protocol/new.h" } class UdpHeaderTest : public ::testing::Test @@ -33,8 +35,8 @@ protected: const char *ipv4_prefix = "12.13.14.15"; const uint32_t suffix = 12345; - UdpHeaderTest (size_t hdr_size, hicn_format_t format) - : buffer_ (new uint8_t[hdr_size]), header_ ((hicn_header_t *) (buffer_)), + UdpHeaderTest (size_t hdr_size, hicn_packet_format_t format) + : buffer_ (new uint8_t[hdr_size]), hdr_size_ (hdr_size), format_ (format), name_{}, name4_{}, name6_{} { int rc = inet_pton (AF_INET6, ipv6_prefix, &ipv6_prefix_bytes.v6); @@ -50,19 +52,26 @@ protected: } UdpHeaderTest () - : UdpHeaderTest (NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN, HF_INET6_UDP) + : UdpHeaderTest (NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN, + HICN_PACKET_FORMAT_IPV6_UDP) { } virtual ~UdpHeaderTest () { delete[] buffer_; } + // checked everytime we build the packet... void - checkCommon (const _ipv6_header_t *ip6_hdr) + checkCommon () { - // Initialize header - int rc = hicn_packet_init_header (format_, header_); + /* Initialize packet buffer headers */ + hicn_packet_set_format (&pkbuf_, format_); + hicn_packet_set_type (&pkbuf_, HICN_PACKET_TYPE_INTEREST); + hicn_packet_set_buffer (&pkbuf_, buffer_, hdr_size_, 0); + int rc = hicn_packet_init_header (&pkbuf_, 0); EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + auto ip6_hdr = (_ipv6_header_t *) buffer_; + // Check fields EXPECT_EQ (ip6_hdr->saddr.as_u64[0], 0UL); EXPECT_EQ (ip6_hdr->saddr.as_u64[1], 0UL); @@ -82,22 +91,22 @@ protected: EXPECT_EQ (new_hdr->suffix, 0UL); EXPECT_EQ (new_hdr->lifetime, 0UL); EXPECT_EQ (new_hdr->path_label, 0UL); - EXPECT_EQ (new_hdr->payload_length, 0UL); + EXPECT_EQ (new_hdr->payload_len, 0UL); EXPECT_EQ (_get_new_header_version (new_hdr), 0x9); } virtual void SetUp () override { - auto ip6_hdr = &header_->protocol.ipv6; - checkCommon (ip6_hdr); + checkCommon (); } uint8_t *buffer_; - hicn_header_t *header_; - hicn_format_t format_; + size_t hdr_size_; + hicn_packet_buffer_t pkbuf_; + hicn_packet_format_t format_; hicn_name_t name_, name4_, name6_; - ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; + hicn_ip_address_t ipv6_prefix_bytes, ipv4_prefix_bytes; }; class UdpHeaderAHTest : public UdpHeaderTest @@ -105,7 +114,7 @@ class UdpHeaderAHTest : public UdpHeaderTest protected: UdpHeaderAHTest () : UdpHeaderTest (AH_HDRLEN + NEW_HDRLEN + UDP_HDRLEN + IPV6_HDRLEN, - HF_INET6_UDP_AH) + HICN_PACKET_FORMAT_IPV6_UDP_AH) { } }; @@ -115,26 +124,21 @@ protected: */ TEST_F (UdpHeaderTest, GetFormat) { - // Get format from existing packet - hicn_format_t format; - int rc = hicn_packet_get_format (header_, &format); - EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); - - // Check it corresponds to the new header format - EXPECT_EQ (format, HF_INET6_UDP); + hicn_packet_format_t format = hicn_packet_get_format (&pkbuf_); + EXPECT_EQ (format.as_u32, HICN_PACKET_FORMAT_IPV6_UDP.as_u32); } TEST_F (UdpHeaderAHTest, GetFormat) { // Get format from existing packet - hicn_format_t format; - int rc = hicn_packet_get_format (header_, &format); - EXPECT_EQ (rc, HICN_LIB_ERROR_NONE); + hicn_packet_format_t format = hicn_packet_get_format (&pkbuf_); // Check it corresponds to the new header format - EXPECT_EQ (format, HF_INET6_UDP_AH); + EXPECT_EQ (format.as_u32, HICN_PACKET_FORMAT_IPV6_UDP_AH.as_u32); } +#if 0 + // /** // * @brief Checksum functions are not required, but we keep them for // * compatibility. @@ -244,7 +248,7 @@ TEST_F (UdpHeaderTest, SetGetName) TEST_F (UdpHeaderTest, SetGetLocator) { // This function does nothing but it is set for compatibility - ip_address_t locator; + hicn_ip_address_t locator; memset (&locator, 0, sizeof (locator)); locator.v6.as_u8[15] = 1; int rc = hicn_packet_set_interest (format_, header_); @@ -353,3 +357,4 @@ TEST_F (UdpHeaderTest, SetGetPayloadType) EXPECT_EQ (payload_type, payload_type_ret); } +#endif diff --git a/lib/src/test/test_vector.cc b/lib/src/test/test_vector.cc new file mode 100644 index 000000000..88b0bb7cf --- /dev/null +++ b/lib/src/test/test_vector.cc @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +extern "C" +{ +#include <hicn/util/vector.h> +} + +static constexpr size_t DEFAULT_SIZE = 10; +static constexpr size_t N_ELEMENTS = 5; + +class VectorTest : public ::testing::Test +{ +protected: + VectorTest () { vector_init (vector, DEFAULT_SIZE, 0); } + virtual ~VectorTest () { vector_free (vector); } + + int *vector = NULL; +}; + +TEST_F (VectorTest, VectorAllocateAndResize) +{ + // Allocated size should be the next power of two + EXPECT_EQ (vector_get_alloc_size (vector), 16UL); + + // Setting elements within the allocated size should not trigger a resize + vector_ensure_pos (vector, 15); + EXPECT_EQ (vector_get_alloc_size (vector), 16UL); + + // Setting elements after should through + vector_ensure_pos (vector, 16); + EXPECT_EQ (vector_get_alloc_size (vector), 32UL); +} + +TEST_F (VectorTest, VectorSize) +{ + EXPECT_EQ (vector_len (vector), size_t (0)); + + // Check size after pushing one element + vector_push (vector, 1); + EXPECT_EQ (vector_len (vector), size_t (1)); + + // Check size after pushing additional elements + vector_push (vector, 2); + vector_push (vector, 3); + EXPECT_EQ (vector_len (vector), size_t (3)); + + // Try adding multiple elements + const int n_elements_to_add = 5; + size_t expected_new_len = vector_len (vector) + n_elements_to_add; + for (int i = 0; i < n_elements_to_add; i++) + vector_push (vector, i); + EXPECT_EQ (vector_len (vector), expected_new_len); +} + +TEST_F (VectorTest, VectorCheckValue) +{ + // Add elements + vector_push (vector, 109); + vector_push (vector, 200); + EXPECT_EQ (vector_at (vector, 0), 109); + EXPECT_EQ (vector_at (vector, 1), 200); + + // Update element + vector_set (vector, 1, 400); + EXPECT_EQ (vector_at (vector, 1), 400); + + // Add at last available position + size_t prev_size = vector_len (vector); + vector_set (vector, vector_len (vector) - 1, 123); + EXPECT_EQ (vector_at (vector, vector_len (vector) - 1), 123); + EXPECT_EQ (prev_size, vector_len (vector)) << "Size should not have changed"; +} + +TEST_F (VectorTest, RemoveElement) +{ + // Populate vector + for (size_t i = 0; i < N_ELEMENTS; i++) + vector_push (vector, i); + EXPECT_EQ (vector_len (vector), N_ELEMENTS); + for (size_t i = 0; i < vector_len (vector); i++) + EXPECT_EQ (vector_at (vector, i), (int) i); + + // Remove element + int value_to_remove = 3; + int num_removed = vector_remove_unordered (vector, value_to_remove); + + EXPECT_EQ (vector_len (vector), N_ELEMENTS - 1); + EXPECT_EQ (num_removed, 1); + for (size_t i = 0; i < vector_len (vector); i++) + EXPECT_NE (vector_at (vector, i), value_to_remove); +} + +TEST_F (VectorTest, RemoveNonExistingElement) +{ + // Push some initial values + vector_push (vector, 1); + vector_push (vector, 2); + vector_push (vector, 3); + EXPECT_EQ (vector_len (vector), size_t (3)); + + // Remove non-existing element + int num_removed = vector_remove_unordered (vector, 5); + EXPECT_EQ (num_removed, 0); + size_t prev_size = vector_len (vector); + EXPECT_EQ (prev_size, vector_len (vector)) << "Size should not have changed"; +} + +TEST_F (VectorTest, RemoveDuplicatedElement) +{ + // Populate vector + for (size_t i = 0; i < N_ELEMENTS; i++) + vector_push (vector, i); + EXPECT_EQ (vector_len (vector), N_ELEMENTS); + for (size_t i = 0; i < vector_len (vector); i++) + EXPECT_EQ (vector_at (vector, i), (int) i); + vector_set (vector, 0, 3); // Duplicate element + + // Remove (duplicated) elements + int value_to_remove = 3; + int num_removed = vector_remove_unordered (vector, value_to_remove); + + EXPECT_EQ (vector_len (vector), N_ELEMENTS - 2); + EXPECT_EQ (num_removed, 2); + for (size_t i = 0; i < vector_len (vector); i++) + EXPECT_NE (vector_at (vector, i), value_to_remove); +} + +TEST_F (VectorTest, Iterate) +{ + for (size_t i = 0; i < N_ELEMENTS; i++) + vector_push (vector, i); + + int count = 0; + int *elem; + vector_foreach (vector, elem, { EXPECT_EQ (*elem, count++); }); +} + +TEST_F (VectorTest, MultipleResize) +{ + // Use small vector (size=1) to force multiple realloc operations + int *small_vector; + vector_init (small_vector, 1, 0); + + for (size_t i = 0; i < N_ELEMENTS; i++) + vector_push (small_vector, i); + + for (size_t i = 0; i < N_ELEMENTS; i++) + EXPECT_EQ (vector_at (small_vector, i), (int) i); + + EXPECT_EQ (vector_len (small_vector), 5UL); + EXPECT_EQ (vector_get_alloc_size (small_vector), 8UL); + + vector_free (small_vector); +} + +TEST_F (VectorTest, MaxSize) +{ + const int max_size = 4; + + // Fill the vector until max size is reached + int *small_vector; + vector_init (small_vector, 2, max_size); + for (int i = 0; i < max_size; i++) + vector_push (small_vector, i); + + // Try expanding or appending elements should fail + int rc = vector_ensure_pos (small_vector, max_size); + EXPECT_EQ (rc, -1); + rc = vector_push (small_vector, 123); + EXPECT_EQ (rc, -1); + + vector_free (small_vector); +} + +TEST_F (VectorTest, Contains) +{ + // No elements + EXPECT_EQ (vector_contains (vector, 1), false); + + // Push one element + vector_push (vector, 1); + EXPECT_EQ (vector_contains (vector, 1), true); + + // Update element + vector_set (vector, 0, 2); + EXPECT_EQ (vector_contains (vector, 1), false); + EXPECT_EQ (vector_contains (vector, 2), true); +} + +TEST_F (VectorTest, Remove) +{ + // Remove element at invalid position + int rc = vector_remove_at (vector, 2); + EXPECT_EQ (rc, -1); // Failure + + // Push two elements and remove the second one + vector_push (vector, 1); + vector_push (vector, 2); + rc = vector_remove_at (vector, 1); + EXPECT_EQ (rc, 0); // Success + EXPECT_EQ (vector_len (vector), size_t (1)); + + // Push another element: it should replace the previous one + vector_push (vector, 3); + EXPECT_EQ (vector_len (vector), size_t (2)); + EXPECT_EQ (vector_at (vector, 1), 3); +} + +TEST_F (VectorTest, RemoveInTheMiddle) +{ + for (size_t i = 0; i < N_ELEMENTS; i++) + vector_push (vector, i); + + // Remove element in central position + int rc = vector_remove_at (vector, 2); + EXPECT_EQ (rc, 0); // Success + EXPECT_EQ (vector_contains (vector, 2), false); + EXPECT_EQ (vector_len (vector), N_ELEMENTS - 1); + + // Check if elements have been shifted (preserving the order) + int expected[] = { 0, 1, 3, 4 }; + for (size_t i = 0; i < vector_len (vector); i++) + EXPECT_EQ (vector_at (vector, i), expected[i]); +} + +TEST_F (VectorTest, Reset) +{ + vector_push (vector, 1); + vector_push (vector, 2); + EXPECT_EQ (vector_len (vector), size_t (2)); + + vector_reset (vector); + EXPECT_EQ (vector_len (vector), size_t (0)); + + vector_push (vector, 5); + EXPECT_EQ (vector_len (vector), size_t (1)); + EXPECT_EQ (vector_contains (vector, 5), true); + EXPECT_EQ (vector_at (vector, 0), 5); +}
\ No newline at end of file diff --git a/lib/src/util/ip_address.c b/lib/src/util/ip_address.c index 412baddcf..ba7c6475b 100644 --- a/lib/src/util/ip_address.c +++ b/lib/src/util/ip_address.c @@ -21,6 +21,7 @@ #include <hicn/util/ip_address.h> #include <hicn/util/log.h> #include <hicn/util/sstrncpy.h> +#include <hicn/common.h> #if __BYTE_ORDER == __LITTLE_ENDIAN #ifdef __ANDROID__ @@ -33,38 +34,44 @@ #endif /* No htonl() with const */ -const ip_address_t IPV4_LOOPBACK = { +const hicn_ip_address_t IPV4_LOOPBACK = { .v4.as_inaddr.s_addr = SWAP (INADDR_LOOPBACK), }; -const ip_address_t IPV6_LOOPBACK = { +const hicn_ip_address_t IPV6_LOOPBACK = { .v6.as_in6addr = IN6ADDR_LOOPBACK_INIT, }; -const ip_address_t IPV4_ANY = { +const hicn_ip_address_t IPV4_ANY = { .v4.as_inaddr.s_addr = INADDR_ANY, }; -const ip_address_t IPV6_ANY = { +const hicn_ip_address_t IPV6_ANY = { .v6.as_in6addr = IN6ADDR_ANY_INIT, }; -const ip4_address_t IP4_ADDRESS_EMPTY = { +const ipv4_address_t IP4_ADDRESS_EMPTY = { .as_u32 = 0, }; -const ip6_address_t IP6_ADDRESS_EMPTY = { +const ipv6_address_t IP6_ADDRESS_EMPTY = { .as_u64 = { 0, 0 }, }; -const ip_address_t IP_ADDRESS_EMPTY = { +const hicn_ip_address_t IP_ADDRESS_EMPTY = { .v6.as_u64 = { 0, 0 }, }; /* IP address */ int -ip_address_get_family (const char *ip_address) +hicn_ip_address_get_family (const hicn_ip_address_t *address) +{ + return hicn_ip_address_is_v4 (address) ? AF_INET : AF_INET6; +} + +int +hicn_ip_address_str_get_family (const char *ip_address) { struct addrinfo hint, *res = NULL; int rc; @@ -85,7 +92,7 @@ ip_address_get_family (const char *ip_address) } int -ip_address_len (int family) +hicn_ip_address_len (int family) { return (family == AF_INET6) ? IPV6_ADDR_LEN : (family == AF_INET) ? IPV4_ADDR_LEN : @@ -93,8 +100,20 @@ ip_address_len (int family) } int -ip_address_ntop (const ip_address_t *ip_address, char *dst, const size_t len, - int family) +hicn_ip_address_get_len (const hicn_ip_address_t *ip_address) +{ + return hicn_ip_address_len (hicn_ip_address_get_family (ip_address)); +} + +int +hicn_ip_address_get_len_bits (const hicn_ip_address_t *ip_address) +{ + return bytes_to_bits (hicn_ip_address_get_len (ip_address)); +} + +int +hicn_ip_address_ntop (const hicn_ip_address_t *ip_address, char *dst, + const size_t len, int family) { const char *s; switch (family) @@ -115,12 +134,13 @@ ip_address_ntop (const ip_address_t *ip_address, char *dst, const size_t len, * Parse ip addresses in presentation format */ int -ip_address_pton (const char *ip_address_str, ip_address_t *ip_address) +hicn_ip_address_pton (const char *hicn_ip_address_str, + hicn_ip_address_t *ip_address) { int pton_fd; int family; - family = ip_address_get_family (ip_address_str); + family = hicn_ip_address_str_get_family (hicn_ip_address_str); switch (family) { @@ -128,10 +148,12 @@ ip_address_pton (const char *ip_address_str, ip_address_t *ip_address) ip_address->pad[0] = 0; ip_address->pad[1] = 0; ip_address->pad[2] = 0; - pton_fd = inet_pton (AF_INET, ip_address_str, &ip_address->v4.buffer); + pton_fd = + inet_pton (AF_INET, hicn_ip_address_str, &ip_address->v4.buffer); break; case AF_INET6: - pton_fd = inet_pton (AF_INET6, ip_address_str, &ip_address->v6.buffer); + pton_fd = + inet_pton (AF_INET6, hicn_ip_address_str, &ip_address->v6.buffer); break; default: return -1; @@ -146,11 +168,11 @@ ip_address_pton (const char *ip_address_str, ip_address_t *ip_address) } int -ip_address_snprintf (char *s, size_t size, const ip_address_t *ip_address, - int family) +hicn_ip_address_snprintf (char *s, size_t size, + const hicn_ip_address_t *ip_address) { - const char *rc; + int family = hicn_ip_address_get_family (ip_address); switch (family) { case AF_INET: @@ -172,8 +194,8 @@ ip_address_snprintf (char *s, size_t size, const ip_address_t *ip_address, } int -ip_address_to_sockaddr (const ip_address_t *ip_address, struct sockaddr *sa, - int family) +hicn_ip_address_to_sockaddr (const hicn_ip_address_t *ip_address, + struct sockaddr *sa, int family) { struct sockaddr_in6 *tmp6 = (struct sockaddr_in6 *) sa; struct sockaddr_in *tmp4 = (struct sockaddr_in *) sa; @@ -199,64 +221,66 @@ ip_address_to_sockaddr (const ip_address_t *ip_address, struct sockaddr *sa, } int -ip_address_cmp (const ip_address_t *ip1, const ip_address_t *ip2, int family) +hicn_ip_address_cmp (const hicn_ip_address_t *ip1, + const hicn_ip_address_t *ip2) { - switch (family) - { - case AF_INET: - return memcmp (ip1->v4.buffer, ip2->v4.buffer, sizeof (ip1->v4)); - case AF_INET6: - default: - return memcmp (ip1->v6.buffer, ip2->v6.buffer, sizeof (ip1->v6)); - } + /* This works as soon as all members are initialized */ + return memcmp (ip1, ip2, sizeof (hicn_ip_address_t)); +} + +bool +hicn_ip_address_equals (const hicn_ip_address_t *ip1, + const hicn_ip_address_t *ip2) +{ + return hicn_ip_address_cmp (ip1, ip2) == 0; } int -ip_address_empty (const ip_address_t *ip) +hicn_ip_address_empty (const hicn_ip_address_t *ip) { - return (memcmp (ip->v6.buffer, &IP_ADDRESS_EMPTY.v6.buffer, - sizeof (IP_ADDRESS_EMPTY)) == 0); + return (memcmp (ip, &IP_ADDRESS_EMPTY, sizeof (hicn_ip_address_t)) == 0); } /* Prefix */ /* Parse IP Prefixes in presentation format (in bits, separated by a slash) */ int -ip_prefix_pton (const char *ip_address_str, ip_prefix_t *ip_prefix) +hicn_ip_prefix_pton (const char *hicn_ip_address_str, + hicn_ip_prefix_t *hicn_ip_prefix) { int pton_fd; char *p; char *eptr; - char *addr = strdup (ip_address_str); + char *addr = strdup (hicn_ip_address_str); p = strchr (addr, '/'); if (!p) { - ip_prefix->len = ~0; // until we get the ip address family + hicn_ip_prefix->len = ~0; // until we get the ip address family } else { - ip_prefix->len = (u8) strtoul (p + 1, &eptr, 10); + hicn_ip_prefix->len = (u8) strtoul (p + 1, &eptr, 10); *p = 0; } - ip_prefix->family = ip_address_get_family (addr); + hicn_ip_prefix->family = hicn_ip_address_str_get_family (addr); - switch (ip_prefix->family) + switch (hicn_ip_prefix->family) { case AF_INET6: - if (ip_prefix->len == (u8) ~0) - ip_prefix->len = IPV6_ADDR_LEN_BITS; - if (ip_prefix->len > IPV6_ADDR_LEN_BITS) + if (hicn_ip_prefix->len == (u8) ~0) + hicn_ip_prefix->len = IPV6_ADDR_LEN_BITS; + if (hicn_ip_prefix->len > IPV6_ADDR_LEN_BITS) goto ERR; - pton_fd = inet_pton (AF_INET6, addr, &ip_prefix->address.v6.buffer); + pton_fd = inet_pton (AF_INET6, addr, &hicn_ip_prefix->address.v6.buffer); break; case AF_INET: - if (ip_prefix->len == (u8) ~0) - ip_prefix->len = IPV4_ADDR_LEN_BITS; - if (ip_prefix->len > IPV4_ADDR_LEN_BITS) + if (hicn_ip_prefix->len == (u8) ~0) + hicn_ip_prefix->len = IPV4_ADDR_LEN_BITS; + if (hicn_ip_prefix->len > IPV4_ADDR_LEN_BITS) goto ERR; - pton_fd = inet_pton (AF_INET, addr, &ip_prefix->address.v4.buffer); + pton_fd = inet_pton (AF_INET, addr, &hicn_ip_prefix->address.v4.buffer); break; default: goto ERR; @@ -275,18 +299,19 @@ ERR: } int -ip_prefix_ntop_short (const ip_prefix_t *ip_prefix, char *dst, size_t size) +hicn_ip_prefix_ntop_short (const hicn_ip_prefix_t *hicn_ip_prefix, char *dst, + size_t size) { char ip_s[MAXSZ_IP_ADDRESS]; const char *s; - switch (ip_prefix->family) + switch (hicn_ip_prefix->family) { case AF_INET: - s = inet_ntop (AF_INET, ip_prefix->address.v4.buffer, ip_s, + s = inet_ntop (AF_INET, hicn_ip_prefix->address.v4.buffer, ip_s, MAXSZ_IP_ADDRESS); break; case AF_INET6: - s = inet_ntop (AF_INET6, ip_prefix->address.v6.buffer, ip_s, + s = inet_ntop (AF_INET6, hicn_ip_prefix->address.v6.buffer, ip_s, MAXSZ_IP_ADDRESS); break; default: @@ -301,18 +326,19 @@ ip_prefix_ntop_short (const ip_prefix_t *ip_prefix, char *dst, size_t size) } int -ip_prefix_ntop (const ip_prefix_t *ip_prefix, char *dst, size_t size) +hicn_ip_prefix_ntop (const hicn_ip_prefix_t *hicn_ip_prefix, char *dst, + size_t size) { char ip_s[MAXSZ_IP_ADDRESS]; const char *s; - switch (ip_prefix->family) + switch (hicn_ip_prefix->family) { case AF_INET: - s = inet_ntop (AF_INET, ip_prefix->address.v4.buffer, ip_s, + s = inet_ntop (AF_INET, hicn_ip_prefix->address.v4.buffer, ip_s, MAXSZ_IP_ADDRESS); break; case AF_INET6: - s = inet_ntop (AF_INET6, ip_prefix->address.v6.buffer, ip_s, + s = inet_ntop (AF_INET6, hicn_ip_prefix->address.v6.buffer, ip_s, MAXSZ_IP_ADDRESS); break; default: @@ -320,26 +346,26 @@ ip_prefix_ntop (const ip_prefix_t *ip_prefix, char *dst, size_t size) } if (!s) return -1; - int rc = snprintf (dst, size, "%s/%d", ip_s, ip_prefix->len); + int rc = snprintf (dst, size, "%s/%d", ip_s, hicn_ip_prefix->len); if (rc >= size) return (int) size; return rc; } int -ip_prefix_snprintf (char *s, size_t size, const ip_prefix_t *prefix) +hicn_ip_prefix_snprintf (char *s, size_t size, const hicn_ip_prefix_t *prefix) { - return ip_prefix_ntop (prefix, s, size); + return hicn_ip_prefix_ntop (prefix, s, size); } int -ip_prefix_len (const ip_prefix_t *prefix) +hicn_ip_prefix_len (const hicn_ip_prefix_t *prefix) { - return prefix->len; // ip_address_len(&prefix->address, prefix->family); + return prefix->len; // hicn_ip_address_len(&prefix->address, prefix->family); } const u8 * -ip_address_get_buffer (const ip_address_t *ip_address, int family) +hicn_ip_address_get_buffer (const hicn_ip_address_t *ip_address, int family) { switch (family) { @@ -353,20 +379,22 @@ ip_address_get_buffer (const ip_address_t *ip_address, int family) } bool -ip_prefix_empty (const ip_prefix_t *prefix) +hicn_ip_prefix_empty (const hicn_ip_prefix_t *prefix) { return prefix->len == 0; } int -ip_prefix_to_sockaddr (const ip_prefix_t *prefix, struct sockaddr *sa) +hicn_ip_prefix_to_sockaddr (const hicn_ip_prefix_t *prefix, + struct sockaddr *sa) { - // XXX assert len == ip_address_len - return ip_address_to_sockaddr (&prefix->address, sa, prefix->family); + // XXX assert len == hicn_ip_address_len + return hicn_ip_address_to_sockaddr (&prefix->address, sa, prefix->family); } int -ip_prefix_cmp (const ip_prefix_t *prefix1, const ip_prefix_t *prefix2) +hicn_ip_prefix_cmp (const hicn_ip_prefix_t *prefix1, + const hicn_ip_prefix_t *prefix2) { if (prefix1->family < prefix2->family) return -1; @@ -378,8 +406,26 @@ ip_prefix_cmp (const ip_prefix_t *prefix1, const ip_prefix_t *prefix2) else if (prefix1->len > prefix2->len) return 1; - return ip_address_cmp (&prefix1->address, &prefix2->address, - prefix1->family); + return hicn_ip_address_cmp (&prefix1->address, &prefix2->address); +} + +uint8_t +hicn_ip_address_get_bit (const hicn_ip_address_t *address, uint8_t pos) +{ + u64 quad = address->v6.as_u64[pos / 64]; + return quad & (0x1 << pos % 64); +} + +bool +hicn_ip_address_match_family (const hicn_ip_address_t *address, int family) +{ + return hicn_ip_address_get_family (address) == family; +} + +uint32_t +hicn_ip_address_get_hash (const hicn_ip_address_t *address) +{ + return hash32 (address, sizeof (address)); } /* URL */ @@ -395,23 +441,27 @@ ip_prefix_cmp (const ip_prefix_t *prefix1, const ip_prefix_t *prefix2) #define MAXSZ_URL MAXSZ_URL_ + NULLTERM int -url_snprintf (char *s, size_t size, int family, const ip_address_t *ip_address, +url_snprintf (char *s, size_t size, const hicn_ip_address_t *ip_address, u16 port) { - char ip_address_s[MAXSZ_IP_ADDRESS]; + char hicn_ip_address_s[MAXSZ_IP_ADDRESS]; int rc; + int family = hicn_ip_address_get_family (ip_address); + /* Other address are currently not supported */ if (!IS_VALID_FAMILY (family)) return -1; + if (!hicn_ip_address_match_family (ip_address, family)) + return -1; rc = - ip_address_snprintf (ip_address_s, MAXSZ_IP_ADDRESS, ip_address, family); + hicn_ip_address_snprintf (hicn_ip_address_s, MAXSZ_IP_ADDRESS, ip_address); if (rc >= MAXSZ_IP_ADDRESS) WARN ("[url_snprintf] Unexpected ip_address truncation"); if (rc < 0) return rc; return snprintf (s, size, "inet%c://%s:%d", (family == AF_INET) ? '4' : '6', - ip_address_s, port); + hicn_ip_address_s, port); } diff --git a/lib/src/util/pool.c b/lib/src/util/pool.c index c6be92ce8..2c1e90b5e 100644 --- a/lib/src/util/pool.c +++ b/lib/src/util/pool.c @@ -28,6 +28,7 @@ #include <stdlib.h> // calloc #include <hicn/util/pool.h> +#include <hicn/util/log.h> #include <stdio.h> // XXX diff --git a/lib/src/util/types.c b/lib/src/util/types.c new file mode 100644 index 000000000..744192593 --- /dev/null +++ b/lib/src/util/types.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <hicn/util/types.h> + +uint32_t +htonf (float f) +{ + uint32_t i; + uint32_t sign = 0; + + if (f < 0) + { + sign = 1; + f = -f; + } + + // i[31] = sign bit + i = sign << 31; + + // i[30 to 16] = int(f)[14 to 0] + i |= (((uint32_t) f) & 0x7fff) << 16; + + // i[15 to 0] = fraction(f) bits [15 to 0] + i |= (uint32_t) ((f - (uint32_t) f) * 65536.0f) & 0xffff; + + return i; +} + +float +ntohf (uint32_t i) +{ + // integer part = i[14 to 0] + float f = (i >> 16) & 0x7fff; + + // fraction part = i[15 to 0] + f += (i & 0xffff) / 65536.0f; + + // sign = i[31] + if ((i >> 31) & 1) + f = -f; + + return f; +} diff --git a/libtransport/includes/hicn/transport/core/connector.h b/libtransport/includes/hicn/transport/core/connector.h index ad0d4f09d..eaf95b2ec 100644 --- a/libtransport/includes/hicn/transport/core/connector.h +++ b/libtransport/includes/hicn/transport/core/connector.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -160,18 +160,25 @@ class Connector : public std::enable_shared_from_this<Connector> { std::size_t size) { utils::MemBuf::Ptr ret; - auto format = Packet::getFormatFromBuffer(buffer, size); + hicn_packet_buffer_t pkbuf; + hicn_packet_set_buffer(&pkbuf, buffer, size, size); + hicn_packet_analyze(&pkbuf); + hicn_packet_type_t type = hicn_packet_get_type(&pkbuf); - if (TRANSPORT_EXPECT_TRUE(format != HF_UNSPEC && !_is_icmp(format))) { - if (Packet::isInterest(buffer)) { + // XXX reuse pkbuf when creating the packet, to avoid reanalyzing it + + switch (type) { + case HICN_PACKET_TYPE_INTEREST: ret = core::PacketManager<>::getInstance() .getPacketFromExistingBuffer<Interest>(buffer, size); - } else { + break; + case HICN_PACKET_TYPE_DATA: ret = core::PacketManager<>::getInstance() .getPacketFromExistingBuffer<ContentObject>(buffer, size); - } - } else { - ret = core::PacketManager<>::getInstance().getMemBuf(buffer, size); + break; + default: + ret = core::PacketManager<>::getInstance().getMemBuf(buffer, size); + break; } return ret; diff --git a/libtransport/includes/hicn/transport/core/content_object.h b/libtransport/includes/hicn/transport/core/content_object.h index f8d95846e..3d6d98c48 100644 --- a/libtransport/includes/hicn/transport/core/content_object.h +++ b/libtransport/includes/hicn/transport/core/content_object.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -29,22 +29,21 @@ namespace core { class ContentObject : public Packet { public: using Ptr = std::shared_ptr<ContentObject>; - using HICNContentObject = hicn_header_t; + using HICNContentObject = u8; ContentObject(Packet::Format format, std::size_t additional_header_size = 0); ContentObject(const Name &name, Packet::Format format, std::size_t additional_header_size = 0); - ContentObject(const Name &name, hicn_format_t format, + ContentObject(const Name &name, hicn_packet_format_t format, std::size_t additional_header_size, const uint8_t *payload, std::size_t payload_size); template <typename... Args> ContentObject(CopyBufferOp op, Args &&...args) : Packet(op, std::forward<Args>(args)...) { - if (hicn_data_get_name(format_, packet_start_, - &name_.getStructReference()) < 0) { + if (hicn_data_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } @@ -52,21 +51,15 @@ class ContentObject : public Packet { template <typename... Args> ContentObject(WrapBufferOp op, Args &&...args) : Packet(op, std::forward<Args>(args)...) { - if (hicn_data_get_name(format_, packet_start_, - &name_.getStructReference()) < 0) { + if (hicn_data_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } template <typename... Args> ContentObject(CreateOp op, Args &&...args) - : Packet(op, std::forward<Args>(args)...) { - if (hicn_packet_set_data(format_, packet_start_) < 0) { - throw errors::MalformedPacketException(); - } - - if (hicn_data_get_name(format_, packet_start_, - &name_.getStructReference()) < 0) { + : Packet(op, HICN_PACKET_TYPE_DATA, std::forward<Args>(args)...) { + if (hicn_data_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } @@ -85,13 +78,13 @@ class ContentObject : public Packet { void setName(const Name &name) override; - uint32_t getPathLabel() const; + hicn_path_label_t getPathLabel() const; - ContentObject &setPathLabel(uint32_t path_label); + ContentObject &setPathLabel(hicn_path_label_t path_label); - void setLocator(const ip_address_t &ip_address) override; + void setLocator(const hicn_ip_address_t &ip_address) override; - ip_address_t getLocator() const override; + hicn_ip_address_t getLocator() const override; void setLifetime(uint32_t lifetime) override; diff --git a/libtransport/includes/hicn/transport/core/interest.h b/libtransport/includes/hicn/transport/core/interest.h index 9e6cdccb9..716ac6b0a 100644 --- a/libtransport/includes/hicn/transport/core/interest.h +++ b/libtransport/includes/hicn/transport/core/interest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -21,6 +21,10 @@ #include <set> +extern "C" { +#include <hicn/interest_manifest.h> +} + namespace transport { namespace core { @@ -42,8 +46,7 @@ class Interest template <typename... Args> Interest(CopyBufferOp op, Args &&...args) : Packet(op, std::forward<Args>(args)...) { - if (hicn_interest_get_name(format_, packet_start_, - &name_.getStructReference()) < 0) { + if (hicn_interest_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } @@ -51,19 +54,14 @@ class Interest template <typename... Args> Interest(WrapBufferOp op, Args &&...args) : Packet(op, std::forward<Args>(args)...) { - if (hicn_interest_get_name(format_, packet_start_, - &name_.getStructReference()) < 0) { + if (hicn_interest_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } template <typename... Args> Interest(CreateOp op, Args &&...args) - : Packet(op, std::forward<Args>(args)...) { - if (hicn_packet_set_interest(format_, packet_start_) < 0) { - throw errors::MalformedPacketException(); - } - } + : Packet(op, HICN_PACKET_TYPE_INTEREST, std::forward<Args>(args)...) {} /* Move constructor */ Interest(Interest &&other_interest); @@ -82,9 +80,9 @@ class Interest void setName(const Name &name) override; - void setLocator(const ip_address_t &ip_address) override; + void setLocator(const hicn_ip_address_t &ip_address) override; - ip_address_t getLocator() const override; + hicn_ip_address_t getLocator() const override; void setLifetime(uint32_t lifetime) override; @@ -94,13 +92,15 @@ class Interest void appendSuffix(std::uint32_t suffix); + void decodeSuffixes(); + void encodeSuffixes(); uint32_t *firstSuffix(); uint32_t numberOfSuffixes(); - uint32_t *getRequestBitmap(); + hicn_uword *getRequestBitmap(); void setRequestBitmap(const uint32_t *request_bitmap); diff --git a/libtransport/includes/hicn/transport/core/io_module.h b/libtransport/includes/hicn/transport/core/io_module.h index 31da0b882..ce6f3a629 100644 --- a/libtransport/includes/hicn/transport/core/io_module.h +++ b/libtransport/includes/hicn/transport/core/io_module.h @@ -110,8 +110,8 @@ class IoModule : utils::NonCopyable { const std::string &getOutputInterface() { return output_interface_; } protected: - ip_address_t inet_address_; - ip_address_t inet6_address_; + hicn_ip_address_t inet_address_; + hicn_ip_address_t inet6_address_; uint16_t mtu_; std::string output_interface_; uint32_t content_store_reserved_; diff --git a/libtransport/includes/hicn/transport/core/name.h b/libtransport/includes/hicn/transport/core/name.h index cf6d3097c..90b665c15 100644 --- a/libtransport/includes/hicn/transport/core/name.h +++ b/libtransport/includes/hicn/transport/core/name.h @@ -96,7 +96,7 @@ class Name { Name &setSuffix(uint32_t seq_number); - ip_prefix_t toIpAddress() const; + hicn_ip_prefix_t toIpAddress() const; void copyPrefixToDestination(uint8_t *destination) const; diff --git a/libtransport/includes/hicn/transport/core/packet.h b/libtransport/includes/hicn/transport/core/packet.h index c1671d439..9277a52c2 100644 --- a/libtransport/includes/hicn/transport/core/packet.h +++ b/libtransport/includes/hicn/transport/core/packet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -26,6 +26,13 @@ #include <hicn/transport/utils/membuf.h> #include <hicn/transport/utils/object_pool.h> +extern "C" { +#ifndef _WIN32 +TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat") +#endif +#include <hicn/packet.h> +} + namespace transport { namespace auth { @@ -52,7 +59,8 @@ class Packet : public utils::MemBuf, public: using Ptr = std::shared_ptr<Packet>; using MemBufPtr = std::shared_ptr<utils::MemBuf>; - using Format = hicn_format_t; + using Format = hicn_packet_format_t; + using Type = hicn_packet_type_t; static constexpr size_t default_mtu = 1500; @@ -61,14 +69,15 @@ class Packet : public utils::MemBuf, * the eventual payload will be added by prepending the payload buffer * to the buffer chain whose the fist buffer is the header itself. */ - Packet(Format format, std::size_t additional_header_size = 0); + Packet(Type type, Format format, std::size_t additional_header_size = 0); /* Copy buffer */ Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size); /* Wrap buffer */ Packet(WrapBufferOp, uint8_t *buffer, std::size_t length, std::size_t size); /* Create new using pre-allocated buffer */ - Packet(CreateOp, uint8_t *buffer, std::size_t length, std::size_t size, - Format format, std::size_t additional_header_size = 0); + Packet(CreateOp, Type type, uint8_t *buffer, std::size_t length, + std::size_t size, Format format, + std::size_t additional_header_size = 0); Packet(MemBuf &&buffer); Packet(Packet &&other); @@ -86,7 +95,15 @@ class Packet : public utils::MemBuf, // Format Format getFormat() const; - void setFormat(Packet::Format format, std::size_t additional_header_size = 0); + void setFormat(Packet::Format format); + + void initialize(std::size_t additional_header_size = 0); + void analyze(); + + hicn_packet_type_t getType() const; + void setType(Packet::Type type); + + void setBuffer(); // Name virtual const Name &getName() const = 0; @@ -98,8 +115,8 @@ class Packet : public utils::MemBuf, virtual uint32_t getLifetime() const = 0; // Locator - virtual void setLocator(const ip_address_t &locator) = 0; - virtual ip_address_t getLocator() const = 0; + virtual void setLocator(const hicn_ip_address_t &locator) = 0; + virtual hicn_ip_address_t getLocator() const = 0; // Payload type PayloadType getPayloadType() const; @@ -117,31 +134,18 @@ class Packet : public utils::MemBuf, // Digest auth::CryptoHash computeDigest(auth::CryptoHashType algorithm) const; + bool isInterest(); + // Reset packet void reset(); // Utils - bool isInterest(); Packet &updateLength(std::size_t length = 0); void dump() const; // TCP methods void setChecksum(); bool checkIntegrity() const; - Packet &setSyn(); - Packet &resetSyn(); - bool testSyn() const; - Packet &setAck(); - Packet &resetAck(); - bool testAck() const; - Packet &setRst(); - Packet &resetRst(); - bool testRst() const; - Packet &setFin(); - Packet &resetFin(); - bool testFin() const; - Packet &resetFlags(); - std::string printFlags() const; Packet &setSrcPort(uint16_t srcPort); Packet &setDstPort(uint16_t dstPort); uint16_t getSrcPort() const; @@ -164,17 +168,18 @@ class Packet : public utils::MemBuf, void setKeyId(const auth::KeyId &key_id); void setValidationAlgorithm(const auth::CryptoSuite &algo); + void saveHeader(u8 *header, size_t *header_len); + void loadHeader(u8 *header, size_t header_len); + // Static methods static Format toAHFormat(const Format &format); static Format getFormatFromBuffer(const uint8_t *buffer, std::size_t length); static std::size_t getHeaderSizeFromFormat(Format format, std::size_t signature_size = 0); - static std::size_t getHeaderSizeFromBuffer(Format format, - const uint8_t *buffer); - static std::size_t getPayloadSizeFromBuffer(Format format, - const uint8_t *buffer); - static bool isInterest(const uint8_t *buffer, - Format format = Format::HF_UNSPEC); + static std::size_t getHeaderSizeFromBuffer(const uint8_t *buffer, + size_t length); + static std::size_t getPayloadSizeFromBuffer(const uint8_t *buffer, + size_t length); static void dump(uint8_t *buffer, std::size_t length); private: @@ -182,9 +187,7 @@ class Packet : public utils::MemBuf, void prependPayload(const uint8_t **buffer, std::size_t *size); protected: - hicn_header_t *packet_start_; - std::size_t header_offset_; - mutable Format format_; + hicn_packet_buffer_t pkbuf_; Name name_; mutable PayloadType payload_type_; static const core::Name base_name; diff --git a/libtransport/includes/hicn/transport/core/payload_type.h b/libtransport/includes/hicn/transport/core/payload_type.h index 3a682e177..a528500ad 100644 --- a/libtransport/includes/hicn/transport/core/payload_type.h +++ b/libtransport/includes/hicn/transport/core/payload_type.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -15,6 +15,15 @@ #pragma once +#include <hicn/transport/portability/portability.h> + +extern "C" { +#ifndef _WIN32 +TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat") +#endif +#include <hicn/base.h> +}; + namespace transport { namespace core { @@ -27,4 +36,4 @@ enum class PayloadType : uint16_t { } // end namespace core -} // end namespace transport
\ No newline at end of file +} // end namespace transport diff --git a/libtransport/includes/hicn/transport/core/prefix.h b/libtransport/includes/hicn/transport/core/prefix.h index 778491a31..791fbc770 100644 --- a/libtransport/includes/hicn/transport/core/prefix.h +++ b/libtransport/includes/hicn/transport/core/prefix.h @@ -49,7 +49,7 @@ class Prefix { int getAddressFamily() const; - bool contains(const ip_address_t &content_name) const; + bool contains(const hicn_ip_address_t &content_name) const; bool contains(const core::Name &content_name) const; @@ -62,7 +62,7 @@ class Prefix { Name makeRandomName() const; Name makeNameWithIndex(std::uint64_t index) const; - const ip_prefix_t &toIpPrefixStruct() const; + const hicn_ip_prefix_t &toIpPrefixStruct() const; private: static bool checkPrefixLengthAndAddressFamily(uint16_t prefix_length, @@ -72,7 +72,7 @@ class Prefix { int family); private: - ip_prefix_t ip_prefix_; + hicn_ip_prefix_t hicn_ip_prefix_; }; } // end namespace core diff --git a/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h b/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h index da8eafcd9..11edae193 100644 --- a/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h +++ b/libtransport/includes/hicn/transport/interfaces/socket_options_default_values.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -15,10 +15,14 @@ #pragma once +#include <hicn/transport/portability/portability.h> + extern "C" { +#ifndef _WIN32 +TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat") +#endif #include <hicn/base.h> -#include <hicn/compat.h> -} +}; #include <chrono> #include <cstdint> @@ -31,21 +35,20 @@ namespace default_values { // Packet format // #define NEW_PACKET_FORMAT -static constexpr hicn_format_t packet_format = +static constexpr hicn_packet_format_t packet_format = #ifdef NEW_PACKET_FORMAT - HF_INET6_UDP; + HICN_PACKET_FORMAT_NEW; #else - HF_INET6_TCP; + HICN_PACKET_FORMAT_IPV6_TCP; #endif // Parameters -static constexpr uint32_t interest_lifetime = 1001; // milliseconds -static constexpr uint32_t never_expire_time = HICN_MAX_LIFETIME; -static constexpr uint32_t content_object_expiry_time = +static const uint32_t interest_lifetime = 1001; // milliseconds +static const uint32_t never_expire_time = HICN_MAX_LIFETIME; +static const uint32_t content_object_expiry_time = never_expire_time; // milliseconds -> 50 seconds -static constexpr uint32_t content_object_packet_size = - 1500; // The ethernet MTU -static constexpr uint32_t producer_socket_output_buffer_size = +static const uint32_t content_object_packet_size = 1500; // The ethernet MTU +static const uint32_t producer_socket_output_buffer_size = 150000; // Content Object static constexpr uint32_t log_2_default_buffer_size = 12; static constexpr uint32_t signature_size = 260; // bytes @@ -58,26 +61,26 @@ static constexpr uint32_t manifest_factor_relevant = 100; static constexpr uint32_t manifest_factor_alert = 20; // RAAQM -static constexpr int sample_number = 30; -static constexpr double gamma_value = 1; -static constexpr double beta_value = 0.8; -static constexpr double drop_factor = 0.2; -static constexpr double minimum_drop_probability = 0.00001; -static constexpr int path_id = 0; -static constexpr double rate_alpha = 0.8; +static const int sample_number = 30; +static const double gamma_value = 1; +static const double beta_value = 0.8; +static const double drop_factor = 0.2; +static const double minimum_drop_probability = 0.00001; +static const int path_id = 0; +static const double rate_alpha = 0.8; // Rate estimation -static constexpr uint32_t batch = 50; -static constexpr uint32_t kv = 20; -static constexpr double alpha = 0.8; -static constexpr uint32_t rate_choice = 0; +static const uint32_t batch = 50; +static const uint32_t kv = 20; +static const double alpha = 0.8; +static const uint32_t rate_choice = 0; // maximum allowed values -static constexpr uint32_t transport_protocol_min_retransmissions = 0; -static constexpr uint32_t transport_protocol_max_retransmissions = 128; -static constexpr uint32_t max_content_object_size = 8096; -static constexpr uint32_t min_window_size = 1; // Interests -static constexpr uint32_t max_window_size = 256 * 2; // Interests +static const uint32_t transport_protocol_min_retransmissions = 0; +static const uint32_t transport_protocol_max_retransmissions = 128; +static const uint32_t max_content_object_size = 8096; +static const uint32_t min_window_size = 1; // Interests +static const uint32_t max_window_size = 256 * 2; // Interests } // namespace default_values diff --git a/libtransport/includes/hicn/transport/utils/membuf.h b/libtransport/includes/hicn/transport/utils/membuf.h index 6f92c2208..4b442dda3 100644 --- a/libtransport/includes/hicn/transport/utils/membuf.h +++ b/libtransport/includes/hicn/transport/utils/membuf.h @@ -30,6 +30,7 @@ #include <cinttypes> #include <cstddef> #include <cstring> +#include <iostream> #include <iterator> #include <limits> #include <memory> diff --git a/libtransport/src/auth/signer.cc b/libtransport/src/auth/signer.cc index f13df53eb..500732ba1 100644 --- a/libtransport/src/auth/signer.cc +++ b/libtransport/src/auth/signer.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -36,8 +36,6 @@ Signer::~Signer() {} void Signer::signPacket(PacketPtr packet) { DCHECK(key_ != nullptr); - core::Packet::Format format = packet->getFormat(); - if (!packet->hasAH()) { throw errors::MalformedAHPacketException(); } @@ -48,8 +46,9 @@ void Signer::signPacket(PacketPtr packet) { packet->updateLength(); // update IP payload length // Copy IP+TCP / ICMP header before zeroing them - hicn_header_t header_copy; - hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false); + u8 header_copy[HICN_HDRLEN_MAX]; + size_t header_len; + packet->saveHeader(header_copy, &header_len); // Copy bitmap from interest manifest uint32_t request_bitmap[BITMAP_SIZE] = {0}; @@ -78,7 +77,7 @@ void Signer::signPacket(PacketPtr packet) { packet->setSignatureSize(signature_len_); // Restore header - hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false); + packet->loadHeader(header_copy, header_len); // Restore bitmap in interest manifest if (packet->isInterest()) { diff --git a/libtransport/src/auth/verifier.cc b/libtransport/src/auth/verifier.cc index e257582f6..f930383e6 100644 --- a/libtransport/src/auth/verifier.cc +++ b/libtransport/src/auth/verifier.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -38,8 +38,6 @@ Verifier::Verifier() Verifier::~Verifier() {} bool Verifier::verifyPacket(PacketPtr packet) { - core::Packet::Format format = packet->getFormat(); - if (!packet->hasAH()) { throw errors::MalformedAHPacketException(); } @@ -49,8 +47,9 @@ bool Verifier::verifyPacket(PacketPtr packet) { CryptoHashType hash_type = getHashType(suite); // Copy IP+TCP / ICMP header before zeroing them - hicn_header_t header_copy; - hicn_packet_copy_header(format, packet->packet_start_, &header_copy, false); + u8 header_copy[HICN_HDRLEN_MAX]; + size_t header_len; + packet->saveHeader(header_copy, &header_len); // Copy bitmap from interest manifest uint32_t request_bitmap[BITMAP_SIZE] = {0}; @@ -74,7 +73,7 @@ bool Verifier::verifyPacket(PacketPtr packet) { signature_raw, hash_type); // Restore header - hicn_packet_copy_header(format, &header_copy, packet->packet_start_, false); + packet->loadHeader(header_copy, header_len); packet->setSignature(signature_raw); packet->setSignatureSize(signature_raw->length()); diff --git a/libtransport/src/core/content_object.cc b/libtransport/src/core/content_object.cc index e66b2a6cd..7ed6c57ab 100644 --- a/libtransport/src/core/content_object.cc +++ b/libtransport/src/core/content_object.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -35,25 +35,18 @@ namespace core { ContentObject::ContentObject(const Name &name, Packet::Format format, std::size_t additional_header_size) - : Packet(format, additional_header_size) { - if (TRANSPORT_EXPECT_FALSE(hicn_packet_set_data(format_, packet_start_) < - 0)) { - throw errors::MalformedPacketException(); - } - - if (TRANSPORT_EXPECT_FALSE( - hicn_data_set_name(format, packet_start_, &name.name_) < 0)) { + : Packet(HICN_PACKET_TYPE_DATA, format, additional_header_size) { + if (TRANSPORT_EXPECT_FALSE(hicn_data_set_name(&pkbuf_, &name.name_) < 0)) { throw errors::RuntimeException("Error filling the packet name."); } - if (TRANSPORT_EXPECT_FALSE(hicn_data_get_name(format_, packet_start_, - &name_.getStructReference()) < - 0)) { + if (TRANSPORT_EXPECT_FALSE( + hicn_data_get_name(&pkbuf_, &name_.getStructReference()) < 0)) { throw errors::MalformedPacketException(); } } -ContentObject::ContentObject(hicn_format_t format, +ContentObject::ContentObject(hicn_packet_format_t format, std::size_t additional_header_size) : ContentObject( #ifdef __ANDROID__ @@ -62,13 +55,9 @@ ContentObject::ContentObject(hicn_format_t format, Packet::base_name, #endif format, additional_header_size) { - if (TRANSPORT_EXPECT_FALSE(hicn_packet_set_data(format_, packet_start_) < - 0)) { - throw errors::MalformedPacketException(); - } } -ContentObject::ContentObject(const Name &name, hicn_format_t format, +ContentObject::ContentObject(const Name &name, hicn_packet_format_t format, std::size_t additional_header_size, const uint8_t *payload, std::size_t size) : ContentObject(name, format, additional_header_size) { @@ -91,9 +80,8 @@ ContentObject::~ContentObject() {} const Name &ContentObject::getName() const { if (!name_) { - if (hicn_data_get_name(format_, packet_start_, - (hicn_name_t *)&name_.getConstStructReference()) < - 0) { + if (hicn_data_get_name( + &pkbuf_, (hicn_name_t *)&name_.getConstStructReference()) < 0) { throw errors::MalformedPacketException(); } } @@ -104,31 +92,27 @@ const Name &ContentObject::getName() const { Name &ContentObject::getWritableName() { return const_cast<Name &>(getName()); } void ContentObject::setName(const Name &name) { - if (hicn_data_set_name(format_, packet_start_, - &name.getConstStructReference()) < 0) { + if (hicn_data_set_name(&pkbuf_, &name.getConstStructReference()) < 0) { throw errors::RuntimeException("Error setting content object name."); } - if (hicn_data_get_name(format_, packet_start_, &name_.getStructReference()) < - 0) { + if (hicn_data_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } -uint32_t ContentObject::getPathLabel() const { - uint32_t path_label; - if (hicn_data_get_path_label(packet_start_, &path_label) < 0) { +hicn_path_label_t ContentObject::getPathLabel() const { + hicn_path_label_t path_label; + if (hicn_data_get_path_label(&pkbuf_, &path_label) < 0) { throw errors::RuntimeException( "Error retrieving the path label from content object"); } - return portability::net_to_host(path_label); + return path_label; } -ContentObject &ContentObject::setPathLabel(uint32_t path_label) { - path_label = portability::host_to_net(path_label); - if (hicn_data_set_path_label((hicn_header_t *)packet_start_, path_label) < - 0) { +ContentObject &ContentObject::setPathLabel(hicn_path_label_t path_label) { + if (hicn_data_set_path_label(&pkbuf_, path_label) < 0) { throw errors::RuntimeException( "Error setting the path label from content object"); } @@ -136,18 +120,18 @@ ContentObject &ContentObject::setPathLabel(uint32_t path_label) { return *this; } -void ContentObject::setLocator(const ip_address_t &ip_address) { - if (hicn_data_set_locator(format_, packet_start_, &ip_address) < 0) { +void ContentObject::setLocator(const hicn_ip_address_t &ip_address) { + if (hicn_data_set_locator(&pkbuf_, &ip_address) < 0) { throw errors::RuntimeException("Error setting content object locator"); } return; } -ip_address_t ContentObject::getLocator() const { - ip_address_t ip; +hicn_ip_address_t ContentObject::getLocator() const { + hicn_ip_address_t ip; - if (hicn_data_get_locator(format_, packet_start_, &ip) < 0) { + if (hicn_data_get_locator(&pkbuf_, &ip) < 0) { throw errors::RuntimeException("Error getting content object locator."); } @@ -155,7 +139,7 @@ ip_address_t ContentObject::getLocator() const { } void ContentObject::setLifetime(uint32_t lifetime) { - if (hicn_data_set_expiry_time(packet_start_, lifetime) < 0) { + if (hicn_data_set_expiry_time(&pkbuf_, lifetime) < 0) { throw errors::MalformedPacketException(); } } @@ -163,7 +147,7 @@ void ContentObject::setLifetime(uint32_t lifetime) { uint32_t ContentObject::getLifetime() const { uint32_t lifetime = 0; - if (hicn_data_get_expiry_time(packet_start_, &lifetime) < 0) { + if (hicn_data_get_expiry_time(&pkbuf_, &lifetime) < 0) { throw errors::MalformedPacketException(); } @@ -171,8 +155,7 @@ uint32_t ContentObject::getLifetime() const { } void ContentObject::resetForHash() { - if (hicn_data_reset_for_hash( - format_, reinterpret_cast<hicn_header_t *>(packet_start_)) < 0) { + if (hicn_data_reset_for_hash(&pkbuf_) < 0) { throw errors::RuntimeException( "Error resetting content object fields for hash computation."); } @@ -180,7 +163,7 @@ void ContentObject::resetForHash() { bool ContentObject::isLast() const { int is_last = 0; - if (hicn_data_is_last(format_, packet_start_, &is_last) < 0) { + if (hicn_data_is_last(&pkbuf_, &is_last) < 0) { throw errors::RuntimeException( "Impossible to get last data flag from packet header."); } @@ -189,7 +172,7 @@ bool ContentObject::isLast() const { } void ContentObject::setLast() { - if (hicn_data_set_last(format_, packet_start_) < 0) { + if (hicn_data_set_last(&pkbuf_) < 0) { throw errors::RuntimeException( "Impossible to set last data flag to packet header."); } diff --git a/libtransport/src/core/interest.cc b/libtransport/src/core/interest.cc index 8b9dcf256..777374b09 100644 --- a/libtransport/src/core/interest.cc +++ b/libtransport/src/core/interest.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -23,6 +23,7 @@ TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat") #endif #include <hicn/base.h> #include <hicn/hicn.h> +#include <hicn/interest_manifest.h> } #include <cstring> @@ -34,23 +35,19 @@ namespace core { Interest::Interest(const Name &interest_name, Packet::Format format, std::size_t additional_header_size) - : Packet(format, additional_header_size) { - if (hicn_packet_set_interest(format_, packet_start_) < 0) { - throw errors::MalformedPacketException(); - } - - if (hicn_interest_set_name(format_, packet_start_, + : Packet(HICN_PACKET_TYPE_INTEREST, format, additional_header_size) { + if (hicn_interest_set_name(&pkbuf_, &interest_name.getConstStructReference()) < 0) { throw errors::MalformedPacketException(); } - if (hicn_interest_get_name(format_, packet_start_, - &name_.getStructReference()) < 0) { + if (hicn_interest_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } -Interest::Interest(hicn_format_t format, std::size_t additional_header_size) +Interest::Interest(hicn_packet_format_t format, + std::size_t additional_header_size) : Interest( #ifdef __ANDROID__ Name("0::0|0"), @@ -58,14 +55,10 @@ Interest::Interest(hicn_format_t format, std::size_t additional_header_size) base_name, #endif format, additional_header_size) { - if (hicn_packet_set_interest(format_, packet_start_) < 0) { - throw errors::MalformedPacketException(); - } } Interest::Interest(MemBuf &&buffer) : Packet(std::move(buffer)) { - if (hicn_interest_get_name(format_, packet_start_, - &name_.getStructReference()) < 0) { + if (hicn_interest_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } @@ -88,8 +81,7 @@ Interest::~Interest() {} const Name &Interest::getName() const { if (!name_) { if (hicn_interest_get_name( - format_, packet_start_, - (hicn_name_t *)&name_.getConstStructReference()) < 0) { + &pkbuf_, (hicn_name_t *)&name_.getConstStructReference()) < 0) { throw errors::MalformedPacketException(); } } @@ -100,29 +92,27 @@ const Name &Interest::getName() const { Name &Interest::getWritableName() { return const_cast<Name &>(getName()); } void Interest::setName(const Name &name) { - if (hicn_interest_set_name(format_, packet_start_, - &name.getConstStructReference()) < 0) { + if (hicn_interest_set_name(&pkbuf_, &name.getConstStructReference()) < 0) { throw errors::RuntimeException("Error setting interest name."); } - if (hicn_interest_get_name(format_, packet_start_, - &name_.getStructReference()) < 0) { + if (hicn_interest_get_name(&pkbuf_, &name_.getStructReference()) < 0) { throw errors::MalformedPacketException(); } } -void Interest::setLocator(const ip_address_t &ip_address) { - if (hicn_interest_set_locator(format_, packet_start_, &ip_address) < 0) { +void Interest::setLocator(const hicn_ip_address_t &ip_address) { + if (hicn_interest_set_locator(&pkbuf_, &ip_address) < 0) { throw errors::RuntimeException("Error setting interest locator."); } return; } -ip_address_t Interest::getLocator() const { - ip_address_t ip; +hicn_ip_address_t Interest::getLocator() const { + hicn_ip_address_t ip; - if (hicn_interest_get_locator(format_, packet_start_, &ip) < 0) { + if (hicn_interest_get_locator(&pkbuf_, &ip) < 0) { throw errors::RuntimeException("Error getting interest locator."); } @@ -130,7 +120,7 @@ ip_address_t Interest::getLocator() const { } void Interest::setLifetime(uint32_t lifetime) { - if (hicn_interest_set_lifetime(packet_start_, lifetime) < 0) { + if (hicn_interest_set_lifetime(&pkbuf_, lifetime) < 0) { throw errors::MalformedPacketException(); } } @@ -138,7 +128,7 @@ void Interest::setLifetime(uint32_t lifetime) { uint32_t Interest::getLifetime() const { uint32_t lifetime = 0; - if (hicn_interest_get_lifetime(packet_start_, &lifetime) < 0) { + if (hicn_interest_get_lifetime(&pkbuf_, &lifetime) < 0) { throw errors::MalformedPacketException(); } @@ -146,8 +136,7 @@ uint32_t Interest::getLifetime() const { } void Interest::resetForHash() { - if (hicn_interest_reset_for_hash( - format_, reinterpret_cast<hicn_header_t *>(packet_start_)) < 0) { + if (hicn_interest_reset_for_hash(&pkbuf_) < 0) { throw errors::RuntimeException( "Error resetting interest fields for hash computation."); } @@ -182,7 +171,7 @@ void Interest::encodeSuffixes() { (interest_manifest_header_t *)(writableData() + headerSize()); int_manifest_header->n_suffixes = (uint32_t)suffix_set_.size(); memset(int_manifest_header->request_bitmap, 0xFFFFFFFF, - BITMAP_SIZE * sizeof(u32)); + BITMAP_SIZE * sizeof(hicn_uword)); uint32_t *suffix = (uint32_t *)(int_manifest_header + 1); for (auto it = suffix_set_.begin(); it != suffix_set_.end(); it++, suffix++) { @@ -192,10 +181,21 @@ void Interest::encodeSuffixes() { std::size_t additional_length = sizeof(interest_manifest_header_t) + int_manifest_header->n_suffixes * sizeof(uint32_t); + + // Serialize interest manifest + interest_manifest_serialize(int_manifest_header); + append(additional_length); updateLength(); } +void Interest::decodeSuffixes() { + if (!hasManifest()) return; + + auto header = (interest_manifest_header_t *)(writableData() + headerSize()); + interest_manifest_deserialize(header); +} + uint32_t *Interest::firstSuffix() { if (!hasManifest()) { return nullptr; @@ -217,7 +217,7 @@ uint32_t Interest::numberOfSuffixes() { return header->n_suffixes; } -uint32_t *Interest::getRequestBitmap() { +hicn_uword *Interest::getRequestBitmap() { if (!hasManifest()) return nullptr; auto header = (interest_manifest_header_t *)(writableData() + headerSize()); @@ -234,24 +234,8 @@ void Interest::setRequestBitmap(const uint32_t *request_bitmap) { bool Interest::isValid() { if (!hasManifest()) return true; - auto header = (interest_manifest_header_t *)(writableData() + headerSize()); - - if (header->n_suffixes == 0 || - header->n_suffixes > MAX_SUFFIXES_IN_MANIFEST) { - std::cerr << "Manifest with invalid number of suffixes " - << header->n_suffixes; - return false; - } - - uint32_t empty_bitmap[BITMAP_SIZE]; - memset(empty_bitmap, 0, sizeof(empty_bitmap)); - if (memcmp(empty_bitmap, header->request_bitmap, sizeof(empty_bitmap)) == 0) { - std::cerr << "Manifest with empty bitmap"; - return false; - } - - return true; + return interest_manifest_is_valid(header, payloadSize()); } } // end namespace core diff --git a/libtransport/src/core/io_module.cc b/libtransport/src/core/io_module.cc index 0f92cc47c..0fdb735c4 100644 --- a/libtransport/src/core/io_module.cc +++ b/libtransport/src/core/io_module.cc @@ -23,7 +23,7 @@ #include <iostream> #ifdef ANDROID -#include <io_modules/hicn-light-ng/hicn_forwarder_module.h> +#include <io_modules/hicn-light/hicn_forwarder_module.h> #elif _WIN32 #include <hicn/util/windows/windows_utils.h> #endif @@ -49,7 +49,7 @@ IoModule *IoModule::load(const char *module_name) { creator = (IoModule * (*)(void)) dlsym(handle, "create_module"); if (!creator) { if ((error = dlerror()) != nullptr) { - LOG(ERROR) << error; + LOG(ERROR) << error << ": " << module_name; } return nullptr; diff --git a/libtransport/src/core/manifest_format_fixed.cc b/libtransport/src/core/manifest_format_fixed.cc index 668169642..bda666c0c 100644 --- a/libtransport/src/core/manifest_format_fixed.cc +++ b/libtransport/src/core/manifest_format_fixed.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -75,6 +75,7 @@ FixedManifestEncoder &FixedManifestEncoder::encodeImpl() { manifest_entry_meta_->nb_entries = manifest_entries_.size(); packet_->append(manifestHeaderSizeImpl()); + packet_->updateLength(); auto params = reinterpret_cast<uint8_t *>(manifest_entry_meta_ + 1); @@ -97,6 +98,7 @@ FixedManifestEncoder &FixedManifestEncoder::encodeImpl() { auto payload = reinterpret_cast<const uint8_t *>(manifest_entries_.data()); packet_->appendPayload(payload, manifestPayloadSizeImpl()); + packet_->updateLength(); if (TRANSPORT_EXPECT_FALSE(packet_->payloadSize() < manifestSizeImpl())) { throw errors::RuntimeException("Error encoding the manifest"); } diff --git a/libtransport/src/core/name.cc b/libtransport/src/core/name.cc index 960947cb9..02cc79be6 100644 --- a/libtransport/src/core/name.cc +++ b/libtransport/src/core/name.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -14,6 +14,7 @@ */ #include <core/manifest_format.h> +#include <hicn/name.h> #include <hicn/transport/core/name.h> #include <hicn/transport/errors/errors.h> #include <hicn/transport/errors/tokenizer_exception.h> @@ -124,8 +125,8 @@ std::string Name::toString() const { } uint32_t Name::getHash32(bool consider_suffix) const { - uint32_t hash; - if (hicn_name_hash(&name_, &hash, consider_suffix) < 0) { + uint32_t hash = _hicn_name_get_hash(&name_, consider_suffix); + if (hash < 0) { throw errors::RuntimeException("Error computing the hash of the name!"); } return hash; @@ -148,20 +149,19 @@ uint32_t Name::getSuffix() const { return ret; } -Name &Name::setSuffix(uint32_t seq_number) { - if (hicn_name_set_seq_number(&name_, seq_number) < 0) { - throw errors::RuntimeException( - "Impossible to set the sequence number to the name."); +Name &Name::setSuffix(hicn_name_suffix_t suffix) { + if (hicn_name_set_suffix(&name_, suffix) < 0) { + throw errors::RuntimeException("Impossible to set name suffix."); } return *this; } -ip_prefix_t Name::toIpAddress() const { - ip_prefix_t ret; +hicn_ip_prefix_t Name::toIpAddress() const { + hicn_ip_prefix_t ret; std::memset(&ret, 0, sizeof(ret)); - if (hicn_name_to_ip_prefix(&name_, &ret) < 0) { + if (hicn_name_to_hicn_ip_prefix(&name_, &ret) < 0) { throw errors::InvalidIpAddressException(); } diff --git a/libtransport/src/core/packet.cc b/libtransport/src/core/packet.cc index 0c08246af..73134ce3d 100644 --- a/libtransport/src/core/packet.cc +++ b/libtransport/src/core/packet.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -24,6 +24,7 @@ extern "C" { #ifndef _WIN32 TRANSPORT_CLANG_DISABLE_WARNING("-Wextern-c-compat") #endif +#include <hicn/base.h> #include <hicn/error.h> } @@ -33,72 +34,78 @@ namespace core { const core::Name Packet::base_name("0::0|0"); -Packet::Packet(Format format, std::size_t additional_header_size) +Packet::Packet(Type type, Format format, std::size_t additional_header_size) : utils::MemBuf(utils::MemBuf(CREATE, 2048)), - packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), - header_offset_(0), - format_(format), payload_type_(PayloadType::UNSPECIFIED) { - setFormat(format_, additional_header_size); + /* + * We define the format and the storage area of the packet buffer we + * manipulate + */ + setType(type); + setFormat(format); + setBuffer(); + initialize(additional_header_size); } Packet::Packet(CopyBufferOp, const uint8_t *buffer, std::size_t size) : utils::MemBuf(COPY_BUFFER, buffer, size), - packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), - header_offset_(0), - format_(getFormatFromBuffer(data(), length())), - payload_type_(PayloadType::UNSPECIFIED) {} + payload_type_(PayloadType::UNSPECIFIED) { + setBuffer(); + analyze(); +} Packet::Packet(WrapBufferOp, uint8_t *buffer, std::size_t length, std::size_t size) : utils::MemBuf(WRAP_BUFFER, buffer, length, size), - packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), - header_offset_(0), - format_(getFormatFromBuffer(this->data(), this->length())), - payload_type_(PayloadType::UNSPECIFIED) {} + payload_type_(PayloadType::UNSPECIFIED) { + setBuffer(); + analyze(); +} -Packet::Packet(CreateOp, uint8_t *buffer, std::size_t length, std::size_t size, - Format format, std::size_t additional_header_size) +Packet::Packet(CreateOp, Type type, uint8_t *buffer, std::size_t length, + std::size_t size, Format format, + std::size_t additional_header_size) : utils::MemBuf(WRAP_BUFFER, buffer, length, size), - packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), - header_offset_(0), - format_(format), payload_type_(PayloadType::UNSPECIFIED) { clear(); - setFormat(format_, additional_header_size); + setType(type); + setFormat(format); + setBuffer(); + initialize(additional_header_size); } Packet::Packet(MemBuf &&buffer) : utils::MemBuf(std::move(buffer)), - packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), - header_offset_(0), - format_(getFormatFromBuffer(data(), length())), - payload_type_(PayloadType::UNSPECIFIED) {} + payload_type_(PayloadType::UNSPECIFIED) { + setBuffer(); + analyze(); +} + +/* + * In the two following constructors, we inherit the pkbuf and only need to + * recompute the pointer fields, aka the buffer. + */ Packet::Packet(Packet &&other) : utils::MemBuf(std::move(other)), - packet_start_(other.packet_start_), - header_offset_(other.header_offset_), - format_(other.format_), + pkbuf_(other.pkbuf_), payload_type_(PayloadType::UNSPECIFIED) { - other.packet_start_ = nullptr; - other.format_ = HF_UNSPEC; - other.header_offset_ = 0; + hicn_packet_reset(&other.pkbuf_); } Packet::Packet(const Packet &other) : utils::MemBuf(other), - packet_start_(reinterpret_cast<hicn_header_t *>(writableData())), - header_offset_(other.header_offset_), - format_(other.format_), - payload_type_(PayloadType::UNSPECIFIED) {} + pkbuf_(other.pkbuf_), + payload_type_(PayloadType::UNSPECIFIED) { + setBuffer(); +} Packet::~Packet() {} Packet &Packet::operator=(const Packet &other) { if (this != &other) { *this = other; - packet_start_ = reinterpret_cast<hicn_header_t *>(writableData()); + setBuffer(); } return *this; @@ -109,38 +116,44 @@ std::shared_ptr<utils::MemBuf> Packet::acquireMemBufReference() { } Packet::Format Packet::getFormat() const { - // We check packet start because after a movement it will result in a nullptr - if (format_ == HF_UNSPEC && length()) { - if (hicn_packet_get_format(packet_start_, &format_) < 0) { - LOG(ERROR) << "Unexpected packet format HF_UNSPEC."; - } - } + return hicn_packet_get_format(&pkbuf_); +} - return format_; +void Packet::setFormat(Packet::Format format) { + hicn_packet_set_format(&pkbuf_, format); } -void Packet::setFormat(Packet::Format format, - std::size_t additional_header_size) { - format_ = format; - if (hicn_packet_init_header(format_, packet_start_) < 0) { +void Packet::initialize(std::size_t additional_header_size) { + if (hicn_packet_init_header(&pkbuf_, additional_header_size) < 0) { throw errors::RuntimeException("Unexpected error initializing the packet."); } - auto header_size = getHeaderSizeFromFormat(format_); + auto header_size = getHeaderSizeFromFormat(getFormat()); DCHECK(header_size <= tailroom()); append(header_size); - DCHECK(additional_header_size <= tailroom()); append(additional_header_size); +} - header_offset_ = length(); +void Packet::analyze() { + if (hicn_packet_analyze(&pkbuf_) < 0) + throw errors::MalformedPacketException(); +} + +Packet::Type Packet::getType() const { return hicn_packet_get_type(&pkbuf_); } + +void Packet::setType(Packet::Type type) { hicn_packet_set_type(&pkbuf_, type); } + +void Packet::setBuffer() { + hicn_packet_set_buffer(&pkbuf_, writableData(), + this->capacity() - this->headroom(), this->length()); } PayloadType Packet::getPayloadType() const { if (payload_type_ == PayloadType::UNSPECIFIED) { hicn_payload_type_t ret; - if (hicn_packet_get_payload_type(format_, packet_start_, &ret) < 0) { + if (hicn_packet_get_payload_type(&pkbuf_, &ret) < 0) { throw errors::RuntimeException("Impossible to retrieve payload type."); } @@ -151,8 +164,8 @@ PayloadType Packet::getPayloadType() const { } Packet &Packet::setPayloadType(PayloadType payload_type) { - if (hicn_packet_set_payload_type(format_, packet_start_, - hicn_payload_type_t(payload_type)) < 0) { + if (hicn_packet_set_payload_type(&pkbuf_, hicn_payload_type_t(payload_type)) < + 0) { throw errors::RuntimeException("Error setting payload type of the packet."); } @@ -184,23 +197,15 @@ Packet &Packet::appendPayload(const uint8_t *buffer, std::size_t length) { } std::size_t Packet::headerSize() const { - if (header_offset_ == 0 && length()) { - const_cast<Packet *>(this)->header_offset_ = getHeaderSizeFromBuffer( - format_, reinterpret_cast<uint8_t *>(packet_start_)); - } - - return header_offset_; + std::size_t len; + hicn_packet_get_header_len(&pkbuf_, &len); + return len; } std::size_t Packet::payloadSize() const { - std::size_t ret = 0; - - if (length()) { - ret = getPayloadSizeFromBuffer(format_, - reinterpret_cast<uint8_t *>(packet_start_)); - } - - return ret; + std::size_t len; + hicn_packet_get_payload_len(&pkbuf_, &len); + return len; } auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const { @@ -208,21 +213,22 @@ auth::CryptoHash Packet::computeDigest(auth::CryptoHashType algorithm) const { hash.setType(algorithm); // Copy IP+TCP/ICMP header before zeroing them - hicn_header_t header_copy; - hicn_packet_copy_header(format_, packet_start_, &header_copy, false); + u8 header_copy[HICN_HDRLEN_MAX]; + size_t header_len; + hicn_packet_save_header(&pkbuf_, header_copy, &header_len, + /* copy_ah */ false); const_cast<Packet *>(this)->resetForHash(); hash.computeDigest(this); - hicn_packet_copy_header(format_, &header_copy, packet_start_, false); + hicn_packet_load_header(&pkbuf_, header_copy, header_len); return hash; } void Packet::reset() { clear(); - packet_start_ = reinterpret_cast<hicn_header_t *>(writableData()); - header_offset_ = 0; - format_ = HF_UNSPEC; + hicn_packet_reset(&pkbuf_); + setBuffer(); payload_type_ = PayloadType::UNSPECIFIED; name_.clear(); @@ -231,7 +237,9 @@ void Packet::reset() { } } -bool Packet::isInterest() { return Packet::isInterest(data(), format_); } +bool Packet::isInterest() { + return hicn_packet_get_type(&pkbuf_) == HICN_PACKET_TYPE_INTEREST; +} Packet &Packet::updateLength(std::size_t length) { std::size_t total_length = length; @@ -242,11 +250,14 @@ Packet &Packet::updateLength(std::size_t length) { current = current->next(); } while (current != this); + if (hicn_packet_set_len(&pkbuf_, total_length) < 0) { + throw errors::RuntimeException("Error setting the packet length."); + } + total_length -= headerSize(); - if (hicn_packet_set_payload_length(format_, packet_start_, total_length) < - 0) { - throw errors::RuntimeException("Error setting the packet payload."); + if (hicn_packet_set_payload_length(&pkbuf_, total_length) < 0) { + throw errors::RuntimeException("Error setting the packet payload length."); } return *this; @@ -265,168 +276,45 @@ void Packet::dump() const { } void Packet::setChecksum() { - if (_is_tcp(format_)) { - uint16_t partial_csum = - csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0); - - for (utils::MemBuf *current = next(); current != this; - current = current->next()) { - partial_csum = csum(current->data(), current->length(), ~partial_csum); - } - - if (hicn_packet_compute_header_checksum(format_, packet_start_, - partial_csum) < 0) { - throw errors::MalformedPacketException(); - } - } -} - -bool Packet::checkIntegrity() const { - if (_is_tcp(format_)) { - uint16_t partial_csum = - csum(data() + HICN_V6_TCP_HDRLEN, length() - HICN_V6_TCP_HDRLEN, 0); - - for (const utils::MemBuf *current = next(); current != this; - current = current->next()) { - partial_csum = csum(current->data(), current->length(), ~partial_csum); - } - - if (hicn_packet_check_integrity_no_payload(format_, packet_start_, - partial_csum) < 0) { - return false; - } - } - - return true; -} - -Packet &Packet::setSyn() { - if (hicn_packet_set_syn(format_, packet_start_) < 0) { - throw errors::RuntimeException("Error setting syn bit in the packet."); - } - - return *this; -} - -Packet &Packet::resetSyn() { - if (hicn_packet_reset_syn(format_, packet_start_) < 0) { - throw errors::RuntimeException("Error resetting syn bit in the packet."); - } - - return *this; -} - -bool Packet::testSyn() const { - bool res = false; - if (hicn_packet_test_syn(format_, packet_start_, &res) < 0) { - throw errors::RuntimeException("Error testing syn bit in the packet."); - } - - return res; -} - -Packet &Packet::setAck() { - if (hicn_packet_set_ack(format_, packet_start_) < 0) { - throw errors::RuntimeException("Error setting ack bit in the packet."); - } - - return *this; -} - -Packet &Packet::resetAck() { - if (hicn_packet_reset_ack(format_, packet_start_) < 0) { - throw errors::RuntimeException("Error resetting ack bit in the packet."); - } - - return *this; -} - -bool Packet::testAck() const { - bool res = false; - if (hicn_packet_test_ack(format_, packet_start_, &res) < 0) { - throw errors::RuntimeException("Error testing ack bit in the packet."); - } - - return res; -} - -Packet &Packet::setRst() { - if (hicn_packet_set_rst(format_, packet_start_) < 0) { - throw errors::RuntimeException("Error setting rst bit in the packet."); - } + size_t header_len = 0; + if (hicn_packet_get_header_len(&pkbuf_, &header_len) < 0) + throw errors::RuntimeException( + "Error setting getting packet header length."); - return *this; -} + uint16_t partial_csum = csum(data() + header_len, length() - header_len, 0); -Packet &Packet::resetRst() { - if (hicn_packet_reset_rst(format_, packet_start_) < 0) { - throw errors::RuntimeException("Error resetting rst bit in the packet."); + for (utils::MemBuf *current = next(); current != this; + current = current->next()) { + partial_csum = csum(current->data(), current->length(), ~partial_csum); } - return *this; -} - -bool Packet::testRst() const { - bool res = false; - if (hicn_packet_test_rst(format_, packet_start_, &res) < 0) { - throw errors::RuntimeException("Error testing rst bit in the packet."); + if (hicn_packet_compute_header_checksum(&pkbuf_, partial_csum) < 0) { + throw errors::MalformedPacketException(); } - - return res; } -Packet &Packet::setFin() { - if (hicn_packet_set_fin(format_, packet_start_) < 0) { - throw errors::RuntimeException("Error setting fin bit in the packet."); - } +bool Packet::checkIntegrity() const { + size_t header_len = 0; + if (hicn_packet_get_header_len(&pkbuf_, &header_len) < 0) + throw errors::RuntimeException( + "Error setting getting packet header length."); - return *this; -} + uint16_t partial_csum = csum(data() + header_len, length() - header_len, 0); -Packet &Packet::resetFin() { - if (hicn_packet_reset_fin(format_, packet_start_) < 0) { - throw errors::RuntimeException("Error resetting fin bit in the packet."); + for (const utils::MemBuf *current = next(); current != this; + current = current->next()) { + partial_csum = csum(current->data(), current->length(), ~partial_csum); } - return *this; -} - -bool Packet::testFin() const { - bool res = false; - if (hicn_packet_test_fin(format_, packet_start_, &res) < 0) { - throw errors::RuntimeException("Error testing fin bit in the packet."); + if (hicn_packet_check_integrity_no_payload(&pkbuf_, partial_csum) < 0) { + return false; } - return res; -} - -Packet &Packet::resetFlags() { - resetSyn(); - resetAck(); - resetRst(); - resetFin(); - return *this; -} - -std::string Packet::printFlags() const { - std::string flags; - if (testSyn()) { - flags += "S"; - } - if (testAck()) { - flags += "A"; - } - if (testRst()) { - flags += "R"; - } - if (testFin()) { - flags += "F"; - } - return flags; + return true; } Packet &Packet::setSrcPort(uint16_t srcPort) { - if (hicn_packet_set_src_port(format_, packet_start_, srcPort) < 0) { + if (hicn_packet_set_src_port(&pkbuf_, srcPort) < 0) { throw errors::RuntimeException("Error setting source port in the packet."); } @@ -434,7 +322,7 @@ Packet &Packet::setSrcPort(uint16_t srcPort) { } Packet &Packet::setDstPort(uint16_t dstPort) { - if (hicn_packet_set_dst_port(format_, packet_start_, dstPort) < 0) { + if (hicn_packet_set_dst_port(&pkbuf_, dstPort) < 0) { throw errors::RuntimeException( "Error setting destination port in the packet."); } @@ -445,7 +333,7 @@ Packet &Packet::setDstPort(uint16_t dstPort) { uint16_t Packet::getSrcPort() const { uint16_t port = 0; - if (hicn_packet_get_src_port(format_, packet_start_, &port) < 0) { + if (hicn_packet_get_src_port(&pkbuf_, &port) < 0) { throw errors::RuntimeException("Error reading source port in the packet."); } @@ -455,7 +343,7 @@ uint16_t Packet::getSrcPort() const { uint16_t Packet::getDstPort() const { uint16_t port = 0; - if (hicn_packet_get_dst_port(format_, packet_start_, &port) < 0) { + if (hicn_packet_get_dst_port(&pkbuf_, &port) < 0) { throw errors::RuntimeException( "Error reading destination port in the packet."); } @@ -464,7 +352,7 @@ uint16_t Packet::getDstPort() const { } Packet &Packet::setTTL(uint8_t hops) { - if (hicn_packet_set_hoplimit(packet_start_, hops) < 0) { + if (hicn_packet_set_ttl(&pkbuf_, hops) < 0) { throw errors::RuntimeException("Error setting TTL."); } @@ -473,14 +361,14 @@ Packet &Packet::setTTL(uint8_t hops) { uint8_t Packet::getTTL() const { uint8_t hops = 0; - if (hicn_packet_get_hoplimit(packet_start_, &hops) < 0) { + if (hicn_packet_get_ttl(&pkbuf_, &hops) < 0) { throw errors::RuntimeException("Error reading TTL."); } return hops; } -bool Packet::hasAH() const { return _is_ah(format_); } +bool Packet::hasAH() const { return _is_ah(hicn_packet_get_format(&pkbuf_)); } utils::MemBuf::Ptr Packet::getSignature() const { if (!hasAH()) { @@ -488,7 +376,7 @@ utils::MemBuf::Ptr Packet::getSignature() const { } uint8_t *signature; - int ret = hicn_packet_get_signature(format_, packet_start_, &signature); + int ret = hicn_packet_get_signature(&pkbuf_, &signature); if (ret < 0) { throw errors::RuntimeException("Error getting signature."); @@ -507,7 +395,7 @@ std::size_t Packet::getSignatureFieldSize() const { } size_t field_size; - int ret = hicn_packet_get_signature_size(format_, packet_start_, &field_size); + int ret = hicn_packet_get_signature_size(&pkbuf_, &field_size); if (ret < 0) { throw errors::RuntimeException("Error reading signature field size"); } @@ -520,7 +408,7 @@ std::size_t Packet::getSignatureSize() const { } size_t padding; - int ret = hicn_packet_get_signature_padding(format_, packet_start_, &padding); + int ret = hicn_packet_get_signature_padding(&pkbuf_, &padding); if (ret < 0) { throw errors::RuntimeException("Error reading signature padding"); } @@ -539,8 +427,7 @@ uint64_t Packet::getSignatureTimestamp() const { } uint64_t timestamp; - int ret = - hicn_packet_get_signature_timestamp(format_, packet_start_, ×tamp); + int ret = hicn_packet_get_signature_timestamp(&pkbuf_, ×tamp); if (ret < 0) { throw errors::RuntimeException("Error getting the signature timestamp."); } @@ -553,8 +440,7 @@ auth::KeyId Packet::getKeyId() const { } auth::KeyId key_id; - int ret = hicn_packet_get_key_id(format_, packet_start_, &key_id.first, - &key_id.second); + int ret = hicn_packet_get_key_id(&pkbuf_, &key_id.first, &key_id.second); if (ret < 0) { throw errors::RuntimeException("Error getting the validation algorithm."); } @@ -567,8 +453,7 @@ auth::CryptoSuite Packet::getValidationAlgorithm() const { } uint8_t return_value; - int ret = hicn_packet_get_validation_algorithm(format_, packet_start_, - &return_value); + int ret = hicn_packet_get_validation_algorithm(&pkbuf_, &return_value); if (ret < 0) { throw errors::RuntimeException("Error getting the validation algorithm."); } @@ -581,7 +466,7 @@ void Packet::setSignature(const utils::MemBuf::Ptr &signature) { } uint8_t *signature_field; - int ret = hicn_packet_get_signature(format_, packet_start_, &signature_field); + int ret = hicn_packet_get_signature(&pkbuf_, &signature_field); if (ret < 0) { throw errors::RuntimeException("Error getting signature."); } @@ -593,7 +478,7 @@ void Packet::setSignatureFieldSize(std::size_t size) { throw errors::RuntimeException("Packet without Authentication Header."); } - int ret = hicn_packet_set_signature_size(format_, packet_start_, size); + int ret = hicn_packet_set_signature_size(&pkbuf_, size); if (ret < 0) { throw errors::RuntimeException("Error setting signature size."); } @@ -609,7 +494,7 @@ void Packet::setSignatureSize(std::size_t size) { throw errors::RuntimeException("Error setting signature padding."); } - int ret = hicn_packet_set_signature_padding(format_, packet_start_, padding); + int ret = hicn_packet_set_signature_padding(&pkbuf_, padding); if (ret < 0) { throw errors::RuntimeException("Error setting signature padding."); } @@ -620,8 +505,7 @@ void Packet::setSignatureTimestamp(const uint64_t ×tamp) { throw errors::RuntimeException("Packet without Authentication Header."); } - int ret = - hicn_packet_set_signature_timestamp(format_, packet_start_, timestamp); + int ret = hicn_packet_set_signature_timestamp(&pkbuf_, timestamp); if (ret < 0) { throw errors::RuntimeException("Error setting the signature timestamp."); } @@ -632,7 +516,7 @@ void Packet::setKeyId(const auth::KeyId &key_id) { throw errors::RuntimeException("Packet without Authentication Header."); } - int ret = hicn_packet_set_key_id(format_, packet_start_, key_id.first); + int ret = hicn_packet_set_key_id(&pkbuf_, key_id.first, key_id.second); if (ret < 0) { throw errors::RuntimeException("Error setting the key id."); } @@ -644,7 +528,7 @@ void Packet::setValidationAlgorithm( throw errors::RuntimeException("Packet without Authentication Header."); } - int ret = hicn_packet_set_validation_algorithm(format_, packet_start_, + int ret = hicn_packet_set_validation_algorithm(&pkbuf_, uint8_t(validation_algorithm)); if (ret < 0) { throw errors::RuntimeException("Error setting the validation algorithm."); @@ -656,10 +540,13 @@ Packet::Format Packet::toAHFormat(const Format &format) { } Packet::Format Packet::getFormatFromBuffer(const uint8_t *buffer, - std::size_t /* length */) { - Packet::Format format = HF_UNSPEC; - hicn_packet_get_format((const hicn_header_t *)buffer, &format); - return format; + std::size_t length) { + hicn_packet_buffer_t pkbuf; + /* un-const to be able to use pkbuf API */ + hicn_packet_set_buffer(&pkbuf, (uint8_t *)buffer, length, length); + if (hicn_packet_analyze(&pkbuf) < 0) throw errors::MalformedPacketException(); + + return hicn_packet_get_format(&pkbuf); } std::size_t Packet::getHeaderSizeFromFormat(Format format, @@ -670,44 +557,34 @@ std::size_t Packet::getHeaderSizeFromFormat(Format format, return is_ah * (header_length + signature_size) + (!is_ah) * header_length; } -std::size_t Packet::getHeaderSizeFromBuffer(Format format, - const uint8_t *buffer) { +std::size_t Packet::getHeaderSizeFromBuffer(const uint8_t *buffer, + std::size_t length) { size_t header_length; - if (hicn_packet_get_header_length(format, (hicn_header_t *)buffer, - &header_length) < 0) { - throw errors::MalformedPacketException(); - } + hicn_packet_buffer_t pkbuf; + /* un-const to be able to use pkbuf API */ + hicn_packet_set_buffer(&pkbuf, (uint8_t *)buffer, length, length); + if (hicn_packet_analyze(&pkbuf) < 0) throw errors::MalformedPacketException(); + + int rc = hicn_packet_get_header_len(&pkbuf, &header_length); + if (TRANSPORT_EXPECT_FALSE(rc < 0)) throw errors::MalformedPacketException(); return header_length; } -std::size_t Packet::getPayloadSizeFromBuffer(Format format, - const uint8_t *buffer) { +std::size_t Packet::getPayloadSizeFromBuffer(const uint8_t *buffer, + std::size_t length) { std::size_t payload_length; - if (TRANSPORT_EXPECT_FALSE( - hicn_packet_get_payload_length(format, (hicn_header_t *)buffer, - &payload_length) < 0)) { - throw errors::MalformedPacketException(); - } - return payload_length; -} + hicn_packet_buffer_t pkbuf; + /* un-const to be able to use pkbuf API */ + hicn_packet_set_buffer(&pkbuf, (uint8_t *)buffer, length, length); + if (hicn_packet_analyze(&pkbuf) < 0) throw errors::MalformedPacketException(); -bool Packet::isInterest(const uint8_t *buffer, Format format) { - int is_interest = 0; - - if (TRANSPORT_EXPECT_FALSE(format == Format::HF_UNSPEC)) { - format = getFormatFromBuffer(buffer, /* Unused length */ 128); - } + int rc = hicn_packet_get_payload_len(&pkbuf, &payload_length); + if (TRANSPORT_EXPECT_FALSE(rc < 0)) throw errors::MalformedPacketException(); - if (TRANSPORT_EXPECT_FALSE( - hicn_packet_is_interest(format, (const hicn_header_t *)buffer, - &is_interest) < 0)) { - throw errors::RuntimeException("Error reading ece flag from packet"); - } - - return is_interest; + return payload_length; } void Packet::dump(uint8_t *buffer, std::size_t length) { @@ -723,6 +600,14 @@ void Packet::prependPayload(const uint8_t **buffer, std::size_t *size) { *buffer += to_copy; } +void Packet::saveHeader(u8 *header, size_t *header_len) { + hicn_packet_save_header(&pkbuf_, header, header_len, /* copy_ah */ false); +} + +void Packet::loadHeader(u8 *header, size_t header_len) { + hicn_packet_load_header(&pkbuf_, header, header_len); +} + } // end namespace core } // end namespace transport diff --git a/libtransport/src/core/portal.cc b/libtransport/src/core/portal.cc index c06969f19..72b6a6f37 100644 --- a/libtransport/src/core/portal.cc +++ b/libtransport/src/core/portal.cc @@ -30,11 +30,11 @@ namespace core { #ifdef ANDROID static const constexpr char default_module[] = ""; #elif defined(MACINTOSH) -static const constexpr char default_module[] = "hicnlightng_module.dylib"; +static const constexpr char default_module[] = "hicnlight_module.dylib"; #elif defined(LINUX) -static const constexpr char default_module[] = "hicnlightng_module.so"; +static const constexpr char default_module[] = "hicnlight_module.so"; #elif defined(WINDOWS) -static const constexpr char default_module[] = "hicnlightng_module.lib"; +static const constexpr char default_module[] = "hicnlight_module.lib"; #endif IoModuleConfiguration Portal::conf_; @@ -149,4 +149,4 @@ void Portal::parseIoModuleConfiguration(const libconfig::Setting& io_config, } } // namespace core -} // namespace transport
\ No newline at end of file +} // namespace transport diff --git a/libtransport/src/core/portal.h b/libtransport/src/core/portal.h index 6f3a48e83..f2380347b 100644 --- a/libtransport/src/core/portal.h +++ b/libtransport/src/core/portal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -32,10 +32,6 @@ #include <hicn/transport/utils/event_thread.h> #include <hicn/transport/utils/fixed_block_allocator.h> -extern "C" { -#include <hicn/header.h> -} - #include <future> #include <memory> #include <queue> @@ -575,24 +571,31 @@ class Portal : public ::utils::NonCopyable, return; } - auto format = Packet::getFormatFromBuffer(buffer.data(), buffer.length()); - if (TRANSPORT_EXPECT_TRUE(_is_cmpr(format) || _is_tcp(format))) { - // The buffer is a base class for an interest or a content object - Packet &packet_buffer = static_cast<Packet &>(buffer); - if (is_consumer_ && !packet_buffer.isInterest()) { - processContentObject(static_cast<ContentObject &>(packet_buffer)); - } else if (!is_consumer_ && packet_buffer.isInterest()) { - processInterest(static_cast<Interest &>(packet_buffer)); - } else { - auto packet_type = - packet_buffer.isInterest() ? "Interest" : "ContentObject"; - auto socket_type = is_consumer_ ? "consumer " : "producer "; - LOG(ERROR) << "Received a " << packet_type << " packet with name " - << packet_buffer.getName() << " in a " << socket_type - << " transport. Ignoring it."; - } - } else { - LOG(ERROR) << "Received not supported packet. Ignoring it."; + // The buffer is a base class for an interest or a content object + Packet &packet_buffer = static_cast<Packet &>(buffer); + + switch (packet_buffer.getType()) { + case HICN_PACKET_TYPE_INTEREST: + if (!is_consumer_) { + processInterest(static_cast<Interest &>(packet_buffer)); + } else { + LOG(ERROR) << "Received an Interest packet with name " + << packet_buffer.getName() + << " in a consumer transport. Ignoring it."; + } + break; + case HICN_PACKET_TYPE_DATA: + if (is_consumer_) { + processContentObject(static_cast<ContentObject &>(packet_buffer)); + } else { + LOG(ERROR) << "Received a Data packet with name " + << packet_buffer.getName() + << " in a producer transport. Ignoring it."; + } + break; + default: + LOG(ERROR) << "Received not supported packet. Ignoring it."; + break; } } } diff --git a/libtransport/src/core/prefix.cc b/libtransport/src/core/prefix.cc index 00748148f..d54dc909a 100644 --- a/libtransport/src/core/prefix.cc +++ b/libtransport/src/core/prefix.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -37,7 +37,7 @@ namespace transport { namespace core { -Prefix::Prefix() { std::memset(&ip_prefix_, 0, sizeof(ip_prefix_t)); } +Prefix::Prefix() { std::memset(&hicn_ip_prefix_, 0, sizeof(hicn_ip_prefix_t)); } Prefix::Prefix(const std::string &prefix) { utils::StringTokenizer st(prefix, "/"); @@ -66,9 +66,9 @@ Prefix::Prefix(const core::Name &content_name, uint16_t prefix_length) { throw errors::InvalidIpAddressException(); } - ip_prefix_ = content_name.toIpAddress(); - ip_prefix_.len = (u8)prefix_length; - ip_prefix_.family = family; + hicn_ip_prefix_ = content_name.toIpAddress(); + hicn_ip_prefix_.len = (u8)prefix_length; + hicn_ip_prefix_.family = family; } void Prefix::buildPrefix(const std::string &prefix, uint16_t prefix_length, @@ -77,15 +77,17 @@ void Prefix::buildPrefix(const std::string &prefix, uint16_t prefix_length, throw errors::InvalidIpAddressException(); } - std::memset(&ip_prefix_, 0, sizeof(ip_prefix_t)); + std::memset(&hicn_ip_prefix_, 0, sizeof(hicn_ip_prefix_t)); int ret; switch (family) { case AF_INET: - ret = inet_pton(AF_INET, prefix.c_str(), ip_prefix_.address.v4.buffer); + ret = + inet_pton(AF_INET, prefix.c_str(), hicn_ip_prefix_.address.v4.buffer); break; case AF_INET6: - ret = inet_pton(AF_INET6, prefix.c_str(), ip_prefix_.address.v6.buffer); + ret = inet_pton(AF_INET6, prefix.c_str(), + hicn_ip_prefix_.address.v6.buffer); break; default: throw errors::InvalidIpAddressException(); @@ -95,22 +97,22 @@ void Prefix::buildPrefix(const std::string &prefix, uint16_t prefix_length, throw errors::InvalidIpAddressException(); } - ip_prefix_.len = (u8)prefix_length; - ip_prefix_.family = family; + hicn_ip_prefix_.len = (u8)prefix_length; + hicn_ip_prefix_.family = family; } bool Prefix::operator<(const Prefix &other) const { - return ip_prefix_cmp(&ip_prefix_, &other.ip_prefix_) < 0; + return hicn_ip_prefix_cmp(&hicn_ip_prefix_, &other.hicn_ip_prefix_) < 0; } bool Prefix::operator==(const Prefix &other) const { - return ip_prefix_cmp(&ip_prefix_, &other.ip_prefix_) == 0; + return hicn_ip_prefix_cmp(&hicn_ip_prefix_, &other.hicn_ip_prefix_) == 0; } std::unique_ptr<Sockaddr> Prefix::toSockaddr() const { Sockaddr *ret = nullptr; - switch (ip_prefix_.family) { + switch (hicn_ip_prefix_.family) { case AF_INET6: ret = (Sockaddr *)new Sockaddr6; break; @@ -121,34 +123,37 @@ std::unique_ptr<Sockaddr> Prefix::toSockaddr() const { throw errors::InvalidIpAddressException(); } - if (ip_prefix_to_sockaddr(&ip_prefix_, ret) < 0) { + if (hicn_ip_prefix_to_sockaddr(&hicn_ip_prefix_, ret) < 0) { throw errors::InvalidIpAddressException(); } return std::unique_ptr<Sockaddr>(ret); } -uint16_t Prefix::getPrefixLength() const { return ip_prefix_.len; } +uint16_t Prefix::getPrefixLength() const { return hicn_ip_prefix_.len; } Prefix &Prefix::setPrefixLength(uint16_t prefix_length) { - if (!checkPrefixLengthAndAddressFamily(prefix_length, ip_prefix_.family)) { + if (!checkPrefixLengthAndAddressFamily(prefix_length, + hicn_ip_prefix_.family)) { throw errors::InvalidIpAddressException(); } - ip_prefix_.len = (u8)prefix_length; + hicn_ip_prefix_.len = (u8)prefix_length; return *this; } -int Prefix::getAddressFamily() const { return ip_prefix_.family; } +int Prefix::getAddressFamily() const { return hicn_ip_prefix_.family; } std::string Prefix::getNetwork() const { - if (!checkPrefixLengthAndAddressFamily(ip_prefix_.len, ip_prefix_.family)) { + if (!checkPrefixLengthAndAddressFamily(hicn_ip_prefix_.len, + hicn_ip_prefix_.family)) { throw errors::InvalidIpAddressException(); } char buffer[INET6_ADDRSTRLEN]; - if (ip_prefix_ntop_short(&ip_prefix_, buffer, INET6_ADDRSTRLEN) < 0) { + if (hicn_ip_prefix_ntop_short(&hicn_ip_prefix_, buffer, INET6_ADDRSTRLEN) < + 0) { throw errors::RuntimeException( "Impossible to retrieve network from ip address."); } @@ -156,13 +161,13 @@ std::string Prefix::getNetwork() const { return buffer; } -bool Prefix::contains(const ip_address_t &content_name) const { +bool Prefix::contains(const hicn_ip_address_t &content_name) const { uint64_t mask[2] = {0, 0}; auto content_name_copy = content_name; - auto network_copy = ip_prefix_.address; + auto network_copy = hicn_ip_prefix_.address; auto prefix_length = getPrefixLength(); - if (ip_prefix_.family == AF_INET) { + if (hicn_ip_prefix_.family == AF_INET) { prefix_length += 3 * IPV4_ADDR_LEN_BITS; } @@ -186,8 +191,7 @@ bool Prefix::contains(const ip_address_t &content_name) const { network_copy.v6.as_u64[0] &= mask[0]; network_copy.v6.as_u64[1] &= mask[1]; - return ip_address_cmp(&network_copy, &content_name_copy, ip_prefix_.family) == - 0; + return hicn_ip_address_cmp(&network_copy, &content_name_copy) == 0; } bool Prefix::contains(const core::Name &content_name) const { @@ -200,23 +204,25 @@ bool Prefix::contains(const core::Name &content_name) const { */ Name Prefix::getName(const core::Name &mask, const core::Name &components, const core::Name &content_name) const { - if (ip_prefix_.family != mask.getAddressFamily() || - ip_prefix_.family != components.getAddressFamily() || - ip_prefix_.family != content_name.getAddressFamily()) + if (hicn_ip_prefix_.family != mask.getAddressFamily() || + hicn_ip_prefix_.family != components.getAddressFamily() || + hicn_ip_prefix_.family != content_name.getAddressFamily()) throw errors::RuntimeException( "Prefix, mask, components and content name are not of the same" "address family"); - ip_address_t mask_ip = mask.toIpAddress().address; - ip_address_t component_ip = components.toIpAddress().address; - ip_address_t name_ip = content_name.toIpAddress().address; - const u8 *mask_ip_buffer = ip_address_get_buffer(&mask_ip, ip_prefix_.family); + hicn_ip_address_t mask_ip = mask.toIpAddress().address; + hicn_ip_address_t component_ip = components.toIpAddress().address; + hicn_ip_address_t name_ip = content_name.toIpAddress().address; + const u8 *mask_ip_buffer = + hicn_ip_address_get_buffer(&mask_ip, hicn_ip_prefix_.family); const u8 *component_ip_buffer = - ip_address_get_buffer(&component_ip, ip_prefix_.family); - u8 *name_ip_buffer = - const_cast<u8 *>(ip_address_get_buffer(&name_ip, ip_prefix_.family)); + hicn_ip_address_get_buffer(&component_ip, hicn_ip_prefix_.family); + u8 *name_ip_buffer = const_cast<u8 *>( + hicn_ip_address_get_buffer(&name_ip, hicn_ip_prefix_.family)); - int addr_len = ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN : IPV4_ADDR_LEN; + int addr_len = + hicn_ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN : IPV4_ADDR_LEN; for (int i = 0; i < addr_len; i++) { if (mask_ip_buffer[i]) { @@ -224,39 +230,40 @@ Name Prefix::getName(const core::Name &mask, const core::Name &components, } } - return Name(ip_prefix_.family, (uint8_t *)&name_ip); + return Name(hicn_ip_prefix_.family, (uint8_t *)&name_ip); } /* * Map a name in a different name prefix to this name prefix */ Name Prefix::mapName(const core::Name &content_name) const { - if (ip_prefix_.family != content_name.getAddressFamily()) + if (hicn_ip_prefix_.family != content_name.getAddressFamily()) throw errors::RuntimeException( "Prefix content name are not of the same address " "family"); - ip_address_t name_ip = content_name.toIpAddress().address; - const u8 *ip_prefix_buffer = - ip_address_get_buffer(&(ip_prefix_.address), ip_prefix_.family); - u8 *name_ip_buffer = - const_cast<u8 *>(ip_address_get_buffer(&name_ip, ip_prefix_.family)); - - memcpy(name_ip_buffer, ip_prefix_buffer, ip_prefix_.len / 8); - - if (ip_prefix_.len != (ip_prefix_.family == AF_INET6 ? IPV6_ADDR_LEN_BITS - : IPV4_ADDR_LEN_BITS)) { - uint8_t mask = 0xFF >> (ip_prefix_.len % 8); - name_ip_buffer[ip_prefix_.len / 8 + 1] = - (name_ip_buffer[ip_prefix_.len / 8 + 1] & mask) | - (ip_prefix_buffer[ip_prefix_.len / 8 + 1] & ~mask); + hicn_ip_address_t name_ip = content_name.toIpAddress().address; + const u8 *hicn_ip_prefix_buffer = hicn_ip_address_get_buffer( + &(hicn_ip_prefix_.address), hicn_ip_prefix_.family); + u8 *name_ip_buffer = const_cast<u8 *>( + hicn_ip_address_get_buffer(&name_ip, hicn_ip_prefix_.family)); + + memcpy(name_ip_buffer, hicn_ip_prefix_buffer, hicn_ip_prefix_.len / 8); + + if (hicn_ip_prefix_.len != (hicn_ip_prefix_.family == AF_INET6 + ? IPV6_ADDR_LEN_BITS + : IPV4_ADDR_LEN_BITS)) { + uint8_t mask = 0xFF >> (hicn_ip_prefix_.len % 8); + name_ip_buffer[hicn_ip_prefix_.len / 8 + 1] = + (name_ip_buffer[hicn_ip_prefix_.len / 8 + 1] & mask) | + (hicn_ip_prefix_buffer[hicn_ip_prefix_.len / 8 + 1] & ~mask); } - return Name(ip_prefix_.family, (uint8_t *)&name_ip); + return Name(hicn_ip_prefix_.family, (uint8_t *)&name_ip); } Prefix &Prefix::setNetwork(const std::string &network) { - if (!ip_address_pton(network.c_str(), &ip_prefix_.address)) { + if (!hicn_ip_address_pton(network.c_str(), &hicn_ip_prefix_.address)) { throw errors::RuntimeException("The network name is not valid."); } @@ -288,7 +295,7 @@ Name Prefix::makeNameWithIndex(std::uint64_t index) const { } std::memcpy(ret.getStructReference().prefix.v6.as_u8, - ip_prefix_.address.v6.as_u8, sizeof(ip_address_t)); + hicn_ip_prefix_.address.v6.as_u8, sizeof(hicn_ip_address_t)); // Convert index in network byte order index = portability::host_to_net(index); @@ -334,7 +341,9 @@ bool Prefix::checkPrefixLengthAndAddressFamily(uint16_t prefix_length, return true; } -const ip_prefix_t &Prefix::toIpPrefixStruct() const { return ip_prefix_; } +const hicn_ip_prefix_t &Prefix::toIpPrefixStruct() const { + return hicn_ip_prefix_; +} } // namespace core diff --git a/libtransport/src/core/udp_connector.cc b/libtransport/src/core/udp_connector.cc index 5d8e76bb1..7d059dd9d 100644 --- a/libtransport/src/core/udp_connector.cc +++ b/libtransport/src/core/udp_connector.cc @@ -105,25 +105,23 @@ void UdpTunnelConnector::doSendPacket( current = current->next(); } while (current != packet); - socket_->async_send_to( - std::move(array), remote_endpoint_send_, - [this, self](const std::error_code &ec, std::size_t length) { - if (TRANSPORT_EXPECT_TRUE(!ec)) { - sent_callback_(this, make_error_code(core_error::success)); - } else if (ec.value() == - static_cast<int>(std::errc::operation_canceled)) { - // The connection has been closed by the application. - return; - } else { - sendFailed(); - sent_callback_(this, ec); - } + socket_->async_send(std::move(array), [this, self](const std::error_code &ec, + std::size_t length) { + if (TRANSPORT_EXPECT_TRUE(!ec)) { + sent_callback_(this, make_error_code(core_error::success)); + } else if (ec.value() == static_cast<int>(std::errc::operation_canceled)) { + // The connection has been closed by the application. + return; + } else { + sendFailed(); + sent_callback_(this, ec); + } - output_buffer_.pop_front(); - if (!output_buffer_.empty()) { - doSendPacket(self); - } - }); + output_buffer_.pop_front(); + if (!output_buffer_.empty()) { + doSendPacket(self); + } + }); #endif } diff --git a/libtransport/src/implementation/socket.cc b/libtransport/src/implementation/socket.cc index b80fbb58c..8e9760a5d 100644 --- a/libtransport/src/implementation/socket.cc +++ b/libtransport/src/implementation/socket.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -28,7 +28,7 @@ Socket::Socket(std::shared_ptr<core::Portal> &&portal) verifier_(std::make_shared<auth::VoidVerifier>()) {} int Socket::setSocketOption(int socket_option_key, - hicn_format_t packet_format) { + hicn_packet_format_t packet_format) { switch (socket_option_key) { case interface::GeneralTransportOptions::PACKET_FORMAT: packet_format_ = packet_format; @@ -41,7 +41,7 @@ int Socket::setSocketOption(int socket_option_key, } int Socket::getSocketOption(int socket_option_key, - hicn_format_t &packet_format) { + hicn_packet_format_t &packet_format) { switch (socket_option_key) { case interface::GeneralTransportOptions::PACKET_FORMAT: packet_format = packet_format_; @@ -54,4 +54,4 @@ int Socket::getSocketOption(int socket_option_key, } } // namespace implementation -} // namespace transport
\ No newline at end of file +} // namespace transport diff --git a/libtransport/src/implementation/socket.h b/libtransport/src/implementation/socket.h index 3eb93cff6..55132eb75 100644 --- a/libtransport/src/implementation/socket.h +++ b/libtransport/src/implementation/socket.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -44,8 +44,10 @@ class Socket { return portal_->getThread().getIoService(); } - int setSocketOption(int socket_option_key, hicn_format_t packet_format); - int getSocketOption(int socket_option_key, hicn_format_t &packet_format); + int setSocketOption(int socket_option_key, + hicn_packet_format_t packet_format); + int getSocketOption(int socket_option_key, + hicn_packet_format_t &packet_format); int getSocketOption(int socket_option_key, std::shared_ptr<core::Portal> &socket_option_value) { @@ -69,7 +71,7 @@ class Socket { protected: std::shared_ptr<core::Portal> portal_; bool is_async_; - hicn_format_t packet_format_; + hicn_packet_format_t packet_format_; std::shared_ptr<auth::Signer> signer_; std::shared_ptr<auth::Verifier> verifier_; }; diff --git a/libtransport/src/io_modules/CMakeLists.txt b/libtransport/src/io_modules/CMakeLists.txt index f1a27d3cb..fcf69cd42 100644 --- a/libtransport/src/io_modules/CMakeLists.txt +++ b/libtransport/src/io_modules/CMakeLists.txt @@ -17,11 +17,11 @@ ############################################################## if (${CMAKE_SYSTEM_NAME} MATCHES Android OR ${CMAKE_SYSTEM_NAME} MATCHES iOS) list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn-light-ng/hicn_forwarder_module.cc + ${CMAKE_CURRENT_SOURCE_DIR}/hicn-light/hicn_forwarder_module.cc ) list(APPEND HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn-light-ng/hicn_forwarder_module.h + ${CMAKE_CURRENT_SOURCE_DIR}/hicn-light/hicn_forwarder_module.h ) if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) @@ -69,7 +69,7 @@ else() ############################################################## # Compile submodules ############################################################## - add_subdirectory(hicn-light-ng) + add_subdirectory(hicn-light) add_subdirectory(loopback) add_subdirectory(forwarder) diff --git a/libtransport/src/io_modules/hicn-light-ng/CMakeLists.txt b/libtransport/src/io_modules/hicn-light/CMakeLists.txt index 325a8bd1d..ae3aec52d 100644 --- a/libtransport/src/io_modules/hicn-light-ng/CMakeLists.txt +++ b/libtransport/src/io_modules/hicn-light/CMakeLists.txt @@ -12,7 +12,7 @@ # limitations under the License. if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - find_package(Libhicnctrl ${CURRENT_VERSION} REQUIRED NO_MODULE) + find_package(Libhicnctrl ${HICN_CURRENT_VERSION} REQUIRED NO_MODULE) if (DISABLE_SHARED_LIBRARIES) set(LIBTYPE static) @@ -47,16 +47,17 @@ list(APPEND MODULE_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/hicn_forwarder_module.cc ) -build_module(hicnlightng_module - SHARED - SOURCES ${MODULE_SOURCE_FILES} - DEPENDS ${DEPENDENCIES} - COMPONENT ${LIBTRANSPORT_COMPONENT} - LINK_LIBRARIES PRIVATE ${LIBHICNCTRL_LIBRARIES} - INCLUDE_DIRS - PRIVATE - ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} - ${Libhicnctrl_INCLUDE_DIRS} - DEFINITIONS ${COMPILER_DEFINITIONS} - COMPILE_OPTIONS ${COMPILER_OPTIONS} +build_module(hicnlight_module + SHARED + SOURCES ${MODULE_SOURCE_FILES} + DEPENDS ${DEPENDENCIES} + COMPONENT ${LIBTRANSPORT_COMPONENT} + LINK_LIBRARIES PRIVATE ${LIBHICNCTRL_LIBRARIES} + INCLUDE_DIRS + PRIVATE + ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} + ${Libhicn_INCLUDE_DIRS} + ${Libhicnctrl_INCLUDE_DIRS} + DEFINITIONS ${COMPILER_DEFINITIONS} + COMPILE_OPTIONS ${COMPILER_OPTIONS} ) diff --git a/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc b/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.cc index 95f04822f..ae8aebec6 100644 --- a/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.cc +++ b/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.cc @@ -14,10 +14,10 @@ */ #include <core/udp_connector.h> -#include <io_modules/hicn-light-ng/hicn_forwarder_module.h> +#include <io_modules/hicn-light/hicn_forwarder_module.h> extern "C" { -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> } namespace transport { diff --git a/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h b/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.h index 7f0e7aca8..0d6acb484 100644 --- a/libtransport/src/io_modules/hicn-light-ng/hicn_forwarder_module.h +++ b/libtransport/src/io_modules/hicn-light/hicn_forwarder_module.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -19,7 +19,7 @@ #include <hicn/transport/core/prefix.h> extern "C" { -#include <hicn/ctrl/hicn-light-ng.h> +#include <hicn/ctrl/hicn-light.h> } namespace transport { @@ -32,6 +32,7 @@ class HicnForwarderModule : public IoModule { static constexpr std::uint16_t interface_mtu = 1500; public: +#if 0 union addressLight { uint32_t ipv4; struct in6_addr ipv6; @@ -50,6 +51,7 @@ class HicnForwarderModule : public IoModule { }; using route_to_self_command = struct route_to_self_command; +#endif HicnForwarderModule(); diff --git a/libtransport/src/io_modules/loopback/local_face.cc b/libtransport/src/io_modules/loopback/local_face.cc index 7ef3f1a59..30a46c93b 100644 --- a/libtransport/src/io_modules/loopback/local_face.cc +++ b/libtransport/src/io_modules/loopback/local_face.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -57,12 +57,18 @@ Face &Face::operator=(Face &&other) { void Face::onPacket(const Packet &packet) { DLOG_IF(INFO, VLOG_IS_ON(3)) << "Sending content to local socket."; - if (Packet::isInterest(packet.data())) { - rescheduleOnIoService<Interest>(packet); - } else { - rescheduleOnIoService<ContentObject>(packet); + switch (packet->getFormat()) { + case HICN_PACKET_FORMAT_INTEREST: + rescheduleOnIoService<Interest>(packet); + break; + case HICN_PACKET_FORMAT_DATA: + rescheduleOnIoService<ContentObject>(packet); + break; + default: + /* Should not occur */ + break; } } } // namespace core -} // namespace transport
\ No newline at end of file +} // namespace transport diff --git a/libtransport/src/io_modules/memif/hicn_vapi.c b/libtransport/src/io_modules/memif/hicn_vapi.c index 753679f54..9fc64f720 100644 --- a/libtransport/src/io_modules/memif/hicn_vapi.c +++ b/libtransport/src/io_modules/memif/hicn_vapi.c @@ -53,14 +53,15 @@ static vapi_error_e register_prod_app_cb( if (reply == NULL) return rv; output_params->cs_reserved = reply->cs_reserved; - output_params->prod_addr = (ip_address_t *)malloc(sizeof(ip_address_t)); - memset(output_params->prod_addr, 0, sizeof(ip_address_t)); + output_params->prod_addr = + (hicn_ip_address_t *)malloc(sizeof(hicn_ip_address_t)); + memset(output_params->prod_addr, 0, sizeof(hicn_ip_address_t)); if (reply->prod_addr.af == ADDRESS_IP6) memcpy(&output_params->prod_addr->v6, reply->prod_addr.un.ip6, - sizeof(ip6_address_t)); + sizeof(ipv6_address_t)); else memcpy(&output_params->prod_addr->v4, reply->prod_addr.un.ip4, - sizeof(ip4_address_t)); + sizeof(ipv4_address_t)); output_params->face_id = reply->faceid; return reply->retval; @@ -73,13 +74,14 @@ int hicn_vapi_register_prod_app(vapi_ctx_t ctx, vapi_msg_hicn_api_register_prod_app *msg = vapi_alloc_hicn_api_register_prod_app(ctx); - if (ip_address_is_v4((ip_address_t *)&input_params->prefix->address)) { + if (hicn_ip_address_is_v4( + (hicn_ip_address_t *)&input_params->prefix->address)) { memcpy(&msg->payload.prefix.address.un.ip4, &input_params->prefix->address, - sizeof(ip4_address_t)); + sizeof(ipv4_address_t)); msg->payload.prefix.address.af = ADDRESS_IP4; } else { memcpy(&msg->payload.prefix.address.un.ip6, &input_params->prefix->address, - sizeof(ip6_address_t)); + sizeof(ipv6_address_t)); msg->payload.prefix.address.af = ADDRESS_IP6; } msg->payload.prefix.len = input_params->prefix->len; @@ -121,14 +123,14 @@ static vapi_error_e register_cons_app_cb( if (reply == NULL) return rv; - output_params->src6 = (ip_address_t *)malloc(sizeof(ip_address_t)); - output_params->src4 = (ip_address_t *)malloc(sizeof(ip_address_t)); - memset(output_params->src6, 0, sizeof(ip_address_t)); - memset(output_params->src4, 0, sizeof(ip_address_t)); + output_params->src6 = (hicn_ip_address_t *)malloc(sizeof(hicn_ip_address_t)); + output_params->src4 = (hicn_ip_address_t *)malloc(sizeof(hicn_ip_address_t)); + memset(output_params->src6, 0, sizeof(hicn_ip_address_t)); + memset(output_params->src4, 0, sizeof(hicn_ip_address_t)); memcpy(&output_params->src6->v6, &reply->src_addr6.un.ip6, - sizeof(ip6_address_t)); + sizeof(ipv6_address_t)); memcpy(&output_params->src4->v4, &reply->src_addr4.un.ip4, - sizeof(ip4_address_t)); + sizeof(ipv4_address_t)); output_params->face_id1 = reply->faceid1; output_params->face_id2 = reply->faceid2; @@ -185,27 +187,27 @@ int hicn_vapi_register_route(vapi_ctx_t ctx, vapi_msg_ip_route_add_del *msg = vapi_alloc_ip_route_add_del(ctx, 1); msg->payload.is_add = 1; - if (ip_address_is_v4((ip_address_t *)(input_params->prod_addr))) { + if (hicn_ip_address_is_v4((hicn_ip_address_t *)(input_params->prod_addr))) { memcpy(&msg->payload.route.prefix.address.un.ip4, - &input_params->prefix->address.v4, sizeof(ip4_address_t)); + &input_params->prefix->address.v4, sizeof(ipv4_address_t)); msg->payload.route.prefix.address.af = ADDRESS_IP4; msg->payload.route.prefix.len = input_params->prefix->len; } else { memcpy(&msg->payload.route.prefix.address.un.ip6, - &input_params->prefix->address.v6, sizeof(ip6_address_t)); + &input_params->prefix->address.v6, sizeof(ipv6_address_t)); msg->payload.route.prefix.address.af = ADDRESS_IP6; msg->payload.route.prefix.len = input_params->prefix->len; } msg->payload.route.paths[0].sw_if_index = ~0; msg->payload.route.paths[0].table_id = 0; - if (ip_address_is_v4((ip_address_t *)(input_params->prod_addr))) { + if (hicn_ip_address_is_v4((hicn_ip_address_t *)(input_params->prod_addr))) { memcpy(&(msg->payload.route.paths[0].nh.address.ip4), - input_params->prod_addr->v4.as_u8, sizeof(ip4_address_t)); + input_params->prod_addr->v4.as_u8, sizeof(ipv4_address_t)); msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP4; } else { memcpy(&(msg->payload.route.paths[0].nh.address.ip6), - input_params->prod_addr->v6.as_u8, sizeof(ip6_address_t)); + input_params->prod_addr->v6.as_u8, sizeof(ipv6_address_t)); msg->payload.route.paths[0].proto = FIB_API_PATH_NH_PROTO_IP6; } diff --git a/libtransport/src/io_modules/memif/hicn_vapi.h b/libtransport/src/io_modules/memif/hicn_vapi.h index 967179f68..cfdc93fe3 100644 --- a/libtransport/src/io_modules/memif/hicn_vapi.h +++ b/libtransport/src/io_modules/memif/hicn_vapi.h @@ -27,7 +27,7 @@ extern "C" { #include "stdint.h" typedef struct { - ip_prefix_t* prefix; + hicn_ip_prefix_t* prefix; uint32_t swif; uint32_t cs_reserved; } hicn_producer_input_params; @@ -42,20 +42,20 @@ typedef struct { typedef struct { uint32_t cs_reserved; - ip_address_t* prod_addr; + hicn_ip_address_t* prod_addr; uint32_t face_id; } hicn_producer_output_params; typedef struct { - ip_address_t* src4; - ip_address_t* src6; + hicn_ip_address_t* src4; + hicn_ip_address_t* src6; uint32_t face_id1; uint32_t face_id2; } hicn_consumer_output_params; typedef struct { - ip_prefix_t* prefix; - ip_address_t* prod_addr; + hicn_ip_prefix_t* prefix; + hicn_ip_address_t* prod_addr; } hicn_producer_set_route_params; int hicn_vapi_register_prod_app(vapi_ctx_t ctx, diff --git a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc index c096a71b8..ab11828ec 100644 --- a/libtransport/src/io_modules/memif/vpp_forwarder_module.cc +++ b/libtransport/src/io_modules/memif/vpp_forwarder_module.cc @@ -124,8 +124,8 @@ uint32_t VPPForwarderModule::getMemifConfiguration() { void VPPForwarderModule::consumerConnection() { hicn_consumer_input_params input = {0}; hicn_consumer_output_params output = {0}; - ip_address_t ip4_address; - ip_address_t ip6_address; + hicn_ip_address_t ip4_address; + hicn_ip_address_t ip6_address; output.src4 = &ip4_address; output.src6 = &ip6_address; @@ -181,10 +181,10 @@ void VPPForwarderModule::connect(bool is_consumer) { } void VPPForwarderModule::registerRoute(const Prefix &prefix) { - const ip_prefix_t &addr = prefix.toIpPrefixStruct(); + const hicn_ip_prefix_t &addr = prefix.toIpPrefixStruct(); - ip_prefix_t producer_prefix; - ip_address_t producer_locator; + hicn_ip_prefix_t producer_prefix; + hicn_ip_address_t producer_locator; if (face_id1_ == uint32_t(~0)) { hicn_producer_input_params input; diff --git a/libtransport/src/protocols/prod_protocol_rtc.cc b/libtransport/src/protocols/prod_protocol_rtc.cc index cb8dff6e4..3d1562801 100644 --- a/libtransport/src/protocols/prod_protocol_rtc.cc +++ b/libtransport/src/protocols/prod_protocol_rtc.cc @@ -24,6 +24,10 @@ #include <unordered_set> +extern "C" { +#include <hicn/util/bitmap.h> +} + namespace transport { namespace protocol { @@ -568,7 +572,7 @@ void RTCProductionProtocol::onInterest(Interest &interest) { uint32_t *suffix = interest.firstSuffix(); uint32_t n_suffixes_in_manifest = interest.numberOfSuffixes(); - uint32_t *request_bitmap = interest.getRequestBitmap(); + hicn_uword *request_bitmap = interest.getRequestBitmap(); Name name = interest.getName(); uint32_t pos = 0; // Position of current suffix in manifest @@ -580,7 +584,8 @@ void RTCProductionProtocol::onInterest(Interest &interest) { // Process the suffix in the interest header // (first loop iteration), then suffixes in the manifest do { - if (!interest.hasManifest() || is_bit_set(request_bitmap, pos)) { + if (!interest.hasManifest() || + bitmap_is_set_no_check(request_bitmap, pos)) { const std::shared_ptr<ContentObject> content_object = output_buffer_.find(name); diff --git a/libtransport/src/protocols/rtc/rtc_recovery_strategy.h b/libtransport/src/protocols/rtc/rtc_recovery_strategy.h index aceb85888..405e1ebba 100644 --- a/libtransport/src/protocols/rtc/rtc_recovery_strategy.h +++ b/libtransport/src/protocols/rtc/rtc_recovery_strategy.h @@ -21,6 +21,7 @@ #include <protocols/rtc/rtc_state.h> #include <map> +#include <optional> #include <unordered_map> namespace transport { diff --git a/libtransport/src/test/CMakeLists.txt b/libtransport/src/test/CMakeLists.txt index b7f14766e..356ee0067 100644 --- a/libtransport/src/test/CMakeLists.txt +++ b/libtransport/src/test/CMakeLists.txt @@ -17,7 +17,7 @@ list(APPEND TESTS_SRC main.cc test_aggregated_header.cc - test_auth.cc + #######test_auth.cc # test_consumer_producer_rtc.cc test_core_manifest.cc # test_event_thread.cc @@ -42,11 +42,11 @@ if (ENABLE_RELY) ) endif() -if (UNIX AND NOT APPLE) - list(APPEND TESTS_SRC - test_memif_connector.cc - ) -endif() +#if (UNIX AND NOT APPLE) +# list(APPEND TESTS_SRC +# test_memif_connector.cc +# ) +#endif() ############################################################## diff --git a/libtransport/src/test/packet_samples.h b/libtransport/src/test/packet_samples.h index e98d06a18..216ac7f9f 100644 --- a/libtransport/src/test/packet_samples.h +++ b/libtransport/src/test/packet_samples.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -56,3 +56,16 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +#define SIGNATURE \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 diff --git a/libtransport/src/test/test_aggregated_header.cc b/libtransport/src/test/test_aggregated_header.cc index 0d88af5ab..4dd71f60d 100644 --- a/libtransport/src/test/test_aggregated_header.cc +++ b/libtransport/src/test/test_aggregated_header.cc @@ -54,6 +54,7 @@ class AggregatedPktHeaderTest : public ::testing::Test { } // namespace +#if 0 TEST_F(AggregatedPktHeaderTest, Add2Packets8bit) { uint8_t buf[1500]; std::vector<uint8_t> pkt1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; @@ -103,6 +104,7 @@ TEST_F(AggregatedPktHeaderTest, Add2Packets8bit) { EXPECT_EQ(*(pkt_ptr + i), pkt2[i]); } } +#endif TEST_F(AggregatedPktHeaderTest, Add2Packets8bit255) { uint8_t buf[1500]; diff --git a/libtransport/src/test/test_auth.cc b/libtransport/src/test/test_auth.cc index 0c47dd958..5b9b04c5c 100644 --- a/libtransport/src/test/test_auth.cc +++ b/libtransport/src/test/test_auth.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -42,7 +42,7 @@ class AuthTest : public ::testing::Test { TEST_F(AuthTest, VoidVerifier) { // Create a content object - core::ContentObject packet(HF_INET6_TCP_AH); + core::ContentObject packet(HICN_PACKET_FORMAT_IPV6_TCP_AH); // Fill it with bogus data uint8_t buffer[256] = {0}; @@ -74,7 +74,8 @@ TEST_F(AuthTest, AsymmetricRSA) { CryptoSuite::RSA_SHA256, privateKey, pubKey); // Create a content object - core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + core::ContentObject packet(HICN_PACKET_FORMAT_IPV6_TCP_AH, + signer->getSignatureSize()); // Fill it with bogus data uint8_t buffer[256] = {0}; @@ -87,7 +88,7 @@ TEST_F(AuthTest, AsymmetricRSA) { std::shared_ptr<Verifier> verifier = std::make_shared<AsymmetricVerifier>(pubKey); - EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH); + EXPECT_EQ(packet.getFormat().as_u32, HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32); EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256); EXPECT_EQ(signer->getSuite(), CryptoSuite::RSA_SHA256); EXPECT_EQ(signer->getSignatureSize(), 256u); @@ -189,7 +190,8 @@ TEST_F(AuthTest, AsymmetricVerifierDSA) { CryptoSuite::DSA_SHA256, privateKey, pubKey); // Create a content object - core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + core::ContentObject packet(HICN_PACKET_FORMAT_IPV6_TCP_AH, + signer->getSignatureSize()); // Fill it with bogus data uint8_t buffer[256] = {0}; @@ -200,7 +202,7 @@ TEST_F(AuthTest, AsymmetricVerifierDSA) { std::shared_ptr<Verifier> verifier = std::make_shared<AsymmetricVerifier>(cert); - EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH); + EXPECT_EQ(packet.getFormat().as_u32, HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32); EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256); EXPECT_EQ(signer->getSuite(), CryptoSuite::DSA_SHA256); EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); @@ -259,14 +261,15 @@ TEST_F(AuthTest, AsymmetricVerifierECDSA) { std::shared_ptr<AsymmetricVerifier> verifier = std::make_shared<AsymmetricVerifier>(pubKey); for (int i = 0; i < 100; i++) { - core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + core::ContentObject packet(HICN_PACKET_FORMAT_IPV6_TCP_AH, + signer->getSignatureSize()); // Fill it with bogus data uint8_t buffer[256] = {0}; packet.appendPayload(buffer, 256); signer->signPacket(&packet); - EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH); + EXPECT_EQ(packet.getFormat().as_u32, HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32); EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256); EXPECT_EQ(signer->getSuite(), CryptoSuite::ECDSA_SHA256); EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); @@ -279,7 +282,8 @@ TEST_F(AuthTest, HMACbuffer) { std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256, PASSPHRASE); // Create a content object - core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + core::ContentObject packet(HICN_PACKET_FORMAT_IPV6_TCP_AH, + signer->getSignatureSize()); std::string payload = "bonjour"; std::vector<uint8_t> buffer(payload.begin(), payload.end()); @@ -296,7 +300,8 @@ TEST_F(AuthTest, HMACVerifier) { std::make_shared<SymmetricSigner>(CryptoSuite::HMAC_SHA256, PASSPHRASE); // Create a content object - core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + core::ContentObject packet(HICN_PACKET_FORMAT_IPV6_TCP_AH, + signer->getSignatureSize()); // Fill it with bogus data uint8_t buffer[256] = {0}; @@ -309,7 +314,7 @@ TEST_F(AuthTest, HMACVerifier) { std::shared_ptr<Verifier> verifier = std::make_shared<SymmetricVerifier>(PASSPHRASE); - EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH); + EXPECT_EQ(packet.getFormat().as_u32, HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32); EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256); EXPECT_EQ(signer->getSuite(), CryptoSuite::HMAC_SHA256); EXPECT_EQ(signer->getSignatureSize(), 32u); diff --git a/libtransport/src/test/test_core_manifest.cc b/libtransport/src/test/test_core_manifest.cc index e3d66c1cd..99c71a56c 100644 --- a/libtransport/src/test/test_core_manifest.cc +++ b/libtransport/src/test/test_core_manifest.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -36,7 +36,9 @@ class ManifestTest : public ::testing::Test { using ContentObjectManifest = Manifest<Fixed>; ManifestTest() - : format_(HF_INET6_TCP_AH), name_("b001::123|321"), signature_size_(0) { + : format_(HICN_PACKET_FORMAT_IPV6_TCP_AH), + name_("b001::123|321"), + signature_size_(0) { manifest_ = ContentObjectManifest::createContentManifest(format_, name_, signature_size_); } diff --git a/libtransport/src/test/test_fec_base_rely.cc b/libtransport/src/test/test_fec_base_rely.cc index 41e1eae49..2ee00e25e 100644 --- a/libtransport/src/test/test_fec_base_rely.cc +++ b/libtransport/src/test/test_fec_base_rely.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -46,7 +46,7 @@ class PacketFactory { // create data packet auto data = packet_manager.getPacket<transport::core::ContentObject>( - HF_INET6_TCP, 0); + HICN_PACKET_FORMAT_IPV6_TCP, 0); struct rtc::data_packet_t header; header.setTimestamp(1000); header.setProductionRate(1); @@ -64,7 +64,7 @@ class PacketFactory { auto &packet_manager = core::PacketManager<>::getInstance(); auto data = packet_manager.getPacket<transport::core::ContentObject>( - HF_INET6_TCP, 0); + HICN_PACKET_FORMAT_IPV6_TCP, 0); struct rtc::data_packet_t header; header.setTimestamp(1000); header.setProductionRate(1); @@ -101,7 +101,8 @@ class Encoder { fec::buffer getBuffer(std::size_t size) { auto ret = core::PacketManager<>::getInstance() - .getPacket<transport::core::ContentObject>(HF_INET6_TCP, 0); + .getPacket<transport::core::ContentObject>( + HICN_PACKET_FORMAT_IPV6_TCP, 0); ret->updateLength(rtc::DATA_HEADER_SIZE + size); ret->append(rtc::DATA_HEADER_SIZE + size); ret->trimStart(ret->headerSize() + rtc::DATA_HEADER_SIZE); diff --git a/libtransport/src/test/test_fec_base_rs.cc b/libtransport/src/test/test_fec_base_rs.cc index 7d7bcebc3..549bb3f08 100644 --- a/libtransport/src/test/test_fec_base_rs.cc +++ b/libtransport/src/test/test_fec_base_rs.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -46,7 +46,7 @@ class PacketFactory { // create data packet auto data = packet_manager.getPacket<transport::core::ContentObject>( - HF_INET6_TCP, 0); + HICN_PACKET_FORMAT_IPV6_TCP, 0); struct rtc::data_packet_t header; header.setTimestamp(1000); header.setProductionRate(1); @@ -64,7 +64,7 @@ class PacketFactory { auto &packet_manager = core::PacketManager<>::getInstance(); auto data = packet_manager.getPacket<transport::core::ContentObject>( - HF_INET6_TCP, 0); + HICN_PACKET_FORMAT_IPV6_TCP, 0); struct rtc::data_packet_t header; header.setTimestamp(1000); header.setProductionRate(1); @@ -99,7 +99,8 @@ class Encoder { fec::buffer getBuffer(std::size_t size) { auto ret = core::PacketManager<>::getInstance() - .getPacket<transport::core::ContentObject>(HF_INET6_TCP, 0); + .getPacket<transport::core::ContentObject>( + HICN_PACKET_FORMAT_IPV6_TCP, 0); ret->updateLength(rtc::DATA_HEADER_SIZE + size); ret->append(rtc::DATA_HEADER_SIZE + size); ret->trimStart(ret->headerSize() + rtc::DATA_HEADER_SIZE); diff --git a/libtransport/src/test/test_interest.cc b/libtransport/src/test/test_interest.cc index e36ca0f93..ba63b6c93 100644 --- a/libtransport/src/test/test_interest.cc +++ b/libtransport/src/test/test_interest.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -30,7 +30,8 @@ namespace { // The fixture for testing class Foo. class InterestTest : public ::testing::Test { protected: - InterestTest() : name_("b001::123|321"), interest_(HF_INET6_TCP) { + InterestTest() + : name_("b001::123|321"), interest_(HICN_PACKET_FORMAT_IPV6_TCP) { // You can do set-up work for each test here. } @@ -63,15 +64,18 @@ class InterestTest : public ::testing::Test { PAYLOAD}; }; -void testFormatConstructor(Packet::Format format = HF_UNSPEC) { +void testFormatConstructor( + hicn_packet_format_t format = HICN_PACKET_FORMAT_NONE) { try { Interest interest(format, 0); } catch (...) { - FAIL() << "ERROR: Unexpected exception thrown for " << format; + char buf[MAXSZ_HICN_PACKET_FORMAT]; + FAIL() << "ERROR: Unexpected exception thrown for " << buf; } } -void testFormatConstructorException(Packet::Format format = HF_UNSPEC) { +void testFormatConstructorException( + Packet::Format format = HICN_PACKET_FORMAT_NONE) { try { Interest interest(format, 0); FAIL() << "We expected an exception here"; @@ -86,29 +90,29 @@ void testFormatConstructorException(Packet::Format format = HF_UNSPEC) { TEST_F(InterestTest, ConstructorWithFormat) { /** - * Without arguments it should be format = HF_UNSPEC. + * Without arguments it should be format = HICN_PACKET_FORMAT_NONE. * We expect a crash. */ - testFormatConstructor(Packet::Format::HF_INET_TCP); - testFormatConstructor(Packet::Format::HF_INET6_TCP); - testFormatConstructorException(Packet::Format::HF_INET_ICMP); - testFormatConstructorException(Packet::Format::HF_INET6_ICMP); - testFormatConstructor(Packet::Format::HF_INET_TCP_AH); - testFormatConstructor(Packet::Format::HF_INET6_TCP_AH); - testFormatConstructorException(Packet::Format::HF_INET_ICMP_AH); - testFormatConstructorException(Packet::Format::HF_INET6_ICMP_AH); + testFormatConstructor(HICN_PACKET_FORMAT_IPV4_TCP); + testFormatConstructor(HICN_PACKET_FORMAT_IPV6_TCP); + testFormatConstructorException(HICN_PACKET_FORMAT_IPV4_ICMP); + testFormatConstructorException(HICN_PACKET_FORMAT_IPV6_ICMP); + testFormatConstructor(HICN_PACKET_FORMAT_IPV4_TCP_AH); + testFormatConstructor(HICN_PACKET_FORMAT_IPV6_TCP_AH); + testFormatConstructorException(HICN_PACKET_FORMAT_IPV4_ICMP_AH); + testFormatConstructorException(HICN_PACKET_FORMAT_IPV6_ICMP_AH); } TEST_F(InterestTest, ConstructorWithName) { /** - * Without arguments it should be format = HF_UNSPEC. + * Without arguments it should be format = HICN_PACKET_FORMAT_NONE. * We expect a crash. */ Name n("b001::1|123"); try { - Interest interest(HF_INET6_TCP, n); + Interest interest(HICN_PACKET_FORMAT_IPV6_TCP, n); } catch (...) { FAIL() << "ERROR: Unexpected exception thrown"; } @@ -116,8 +120,10 @@ TEST_F(InterestTest, ConstructorWithName) { TEST_F(InterestTest, ConstructorWithBuffer) { // Ensure buffer is interest +#if 0 auto ret = Interest::isInterest(&buffer_[0]); EXPECT_TRUE(ret); +#endif // Create interest from buffer try { @@ -175,9 +181,9 @@ TEST_F(InterestTest, SetGetLocator) { // Get locator auto l = interest.getLocator(); - ip_address_t address; + hicn_ip_address_t address; inet_pton(AF_INET6, "b006::ab:cdab:cdef", &address); - auto ret = !ip_address_cmp(&l, &address, AF_INET6); + auto ret = !hicn_ip_address_cmp(&l, &address); EXPECT_TRUE(ret); @@ -189,14 +195,14 @@ TEST_F(InterestTest, SetGetLocator) { // Check it was set l = interest.getLocator(); - ret = !ip_address_cmp(&l, &address, AF_INET6); + ret = !hicn_ip_address_cmp(&l, &address); EXPECT_TRUE(ret); } TEST_F(InterestTest, SetGetLifetime) { // Create interest from buffer - Interest interest(HF_INET6_TCP); + Interest interest(HICN_PACKET_FORMAT_IPV6_TCP); const constexpr uint32_t lifetime = 10000; // Set lifetime @@ -211,7 +217,7 @@ TEST_F(InterestTest, SetGetLifetime) { TEST_F(InterestTest, HasManifest) { // Create interest from buffer - Interest interest(HF_INET6_TCP); + Interest interest(HICN_PACKET_FORMAT_IPV6_TCP); // Let's expect anexception here try { @@ -232,7 +238,7 @@ TEST_F(InterestTest, HasManifest) { TEST_F(InterestTest, AppendSuffixesEncodeAndIterate) { // Create interest from buffer - Interest interest(HF_INET6_TCP); + Interest interest(HICN_PACKET_FORMAT_IPV6_TCP); // Appenad some suffixes, with some duplicates interest.appendSuffix(1); @@ -249,7 +255,11 @@ TEST_F(InterestTest, AppendSuffixesEncodeAndIterate) { // Encode them in wire format interest.encodeSuffixes(); + // Decode suffixes from wire format + interest.decodeSuffixes(); + // Iterate over them. They should be in order and without repetitions + auto suffix = interest.firstSuffix(); auto n_suffixes = interest.numberOfSuffixes(); @@ -260,7 +270,7 @@ TEST_F(InterestTest, AppendSuffixesEncodeAndIterate) { TEST_F(InterestTest, AppendSuffixesWithGaps) { // Create interest from buffer - Interest interest(HF_INET6_TCP); + Interest interest(HICN_PACKET_FORMAT_IPV6_TCP); // Appenad some suffixes, out of order and with gaps interest.appendSuffix(6); @@ -272,6 +282,9 @@ TEST_F(InterestTest, AppendSuffixesWithGaps) { interest.encodeSuffixes(); EXPECT_TRUE(interest.hasManifest()); + // Decode suffixes from wire format + interest.decodeSuffixes(); + // Check first suffix correctness auto suffix = interest.firstSuffix(); EXPECT_NE(suffix, nullptr); @@ -289,7 +302,7 @@ TEST_F(InterestTest, AppendSuffixesWithGaps) { TEST_F(InterestTest, InterestWithoutManifest) { // Create interest without manifest - Interest interest(HF_INET6_TCP); + Interest interest(HICN_PACKET_FORMAT_IPV6_TCP); auto suffix = interest.firstSuffix(); EXPECT_FALSE(interest.hasManifest()); diff --git a/libtransport/src/test/test_packet.cc b/libtransport/src/test/test_packet.cc index ca20cdfb7..3dfca8f9a 100644 --- a/libtransport/src/test/test_packet.cc +++ b/libtransport/src/test/test_packet.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -23,6 +23,8 @@ #include <random> #include <vector> +#include "../../lib/src/protocol.h" + namespace transport { namespace core { @@ -56,13 +58,13 @@ class PacketForTest : public Packet { throw errors::NotImplementedException(); } - void setLocator(const ip_address_t &locator) override { + void setLocator(const hicn_ip_address_t &locator) override { throw errors::NotImplementedException(); } void resetForHash() override { throw errors::NotImplementedException(); } - ip_address_t getLocator() const override { + hicn_ip_address_t getLocator() const override { throw errors::NotImplementedException(); } }; @@ -73,8 +75,9 @@ class PacketTest : public ::testing::Test { protected: PacketTest() : name_("b001::123|321"), - packet(Packet::COPY_BUFFER, &raw_packets_[HF_INET6_TCP][0], - raw_packets_[HF_INET6_TCP].size()) { + packet(Packet::COPY_BUFFER, + &raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size()) { // You can do set-up work for each test here. } @@ -99,7 +102,7 @@ class PacketTest : public ::testing::Test { PacketForTest packet; - static std::map<Packet::Format, std::vector<uint8_t>> raw_packets_; + static std::map<uint32_t, std::vector<uint8_t>> raw_packets_; std::vector<uint8_t> payload = { 0x11, 0x11, 0x01, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -115,8 +118,8 @@ class PacketTest : public ::testing::Test { }; }; -std::map<Packet::Format, std::vector<uint8_t>> PacketTest::raw_packets_ = { - {Packet::Format::HF_INET6_TCP, +std::map<uint32_t, std::vector<uint8_t>> PacketTest::raw_packets_ = { + {HICN_PACKET_FORMAT_IPV6_TCP.as_u32, {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca IPV6_HEADER(TCP_PROTO, 20 + PAYLOAD_SIZE), @@ -125,7 +128,7 @@ std::map<Packet::Format, std::vector<uint8_t>> PacketTest::raw_packets_ = { // Payload PAYLOAD}}, - {Packet::Format::HF_INET_TCP, + {HICN_PACKET_FORMAT_IPV4_TCP.as_u32, {// IPv4 src=3.13.127.8, dst=192.168.1.92 IPV4_HEADER(TCP_PROTO, 20 + PAYLOAD_SIZE), // TCP src=0x1234 dst=0x4321, seq=0x0001 @@ -133,64 +136,68 @@ std::map<Packet::Format, std::vector<uint8_t>> PacketTest::raw_packets_ = { // Other PAYLOAD}}, - {Packet::Format::HF_INET_ICMP, + {HICN_PACKET_FORMAT_IPV4_ICMP.as_u32, {// IPv4 src=3.13.127.8, dst=192.168.1.92 IPV4_HEADER(ICMP_PROTO, 64), // ICMP echo request ICMP_ECHO_REQUEST}}, - {Packet::Format::HF_INET6_ICMP, + {HICN_PACKET_FORMAT_IPV6_ICMP.as_u32, {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca IPV6_HEADER(ICMP6_PROTO, 60), // ICMP6 echo request ICMP6_ECHO_REQUEST}}, - {Packet::Format::HF_INET6_TCP_AH, + {HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32, {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca IPV6_HEADER(TCP_PROTO, 20 + 44 + 128), // ICMP6 echo request TCP_HEADER(0x18), // hICN AH header - AH_HEADER}}, + AH_HEADER, SIGNATURE}}, - {Packet::Format::HF_INET_TCP_AH, + {HICN_PACKET_FORMAT_IPV4_TCP_AH.as_u32, {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca IPV4_HEADER(TCP_PROTO, 20 + 44 + 128), // ICMP6 echo request TCP_HEADER(0x18), // hICN AH header - AH_HEADER}}, + AH_HEADER, SIGNATURE}}, // XXX No flag defined in ICMP header to signal AH header. - {Packet::Format::HF_INET_ICMP_AH, + {HICN_PACKET_FORMAT_IPV4_ICMP_AH.as_u32, {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca IPV4_HEADER(ICMP_PROTO, 64 + 44), // ICMP6 echo request ICMP_ECHO_REQUEST, // hICN AH header - AH_HEADER}}, + AH_HEADER, SIGNATURE}}, - {Packet::Format::HF_INET6_ICMP_AH, + {HICN_PACKET_FORMAT_IPV6_ICMP_AH.as_u32, {// IPv6 src=b001::ab:cdab:cdef, dst=b002::ca IPV6_HEADER(ICMP6_PROTO, 60 + 44), // ICMP6 echo request ICMP6_ECHO_REQUEST, // hICN AH header - AH_HEADER}}, + AH_HEADER, SIGNATURE}}, }; -void testFormatConstructor(Packet::Format format = HF_UNSPEC) { +void testFormatConstructor(Packet::Format format = HICN_PACKET_FORMAT_NONE) { try { - PacketForTest packet(format); + PacketForTest packet(HICN_PACKET_TYPE_INTEREST, format); } catch (...) { - FAIL() << "ERROR: Unexpected exception thrown for " << format; + char buf[MAXSZ_HICN_PACKET_FORMAT]; + int rc = hicn_packet_format_snprintf(buf, MAXSZ_HICN_PACKET_FORMAT, format); + if (rc < 0 || rc >= MAXSZ_HICN_PACKET_FORMAT) + snprintf(buf, MAXSZ_HICN_PACKET_FORMAT, "%s", "(error"); + FAIL() << "ERROR: Unexpected exception thrown for " << buf; } } void testFormatAndAdditionalHeaderConstructor(Packet::Format format, std::size_t additional_header) { - PacketForTest packet(format, additional_header); + PacketForTest packet(HICN_PACKET_TYPE_INTEREST, format, additional_header); // Packet length should be the one of the normal header + the // additional_header @@ -206,7 +213,7 @@ void testRawBufferConstructor(std::vector<uint8_t> packet, packet.size()); // Check format is expected one. - EXPECT_EQ(p.getFormat(), format); + EXPECT_EQ(p.getFormat().as_u32, format.as_u32); // // Try the same using a MemBuf // auto buf = utils::MemBuf::wrapBuffer(&packet[0], packet.size()); @@ -229,17 +236,19 @@ void testRawBufferConstructor(std::vector<uint8_t> packet, PacketForTest p(Packet::WRAP_BUFFER, &packet[0], packet.size(), packet.size()); - // Format should fallback to HF_UNSPEC - EXPECT_EQ(p.getFormat(), HF_UNSPEC); + // Format should fallback to HICN_PACKET_FORMAT_NONE + EXPECT_EQ(p.getFormat().as_u32, HICN_PACKET_FORMAT_NONE.as_u32); + } catch (errors::MalformedPacketException &exc) { + // Ok right exception } catch (...) { FAIL() << "ERROR: Unexpected exception thrown."; } } -void getHeaderSizeFromBuffer(Packet::Format format, - std::vector<uint8_t> &packet, +void getHeaderSizeFromBuffer(std::vector<uint8_t> &packet, std::size_t expected) { - auto header_size = PacketForTest::getHeaderSizeFromBuffer(format, &packet[0]); + auto header_size = + PacketForTest::getHeaderSizeFromBuffer(&packet[0], packet.size()); EXPECT_EQ(header_size, expected); } @@ -248,18 +257,17 @@ void getHeaderSizeFromFormat(Packet::Format format, std::size_t expected) { EXPECT_EQ(header_size, expected); } -void getPayloadSizeFromBuffer(Packet::Format format, - std::vector<uint8_t> &packet, +void getPayloadSizeFromBuffer(std::vector<uint8_t> &packet, std::size_t expected) { auto payload_size = - PacketForTest::getPayloadSizeFromBuffer(format, &packet[0]); + PacketForTest::getPayloadSizeFromBuffer(&packet[0], packet.size()); EXPECT_EQ(payload_size, expected); } void getFormatFromBuffer(Packet::Format expected, std::vector<uint8_t> &packet) { auto format = PacketForTest::getFormatFromBuffer(&packet[0], packet.size()); - EXPECT_EQ(format, expected); + EXPECT_EQ(format.as_u32, expected.as_u32); } void getHeaderSize(std::size_t expected, const PacketForTest &packet) { @@ -269,143 +277,160 @@ void getHeaderSize(std::size_t expected, const PacketForTest &packet) { void testGetFormat(Packet::Format expected, const Packet &packet) { auto format = packet.getFormat(); - EXPECT_EQ(format, expected); + EXPECT_EQ(format.as_u32, expected.as_u32); } } // namespace TEST_F(PacketTest, ConstructorWithFormat) { - testFormatConstructor(Packet::Format::HF_INET_TCP); - testFormatConstructor(Packet::Format::HF_INET6_TCP); - testFormatConstructor(Packet::Format::HF_INET_ICMP); - testFormatConstructor(Packet::Format::HF_INET6_ICMP); - testFormatConstructor(Packet::Format::HF_INET_TCP_AH); - testFormatConstructor(Packet::Format::HF_INET6_TCP_AH); - testFormatConstructor(Packet::Format::HF_INET_ICMP_AH); - testFormatConstructor(Packet::Format::HF_INET6_ICMP_AH); + testFormatConstructor(HICN_PACKET_FORMAT_IPV4_TCP); + testFormatConstructor(HICN_PACKET_FORMAT_IPV6_TCP); + testFormatConstructor(HICN_PACKET_FORMAT_IPV4_ICMP); + testFormatConstructor(HICN_PACKET_FORMAT_IPV6_ICMP); + testFormatConstructor(HICN_PACKET_FORMAT_IPV4_TCP_AH); + testFormatConstructor(HICN_PACKET_FORMAT_IPV6_TCP_AH); + testFormatConstructor(HICN_PACKET_FORMAT_IPV4_ICMP_AH); + testFormatConstructor(HICN_PACKET_FORMAT_IPV6_ICMP_AH); } TEST_F(PacketTest, ConstructorWithFormatAndAdditionalHeader) { - testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET_TCP, 123); - testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET6_TCP, 360); - testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET_ICMP, 21); - testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET6_ICMP, 444); - testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET_TCP_AH, 555); - testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET6_TCP_AH, - 321); - testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET_ICMP_AH, + testFormatAndAdditionalHeaderConstructor(HICN_PACKET_FORMAT_IPV4_TCP, 123); + testFormatAndAdditionalHeaderConstructor(HICN_PACKET_FORMAT_IPV6_TCP, 360); + testFormatAndAdditionalHeaderConstructor(HICN_PACKET_FORMAT_IPV4_ICMP, 21); + testFormatAndAdditionalHeaderConstructor(HICN_PACKET_FORMAT_IPV6_ICMP, 444); + testFormatAndAdditionalHeaderConstructor(HICN_PACKET_FORMAT_IPV4_TCP_AH, 555); + testFormatAndAdditionalHeaderConstructor(HICN_PACKET_FORMAT_IPV6_TCP_AH, 321); + testFormatAndAdditionalHeaderConstructor(HICN_PACKET_FORMAT_IPV4_ICMP_AH, 123); - testFormatAndAdditionalHeaderConstructor(Packet::Format::HF_INET6_ICMP_AH, - 44); + testFormatAndAdditionalHeaderConstructor(HICN_PACKET_FORMAT_IPV6_ICMP_AH, 44); } TEST_F(PacketTest, ConstructorWithNew) { - auto &_packet = raw_packets_[HF_INET6_TCP]; + auto &_packet = raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32]; auto packet_ptr = new PacketForTest(Packet::WRAP_BUFFER, &_packet[0], _packet.size(), _packet.size()); delete packet_ptr; } TEST_F(PacketTest, ConstructorWithRawBufferInet6Tcp) { - auto format = Packet::Format::HF_INET6_TCP; - testRawBufferConstructor(raw_packets_[format], format); + auto format = HICN_PACKET_FORMAT_IPV6_TCP; + testRawBufferConstructor(raw_packets_[format.as_u32], format); } TEST_F(PacketTest, ConstructorWithRawBufferInetTcp) { - auto format = Packet::Format::HF_INET_TCP; - testRawBufferConstructor(raw_packets_[format], format); + auto format = HICN_PACKET_FORMAT_IPV4_TCP; + testRawBufferConstructor(raw_packets_[format.as_u32], format); } TEST_F(PacketTest, ConstructorWithRawBufferInetIcmp) { - auto format = Packet::Format::HF_INET_ICMP; - testRawBufferConstructor(raw_packets_[format], format); + auto format = HICN_PACKET_FORMAT_IPV4_ICMP; + testRawBufferConstructor(raw_packets_[format.as_u32], format); } TEST_F(PacketTest, ConstructorWithRawBufferInet6Icmp) { - auto format = Packet::Format::HF_INET6_ICMP; - testRawBufferConstructor(raw_packets_[format], format); + auto format = HICN_PACKET_FORMAT_IPV6_ICMP; + testRawBufferConstructor(raw_packets_[format.as_u32], format); } TEST_F(PacketTest, ConstructorWithRawBufferInet6TcpAh) { - auto format = Packet::Format::HF_INET6_TCP_AH; - testRawBufferConstructor(raw_packets_[format], format); + auto format = HICN_PACKET_FORMAT_IPV6_TCP_AH; + testRawBufferConstructor(raw_packets_[format.as_u32], format); } TEST_F(PacketTest, ConstructorWithRawBufferInetTcpAh) { - auto format = Packet::Format::HF_INET_TCP_AH; - testRawBufferConstructor(raw_packets_[format], format); + auto format = HICN_PACKET_FORMAT_IPV4_TCP_AH; + testRawBufferConstructor(raw_packets_[format.as_u32], format); } TEST_F(PacketTest, MoveConstructor) { - PacketForTest p0(Packet::Format::HF_INET6_TCP); + PacketForTest p0(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP); PacketForTest p1(std::move(p0)); - EXPECT_EQ(p0.getFormat(), Packet::Format::HF_UNSPEC); - EXPECT_EQ(p1.getFormat(), Packet::Format::HF_INET6_TCP); + EXPECT_EQ(p0.getFormat().as_u32, HICN_PACKET_FORMAT_NONE.as_u32); + EXPECT_EQ(p1.getFormat().as_u32, HICN_PACKET_FORMAT_IPV6_TCP.as_u32); } TEST_F(PacketTest, TestGetHeaderSizeFromBuffer) { - getHeaderSizeFromBuffer(HF_INET6_TCP, raw_packets_[HF_INET6_TCP], - HICN_V6_TCP_HDRLEN); - getHeaderSizeFromBuffer(HF_INET_TCP, raw_packets_[HF_INET_TCP], - HICN_V4_TCP_HDRLEN); - getHeaderSizeFromBuffer(HF_INET6_ICMP, raw_packets_[HF_INET6_ICMP], + getHeaderSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32], + IPV6_HDRLEN + TCP_HDRLEN); + getHeaderSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP.as_u32], + IPV4_HDRLEN + TCP_HDRLEN); + getHeaderSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32], IPV6_HDRLEN + 4); - getHeaderSizeFromBuffer(HF_INET_ICMP, raw_packets_[HF_INET_ICMP], + getHeaderSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV4_ICMP.as_u32], IPV4_HDRLEN + 4); - getHeaderSizeFromBuffer(HF_INET6_TCP_AH, raw_packets_[HF_INET6_TCP_AH], - HICN_V6_TCP_AH_HDRLEN + 128); - getHeaderSizeFromBuffer(HF_INET_TCP_AH, raw_packets_[HF_INET_TCP_AH], - HICN_V4_TCP_AH_HDRLEN + 128); + getHeaderSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32], + IPV6_HDRLEN + TCP_HDRLEN + AH_HDRLEN + 128); + getHeaderSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP_AH.as_u32], + IPV4_HDRLEN + TCP_HDRLEN + AH_HDRLEN + 128); } TEST_F(PacketTest, TestGetHeaderSizeFromFormat) { - getHeaderSizeFromFormat(HF_INET6_TCP, HICN_V6_TCP_HDRLEN); - getHeaderSizeFromFormat(HF_INET_TCP, HICN_V4_TCP_HDRLEN); - getHeaderSizeFromFormat(HF_INET6_ICMP, IPV6_HDRLEN + 4); - getHeaderSizeFromFormat(HF_INET_ICMP, IPV4_HDRLEN + 4); - getHeaderSizeFromFormat(HF_INET6_TCP_AH, HICN_V6_TCP_AH_HDRLEN); - getHeaderSizeFromFormat(HF_INET_TCP_AH, HICN_V4_TCP_AH_HDRLEN); + getHeaderSizeFromFormat(HICN_PACKET_FORMAT_IPV6_TCP, + IPV6_HDRLEN + TCP_HDRLEN); + getHeaderSizeFromFormat(HICN_PACKET_FORMAT_IPV4_TCP, + IPV4_HDRLEN + TCP_HDRLEN); + getHeaderSizeFromFormat(HICN_PACKET_FORMAT_IPV6_ICMP, IPV6_HDRLEN + 4); + getHeaderSizeFromFormat(HICN_PACKET_FORMAT_IPV4_ICMP, IPV4_HDRLEN + 4); + getHeaderSizeFromFormat(HICN_PACKET_FORMAT_IPV6_TCP_AH, + IPV6_HDRLEN + TCP_HDRLEN + AH_HDRLEN); + getHeaderSizeFromFormat(HICN_PACKET_FORMAT_IPV4_TCP_AH, + IPV4_HDRLEN + TCP_HDRLEN + AH_HDRLEN); } TEST_F(PacketTest, TestGetPayloadSizeFromBuffer) { - getPayloadSizeFromBuffer(HF_INET6_TCP, raw_packets_[HF_INET6_TCP], 12); - getPayloadSizeFromBuffer(HF_INET_TCP, raw_packets_[HF_INET_TCP], 12); - getPayloadSizeFromBuffer(HF_INET6_ICMP, raw_packets_[HF_INET6_ICMP], 56); - getPayloadSizeFromBuffer(HF_INET_ICMP, raw_packets_[HF_INET_ICMP], 60); - getPayloadSizeFromBuffer(HF_INET6_TCP_AH, raw_packets_[HF_INET6_TCP_AH], 0); - getPayloadSizeFromBuffer(HF_INET_TCP_AH, raw_packets_[HF_INET_TCP_AH], 0); -} - + getPayloadSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32], + 12); + getPayloadSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP.as_u32], + 12); + getPayloadSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32], + 56); + getPayloadSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV4_ICMP.as_u32], + 60); + getPayloadSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32], + 0); + getPayloadSizeFromBuffer(raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP_AH.as_u32], + 0); +} + +#if 0 TEST_F(PacketTest, TestIsInterest) { - auto ret = PacketForTest::isInterest(&raw_packets_[HF_INET6_TCP][0]); + auto ret = PacketForTest::isInterest(&raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32][0]); EXPECT_TRUE(ret); } +#endif TEST_F(PacketTest, TestGetFormatFromBuffer) { - getFormatFromBuffer(HF_INET6_TCP, raw_packets_[HF_INET6_TCP]); - getFormatFromBuffer(HF_INET_TCP, raw_packets_[HF_INET_TCP]); - getFormatFromBuffer(HF_INET6_ICMP, raw_packets_[HF_INET6_ICMP]); - getFormatFromBuffer(HF_INET_ICMP, raw_packets_[HF_INET_ICMP]); - getFormatFromBuffer(HF_INET6_TCP_AH, raw_packets_[HF_INET6_TCP_AH]); - getFormatFromBuffer(HF_INET_TCP_AH, raw_packets_[HF_INET_TCP_AH]); + getFormatFromBuffer(HICN_PACKET_FORMAT_IPV6_TCP, + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32]); + getFormatFromBuffer(HICN_PACKET_FORMAT_IPV4_TCP, + raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP.as_u32]); + getFormatFromBuffer(HICN_PACKET_FORMAT_IPV6_ICMP, + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32]); + getFormatFromBuffer(HICN_PACKET_FORMAT_IPV4_ICMP, + raw_packets_[HICN_PACKET_FORMAT_IPV4_ICMP.as_u32]); + getFormatFromBuffer(HICN_PACKET_FORMAT_IPV6_TCP_AH, + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32]); + getFormatFromBuffer(HICN_PACKET_FORMAT_IPV4_TCP_AH, + raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP_AH.as_u32]); } // TEST_F(PacketTest, TestReplace) { -// PacketForTest packet(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_TCP][0], -// raw_packets_[HF_INET6_TCP].size()); +// PacketForTest packet(Packet::WRAP_BUFFER, +// &raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32][0], +// raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size()); // // Replace current packet with another one -// packet.replace(&raw_packets_[HF_INET_TCP][0], -// raw_packets_[HF_INET_TCP].size()); +// packet.replace(&raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP.as_u32][0], +// raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP.as_u32].size()); // // Check new format -// ASSERT_EQ(packet.getFormat(), HF_INET_TCP); +// ASSERT_EQ(packet.getFormat(), HICN_PACKET_FORMAT_IPV4_TCP); // } TEST_F(PacketTest, TestPayloadSize) { // Check payload size of existing packet - auto &_packet = raw_packets_[HF_INET6_TCP]; + auto &_packet = raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32]; PacketForTest packet(Packet::WRAP_BUFFER, &_packet[0], _packet.size(), _packet.size()); @@ -415,7 +440,7 @@ TEST_F(PacketTest, TestPayloadSize) { std::string payload0(1024, 'X'); // Create the packet - PacketForTest packet2(HF_INET6_TCP); + PacketForTest packet2(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP); // Payload size should now be zero EXPECT_EQ(packet2.payloadSize(), std::size_t(0)); @@ -442,22 +467,29 @@ TEST_F(PacketTest, TestPayloadSize) { } TEST_F(PacketTest, TestHeaderSize) { - getHeaderSize(HICN_V6_TCP_HDRLEN, - PacketForTest(Packet::Format::HF_INET6_TCP)); - getHeaderSize(HICN_V4_TCP_HDRLEN, PacketForTest(Packet::Format::HF_INET_TCP)); - getHeaderSize(HICN_V6_ICMP_HDRLEN, - PacketForTest(Packet::Format::HF_INET6_ICMP)); - getHeaderSize(HICN_V4_ICMP_HDRLEN, - PacketForTest(Packet::Format::HF_INET_ICMP)); - getHeaderSize(HICN_V6_TCP_AH_HDRLEN, - PacketForTest(Packet::Format::HF_INET6_TCP_AH)); - getHeaderSize(HICN_V4_TCP_AH_HDRLEN, - PacketForTest(Packet::Format::HF_INET_TCP_AH)); + getHeaderSize( + IPV6_HDRLEN + TCP_HDRLEN, + PacketForTest(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP)); + getHeaderSize( + IPV4_HDRLEN + TCP_HDRLEN, + PacketForTest(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV4_TCP)); + getHeaderSize( + IPV6_HDRLEN + ICMP_HDRLEN, + PacketForTest(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_ICMP)); + getHeaderSize( + IPV4_HDRLEN + ICMP_HDRLEN, + PacketForTest(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV4_ICMP)); + getHeaderSize( + IPV6_HDRLEN + TCP_HDRLEN + AH_HDRLEN, + PacketForTest(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP_AH)); + getHeaderSize( + IPV4_HDRLEN + TCP_HDRLEN + AH_HDRLEN, + PacketForTest(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV4_TCP_AH)); } TEST_F(PacketTest, TestMemBufReference) { // Create packet - auto &_packet = raw_packets_[HF_INET6_TCP]; + auto &_packet = raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32]; // Packet was not created as a shared_ptr. If we try to get a membuf shared // ptr we should get an exception. @@ -498,16 +530,17 @@ TEST_F(PacketTest, TestMemBufReference) { TEST_F(PacketTest, TestReset) { // Check everything is ok - EXPECT_EQ(packet.getFormat(), HF_INET6_TCP); - EXPECT_EQ(packet.length(), raw_packets_[HF_INET6_TCP].size()); - EXPECT_EQ(packet.headerSize(), HICN_V6_TCP_HDRLEN); + EXPECT_EQ(packet.getFormat().as_u32, HICN_PACKET_FORMAT_IPV6_TCP.as_u32); + EXPECT_EQ(packet.length(), + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size()); + EXPECT_EQ(packet.headerSize(), IPV6_HDRLEN + TCP_HDRLEN); EXPECT_EQ(packet.payloadSize(), packet.length() - packet.headerSize()); // Reset the packet packet.reset(); // Rerun test - EXPECT_EQ(packet.getFormat(), HF_UNSPEC); + EXPECT_EQ(packet.getFormat().as_u32, HICN_PACKET_FORMAT_NONE.as_u32); EXPECT_EQ(packet.length(), std::size_t(0)); EXPECT_EQ(packet.headerSize(), std::size_t(0)); EXPECT_EQ(packet.payloadSize(), std::size_t(0)); @@ -548,7 +581,7 @@ TEST_F(PacketTest, TestAppendPayload) { // There should be no more bufferls left in the chain EXPECT_EQ(&packet, packet.next()); - EXPECT_EQ(packet.getFormat(), HF_UNSPEC); + EXPECT_EQ(packet.getFormat().as_u32, HICN_PACKET_FORMAT_NONE.as_u32); EXPECT_EQ(packet.length(), std::size_t(0)); EXPECT_EQ(packet.headerSize(), std::size_t(0)); EXPECT_EQ(packet.payloadSize(), std::size_t(0)); @@ -557,6 +590,7 @@ TEST_F(PacketTest, TestAppendPayload) { TEST_F(PacketTest, GetPayload) { // Append payload with raw buffer uint8_t raw_buffer[2048]; + memset(raw_buffer, 0, sizeof(raw_buffer)); auto original_payload_length = packet.payloadSize(); packet.appendPayload(raw_buffer, 2048); @@ -621,61 +655,63 @@ TEST_F(PacketTest, SetGetPayloadType) { TEST_F(PacketTest, GetFormat) { { PacketForTest p0(Packet::WRAP_BUFFER, - &raw_packets_[Packet::Format::HF_INET_TCP][0], - raw_packets_[Packet::Format::HF_INET_TCP].size(), - raw_packets_[Packet::Format::HF_INET_TCP].size()); - testGetFormat(Packet::Format::HF_INET_TCP, p0); + &raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP.as_u32].size()); + testGetFormat(HICN_PACKET_FORMAT_IPV4_TCP, p0); PacketForTest p1(Packet::WRAP_BUFFER, - &raw_packets_[Packet::Format::HF_INET6_TCP][0], - raw_packets_[Packet::Format::HF_INET6_TCP].size(), - raw_packets_[Packet::Format::HF_INET6_TCP].size()); - testGetFormat(Packet::Format::HF_INET6_TCP, p1); + &raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size()); + testGetFormat(HICN_PACKET_FORMAT_IPV6_TCP, p1); PacketForTest p2(Packet::WRAP_BUFFER, - &raw_packets_[Packet::Format::HF_INET_ICMP][0], - raw_packets_[Packet::Format::HF_INET_ICMP].size(), - raw_packets_[Packet::Format::HF_INET_ICMP].size()); - testGetFormat(Packet::Format::HF_INET_ICMP, p2); + &raw_packets_[HICN_PACKET_FORMAT_IPV4_ICMP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV4_ICMP.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV4_ICMP.as_u32].size()); + testGetFormat(HICN_PACKET_FORMAT_IPV4_ICMP, p2); PacketForTest p3(Packet::WRAP_BUFFER, - &raw_packets_[Packet::Format::HF_INET6_ICMP][0], - raw_packets_[Packet::Format::HF_INET6_ICMP].size(), - raw_packets_[Packet::Format::HF_INET6_ICMP].size()); - testGetFormat(Packet::Format::HF_INET6_ICMP, p3); - - PacketForTest p4(Packet::WRAP_BUFFER, - &raw_packets_[Packet::Format::HF_INET_TCP_AH][0], - raw_packets_[Packet::Format::HF_INET_TCP_AH].size(), - raw_packets_[Packet::Format::HF_INET_TCP_AH].size()); - testGetFormat(Packet::Format::HF_INET_TCP_AH, p4); - - PacketForTest p5(Packet::WRAP_BUFFER, - &raw_packets_[Packet::Format::HF_INET6_TCP_AH][0], - raw_packets_[Packet::Format::HF_INET6_TCP_AH].size(), - raw_packets_[Packet::Format::HF_INET6_TCP_AH].size()); - testGetFormat(Packet::Format::HF_INET6_TCP_AH, p5); + &raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32].size()); + testGetFormat(HICN_PACKET_FORMAT_IPV6_ICMP, p3); + + PacketForTest p4( + Packet::WRAP_BUFFER, + &raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP_AH.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP_AH.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV4_TCP_AH.as_u32].size()); + testGetFormat(HICN_PACKET_FORMAT_IPV4_TCP_AH, p4); + + PacketForTest p5( + Packet::WRAP_BUFFER, + &raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP_AH.as_u32].size()); + testGetFormat(HICN_PACKET_FORMAT_IPV6_TCP_AH, p5); } // Let's try now creating empty packets { - PacketForTest p0(Packet::Format::HF_INET_TCP); - testGetFormat(Packet::Format::HF_INET_TCP, p0); + PacketForTest p0(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV4_TCP); + testGetFormat(HICN_PACKET_FORMAT_IPV4_TCP, p0); - PacketForTest p1(Packet::Format::HF_INET6_TCP); - testGetFormat(Packet::Format::HF_INET6_TCP, p1); + PacketForTest p1(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP); + testGetFormat(HICN_PACKET_FORMAT_IPV6_TCP, p1); - PacketForTest p2(Packet::Format::HF_INET_ICMP); - testGetFormat(Packet::Format::HF_INET_ICMP, p2); + PacketForTest p2(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV4_ICMP); + testGetFormat(HICN_PACKET_FORMAT_IPV4_ICMP, p2); - PacketForTest p3(Packet::Format::HF_INET6_ICMP); - testGetFormat(Packet::Format::HF_INET6_ICMP, p3); + PacketForTest p3(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_ICMP); + testGetFormat(HICN_PACKET_FORMAT_IPV6_ICMP, p3); - PacketForTest p4(Packet::Format::HF_INET_TCP_AH); - testGetFormat(Packet::Format::HF_INET_TCP_AH, p4); + PacketForTest p4(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV4_TCP_AH); + testGetFormat(HICN_PACKET_FORMAT_IPV4_TCP_AH, p4); - PacketForTest p5(Packet::Format::HF_INET6_TCP_AH); - testGetFormat(Packet::Format::HF_INET6_TCP_AH, p5); + PacketForTest p5(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP_AH); + testGetFormat(HICN_PACKET_FORMAT_IPV6_TCP_AH, p5); } } @@ -707,7 +743,7 @@ TEST_F(PacketTest, SetGetTestSignatureTimestamp) { } // Now let's construct a AH packet, with no additional space for signature - PacketForTest p(HF_INET6_TCP_AH); + PacketForTest p(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP_AH); p.setSignatureTimestamp(now); uint64_t now_get = p.getSignatureTimestamp(); @@ -741,7 +777,7 @@ TEST_F(PacketTest, TestSetGetValidationAlgorithm) { } // Now let's construct a AH packet, with no additional space for signature - PacketForTest p(HF_INET6_TCP_AH); + PacketForTest p(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP_AH); p.setValidationAlgorithm(auth::CryptoSuite::RSA_SHA256); auto v_get = p.getValidationAlgorithm(); @@ -751,6 +787,7 @@ TEST_F(PacketTest, TestSetGetValidationAlgorithm) { TEST_F(PacketTest, TestSetGetKeyId) { uint8_t key[32]; + memset(key, 0, sizeof(key)); auth::KeyId key_id = std::make_pair(key, sizeof(key)); try { @@ -762,7 +799,7 @@ TEST_F(PacketTest, TestSetGetKeyId) { FAIL() << "Unexpected exception"; } - // Same fot get method + // Same for get method try { auto k = packet.getKeyId(); // Let's make compiler happy @@ -775,7 +812,7 @@ TEST_F(PacketTest, TestSetGetKeyId) { } // Now let's construct a AH packet, with no additional space for signature - PacketForTest p(HF_INET6_TCP_AH); + PacketForTest p(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP_AH); p.setKeyId(key_id); auto p_get = p.getKeyId(); @@ -799,7 +836,8 @@ TEST_F(PacketTest, DISABLED_TestChecksum) { EXPECT_TRUE(integrity); // Check with AH header and 300 bytes signature - PacketForTest p(HF_INET6_TCP_AH, 300); + PacketForTest p(HICN_PACKET_TYPE_INTEREST, HICN_PACKET_FORMAT_IPV6_TCP_AH, + 300); std::string payload(5000, 'X'); p.appendPayload((const uint8_t *)payload.c_str(), payload.size() / 2); p.appendPayload((const uint8_t *)(payload.c_str() + payload.size() / 2), @@ -810,116 +848,13 @@ TEST_F(PacketTest, DISABLED_TestChecksum) { EXPECT_TRUE(integrity); } -TEST_F(PacketTest, TestSetSyn) { - // Test syn of non-tcp format and check exception is thrown - try { - auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0], - raw_packets_[HF_INET6_ICMP].size(), - raw_packets_[HF_INET6_ICMP].size()); - // Let's make compiler happy - p.setSyn(); - FAIL() << "We should not reach this point."; - } catch (const errors::RuntimeException &exc) { - /* ok right exception*/ - } catch (...) { - FAIL() << "Unexpected exception"; - } - - packet.setSyn(); - EXPECT_TRUE(packet.testSyn()); - - packet.resetSyn(); - EXPECT_FALSE(packet.testSyn()); -} - -TEST_F(PacketTest, TestSetFin) { - // Test syn of non-tcp format and check exception is thrown - try { - auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0], - raw_packets_[HF_INET6_ICMP].size(), - raw_packets_[HF_INET6_ICMP].size()); - // Let's make compiler happy - p.setFin(); - FAIL() << "We should not reach this point."; - } catch (const errors::RuntimeException &exc) { - /* ok right exception*/ - } catch (...) { - FAIL() << "Unexpected exception"; - } - - packet.setFin(); - EXPECT_TRUE(packet.testFin()); - - packet.resetFin(); - EXPECT_FALSE(packet.testFin()); -} - -TEST_F(PacketTest, TestSetAck) { - // Test syn of non-tcp format and check exception is thrown - try { - auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0], - raw_packets_[HF_INET6_ICMP].size(), - raw_packets_[HF_INET6_ICMP].size()); - // Let's make compiler happy - p.setAck(); - FAIL() << "We should not reach this point."; - } catch (const errors::RuntimeException &exc) { - /* ok right exception*/ - } catch (...) { - FAIL() << "Unexpected exception"; - } - - packet.setAck(); - EXPECT_TRUE(packet.testAck()); - - packet.resetAck(); - EXPECT_FALSE(packet.testAck()); -} - -TEST_F(PacketTest, TestSetRst) { - // Test syn of non-tcp format and check exception is thrown - try { - auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0], - raw_packets_[HF_INET6_ICMP].size(), - raw_packets_[HF_INET6_ICMP].size()); - // Let's make compiler happy - p.setRst(); - FAIL() << "We should not reach this point."; - } catch (const errors::RuntimeException &exc) { - /* ok right exception*/ - } catch (...) { - FAIL() << "Unexpected exception"; - } - - packet.setRst(); - EXPECT_TRUE(packet.testRst()); - - packet.resetRst(); - EXPECT_FALSE(packet.testRst()); -} - -TEST_F(PacketTest, TestResetFlags) { - packet.setRst(); - packet.setSyn(); - packet.setAck(); - packet.setFin(); - EXPECT_TRUE(packet.testRst()); - EXPECT_TRUE(packet.testAck()); - EXPECT_TRUE(packet.testFin()); - EXPECT_TRUE(packet.testSyn()); - - packet.resetFlags(); - EXPECT_FALSE(packet.testRst()); - EXPECT_FALSE(packet.testAck()); - EXPECT_FALSE(packet.testFin()); - EXPECT_FALSE(packet.testSyn()); -} - TEST_F(PacketTest, TestSetGetSrcPort) { try { - auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0], - raw_packets_[HF_INET6_ICMP].size(), - raw_packets_[HF_INET6_ICMP].size()); + auto p = + PacketForTest(Packet::WRAP_BUFFER, + &raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32].size()); // Let's make compiler happy p.setSrcPort(12345); FAIL() << "We should not reach this point."; @@ -935,9 +870,11 @@ TEST_F(PacketTest, TestSetGetSrcPort) { TEST_F(PacketTest, TestSetGetDstPort) { try { - auto p = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0], - raw_packets_[HF_INET6_ICMP].size(), - raw_packets_[HF_INET6_ICMP].size()); + auto p = + PacketForTest(Packet::WRAP_BUFFER, + &raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32].size()); // Let's make compiler happy p.setDstPort(12345); FAIL() << "We should not reach this point."; @@ -955,58 +892,73 @@ TEST_F(PacketTest, TestEnsureCapacity) { PacketForTest &p = packet; // This shoul be false - auto ret = p.ensureCapacity(raw_packets_[HF_INET6_TCP].size() + 10); + auto ret = p.ensureCapacity( + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size() + 10); EXPECT_FALSE(ret); // This should be true - ret = p.ensureCapacity(raw_packets_[HF_INET6_TCP].size()); + ret = + p.ensureCapacity(raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size()); EXPECT_TRUE(ret); // This should be true - ret = p.ensureCapacity(raw_packets_[HF_INET6_TCP].size() - 10); + ret = p.ensureCapacity( + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size() - 10); EXPECT_TRUE(ret); // Try to trim the packet start p.trimStart(10); // Now this should be false - ret = p.ensureCapacity(raw_packets_[HF_INET6_TCP].size()); + ret = + p.ensureCapacity(raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size()); EXPECT_FALSE(ret); // Create a new packet - auto p2 = PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_ICMP][0], - raw_packets_[HF_INET6_ICMP].size(), - raw_packets_[HF_INET6_ICMP].size()); + auto p2 = + PacketForTest(Packet::WRAP_BUFFER, + &raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32].size(), + raw_packets_[HICN_PACKET_FORMAT_IPV6_ICMP.as_u32].size()); p2.appendPayload(utils::MemBuf::createCombined(2000)); // This should be false, since the buffer is chained - ret = p2.ensureCapacity(raw_packets_[HF_INET6_TCP].size() - 10); + ret = p2.ensureCapacity( + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size() - 10); EXPECT_FALSE(ret); } -TEST_F(PacketTest, TestEnsureCapacityAndFillUnused) { +// +// This test is disabled as it manipulates a ipv6 header with the wrong payload +// length inside. +// +TEST_F(PacketTest, DISABLED_TestEnsureCapacityAndFillUnused) { // Create packet by excluding the payload (So only L3 + L4 headers). The // payload will be trated as unused tailroom - PacketForTest p = - PacketForTest(Packet::WRAP_BUFFER, &raw_packets_[HF_INET6_TCP][0], - raw_packets_[HF_INET6_TCP].size() - PAYLOAD_SIZE, - raw_packets_[HF_INET6_TCP].size()); + PacketForTest p = PacketForTest( + Packet::WRAP_BUFFER, &raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32][0], + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size() - PAYLOAD_SIZE, + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size()); // Copy original packet payload, which is here trated as a unused tailroom uint8_t original_payload[PAYLOAD_SIZE]; - uint8_t *payload = &raw_packets_[HF_INET6_TCP][0] + - raw_packets_[HF_INET6_TCP].size() - PAYLOAD_SIZE; + uint8_t *payload = &raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32][0] + + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size() - + PAYLOAD_SIZE; std::memcpy(original_payload, payload, PAYLOAD_SIZE); // This should be true and the unused tailroom should be unmodified auto ret = p.ensureCapacityAndFillUnused( - raw_packets_[HF_INET6_TCP].size() - (PAYLOAD_SIZE + 10), 0); + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size() - + (PAYLOAD_SIZE + 10), + 0); EXPECT_TRUE(ret); ret = std::memcmp(original_payload, payload, PAYLOAD_SIZE); EXPECT_EQ(ret, 0); // This should fill the payload with zeros - ret = p.ensureCapacityAndFillUnused(raw_packets_[HF_INET6_TCP].size(), 0); + ret = p.ensureCapacityAndFillUnused( + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size(), 0); EXPECT_TRUE(ret); uint8_t zeros[PAYLOAD_SIZE]; std::memset(zeros, 0, PAYLOAD_SIZE); @@ -1014,7 +966,8 @@ TEST_F(PacketTest, TestEnsureCapacityAndFillUnused) { EXPECT_EQ(ret, 0); // This should fill the payload with ones - ret = p.ensureCapacityAndFillUnused(raw_packets_[HF_INET6_TCP].size(), 1); + ret = p.ensureCapacityAndFillUnused( + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size(), 1); EXPECT_TRUE(ret); uint8_t ones[PAYLOAD_SIZE]; std::memset(ones, 1, PAYLOAD_SIZE); @@ -1022,7 +975,8 @@ TEST_F(PacketTest, TestEnsureCapacityAndFillUnused) { EXPECT_EQ(ret, 0); // This should return false and the payload should be unmodified - ret = p.ensureCapacityAndFillUnused(raw_packets_[HF_INET6_TCP].size() + 1, 1); + ret = p.ensureCapacityAndFillUnused( + raw_packets_[HICN_PACKET_FORMAT_IPV6_TCP.as_u32].size() + 1, 1); EXPECT_FALSE(ret); ret = std::memcmp(payload, ones, PAYLOAD_SIZE); EXPECT_EQ(ret, 0); diff --git a/libtransport/src/test/test_packet_allocator.cc b/libtransport/src/test/test_packet_allocator.cc index 744f1bd24..0de35a817 100644 --- a/libtransport/src/test/test_packet_allocator.cc +++ b/libtransport/src/test/test_packet_allocator.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Cisco and/or its affiliates. + * Copyright (c) 2021-2022 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: @@ -70,11 +70,11 @@ class PacketAllocatorTest : public ::testing::Test { }; TEST_F(PacketAllocatorTest, ContentObjectAllocation) { - allocationTest<core::ContentObject>(HF_INET_TCP); + allocationTest<core::ContentObject>(HICN_PACKET_FORMAT_IPV4_TCP); } TEST_F(PacketAllocatorTest, InterestAllocation) { - allocationTest<core::Interest>(HF_INET_TCP); + allocationTest<core::Interest>(HICN_PACKET_FORMAT_IPV4_TCP); } // TEST_F(PacketAllocatorTest, MemBufAllocation) { @@ -83,7 +83,8 @@ TEST_F(PacketAllocatorTest, InterestAllocation) { TEST_F(PacketAllocatorTest, CheckAllocationIsCorrect) { // Create packet - auto packet = allocator_.getPacket<core::ContentObject>(HF_INET_TCP); + auto packet = + allocator_.getPacket<core::ContentObject>(HICN_PACKET_FORMAT_IPV4_TCP); // Address of actual buffer uint8_t *buffer_address = packet->writableData(); @@ -128,4 +129,4 @@ TEST_F(PacketAllocatorTest, CheckAllocationSpeed) { } } // namespace core -} // namespace transport
\ No newline at end of file +} // namespace transport diff --git a/libtransport/src/test/test_prefix.cc b/libtransport/src/test/test_prefix.cc index 5de737566..3eab72bcb 100644 --- a/libtransport/src/test/test_prefix.cc +++ b/libtransport/src/test/test_prefix.cc @@ -194,47 +194,47 @@ TEST_F(PrefixTest, SetGetNetwork) { TEST_F(PrefixTest, Contains) { // IPv6 prefix Prefix p0(prefix_str0); - ip_address_t ip0, ip1; + hicn_ip_address_t ip0, ip1; - ip_address_pton("2001:db8:1::1234", &ip0); - ip_address_pton("2001:db9:1::1234", &ip1); + hicn_ip_address_pton("2001:db8:1::1234", &ip0); + hicn_ip_address_pton("2001:db9:1::1234", &ip1); EXPECT_TRUE(p0.contains(ip0)); EXPECT_FALSE(p0.contains(ip1)); Prefix p1(prefix_str1); - ip_address_pton("10.11.12.12", &ip0); - ip_address_pton("10.12.12.13", &ip1); + hicn_ip_address_pton("10.11.12.12", &ip0); + hicn_ip_address_pton("10.12.12.13", &ip1); EXPECT_TRUE(p1.contains(ip0)); EXPECT_FALSE(p1.contains(ip1)); Prefix p2(prefix_str2); - ip_address_pton("2001:db8:1::dbca", &ip0); - ip_address_pton("10.12.12.12", &ip1); + hicn_ip_address_pton("2001:db8:1::dbca", &ip0); + hicn_ip_address_pton("10.12.12.12", &ip1); EXPECT_TRUE(p2.contains(ip0)); EXPECT_FALSE(p2.contains(ip1)); Prefix p3(prefix_str3); - ip_address_pton("10.11.12.245", &ip0); - ip_address_pton("10.11.12.1", &ip1); + hicn_ip_address_pton("10.11.12.245", &ip0); + hicn_ip_address_pton("10.11.12.1", &ip1); EXPECT_TRUE(p3.contains(ip0)); EXPECT_FALSE(p3.contains(ip1)); // Corner cases Prefix p4("::/0"); - ip_address_pton("7001:db8:1::1234", &ip0); - ip_address_pton("8001:db8:1::1234", &ip1); + hicn_ip_address_pton("7001:db8:1::1234", &ip0); + hicn_ip_address_pton("8001:db8:1::1234", &ip1); EXPECT_TRUE(p4.contains(ip0)); EXPECT_TRUE(p4.contains(ip1)); // Corner cases Prefix p5("b001:a:b:c:d:e:f:1/128"); - ip_address_pton("b001:a:b:c:d:e:f:1", &ip0); - ip_address_pton("b001:a:b:c:d:e:f:2", &ip1); + hicn_ip_address_pton("b001:a:b:c:d:e:f:1", &ip0); + hicn_ip_address_pton("b001:a:b:c:d:e:f:2", &ip1); EXPECT_TRUE(p5.contains(ip0)); EXPECT_FALSE(p5.contains(ip1)); @@ -331,4 +331,4 @@ TEST_F(PrefixTest, MakeNameWithIndex) { } // namespace } // namespace core -} // namespace transport
\ No newline at end of file +} // namespace transport diff --git a/libtransport/third-party/CMakeLists.txt b/libtransport/third-party/CMakeLists.txt index ad7b14ead..bcda41c1e 100644 --- a/libtransport/third-party/CMakeLists.txt +++ b/libtransport/third-party/CMakeLists.txt @@ -110,7 +110,7 @@ if(UNIX AND (NOT APPLE) AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES Android)) GIT_TAG v${MEMIF_VERSION} GIT_SHALLOW GIT_PROGRESS - PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/memif.patch + PATCH_COMMAND git apply ${CMAKE_CURRENT_SOURCE_DIR}/memif.patch || true EXCLUDE_FROM_ALL ) diff --git a/scripts/checkstyle.sh b/scripts/checkstyle.sh index 46cba4507..786e81cfe 100644 --- a/scripts/checkstyle.sh +++ b/scripts/checkstyle.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Cisco and/or its affiliates. +# Copyright (c) 2022 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -11,4 +11,93 @@ # See the License for the specific language governing permissions and # limitations under the License. -exit 0 +#!/bin/bash + +set -eEo pipefail + +sudo apt-get install -y clang-format-12 + +CLANG_FORMAT_VER_REGEX='([0-9]+)\.[0-9]+\.[0-9]+' +CLANG_FORMAT_DIFF="/usr/share/clang/clang-format-diff.py" + +if [[ -z ${CHANGE_TARGET} ]]; then + DIFF_TARGET="HEAD~1" +else + DIFF_TARGET="origin/${CHANGE_TARGET}...HEAD" +fi + +CLANG_FORMAT_VER=${CLANG_FORMAT_VER:-12} +GIT_DIFF_ARGS="-U0 --no-color --relative ${DIFF_TARGET}" +CLANG_FORMAT_DIFF_ARGS="-style file -p1" +SUFFIX="-${CLANG_FORMAT_VER}" + +# Attempt to find clang-format to confirm Clang version. +if command -v clang-format${SUFFIX} &>/dev/null; then + CLANG_FORMAT=clang-format${SUFFIX} +elif command -v clang-format &>/dev/null; then + CLANG_FORMAT=clang-format +fi + +CLANG_FORMAT_VERSION=$(${CLANG_FORMAT} --version) +echo $CLANG_FORMAT_VERSION + +# Confirm that Clang is the expected version. +if [[ ! $CLANG_FORMAT_VERSION =~ $CLANG_FORMAT_VER_REGEX ]]; then + echo "*******************************************************************" + echo "* CHECKSTYLE VERSION REGEX CHECK FAILED" + echo "* $CLANG_FORMAT_VERSION" + echo "*******************************************************************" + exit 1 +fi + +if [[ ! $CLANG_FORMAT_VER == "${BASH_REMATCH[1]}" ]]; then + echo "*******************************************************************" + echo "* CHECKSTYLE VERSION CHECK FAILED" + echo "* Expected major version $CLANG_FORMAT_VER, found ${BASH_REMATCH[1]}" + echo "*******************************************************************" + exit 1 +fi + +# Attempt to find clang-format-diff. +if command -v clang-format-diff${SUFFIX} &>/dev/null; then + CLANG_FORMAT_DIFF=clang-format-diff${SUFFIX} +elif command -v clang-format-diff &>/dev/null; then + CLANG_FORMAT=clang-format-diff +elif [ ! -f $CLANG_FORMAT_DIFF ]; then + echo "*******************************************************************" + echo "* CHECKSTYLE FAILED" + echo "* Could not locate the clang-format-diff script" + echo "*******************************************************************" + exit 1 +fi + +in=$(mktemp) +git diff ${GIT_DIFF_ARGS} ':!*.patch' >${in} + +out=$(mktemp) +cat ${in} | ${CLANG_FORMAT_DIFF} ${CLANG_FORMAT_DIFF_ARGS} >${out} +rm ${in} + +line_count=$(cat ${out} | wc -l) + +if [ -t 1 ] && [ -n $(tput colors) ] && [ $(tput colors) -ge 1 ] && + command -v highlight &>/dev/null; then + highlight --syntax diff -O ansi ${out} +else + cat ${out} +fi + +rm ${out} + +if [ ${line_count} -gt 0 ]; then + echo "*******************************************************************" + echo "* CHECKSTYLE FAILED" + echo "* CONSULT DIFF ABOVE" + echo "*******************************************************************" + exit 1 +else + echo "*******************************************************************" + echo "* CHECKSTYLE SUCCESSFULLY COMPLETED" + echo "*******************************************************************" + exit 0 +fi diff --git a/tests/1-node.yml b/tests/1-node.yml index 5cd8bd46c..a543e70f1 100644 --- a/tests/1-node.yml +++ b/tests/1-node.yml @@ -16,6 +16,7 @@ services: command: - | if [ -d /workspace/build-dev ]; then + git config --global --add safe.directory \* ninja -C /workspace/build-dev install fi diff --git a/versions.cmake b/versions.cmake index 97e843298..722b49df4 100644 --- a/versions.cmake +++ b/versions.cmake @@ -6,5 +6,5 @@ set(LIBMEMIF_DEFAULT_VERSION "22.02" "EXACT") set(LIBCONFIG_DEFAULT_VERSION "1.5.0") set(COLLECTD_DEFAULT_VERSION "5.9.2" "EXACT") set(RDKAFKA_DEFAULT_VERSION "1.8.2" "EXACT") -set(ANDORID_SDK_DEP_DEFAULT_VERSION "2.1.1" "EXACT") -set(IOS_TOOLCHAIN_DEP_DEFAULT_VERSION "1.0.1" "EXACT") +set(ANDORID_SDK_DEP_DEFAULT_VERSION "2.1.2" "EXACT") +set(IOS_TOOLCHAIN_DEP_DEFAULT_VERSION "1.0.2" "EXACT") |