# Release Notes {#release_notes} * @subpage release_notes_2001 * @subpage release_notes_1908 * @subpage release_notes_19042 * @subpage release_notes_19041 * @subpage release_notes_1904 * @subpage release_notes_19013 * @subpage release_notes_19012 * @subpage release_notes_19011 * @subpage release_notes_1901 * @subpage release_notes_1810 * @subpage release_notes_1807 * @subpage release_notes_1804 * @subpage release_notes_18012 * @subpage release_notes_18011 * @subpage release_notes_1801 * @subpage release_notes_1710 * @subpage release_notes_1707 * @subpage release_notes_1704 * @subpage release_notes_17011 * @subpage release_notes_1701 * @subpage release_notes_1609 * @subpage release_notes_1606 @page release_notes_2001 Release notes for VPP 20.01 TBD @page release_notes_1908 Release notes for VPP 19.08 More than 850 commits since the 19.04 release. ## Features ### Infrastructure - API - API language: new types and limits support - Python API - add support for defaults - Export ip_types.api for out-of-tree plugins use - Refactor ipip.api with explicit types - DPDK - 19.05 integration - Remove bonding code - Rework extended stats - Debugging & Servicability - debug CLI leak-checker - vlib: add "memory-trace stats-segment" - vppapitrace JSON/API trace converter - ARP: add arp-disabled node - igmp: Trace more data from input packets - ip: Trace the packet from the punt node - Python API debug introspection improvements - Pin dependencies for make test infra - FEATURE.yaml meta-data infrastructure - tcp: add cc stats plotting tools - Packet tracer support for thread handoffs - libmemif: support for multi-thread connection establishment - svm - fifo ooo reads/writes with multiple chunks - support addition/removal of chunks to fifos - vppinfra - Mapped pcap file support - More AVX2 and AVX512 inlines - VLIB_INIT_FUNCTION sequencing rework - refactor spinlocks and rwlocks - add rbtree - add doubly linked list - rdma: bump rdma-core to v25.0 - stats - Add the number of worker threads and per worker thread vector rates - Support multiple workers for error counters ### VNET & Plugins - New Plugins - HTTP static page server with TLS support - L3 cross connect - acl: implement stat-segment counters - arp: add feature arcs: arp-reply, arp-input, arp-proxy - avf: improved logging and added 2.5/5 Gbps speeds - bonding: NUMA-related improvements - crypto: add support for AES-CTR cipher - fib - FIB Entry tracking - Support the POP of a Pseudo Wire Control Word - gbp - Anonymous l3-out subnets support - ARP unicast forward in gbp bridge domain - An Endpoint can change sclass - Consider data-plane learnt source better than control-plane - VRF scoped contracts - gso (experimental) - Add support to pg interfaces - Add support to vhost user - Add support to native virtio - Add support for tagged interfaces - punt: allow to specify packets by IP protocol Type - ip6-local: hop-by-hop protocol demux table - ipsec - intel-ipsec-mb version 0.52 - AH encrypt rework - handle UDP keepalives - support GCM in ESP - virtio - Refactor control queue support - dhcp-client: DSCP marking for transmitted packets - Idle resource usage improvements - Allocate bihash virtual space on demand - gre: don't register gre input nodes unless a gre tunnel is created - gtpu: don't register udp ports unless a tunnel is created - lacp: create lacp-process on demand - lisp-cp: start lisp retry service on demand - start the cdp period and dns resolver process on demand - vat: unload unused vat plugins - nat: api cleanup & update - nsim: make available as an output feature - load-balance performance improvements - l2: Add support for arp unicast forwarding - mactime - Mini-ACLs - Per-MAC allow-with-quota feature - qos - QoS dump APIs - Store function - rdma: add support for promiscuous mode (l2-switching and xconnect) - sr: update the Segment Routing definition to be compliant with current in IETF - udp-ping: disable due to conflict with mldv2 - vxlan-gpe: improve encap performance - vom - QoS support - Bridge domain arp unicast forwarding flag - Bridge domain unknown unicast flooding flag ### Host stack - session - API to support manual svm fifo resizing - Improved session output scheduler and close state machine - Transport and session cleanup notifications for builtin apps - Session migration notifications for builtin apps - Support for no session layer lookup transports (quic and tls) - Ability to retrieve local/remote endpoint in transport vft - Cleanup segment manager and fifo segment - Fix vpp to app msg generation on enqueue fail - Improve event logging - Moved test applications to hsa plugin - tcp - Congestion control algorithm enhancements - Delivery rate estimator - ACK/retransmission refactor and pacing - Add tcp-input sibling nodes without full 6-tuple lookup - More RFC4898 connection statistics - Allow custom output next node - Allow custom congestion control algorithms - quic - Multi-thread support - Logs readability improvements - Multistream support - tls - Fix close with data and listen failures - Handle TCP transport rests - Support endpoint retrieval interface - vcl - support quic streams and "connectable listeners" - worker unregister api - fix epoll with large events batch - ldp: add option to eanble transparent TLS connections - udp: - support close with data - fixed session migration - sctp - add option to enable/disable default to disable - moved from vnet to plugins ## Known issues For the full list of issues please refer to fd.io [JIRA](https://jira.fd.io). ## Issues fixed For the full list of fixed issues please refer to: - fd.io [JIRA](https://jira.fd.io) - git [commit log](https://git.fd.io/vpp/log/?h=stable/1908) ## API changes Description of results: * _Definition changed_: indicates that the API file was modified between releases. * _Only in image_: indicates the API is new for this release. * _Only in file_: indicates the API has been removed in this release. Message Name | Result -------------------------------------------------------------|------------------ abf_itf_attach_add_del | definition changed abf_itf_attach_details | definition changed abf_policy_add_del | definition changed abf_policy_details | definition changed acl_add_replace | definition changed acl_details | definition changed acl_stats_intf_counters_enable | only in image acl_stats_intf_counters_enable_reply | only in image api_versions_reply | definition changed bd_ip_mac_add_del | definition changed bd_ip_mac_details | definition changed bier_disp_entry_add_del | definition changed bier_disp_entry_details | definition changed bier_imp_add | definition changed bier_imp_details | definition changed bier_route_add_del | definition changed bier_route_details | definition changed bier_route_dump | definition changed bier_table_add_del | definition changed bier_table_details | definition changed bond_create | definition changed bridge_domain_add_del | definition changed bridge_domain_details | definition changed bridge_flags | definition changed connect_sock | definition changed create_vhost_user_if | definition changed ct6_enable | only in file ct6_enable_disable | only in image ct6_enable_disable_reply | only in image ct6_enable_disable | only in file dhcp6_pd_reply_event | definition changed dhcp6_pd_send_client_message | definition changed dhcp6_reply_event | definition changed dhcp6_send_client_message | definition changed dhcp_client_config | definition changed dhcp_client_details | definition changed dhcp_compl_event | definition changed dhcp_proxy_details | definition changed dslite_add_del_pool_addr_range | definition changed dslite_address_details | definition changed dslite_get_aftr_addr_reply | definition changed dslite_get_b4_addr_reply | definition changed dslite_set_aftr_addr | definition changed dslite_set_b4_addr | definition changed gbp_bridge_domain_add | definition changed gbp_bridge_domain_details | definition changed gbp_contract_add_del | definition changed gbp_contract_details | definition changed gbp_endpoint_add | definition changed gbp_endpoint_details | definition changed gbp_endpoint_group_add | definition changed gbp_endpoint_group_details | definition changed gbp_ext_itf_add_del | definition changed gbp_ext_itf_details | definition changed gbp_recirc_add_del | definition changed gbp_recirc_details | definition changed gbp_route_domain_add | definition changed gbp_route_domain_details | definition changed gbp_subnet_add_del | definition changed gbp_subnet_details | definition changed gbp_vxlan_tunnel_add | definition changed gbp_vxlan_tunnel_details | definition changed get_f64_endian_value | only in image get_f64_endian_value_reply | only in image get_f64_increment_by_one | only in image get_f64_increment_by_one_reply | only in image gpe_add_del_fwd_entry | definition changed gpe_fwd_entries_get_reply | definition changed gpe_fwd_entry_path_details | definition changed gpe_native_fwd_rpaths_get_reply | definition changed gre_add_del_tunnel | only in file gre_add_del_tunnel_reply | only in file gre_tunnel_add_del | only in image gre_tunnel_add_del_reply | only in image gre_tunnel_details | definition changed gre_tunnel_dump | definition changed http_static_enable | only in image http_static_enable_reply | only in image igmp_event | definition changed igmp_group_prefix_details | definition changed igmp_group_prefix_set | definition changed igmp_listen | definition changed ip6_fib_details | only in file ip6_fib_dump | only in file ip6_mfib_details | only in file ip6_mfib_dump | only in file ip6_ra_event | definition changed ip_add_del_route | only in file ip_add_del_route_reply | only in file ip_address_details | definition changed ip_container_proxy_add_del | definition changed ip_container_proxy_details | definition changed ip_fib_details | only in file ip_fib_dump | only in file ip_mfib_details | only in file ip_mfib_dump | only in file ip_mroute_add_del | definition changed ip_mroute_details | only in image ip_mroute_dump | only in image ip_mtable_details | only in image ip_mtable_dump | only in image ip_neighbor_add_del | definition changed ip_neighbor_details | definition changed ip_probe_neighbor | definition changed ip_punt_redirect | definition changed ip_punt_redirect_details | definition changed ip_reassembly_get_reply | definition changed ip_reassembly_set | definition changed ip_route_add_del | only in image ip_route_add_del_reply | only in image ip_route_details | only in image ip_route_dump | only in image ip_source_and_port_range_check_add_del | definition changed ip_table_add_del | definition changed ip_table_details | only in image ip_table_dump | only in image ipfix_flush | only in image ipfix_flush_reply | only in image ipip_6rd_add_tunnel | definition changed ipip_add_tunnel | definition changed ipip_tunnel_details | definition changed ipsec_backend_details | definition changed ipsec_gre_tunnel_add_del | only in file ipsec_gre_tunnel_add_del_reply | only in file ipsec_gre_tunnel_details | only in file ipsec_gre_tunnel_dump | only in file ipsec_sa_details | definition changed ipsec_sa_set_key | only in file ipsec_sa_set_key_reply | only in file ipsec_sad_entry_add_del | definition changed ipsec_select_backend | definition changed ipsec_spd_details | definition changed ipsec_spd_entry_add_del | definition changed ipsec_tunnel_if_add_del | definition changed ipsec_tunnel_if_set_key | only in file ipsec_tunnel_if_set_key_reply | only in file ipsec_tunnel_protect_del | only in image ipsec_tunnel_protect_del_reply | only in image ipsec_tunnel_protect_details | only in image ipsec_tunnel_protect_dump | only in image ipsec_tunnel_protect_update | only in image ipsec_tunnel_protect_update_reply | only in image l2_macs_event | definition changed l3xc_del | only in image l3xc_del_reply | only in image l3xc_details | only in image l3xc_dump | only in image l3xc_plugin_get_version | only in image l3xc_plugin_get_version_reply | only in image l3xc_update | only in image l3xc_update_reply | only in image lb_add_del_as | definition changed lb_add_del_vip | definition changed lb_as_details | only in image lb_as_dump | only in image lb_flush_vip | definition changed lb_vip_details | only in image lb_vip_dump | only in image lisp_add_del_locator_set | definition changed lisp_add_del_remote_mapping | definition changed lisp_adjacencies_get_reply | definition changed log_details | only in image log_dump | only in image macip_acl_add | definition changed macip_acl_add_replace | definition changed macip_acl_details | definition changed mactime_add_del_range | definition changed map_add_domain | definition changed map_domain_details | definition changed mfib_signal_details | definition changed modify_vhost_user_if | definition changed mpls_fib_details | only in file mpls_fib_dump | only in file mpls_ip_bind_unbind | definition changed mpls_route_add_del | definition changed mpls_route_details | only in image mpls_route_dump | only in image mpls_table_add_del | definition changed mpls_table_details | only in image mpls_table_dump | only in image mpls_tunnel_add_del | definition changed mpls_tunnel_details | definition changed nat44_add_del_address_range | definition changed nat44_add_del_identity_mapping | definition changed nat44_add_del_interface_addr | definition changed nat44_add_del_lb_static_mapping | definition changed nat44_add_del_static_mapping | definition changed nat44_address_details | definition changed nat44_del_session | definition changed nat44_forwarding_enable_disable | definition changed nat44_forwarding_is_enabled_reply | definition changed nat44_identity_mapping_details | definition changed nat44_interface_add_del_feature | definition changed nat44_interface_add_del_output_feature | definition changed nat44_interface_addr_details | definition changed nat44_interface_details | definition changed nat44_interface_output_feature_details | definition changed nat44_lb_static_mapping_add_del_local | definition changed nat44_lb_static_mapping_details | definition changed nat44_static_mapping_details | definition changed nat44_user_details | definition changed nat44_user_session_details | definition changed nat44_user_session_dump | definition changed nat64_add_del_interface_addr | definition changed nat64_add_del_interface | definition changed nat64_add_del_pool_addr_range | definition changed nat64_add_del_prefix | definition changed nat64_add_del_static_bib | definition changed nat64_bib_details | definition changed nat64_interface_details | definition changed nat64_pool_addr_details | definition changed nat64_prefix_details | definition changed nat64_st_details | definition changed nat66_add_del_interface | definition changed nat66_add_del_static_mapping | definition changed nat66_interface_details | definition changed nat66_static_mapping_details | definition changed nat_det_add_del_map | definition changed nat_det_close_session_in | definition changed nat_det_close_session_out | definition changed nat_det_forward | definition changed nat_det_forward_reply | definition changed nat_det_map_details | definition changed nat_det_reverse | definition changed nat_det_reverse_reply | definition changed nat_det_session_details | definition changed nat_det_session_dump | definition changed nat_get_mss_clamping_reply | definition changed nat_ipfix_enable_disable | definition changed nat_reass_details | definition changed nat_set_log_level | only in image nat_set_log_level_reply | only in image nat_set_mss_clamping | definition changed nat_set_reass | definition changed nat_show_config_reply | definition changed nat_worker_details | definition changed nsim_cross_connect_enable_disable | only in image nsim_cross_connect_enable_disable_reply | only in image nsim_enable_disable | only in file nsim_enable_disable_reply | only in file nsim_output_feature_enable_disable | only in image nsim_output_feature_enable_disable_reply | only in image oam_add_del | only in file oam_add_del_reply | only in file oam_event | only in file one_add_del_locator_set | definition changed one_add_del_remote_mapping | definition changed one_adjacencies_get_reply | definition changed one_l2_arp_entries_get_reply | definition changed one_ndp_entries_get_reply | definition changed p2p_ethernet_add | definition changed p2p_ethernet_add_reply | definition changed p2p_ethernet_del | definition changed pg_create_interface | definition changed proxy_arp_add_del | definition changed proxy_arp_details | definition changed punt_details | only in file punt_dump | only in file punt_reason_details | only in image punt_reason_dump | only in image punt_socket_deregister | definition changed punt_socket_details | definition changed punt_socket_dump | definition changed punt_socket_register | definition changed qos_egress_map_delete | definition changed qos_egress_map_details | only in image qos_egress_map_dump | only in image qos_egress_map_update | definition changed qos_mark_details | only in image qos_mark_details_reply | only in image qos_mark_dump | only in image qos_mark_enable_disable | definition changed qos_record_details | only in image qos_record_dump | only in image qos_record_enable_disable | definition changed qos_store_details | only in image qos_store_dump | only in image qos_store_enable_disable | only in image qos_store_enable_disable_reply | only in image sctp_add_src_dst_connection | only in file sctp_add_src_dst_connection_reply | only in file sctp_config | only in file sctp_config_reply | only in file sctp_del_src_dst_connection | only in file sctp_del_src_dst_connection_reply | only in file set_punt | definition changed show_threads_reply | definition changed show_vpe_system_time | only in image show_vpe_system_time_reply | only in image sockclnt_create_reply | definition changed sr_localsid_add_del | definition changed sr_localsids_details | definition changed sr_policies_details | definition changed sr_policy_add | definition changed sr_policy_del | definition changed sr_policy_mod | definition changed sr_steering_pol_details | definition changed svs_details | definition changed svs_enable_disable | definition changed svs_route_add_del | definition changed svs_table_add_del | definition changed sw_interface_bond_details | definition changed sw_interface_dump | definition changed sw_interface_ip6_set_link_local_address | only in image sw_interface_ip6_set_link_local_address_reply | only in image sw_interface_ip6nd_ra_prefix | definition changed sw_interface_set_l2_bridge | definition changed sw_interface_tap_v2_details | definition changed syslog_get_filter_reply | definition changed syslog_set_filter | definition changed tap_create_v2 | definition changed udp_encap_add | definition changed udp_encap_details | definition changed virtio_pci_create | definition changed vmxnet3_details | definition changed vxlan_gbp_tunnel_add_del | definition changed vxlan_gbp_tunnel_details | definition changed want_oam_events | only in file want_oam_events_reply | only in file Found 319 api message signature differences ### Patches that changed API definitions | @c src/vpp/api/vpe_types.api || | ------- | ------- | | [b'a47a5f20a'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'a47a5f20a') | api papi: add alias for timestamp(datetime)/timedelta | | [b'3cf9e67f5'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'3cf9e67f5') | api: add vl_api_version_t type | | @c src/vpp/api/vpe.api || | ------- | ------- | | [b'a47a5f20a'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'a47a5f20a') | api papi: add alias for timestamp(datetime)/timedelta | | [b'888640a39'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'888640a39') | map gbp papi: match endianess of f64 | | [b'03f1af23b'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'03f1af23b') | api: Implement log_dump/log_details | | [b'c87b66c86'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'c87b66c86') | ipsec: ipsec-tun protect | | [b'9ac113815'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'9ac113815') | API: Add support for limits to language. | | @c src/examples/sample-plugin/sample/sample.api || | ------- | ------- | | [b'78d91cf9a'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'78d91cf9a') | sample-plugin: refactor .api to use explicit types | | @c src/vnet/interface.api || | ------- | ------- | | [b'0ad4a439d'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'0ad4a439d') | Fix vpp crash bug while deleting dhcp client | | [b'9a29f795a'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'9a29f795a') | vpp_papi_provider.py: update defautmapping. | | [b'b8591ac91'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'b8591ac91') | API sw_interface_dump: Dump all if index is zero | | [b'4a7240636'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'4a7240636') | Make sw_interface_dump more compatible with 2.2.0 | | [b'6407ba56a'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'6407ba56a') | api: Add to interface crud - read by sw_if_index. | | @c src/vnet/qos/qos.api || | ------- | ------- | | [b'83832e7ce'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'83832e7ce') | qos: Store function | | [b'5281a9029'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'5281a9029') | qos: QoS dump APIs | | @c src/vnet/bier/bier.api || | ------- | ------- | | [b'097fa66b9'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'097fa66b9') | fib: fib api updates | | [b'e6eefb6e3'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'e6eefb6e3') | Trivial Typo's in bier comments/docs. | | @c src/vnet/ipfix-export/ipfix_export.api || | ------- | ------- | | [b'21b83e96d'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'21b83e96d') | api: implement ipfix_flush | | @c src/vnet/session/session.api || | ------- | ------- | | [b'8ac1d6d05'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'8ac1d6d05') | session: Use parent_handle instead of transport_opts | | [b'ba65ca496'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'ba65ca496') | Add transport_opts to connect_sock bapi | | @c src/vnet/gre/gre.api || | ------- | ------- | | [b'814f15948'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'814f15948') | gre: update gre.api with explicit types | | [b'd0aed2eb3'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'd0aed2eb3') | GRE: set gre_tunnel_type init value to zero in API | | [b'5a8844bdb'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'5a8844bdb') | GRE: API update | | @c src/vnet/pg/pg.api || | ------- | ------- | | [b'22e9cfd76'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'22e9cfd76') | pg: add GSO support | | @c src/vnet/l2/l2.api || | ------- | ------- | | [b'bc764c8bc'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'bc764c8bc') | l2: BD ARP termination entry API update | | [b'54bc5e40c'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'54bc5e40c') | Update API description | | [b'5e6f7348c'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'5e6f7348c') | l2: Add support for arp unicast forwarding | | @c src/vnet/udp/udp.api || | ------- | ------- | | [b'10dc2eabd'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'10dc2eabd') | udp: fix copyright typo | | @c src/vnet/devices/tap/tapv2.api || | ------- | ------- | | [b'97d54ed43'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'97d54ed43') | tap: add support to configure tap interface host MTU size | | @c src/vnet/devices/virtio/vhost_user.api || | ------- | ------- | | [b'4208a4ce8'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'4208a4ce8') | devices interface tests: vhosst GSO support | | @c src/vnet/devices/virtio/virtio.api || | ------- | ------- | | [b'bbd6b746e'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'bbd6b746e') | virtio: Add gso support for native virtio driver | | [b'43b512cac'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'43b512cac') | virtio: remove configurable queue size support | | @c src/vnet/mfib/mfib_types.api || | ------- | ------- | | [b'097fa66b9'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'097fa66b9') | fib: fib api updates | | @c src/vnet/ipsec/ipsec.api || | ------- | ------- | | [b'c87b66c86'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'c87b66c86') | ipsec: ipsec-tun protect | | [b'f2922422d'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'f2922422d') | ipsec: remove the set_key API | | [b'80f6fd53f'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'80f6fd53f') | IPSEC: Pass the algorithm salt (used in GCM) over the API | | @c src/vnet/ethernet/p2p_ethernet.api || | ------- | ------- | | [b'8edca1361'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'8edca1361') | p2p ethernet: update p2p_ethernet.api with explicit types. | | @c src/vnet/bonding/bond.api || | ------- | ------- | | [b'751e3f382'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'751e3f382') | bonding: add support for numa-only in lacp mode | | @c src/vnet/mpls/mpls.api || | ------- | ------- | | [b'097fa66b9'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'097fa66b9') | fib: fib api updates | | @c src/vnet/ipip/ipip.api || | ------- | ------- | | [b'288e09362'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'288e09362') | ipip: refactor ipip.api with explicit types | | [b'cbd0824d6'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'cbd0824d6') | IPIP tunnel: use address types on API | | @c src/vnet/fib/fib_types.api || | ------- | ------- | | [b'1dbcf30b7'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'1dbcf30b7') | fib: Support the POP of a Psuedo Wire Control Word | | [b'097fa66b9'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'097fa66b9') | fib: fib api updates | | @c src/vnet/dhcp/dhcp.api || | ------- | ------- | | [b'038e1dfbd'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'038e1dfbd') | dhcp ip: DSCP settings for transmitted DHCP packets | | [b'56bc738dc'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'56bc738dc') | Fix VPP-1487 DHCP client does not support option 6-domain server | | @c src/vnet/ip/punt.api || | ------- | ------- | | [b'719beb709'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'719beb709') | ip ipsec: Remove IPSec SPI-0 punt reason | | [b'b538dd868'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'b538dd868') | Punt: specify packets by IP protocol Type | | [b'50f0ac0f0'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'50f0ac0f0') | Punt: socket register for exception dispatched/punted packets based on reason | | @c src/vnet/ip/ip.api || | ------- | ------- | | [b'097fa66b9'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'097fa66b9') | fib: fib api updates | | [b'3a343d42d'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'3a343d42d') | reassembly: prevent long chain attack | | @c src/vnet/ip/ip_types.api || | ------- | ------- | | [b'515eed425'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'515eed425') | api: add prefix matcher typedef | | [b'038e1dfbd'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'038e1dfbd') | dhcp ip: DSCP settings for transmitted DHCP packets | | [b'53c501512'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'53c501512') | api: add DSCP definitions to ip_types.api | | [b'ab05508e1'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'ab05508e1') | api: refactor format_vl_api_prefix_t return keys | | [b'b538dd868'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'b538dd868') | Punt: specify packets by IP protocol Type | | [b'50f0ac0f0'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'50f0ac0f0') | Punt: socket register for exception dispatched/punted packets based on reason | | @c src/plugins/l3xc/l3xc.api || | ------- | ------- | | [b'59fa121f8'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'59fa121f8') | L3 cross connect | | @c src/plugins/map/map.api || | ------- | ------- | | [b'4d376f67a'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'4d376f67a') | map: Use vl_api_string macros. | | @c src/plugins/http_static/http_static.api || | ------- | ------- | | [b'68b24e2c9'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'68b24e2c9') | plugins: http_static. Migrate to use api string type. | | [b'22bc2c46e'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'22bc2c46e') | Static http server | | @c src/plugins/igmp/igmp.api || | ------- | ------- | | [b'4ff09ae34'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'4ff09ae34') | API: Python and Unix domain socket improvement | | @c src/plugins/sctp/sctp.api || | ------- | ------- | | [b'3ffe6cadf'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'3ffe6cadf') | sctp: move to plugins, disabled by default | | @c src/plugins/lb/lb.api || | ------- | ------- | | [b'3efcd0d7c'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'3efcd0d7c') | lb: vip and as dump/detail api's | | [b'a0cb32cb9'](https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commit;h=b'a0cb32cb9') | lb: update api.c to use scaffolding from latest skel | | @c src/plugins/lb/lb_types.api || | ------- | ------- | | [b'3efcd0d7c'](https://gerrit.fd }
/*
* Copyright (c) 2017 SUSE LLC.
* 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 <vnet/sctp/sctp.h>
#include <vnet/sctp/sctp_debug.h>
sctp_main_t sctp_main;
static u32
sctp_connection_bind (u32 session_index, transport_endpoint_t * tep)
{
sctp_main_t *tm = &sctp_main;
sctp_connection_t *listener;
void *iface_ip;
pool_get (tm->listener_pool, listener);
memset (listener, 0, sizeof (*listener));
listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].parent = listener;
listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_c_index =
listener - tm->listener_pool;
listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.lcl_port = tep->port;
/* If we are provided a sw_if_index, bind using one of its IPs */
if (ip_is_zero (&tep->ip, 1) && tep->sw_if_index != ENDPOINT_INVALID_INDEX)
{
if ((iface_ip = ip_interface_get_first_ip (tep->sw_if_index,
tep->is_ip4)))
ip_set (&tep->ip, iface_ip, tep->is_ip4);
}
ip_copy (&listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.lcl_ip,
&tep->ip, tep->is_ip4);
listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.is_ip4 = tep->is_ip4;
listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.proto =
TRANSPORT_PROTO_SCTP;
listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_s_index = session_index;
listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.fib_index =
tep->fib_index;
listener->state = SCTP_STATE_CLOSED;
sctp_connection_timers_init (listener);
return listener->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_c_index;
}
u32
sctp_session_bind (u32 session_index, transport_endpoint_t * tep)
{
return sctp_connection_bind (session_index, tep);
}
static void
sctp_connection_unbind (u32 listener_index)
{
sctp_main_t *tm = vnet_get_sctp_main ();
sctp_connection_t *tc;
tc = pool_elt_at_index (tm->listener_pool, listener_index);
/* Poison the entry */
if (CLIB_DEBUG > 0)
memset (tc, 0xFA, sizeof (*tc));
pool_put_index (tm->listener_pool, listener_index);
}
u32
sctp_session_unbind (u32 listener_index)
{
sctp_connection_unbind (listener_index);
return 0;
}
void
sctp_punt_unknown (vlib_main_t * vm, u8 is_ip4, u8 is_add)
{
sctp_main_t *tm = &sctp_main;
if (is_ip4)
tm->punt_unknown4 = is_add;
else
tm->punt_unknown6 = is_add;
}
static int
sctp_alloc_custom_local_endpoint (sctp_main_t * tm, ip46_address_t * lcl_addr,
u16 * lcl_port, u8 is_ip4)
{
int index, port;
if (is_ip4)
{
index = tm->last_v4_address_rotor++;
if (tm->last_v4_address_rotor >= vec_len (tm->ip4_src_addresses))
tm->last_v4_address_rotor = 0;
lcl_addr->ip4.as_u32 = tm->ip4_src_addresses[index].as_u32;
}
else
{
index = tm->last_v6_address_rotor++;
if (tm->last_v6_address_rotor >= vec_len (tm->ip6_src_addresses))
tm->last_v6_address_rotor = 0;
clib_memcpy (&lcl_addr->ip6, &tm->ip6_src_addresses[index],
sizeof (ip6_address_t));
}
port = transport_alloc_local_port (TRANSPORT_PROTO_SCTP, lcl_addr);
if (port < 1)
{
clib_warning ("Failed to allocate src port");
return -1;
}
*lcl_port = port;
return 0;
}
/**
* Initialize all connection timers as invalid
*/
void
sctp_connection_timers_init (sctp_connection_t * tc)
{
int i, j;
/* Set all to invalid */
for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
for (j = 0; j < SCTP_N_TIMERS; j++)
{
tc->sub_conn[i].timers[j] = SCTP_TIMER_HANDLE_INVALID;
}
tc->rto = SCTP_RTO_INIT;
}
/**
* Stop all connection timers
*/
void
sctp_connection_timers_reset (sctp_connection_t * tc)
{
int i, j;
for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
{
for (j = 0; j < SCTP_N_TIMERS; j++)
sctp_timer_reset (tc, i, j);
}
}
const char *sctp_fsm_states[] = {
#define _(sym, str) str,
foreach_sctp_fsm_state
#undef _
};
u8 *
format_sctp_state (u8 * s, va_list * args)
{
u32 state = va_arg (*args, u32);
if (state < SCTP_N_STATES)
s = format (s, "%s", sctp_fsm_states[state]);
else
s = format (s, "UNKNOWN (%d (0x%x))", state, state);
return s;
}
u8 *
format_sctp_connection_id (u8 * s, va_list * args)
{
/*
sctp_connection_t *tc = va_arg (*args, sctp_connection_t *);
if (!tc)
return s;
if (tc->c_is_ip4)
{
s = format (s, "[#%d][%s] %U:%d->%U:%d", tc->c_thread_index, "T",
format_ip4_address, &tc->c_lcl_ip4,
clib_net_to_host_u16 (tc->c_lcl_port), format_ip4_address,
&tc->c_rmt_ip4, clib_net_to_host_u16 (tc->c_rmt_port));
}
else
{
s = format (s, "[#%d][%s] %U:%d->%U:%d", tc->c_thread_index, "T",
format_ip6_address, &tc->c_lcl_ip6,
clib_net_to_host_u16 (tc->c_lcl_port), format_ip6_address,
&tc->c_rmt_ip6, clib_net_to_host_u16 (tc->c_rmt_port));
}
*/
return s;
}
u8 *
format_sctp_connection (u8 * s, va_list * args)
{
sctp_connection_t *tc = va_arg (*args, sctp_connection_t *);
u32 verbose = va_arg (*args, u32);
if (!tc)
return s;
s = format (s, "%-50U", format_sctp_connection_id, tc);
if (verbose)
{
s = format (s, "%-15U", format_sctp_state, tc->state);
}
return s;
}
/**
* Initialize connection send variables.
*/
void
sctp_init_snd_vars (sctp_connection_t * tc)
{
u32 time_now;
/*
* We use the time to randomize iss and for setting up the initial
* timestamp. Make sure it's updated otherwise syn and ack in the
* handshake may make it look as if time has flown in the opposite
* direction for us.
*/
sctp_set_time_now (vlib_get_thread_index ());
time_now = sctp_time_now ();
tc->iss = random_u32 (&time_now);
tc->snd_una = tc->iss;
tc->snd_nxt = tc->iss + 1;
tc->snd_una_max = tc->snd_nxt;
}
/**
* Update max segment size we're able to process.
*
* The value is constrained by our interface's MTU and IP options. It is
* also what we advertise to our peer.
*/
void
sctp_update_rcv_mss (sctp_connection_t * tc)
{
/* TODO find our iface MTU */
tc->a_rwnd = DEFAULT_A_RWND - sizeof (sctp_full_hdr_t);
tc->rcv_opts.a_rwnd = tc->a_rwnd;
tc->rcv_a_rwnd = tc->a_rwnd; /* This will be updated by our congestion algos */
}
void
sctp_init_mss (sctp_connection_t * tc)
{
SCTP_DBG ("CONN_INDEX = %u",
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.c_index);
u16 default_a_rwnd = 536;
sctp_update_rcv_mss (tc);
/* TODO cache mss and consider PMTU discovery */
tc->snd_a_rwnd = clib_min (tc->rcv_opts.a_rwnd, tc->a_rwnd);
if (tc->snd_a_rwnd < sizeof (sctp_full_hdr_t))
{
SCTP_ADV_DBG ("tc->snd_a_rwnd < sizeof(sctp_full_hdr_t)");
/* Assume that at least the min default mss works */
tc->snd_a_rwnd = default_a_rwnd;
tc->rcv_opts.a_rwnd = default_a_rwnd;
}
ASSERT (tc->snd_a_rwnd > sizeof (sctp_full_hdr_t));
}
/** Initialize sctp connection variables
*
* Should be called after having received a msg from the peer, i.e., a SYN or
* a SYNACK, such that connection options have already been exchanged. */
void
sctp_connection_init_vars (sctp_connection_t * tc)
{
sctp_init_mss (tc);
sctp_init_snd_vars (tc);
}
always_inline sctp_connection_t *
sctp_sub_connection_add (u8 thread_index)
{
sctp_main_t *tm = vnet_get_sctp_main ();
sctp_connection_t *tc = tm->connections[thread_index];
tc->sub_conn[tc->next_avail_sub_conn].connection.c_index =
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.c_index;
tc->sub_conn[tc->next_avail_sub_conn].connection.thread_index =
thread_index;
tc->sub_conn[tc->next_avail_sub_conn].parent = tc;
tc->next_avail_sub_conn += 1;
return tc;
}
void
sctp_sub_connection_add_ip4 (u8 thread_index,
sctp_ipv4_addr_param_t * ipv4_addr)
{
sctp_connection_t *tc = sctp_sub_connection_add (thread_index);
clib_memcpy (&tc->sub_conn[tc->next_avail_sub_conn].connection.lcl_ip.ip4,
&ipv4_addr->address, sizeof (ipv4_addr->address));
}
void
sctp_sub_connection_add_ip6 (u8 thread_index,
sctp_ipv6_addr_param_t * ipv6_addr)
{
sctp_connection_t *tc = sctp_sub_connection_add (thread_index);
clib_memcpy (&tc->sub_conn[tc->next_avail_sub_conn].connection.lcl_ip.ip6,
&ipv6_addr->address, sizeof (ipv6_addr->address));
}
sctp_connection_t *
sctp_connection_new (u8 thread_index)
{
sctp_main_t *tm = vnet_get_sctp_main ();
sctp_connection_t *tc;
pool_get (tm->connections[thread_index], tc);
memset (tc, 0, sizeof (*tc));
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].parent = tc;
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_c_index =
tc - tm->connections[thread_index];
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_thread_index = thread_index;
tc->local_tag = 0;
tc->next_avail_sub_conn = 1;
return tc;
}
sctp_connection_t *
sctp_half_open_connection_new (u8 thread_index)
{
sctp_main_t *tm = vnet_get_sctp_main ();
sctp_connection_t *tc = 0;
ASSERT (vlib_get_thread_index () == 0);
pool_get (tm->half_open_connections, tc);
memset (tc, 0, sizeof (*tc));
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].c_c_index =
tc - tm->half_open_connections;
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].parent = tc;
return tc;
}
static inline int
sctp_connection_open (transport_endpoint_t * rmt)
{
sctp_main_t *tm = vnet_get_sctp_main ();
sctp_connection_t *tc;
ip46_address_t lcl_addr;
u16 lcl_port;
uword thread_id;
int rv;
u8 idx = sctp_pick_conn_idx_on_state (SCTP_STATE_CLOSED);
/*
* Allocate local endpoint
*/
if ((rmt->is_ip4 && vec_len (tm->ip4_src_addresses))
|| (!rmt->is_ip4 && vec_len (tm->ip6_src_addresses)))
rv = sctp_alloc_custom_local_endpoint (tm, &lcl_addr, &lcl_port,
rmt->is_ip4);
else
rv = transport_alloc_local_endpoint (TRANSPORT_PROTO_SCTP,
rmt, &lcl_addr, &lcl_port);
if (rv)
return -1;
/*
* Create connection and send INIT CHUNK
*/
thread_id = vlib_get_thread_index ();
ASSERT (thread_id == 0);
clib_spinlock_lock_if_init (&tm->half_open_lock);
tc = sctp_half_open_connection_new (thread_id);
transport_connection_t *t_conn = &tc->sub_conn[idx].connection;
ip_copy (&t_conn->rmt_ip, &rmt->ip, rmt->is_ip4);
ip_copy (&t_conn->lcl_ip, &lcl_addr, rmt->is_ip4);
tc->sub_conn[idx].parent = tc;
t_conn->rmt_port = rmt->port;
t_conn->lcl_port = clib_host_to_net_u16 (lcl_port);
t_conn->is_ip4 = rmt->is_ip4;
t_conn->proto = TRANSPORT_PROTO_SCTP;
t_conn->fib_index = rmt->fib_index;
sctp_connection_timers_init (tc);
/* The other connection vars will be initialized after INIT_ACK chunk received */
sctp_init_snd_vars (tc);
sctp_send_init (tc);
clib_spinlock_unlock_if_init (&tm->half_open_lock);
return tc->sub_conn[idx].connection.c_index;
}
/**
* Cleans up connection state.
*
* No notifications.
*/
void
sctp_connection_cleanup (sctp_connection_t * tc)
{
sctp_main_t *tm = &sctp_main;
u8 i;
/* Cleanup local endpoint if this was an active connect */
for (i = 0; i < MAX_SCTP_CONNECTIONS; i++)
transport_endpoint_cleanup (TRANSPORT_PROTO_SCTP,
&tc->sub_conn[i].connection.lcl_ip,
tc->sub_conn[i].connection.lcl_port);
/* Check if connection is not yet fully established */
if (tc->state == SCTP_STATE_COOKIE_WAIT)
{
}
else
{
int thread_index =
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.thread_index;
/* Make sure all timers are cleared */
sctp_connection_timers_reset (tc);
/* Poison the entry */
if (CLIB_DEBUG > 0)
memset (tc, 0xFA, sizeof (*tc));
pool_put (tm->connections[thread_index], tc);
}
}
int
sctp_session_open (transport_endpoint_t * tep)
{
return sctp_connection_open (tep);
}
u16
sctp_check_outstanding_data_chunks (sctp_connection_t * tc)
{
return 0; /* Indicates no more data to be read/sent */
}
void
sctp_connection_close (sctp_connection_t * tc)
{
SCTP_DBG ("Closing connection %u...",
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection.c_index);
tc->state = SCTP_STATE_SHUTDOWN_PENDING;
sctp_send_shutdown (tc);
}
void
sctp_session_close (u32 conn_index, u32 thread_index)
{
ASSERT (thread_index == 0);
sctp_connection_t *tc;
tc = sctp_connection_get (conn_index, thread_index);
sctp_connection_close (tc);
}
void
sctp_session_cleanup (u32 conn_index, u32 thread_index)
{
sctp_connection_t *tc;
tc = sctp_connection_get (conn_index, thread_index);
sctp_connection_timers_reset (tc);
/* Wait for the session tx events to clear */
tc->state = SCTP_STATE_CLOSED;
}
/**
* Update snd_mss to reflect the effective segment size that we can send
*/
void
sctp_update_snd_mss (sctp_connection_t * tc)
{
/* The overhead for the sctp_header_t and sctp_chunks_common_hdr_t
* (the sum equals to sctp_full_hdr_t) is already taken into account
* for the tc->a_rwnd computation.
* So let's not account it again here.
*/
tc->snd_hdr_length =
sizeof (sctp_payload_data_chunk_t) - sizeof (sctp_full_hdr_t);
tc->snd_a_rwnd =
clib_min (tc->a_rwnd, tc->rcv_opts.a_rwnd) - tc->snd_hdr_length;
SCTP_DBG ("tc->snd_a_rwnd = %u, tc->snd_hdr_length = %u ",
tc->snd_a_rwnd, tc->snd_hdr_length);
ASSERT (tc->snd_a_rwnd > 0);
}
u16
sctp_session_send_mss (transport_connection_t * trans_conn)
{
SCTP_DBG ("CONN_INDEX: %u", trans_conn->c_index);
sctp_connection_t *tc = sctp_get_connection_from_transport (trans_conn);
if (trans_conn == NULL)
{
SCTP_DBG ("trans_conn == NULL");
return 0;
}
if (tc == NULL)
{
SCTP_DBG ("tc == NULL");
return 0;
}
/* Ensure snd_mss does accurately reflect the amount of data we can push
* in a segment. This also makes sure that options are updated according to
* the current state of the connection. */
sctp_update_snd_mss (tc);
return tc->snd_a_rwnd;
}
u16
sctp_snd_space (sctp_connection_t * sctp_conn)
{
/* TODO: This requires a real implementation */
if (sctp_conn == NULL)
{
SCTP_DBG ("sctp_conn == NULL");
return 0;
}
if (sctp_conn->state != SCTP_STATE_ESTABLISHED)
{
SCTP_DBG_STATE_MACHINE
("Trying to send DATA while not in SCTP_STATE_ESTABLISHED");
return 0;
}
return sctp_conn->snd_a_rwnd;
}
u32
sctp_session_send_space (transport_connection_t * trans_conn)
{
SCTP_DBG ("CONN_INDEX: %u", trans_conn->c_index);
sctp_connection_t *tc = sctp_get_connection_from_transport (trans_conn);
return sctp_snd_space (tc);
}
u32
sctp_session_tx_fifo_offset (transport_connection_t * trans_conn)
{
SCTP_DBG ("CONN_INDEX: %u", trans_conn->c_index);
sctp_connection_t *tc = sctp_get_connection_from_transport (trans_conn);
if (tc == NULL)
{
SCTP_DBG ("tc == NULL");
return 0;
}
/* This still works if fast retransmit is on */
return (tc->snd_nxt - tc->snd_una);
}
transport_connection_t *
sctp_session_get_transport (u32 conn_index, u32 thread_index)
{
sctp_connection_t *tc = sctp_connection_get (conn_index, thread_index);
return &tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection;
}
transport_connection_t *
sctp_session_get_listener (u32 listener_index)
{
sctp_main_t *tm = vnet_get_sctp_main ();
sctp_connection_t *tc;
tc = pool_elt_at_index (tm->listener_pool, listener_index);
return &tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection;
}
u8 *
format_sctp_session (u8 * s, va_list * args)
{
return NULL;
}
u8 *
format_sctp_listener_session (u8 * s, va_list * args)
{
return NULL;
}
void
sctp_timer_init_handler (u32 conn_index)
{
sctp_connection_t *tc;
tc = sctp_connection_get (conn_index, vlib_get_thread_index ());
/* note: the connection may have already disappeared */
if (PREDICT_FALSE (tc == 0))
return;
ASSERT (tc->state == SCTP_STATE_COOKIE_ECHOED);
/* Start cleanup. App wasn't notified yet so use delete notify as
* opposed to delete to cleanup session layer state. */
stream_session_delete_notify (&tc->
sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection);
tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].timers[SCTP_TIMER_T1_INIT] =
SCTP_TIMER_HANDLE_INVALID;
sctp_connection_cleanup (tc);
}
/* *INDENT OFF* */
static timer_expiration_handler *sctp_timer_expiration_handlers[SCTP_N_TIMERS]
= {
sctp_timer_init_handler
};
/* *INDENT ON* */
static void
sctp_expired_timers_dispatch (u32 * expired_timers)
{
int i;
u32 connection_index, timer_id;
for (i = 0; i < vec_len (expired_timers); i++)
{
/* Get session index and timer id */
connection_index = expired_timers[i] & 0x0FFFFFFF;
timer_id = expired_timers[i] >> 28;
/* Handle expiration */
(*sctp_timer_expiration_handlers[timer_id]) (connection_index);
}
}
void
sctp_initialize_timer_wheels (sctp_main_t * tm)
{
tw_timer_wheel_16t_2w_512sl_t *tw;
/* *INDENT-OFF* */
foreach_vlib_main (({
tw = &tm->timer_wheels[ii];
tw_timer_wheel_init_16t_2w_512sl (tw, sctp_expired_timers_dispatch,
100e-3 /* timer period 100ms */ , ~0);
tw->last_run_time = vlib_time_now (this_vlib_main);
}));
/* *INDENT-ON* */
}
clib_error_t *
sctp_main_enable (vlib_main_t * vm)
{
sctp_main_t *tm = vnet_get_sctp_main ();
vlib_thread_main_t *vtm = vlib_get_thread_main ();
clib_error_t *error = 0;
u32 num_threads;
int thread;
sctp_connection_t *tc __attribute__ ((unused));
u32 preallocated_connections_per_thread;
if ((error = vlib_call_init_function (vm, ip_main_init)))
return error;
if ((error = vlib_call_init_function (vm, ip4_lookup_init)))
return error;
if ((error = vlib_call_init_function (vm, ip6_lookup_init)))
return error;
/*
* Registrations
*/
ip4_register_protocol (IP_PROTOCOL_SCTP, sctp4_input_node.index);
ip6_register_protocol (IP_PROTOCOL_SCTP, sctp6_input_node.index);
/*
* Initialize data structures
*/
num_threads = 1 /* main thread */ + vtm->n_threads;
vec_validate (tm->connections, num_threads - 1);
/*
* Preallocate connections. Assume that thread 0 won't
* use preallocated threads when running multi-core
*/
if (num_threads == 1)
{
thread = 0;
preallocated_connections_per_thread = tm->preallocated_connections;
}
else
{
thread = 1;
preallocated_connections_per_thread =
tm->preallocated_connections / (num_threads - 1);
}
for (; thread < num_threads; thread++)
{
if (preallocated_connections_per_thread)
pool_init_fixed (tm->connections[thread],
preallocated_connections_per_thread);
}
/* Initialize per worker thread tx buffers (used for control messages) */
vec_validate (tm->tx_buffers, num_threads - 1);
/* Initialize timer wheels */
vec_validate (tm->timer_wheels, num_threads - 1);
sctp_initialize_timer_wheels (tm);
/* Initialize clocks per tick for SCTP timestamp. Used to compute
* monotonically increasing timestamps. */
tm->tstamp_ticks_per_clock = vm->clib_time.seconds_per_clock
/ SCTP_TSTAMP_RESOLUTION;
if (num_threads > 1)
{
}
vec_validate (tm->tx_frames[0], num_threads - 1);
vec_validate (tm->tx_frames[1], num_threads - 1);
vec_validate (tm->ip_lookup_tx_frames[0], num_threads - 1);
vec_validate (tm->ip_lookup_tx_frames[1], num_threads - 1);
tm->bytes_per_buffer = vlib_buffer_free_list_buffer_size
(vm, VLIB_BUFFER_DEFAULT_FREE_LIST_INDEX);
vec_validate (tm->time_now, num_threads - 1);
return error;
}
clib_error_t *
sctp_enable_disable (vlib_main_t * vm, u8 is_en)
{
if (is_en)
{
if (sctp_main.is_enabled)
return 0;
return sctp_main_enable (vm);
}
else
{
sctp_main.is_enabled = 0;
}
return 0;
}
transport_connection_t *
sctp_half_open_session_get_transport (u32 conn_index)
{
sctp_connection_t *tc = sctp_half_open_connection_get (conn_index);
return &tc->sub_conn[MAIN_SCTP_SUB_CONN_IDX].connection;
}
u8 *
format_sctp_half_open (u8 * s, va_list * args)
{
u32 tci = va_arg (*args, u32);
sctp_connection_t *tc = sctp_half_open_connection_get (tci);
return format (s, "%U", format_sctp_connection_id, tc);
}
/* *INDENT OFF* */
const static transport_proto_vft_t sctp_proto = {
.enable = sctp_enable_disable,
.bind = sctp_session_bind,
.unbind = sctp_session_unbind,
.open = sctp_session_open,
.close = sctp_session_close,
.cleanup = sctp_session_cleanup,
.push_header = sctp_push_header,
.send_mss = sctp_session_send_mss,
.send_space = sctp_session_send_space,
.tx_fifo_offset = NULL, //sctp_session_tx_fifo_offset,
.get_connection = sctp_session_get_transport,
.get_listener = sctp_session_get_listener,
.get_half_open = sctp_half_open_session_get_transport,
.format_connection = format_sctp_session,
.format_listener = format_sctp_listener_session,
.format_half_open = format_sctp_half_open,
};
/* *INDENT ON* */
clib_error_t *
sctp_init (vlib_main_t * vm)
{
sctp_main_t *tm = vnet_get_sctp_main ();
ip_main_t *im = &ip_main;
ip_protocol_info_t *pi;
/* Session layer, and by implication SCTP, are disabled by default */
tm->is_enabled = 0;
/* Register with IP for header parsing */
pi = ip_get_protocol_info (im, IP_PROTOCOL_SCTP);
if (pi == 0)
return clib_error_return (0, "SCTP protocol info AWOL");
pi->format_header = format_sctp_header;
pi->unformat_pg_edit = unformat_pg_sctp_header;
/* Register as transport with session layer */
transport_register_protocol (TRANSPORT_PROTO_SCTP, &sctp_proto,
FIB_PROTOCOL_IP4, sctp4_output_node.index);
transport_register_protocol (TRANSPORT_PROTO_SCTP, &sctp_proto,
FIB_PROTOCOL_IP6, sctp6_output_node.index);
return 0;
}
VLIB_INIT_FUNCTION (sctp_init);
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/