diff --git a/src/lib/yang/snabb-softwire-v1.yang b/src/lib/yang/snabb-softwire-v1.yang deleted file mode 100644 index 44ebb2d337..0000000000 --- a/src/lib/yang/snabb-softwire-v1.yang +++ /dev/null @@ -1,750 +0,0 @@ -module snabb-softwire-v1 { - namespace snabb:lwaftr; - prefix softwire; - - import ietf-inet-types { prefix inet; } - import ietf-yang-types { prefix yang; } - - organization "Igalia, S.L."; - contact "Jessica Tallon "; - description - "Configuration for the Snabb Switch lwAFTR."; - - revision 2016-11-04 { - description - "Initial revision."; - } - - container softwire-config { - description - "Configuration for Snabb lwaftr."; - - grouping traffic-filters { - description - "Ingress and egress filters describing the set of packets - that should be allowed to pass, as pflang filters. pflang - is the language of tcpdump, libpcap and other tools. Note - that if VLAN tagging is enabled, the filters run on packets - after VLAN tags have been stripped off."; - leaf ingress-filter { - type string; - description - "Filter for incoming traffic. Packets that do not match - the filter will be silently dropped."; - } - leaf egress-filter { - type string; - description - "Filter for outgoing traffic. Packets that do not match - the filter will be silently dropped."; - } - } - - grouping icmp-policy { - description - "The lwAFTR can be configured to allow or drop incoming ICMP - messages, and to generate outgoing ICMP error messages or - not."; - - leaf allow-incoming-icmp { - type boolean; - default true; - description - "Whether to allow incoming ICMP packets."; - } - - leaf generate-icmp-errors { - type boolean; - default true; - description - "Whether to generate outgoing ICMP error messages."; - } - } - - grouping vlan-tagging { - description - "802.1Q Ethernet tagging."; - - leaf vlan-tag { - type uint16 { - range 0..4095; - } - description - "802.1Q Ethernet VLAN tag for this interface."; - } - } - - grouping error-rate-limiting { - description - "These settings limit the rate of ICMP error message - transmission."; - - container error-rate-limiting { - leaf packets { - type uint32; - description - "The number of ICMP error messages which can be sent within - the specified time period."; - } - - leaf period { - type uint32 { range 1..max; } - default 2; - description - "The time period given in seconds."; - } - } - } - - grouping reassembly { - description - "These settings limit the resources devoted to reassembling - fragmented packets."; - - container reassembly { - leaf max-fragments-per-packet { - type uint32 { range 1..max; } - default 20; - description - "The maximum number of fragments per reassembled packet. - Attempts to reassemble a packet using more fragments than - this threshold will fail and the reassembly data will be - discarded."; - } - - leaf max-packets { - type uint32; - default 20000; - description - "The maximum number of concurrent reassembly attempts. If - this limit is reached, an additional reassembly will cause - random eviction of an ongoing reassembly. Note that this - setting directly affects memory usage; the memory buffer - allocated to reassembly is this maximum number of - reassemblies times 25 kilobytes each."; - } - } - } - - leaf name { - type string; - description - "Name of lwAFTR instance. This must be unique amongst the Snabb - processes on the system. This may be specified either here, in the - YANG configuration or via the command line when the lwAFTR is started. - - The order of presidence for this leaf is as followers: - 1. The name set on an already running lwAFTR instance via snabb set. - 2. A command line option to specify the name upon starting the lwAFTR - instance (i.e. overriding this value). - 3. The value here in the configuration when starting a lwaftr instance. - - If no name is specified the lwaftr can be referred to using the PID of - the lwAFTR process on the system."; - } - - container external-interface { - description - "Configuration for the external, internet-facing IPv4 - interface."; - - leaf ip { - type inet:ipv4-address; - mandatory true; - description - "L3 Address of the internet-facing network interface. Used - when generating error messages and responding to ICMP echo - requests."; - } - leaf mac { - type yang:mac-address; - mandatory true; - description - "MAC address of the internet-facing NIC."; - } - leaf mtu { - type uint16; - default 1460; - description - "Maximum packet size to send on the IPv4 interface."; - } - - uses traffic-filters; - uses icmp-policy; - uses vlan-tagging; - uses error-rate-limiting; - uses reassembly; - - container next-hop { - leaf ip { - type inet:ipv4-address; - description - "IPv4 address of the next hop for the internet-facing NIC. - The lwAFTR will resolve this to a MAC address using ARP."; - } - leaf mac { - type yang:mac-address; - description - "Statically configured MAC address of the next hop for the - internet-facing NIC."; - } - } - } - - container internal-interface { - description - "Configuration for the internal IPv6 interface."; - - leaf ip { - type inet:ipv6-address; - mandatory true; - description - "L3 Address of the internal-facing network interface. Used - when generating error messages and responding to ICMP echo - requests."; - } - leaf mac { - type yang:mac-address; - mandatory true; - description - "MAC address of the internal-facing NIC."; - } - leaf mtu { - type uint16; - default 1500; - description - "Maximum packet size to sent on the IPv6 interface."; - } - - uses traffic-filters; - uses icmp-policy; - uses vlan-tagging; - uses error-rate-limiting; - uses reassembly; - - container next-hop { - leaf ip { - type inet:ipv6-address; - description - "IPv6 address of the next hop for the internal-facing NIC. - The lwAFTR will resolve this to a MAC address using NDP."; - } - leaf mac { - type yang:mac-address; - description - "Statically configured MAC address of the next hop for the - internal-facing NIC."; - } - } - - leaf hairpinning { - type boolean; - default true; - description - "Indicates whether to support hairpinning of traffic between - two B4s."; - } - } - - container binding-table { - description - "A collection of softwires (tunnels), along with a description - of the IPv4 and IPv6 addresses handled by the lwAFTR."; - - list psid-map { - description - "The set of IPv4 addresses managed by the lwAFTR, along with - the way in which those IPv4 addresses share ports. A PSID map - entry associates a PSID length, shift, and - reserved-ports-bit-count with each IPv4 address served by - the lwAFTR. - - The lightweight 4-over-6 architecture supports sharing of - IPv4 addresses by partitioning the space of TCP/UDP/ICMP - ports into disjoint \"port sets\". Each softwire associated - with an IPv4 address corresponds to a different set of ports - on that address. The way that the ports are partitioned is - specified in RFC 7597: each address has an associated set - of parameters that specifies how to compute a \"port set - identifier\" (PSID) from a given port. - - 0 1 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - +-----------+-----------+-------+ - Ports in | A | PSID | j | - the CE port set | > 0 | | | - +-----------+-----------+-------+ - | a bits | k bits |m bits | - - Figure 2: Structure of a Port-Restricted Port Field - - Source: http://tools.ietf.org/html/rfc7597#section-5.1 - - We find the specification's names to be a bit obtuse, so we - refer to them using the following names: - - a bits = reserved-ports-bit-count. - k bits = psid-length. - m bits = shift."; - - key addr; - - leaf addr { - type inet:ipv4-address; - description - "Public IPv4 address managed by the lwAFTR."; - } - - leaf end-addr { - type inet:ipv4-address; - description - "If present, this PSID map entry applies to all addresses - between 'addr' and this address, inclusive."; - } - - leaf psid-length { - type uint8 { range 0..16; } - mandatory true; - description - "The number of bits devoted to the PSID in the port map. - If the psid-length is N, then the IPv4 address will be - shared 2^N ways. Note that psid-length, shift, and - reserved-ports-bit-count must add up to 16."; - } - - leaf shift { - type uint8 { range 0..16; } - description - "Given an incoming port, one can obtain the PSID by - shifting the port right by 'shift' bits and then masking - off the lowest 'psid-length' bits. Defaults to 16 - - psid-length. Note that psid-length, shift, and - reserved-ports-bit-count must add up to 16."; - } - - leaf reserved-ports-bit-count { - type uint8 { range 0..16; } - default 0; - description - "Reserve the lowest 2^N ports so that they map to no - softwire. This can be useful to prevent the low 1024 - ports (for example) from being mapped to customers. Note - that psid-length and shift must add up to less than or - equal to 16."; - } - } - - leaf-list br-address { - type inet:ipv6-address; - description - "B4-facing address of an lwAFTR."; - } - - list softwire { - key "ipv4 psid padding"; - - leaf ipv4 { - type inet:ipv4-address; - description - "Public IPv4 address of the softwire."; - } - - leaf psid { - type uint16; - description - "Port set ID."; - } - - leaf padding { - type uint16 { range 0..0; } - default 0; - description - "Reserved bytes."; - } - - leaf br { - type uint32; - default 1; - description - "The B4-facing address of the lwAFTR for this softwire, as - a one-based index into br-addresses."; - } - - leaf b4-ipv6 { - type inet:ipv6-address; - mandatory true; - description - "B4 address."; - } - } - } - } - - container softwire-state { - description "State data about lwaftr."; - config false; - - leaf drop-all-ipv4-iface-bytes { - type yang:zero-based-counter64; - description - "All dropped packets and bytes that came in over IPv4 interfaces, - whether or not they actually IPv4 (they only include data about - packets that go in/out over the wires, excluding internally generated - ICMP packets)."; - } - leaf drop-all-ipv4-iface-packets { - type yang:zero-based-counter64; - description - "All dropped packets and bytes that came in over IPv4 interfaces, - whether or not they actually IPv4 (they only include data about - packets that go in/out over the wires, excluding internally generated - ICMP packets)."; - } - leaf drop-all-ipv6-iface-bytes { - type yang:zero-based-counter64; - description - "All dropped packets and bytes that came in over IPv6 interfaces, - whether or not they actually IPv6 (they only include data about packets - that go in/out over the wires, excluding internally generated ICMP - packets)."; - } - leaf drop-all-ipv6-iface-packets { - type yang:zero-based-counter64; - description - "All dropped packets and bytes that came in over IPv6 interfaces, - whether or not they actually IPv6 (they only include data about packets - that go in/out over the wires, excluding internally generated ICMP - packets)."; - } - leaf drop-bad-checksum-icmpv4-bytes { - type yang:zero-based-counter64; - description "ICMPv4 packets dropped because of a bad checksum."; - } - leaf drop-bad-checksum-icmpv4-packets { - type yang:zero-based-counter64; - description "ICMPv4 packets dropped because of a bad checksum."; - } - leaf drop-in-by-policy-icmpv4-bytes { - type yang:zero-based-counter64; - description "Incoming ICMPv4 packets dropped because of current policy."; - } - leaf drop-in-by-policy-icmpv4-packets { - type yang:zero-based-counter64; - description "Incoming ICMPv4 packets dropped because of current policy."; - } - leaf drop-in-by-policy-icmpv6-bytes { - type yang:zero-based-counter64; - description "Incoming ICMPv6 packets dropped because of current policy."; - } - leaf drop-in-by-policy-icmpv6-packets { - type yang:zero-based-counter64; - description "Incoming ICMPv6 packets dropped because of current policy."; - } - leaf drop-in-by-rfc7596-icmpv4-bytes { - type yang:zero-based-counter64; - description - "Incoming ICMPv4 packets with no destination (RFC 7596 section 8.1)."; - } - leaf drop-in-by-rfc7596-icmpv4-packets { - type yang:zero-based-counter64; - description - "Incoming ICMPv4 packets with no destination (RFC 7596 section 8.1)."; - } - leaf drop-ipv4-frag-disabled { - type yang:zero-based-counter64; - description - "If fragmentation is disabled, the only potentially non-zero IPv4 - fragmentation counter is drop-ipv4-frag-disabled. If fragmentation is - enabled, it will always be zero."; - } - leaf drop-ipv4-frag-invalid-reassembly { - type yang:zero-based-counter64; - description - "Two or more IPv4 fragments were received, and reassembly was started, - but was invalid and dropped. Causes include multiple fragments claiming - they are the last fragment, overlapping fragment offsets, or the packet - was being reassembled from too many fragments (the setting is - max_fragments_per_reassembly_packet, and the default is that no packet - should be reassembled from more than 40)."; - } - leaf drop-ipv4-frag-random-evicted { - type yang:zero-based-counter64; - description - "Reassembling an IPv4 packet from fragments was in progress, but the - configured amount of packets to reassemble at once was exceeded, so one - was dropped at random. Consider increasing the setting - max_ipv4_reassembly_packets."; - } - leaf drop-ipv6-frag-disabled { - type yang:zero-based-counter64; - description - "If fragmentation is disabled, the only potentially non-zero IPv6 - fragmentation counter is drop-ipv6-frag-disabled. If fragmentation is - enabled, it will always be zero."; - } - leaf drop-ipv6-frag-invalid-reassembly { - type yang:zero-based-counter64; - description - "Two or more IPv6 fragments were received, and reassembly was started, - but was invalid and dropped. Causes include multiple fragments claiming - they are the last fragment, overlapping fragment offsets, or the packet - was being reassembled from too many fragments (the setting is - max_fragments_per_reassembly_packet, and the default is that no packet - should be reassembled from more than 40)."; - } - leaf drop-ipv6-frag-random-evicted { - type yang:zero-based-counter64; - description - "Reassembling an IPv6 packet from fragments was in progress, but the - configured amount of packets to reassemble at once was exceeded, so one - was dropped at random. Consider increasing the setting - max_ipv6_reassembly_packets."; - } - leaf drop-misplaced-not-ipv4-bytes { - type yang:zero-based-counter64; - description "Non-IPv4 packets incoming on the IPv4 link."; - } - leaf drop-misplaced-not-ipv4-packets { - type yang:zero-based-counter64; - description "Non-IPv4 packets incoming on the IPv4 link."; - } - leaf drop-misplaced-not-ipv6-bytes { - type yang:zero-based-counter64; - description "Non-IPv6 packets incoming on IPv6 link."; - } - leaf drop-misplaced-not-ipv6-packets { - type yang:zero-based-counter64; - description "Non-IPv6 packets incoming on IPv6 link."; - } - leaf drop-no-dest-softwire-ipv4-bytes { - type yang:zero-based-counter64; - description - "No matching destination softwire in the binding table; incremented - whether or not the reason was RFC7596."; - } - leaf drop-no-dest-softwire-ipv4-packets { - type yang:zero-based-counter64; - description - "No matching destination softwire in the binding table; incremented - whether or not the reason was RFC7596."; - } - leaf drop-no-source-softwire-ipv6-bytes { - type yang:zero-based-counter64; - description - "No matching source softwire in the binding table; incremented whether - or not the reason was RFC7596."; - } - leaf drop-no-source-softwire-ipv6-packets { - type yang:zero-based-counter64; - description - "No matching source softwire in the binding table; incremented whether - or not the reason was RFC7596."; - } - leaf drop-out-by-policy-icmpv4-packets { - type yang:zero-based-counter64; - description - "Internally generated ICMPv4 error packets dropped because of current - policy."; - } - leaf drop-out-by-policy-icmpv6-packets { - type yang:zero-based-counter64; - description - "Internally generated ICMPv6 packets dropped because of current - policy."; - } - leaf drop-over-mtu-but-dont-fragment-ipv4-bytes { - type yang:zero-based-counter64; - description - "IPv4 packets whose size exceeded the MTU, but the DF (Don't Fragment) - flag was set."; - } - leaf drop-over-mtu-but-dont-fragment-ipv4-packets { - type yang:zero-based-counter64; - description - "IPv4 packets whose size exceeded the MTU, but the DF (Don't Fragment) - flag was set."; - } - leaf drop-over-rate-limit-icmpv6-bytes { - type yang:zero-based-counter64; - description - "Packets dropped because the outgoing ICMPv6 rate limit was reached."; - } - leaf drop-over-rate-limit-icmpv6-packets { - type yang:zero-based-counter64; - description - "Packets dropped because the outgoing ICMPv6 rate limit was reached."; - } - leaf drop-over-time-but-not-hop-limit-icmpv6-bytes { - type yang:zero-based-counter64; - description - "Packet's time limit was exceeded, but the hop limit was not."; - } - leaf drop-over-time-but-not-hop-limit-icmpv6-packets { - type yang:zero-based-counter64; - description - "Packet's time limit was exceeded, but the hop limit was not."; - } - leaf drop-too-big-type-but-not-code-icmpv6-bytes { - type yang:zero-based-counter64; - description - "Packet's ICMP type was 'Packet too big' but its ICMP code was not an - acceptable one for this type."; - } - leaf drop-too-big-type-but-not-code-icmpv6-packets { - type yang:zero-based-counter64; - description - "Packet's ICMP type was 'Packet too big' but its ICMP code was not an - acceptable one for this type."; - } - leaf drop-ttl-zero-ipv4-bytes { - type yang:zero-based-counter64; - description "IPv4 packets dropped because their TTL was zero."; - } - leaf drop-ttl-zero-ipv4-packets { - type yang:zero-based-counter64; - description "IPv4 packets dropped because their TTL was zero."; - } - leaf drop-unknown-protocol-icmpv6-bytes { - type yang:zero-based-counter64; - description "Packets with an unknown ICMPv6 protocol."; - } - leaf drop-unknown-protocol-icmpv6-packets { - type yang:zero-based-counter64; - description "Packets with an unknown ICMPv6 protocol."; - } - leaf drop-unknown-protocol-ipv6-bytes { - type yang:zero-based-counter64; - description "Packets with an unknown IPv6 protocol."; - } - leaf drop-unknown-protocol-ipv6-packets { - type yang:zero-based-counter64; - description "Packets with an unknown IPv6 protocol."; - } - leaf hairpin-ipv4-bytes { - type yang:zero-based-counter64; - description "IPv4 packets going to a known b4 (hairpinned)."; - } - leaf hairpin-ipv4-packets { - type yang:zero-based-counter64; - description "IPv4 packets going to a known b4 (hairpinned)."; - } - leaf in-ipv4-bytes { - type yang:zero-based-counter64; - description "All valid outgoing IPv4 packets."; - } - leaf in-ipv4-frag-needs-reassembly { - type yang:zero-based-counter64; - description "An IPv4 fragment was received."; - } - leaf in-ipv4-frag-reassembled { - type yang:zero-based-counter64; - description "A packet was successfully reassembled from IPv4 fragments."; - } - leaf in-ipv4-frag-reassembly-unneeded { - type yang:zero-based-counter64; - description - "An IPv4 packet which was not a fragment was received - consequently, - it did not need to be reassembled. This should be the usual case."; - } - leaf in-ipv4-packets { - type yang:zero-based-counter64; - description "All valid outgoing IPv4 packets."; - } - leaf in-ipv6-bytes { - type yang:zero-based-counter64; - description "All valid outgoing IPv4 packets."; - } - leaf in-ipv6-frag-needs-reassembly { - type yang:zero-based-counter64; - description "An IPv6 fragment was received."; - } - leaf in-ipv6-frag-reassembled { - type yang:zero-based-counter64; - description "A packet was successfully reassembled from IPv6 fragments."; - } - leaf in-ipv6-frag-reassembly-unneeded { - type yang:zero-based-counter64; - description - "An IPv6 packet which was not a fragment was received - consequently, it - did not need to be reassembled. This should be the usual case."; - } - leaf in-ipv6-packets { - type yang:zero-based-counter64; - description "All valid outgoing IPv4 packets."; - } - leaf ingress-packet-drops { - type yang:zero-based-counter64; - description "Packets dropped due to ingress filters."; - } - leaf memuse-ipv4-frag-reassembly-buffer { - type yang:zero-based-counter64; - description - "The amount of memory being used by the statically sized data structure - for reassembling IPv4 fragments. This is directly proportional to the - setting max_ipv4_reassembly_packets."; - } - leaf memuse-ipv6-frag-reassembly-buffer { - type yang:zero-based-counter64; - description - "The amount of memory being used by the statically sized data structure - for reassembling IPv6 fragments. This is directly proportional to the - setting max_ipv6_reassembly_packets."; - } - leaf out-icmpv4-bytes { - type yang:zero-based-counter64; - description "Internally generated ICMPv4 packets."; - } - leaf out-icmpv4-packets { - type yang:zero-based-counter64; - description "Internally generated ICMPv4 packets."; - } - leaf out-icmpv6-bytes { - type yang:zero-based-counter64; - description "Internally generted ICMPv6 error packets."; - } - leaf out-icmpv6-packets { - type yang:zero-based-counter64; - description "Internally generted ICMPv6 error packets."; - } - leaf out-ipv4-bytes { - type yang:zero-based-counter64; - description "Valid outgoing IPv4 packets."; - } - leaf out-ipv4-frag { - type yang:zero-based-counter64; - description - "An outgoing packet exceeded the configured IPv4 MTU, so needed to be - fragmented. This may happen, but should be unusual."; - } - leaf out-ipv4-frag-not { - type yang:zero-based-counter64; - description - "An outgoing packet was small enough to pass through unfragmented - this - should be the usual case."; - } - leaf out-ipv4-packets { - type yang:zero-based-counter64; - description "Valid outgoing IPv4 packets."; - } - leaf out-ipv6-bytes { - type yang:zero-based-counter64; - description "All valid outgoing IPv6 packets."; - } - leaf out-ipv6-frag { - type yang:zero-based-counter64; - description - "An outgoing packet exceeded the configured IPv6 MTU, so needed to be - fragmented. This may happen, but should be unusual."; - } - leaf out-ipv6-frag-not { - type yang:zero-based-counter64; - description - "An outgoing packet was small enough to pass through unfragmented - this - should be the usual case."; - } - leaf out-ipv6-packets { - type yang:zero-based-counter64; - description "All valid outgoing IPv6 packets."; - } - } -} diff --git a/src/lib/yang/snabb-softwire-v2.yang b/src/lib/yang/snabb-softwire-v2.yang deleted file mode 100644 index bd14a9e760..0000000000 --- a/src/lib/yang/snabb-softwire-v2.yang +++ /dev/null @@ -1,889 +0,0 @@ -module snabb-softwire-v2 { - yang-version 1.1; - namespace snabb:softwire-v2; - prefix softwire; - - import ietf-inet-types { prefix inet; } - import ietf-yang-types { prefix yang; } - - organization "Igalia, S.L."; - contact "Jessica Tallon "; - description - "Configuration for the Snabb Switch lwAFTR."; - - revision 2019-09-17 { - description - "Add discontinuity time to softwire-state."; - } - - revision 2018-10-13 { - description - "Add flow-label setting."; - } - - revision 2017-04-17 { - description - "Removal of br-address leaf-list and br leaf. It adds the - addition of br-address binding_table.softwire. This is to - make the schema more yang-like. One now only need to specify - the br-address on the softwire rather than managing the index's - to a leaf-list of them. - - This also removes the psid-map list and adds a new port-set - container on the softwire container instead. This will help - adding the softwires as well as bring it more inline with the - ietf-softwire schema. - - The addition of /softwire-config/instance allows for configuring - multiple instances of the lwAFTR with a shared binding table and - other common configuration properties."; - } - - revision 2016-11-04 { - description - "Initial revision."; - } - - grouping state-counters { - container softwire-state { - - description "State data about interface."; - config false; - - leaf discontinuity-time { - type yang:date-and-time; - mandatory true; - description - "The time of the most recent occasion on which the lwaftr instance - suffered a discontinuity. This is set to the current time whenever - the lwaftr instance is started or configured."; - } - - leaf drop-all-ipv4-iface-bytes { - type yang:zero-based-counter64; - description - "All dropped packets and bytes that came in over IPv4 interfaces, - whether or not they actually IPv4 (they only include data about - packets that go in/out over the wires, excluding internally generated - ICMP packets)."; - } - leaf drop-all-ipv4-iface-packets { - type yang:zero-based-counter64; - description - "All dropped packets and bytes that came in over IPv4 interfaces, - whether or not they actually IPv4 (they only include data about - packets that go in/out over the wires, excluding internally generated - ICMP packets)."; - } - leaf drop-all-ipv6-iface-bytes { - type yang:zero-based-counter64; - description - "All dropped packets and bytes that came in over IPv6 interfaces, - whether or not they actually IPv6 (they only include data about packets - that go in/out over the wires, excluding internally generated ICMP - packets)."; - } - leaf drop-all-ipv6-iface-packets { - type yang:zero-based-counter64; - description - "All dropped packets and bytes that came in over IPv6 interfaces, - whether or not they actually IPv6 (they only include data about packets - that go in/out over the wires, excluding internally generated ICMP - packets)."; - } - leaf drop-bad-checksum-icmpv4-bytes { - type yang:zero-based-counter64; - description "ICMPv4 packets dropped because of a bad checksum."; - } - leaf drop-bad-checksum-icmpv4-packets { - type yang:zero-based-counter64; - description "ICMPv4 packets dropped because of a bad checksum."; - } - leaf drop-in-by-policy-icmpv4-bytes { - type yang:zero-based-counter64; - description "Incoming ICMPv4 packets dropped because of current policy."; - } - leaf drop-in-by-policy-icmpv4-packets { - type yang:zero-based-counter64; - description "Incoming ICMPv4 packets dropped because of current policy."; - } - leaf drop-in-by-policy-icmpv6-bytes { - type yang:zero-based-counter64; - description "Incoming ICMPv6 packets dropped because of current policy."; - } - leaf drop-in-by-policy-icmpv6-packets { - type yang:zero-based-counter64; - description "Incoming ICMPv6 packets dropped because of current policy."; - } - leaf drop-in-by-rfc7596-icmpv4-bytes { - type yang:zero-based-counter64; - description - "Incoming ICMPv4 packets with no destination (RFC 7596 section 8.1)."; - } - leaf drop-in-by-rfc7596-icmpv4-packets { - type yang:zero-based-counter64; - description - "Incoming ICMPv4 packets with no destination (RFC 7596 section 8.1)."; - } - leaf drop-ipv4-frag-disabled { - type yang:zero-based-counter64; - description - "If fragmentation is disabled, the only potentially non-zero IPv4 - fragmentation counter is drop-ipv4-frag-disabled. If fragmentation is - enabled, it will always be zero."; - } - leaf drop-ipv4-frag-invalid-reassembly { - type yang:zero-based-counter64; - description - "Two or more IPv4 fragments were received, and reassembly was started, - but was invalid and dropped. Causes include multiple fragments claiming - they are the last fragment, overlapping fragment offsets, or the packet - was being reassembled from too many fragments (the setting is - max_fragments_per_reassembly_packet, and the default is that no packet - should be reassembled from more than 40)."; - } - leaf drop-ipv4-frag-random-evicted { - type yang:zero-based-counter64; - description - "Reassembling an IPv4 packet from fragments was in progress, but the - configured amount of packets to reassemble at once was exceeded, so one - was dropped at random. Consider increasing the setting - max_ipv4_reassembly_packets."; - } - leaf drop-ipv6-frag-disabled { - type yang:zero-based-counter64; - description - "If fragmentation is disabled, the only potentially non-zero IPv6 - fragmentation counter is drop-ipv6-frag-disabled. If fragmentation is - enabled, it will always be zero."; - } - leaf drop-ipv6-frag-invalid-reassembly { - type yang:zero-based-counter64; - description - "Two or more IPv6 fragments were received, and reassembly was started, - but was invalid and dropped. Causes include multiple fragments claiming - they are the last fragment, overlapping fragment offsets, or the packet - was being reassembled from too many fragments (the setting is - max_fragments_per_reassembly_packet, and the default is that no packet - should be reassembled from more than 40)."; - } - leaf drop-ipv6-frag-random-evicted { - type yang:zero-based-counter64; - description - "Reassembling an IPv6 packet from fragments was in progress, but the - configured amount of packets to reassemble at once was exceeded, so one - was dropped at random. Consider increasing the setting - max_ipv6_reassembly_packets."; - } - leaf drop-misplaced-not-ipv4-bytes { - type yang:zero-based-counter64; - description "Non-IPv4 packets incoming on the IPv4 link."; - } - leaf drop-misplaced-not-ipv4-packets { - type yang:zero-based-counter64; - description "Non-IPv4 packets incoming on the IPv4 link."; - } - leaf drop-misplaced-not-ipv6-bytes { - type yang:zero-based-counter64; - description "Non-IPv6 packets incoming on IPv6 link."; - } - leaf drop-misplaced-not-ipv6-packets { - type yang:zero-based-counter64; - description "Non-IPv6 packets incoming on IPv6 link."; - } - leaf drop-no-dest-softwire-ipv4-bytes { - type yang:zero-based-counter64; - description - "No matching destination softwire in the binding table; incremented - whether or not the reason was RFC7596."; - } - leaf drop-no-dest-softwire-ipv4-packets { - type yang:zero-based-counter64; - description - "No matching destination softwire in the binding table; incremented - whether or not the reason was RFC7596."; - } - leaf drop-no-source-softwire-ipv6-bytes { - type yang:zero-based-counter64; - description - "No matching source softwire in the binding table; incremented whether - or not the reason was RFC7596."; - } - leaf drop-no-source-softwire-ipv6-packets { - type yang:zero-based-counter64; - description - "No matching source softwire in the binding table; incremented whether - or not the reason was RFC7596."; - } - leaf drop-out-by-policy-icmpv4-packets { - type yang:zero-based-counter64; - description - "Internally generated ICMPv4 error packets dropped because of current - policy."; - } - leaf drop-out-by-policy-icmpv6-packets { - type yang:zero-based-counter64; - description - "Internally generated ICMPv6 packets dropped because of current - policy."; - } - leaf drop-over-mtu-but-dont-fragment-ipv4-bytes { - type yang:zero-based-counter64; - description - "IPv4 packets whose size exceeded the MTU, but the DF (Don't Fragment) - flag was set."; - } - leaf drop-over-mtu-but-dont-fragment-ipv4-packets { - type yang:zero-based-counter64; - description - "IPv4 packets whose size exceeded the MTU, but the DF (Don't Fragment) - flag was set."; - } - leaf drop-over-rate-limit-icmpv6-bytes { - type yang:zero-based-counter64; - description - "Packets dropped because the outgoing ICMPv6 rate limit was reached."; - } - leaf drop-over-rate-limit-icmpv6-packets { - type yang:zero-based-counter64; - description - "Packets dropped because the outgoing ICMPv6 rate limit was reached."; - } - leaf drop-over-time-but-not-hop-limit-icmpv6-bytes { - type yang:zero-based-counter64; - description - "Packet's time limit was exceeded, but the hop limit was not."; - } - leaf drop-over-time-but-not-hop-limit-icmpv6-packets { - type yang:zero-based-counter64; - description - "Packet's time limit was exceeded, but the hop limit was not."; - } - leaf drop-too-big-type-but-not-code-icmpv6-bytes { - type yang:zero-based-counter64; - description - "Packet's ICMP type was 'Packet too big' but its ICMP code was not an - acceptable one for this type."; - } - leaf drop-too-big-type-but-not-code-icmpv6-packets { - type yang:zero-based-counter64; - description - "Packet's ICMP type was 'Packet too big' but its ICMP code was not an - acceptable one for this type."; - } - leaf drop-ttl-zero-ipv4-bytes { - type yang:zero-based-counter64; - description "IPv4 packets dropped because their TTL was zero."; - } - leaf drop-ttl-zero-ipv4-packets { - type yang:zero-based-counter64; - description "IPv4 packets dropped because their TTL was zero."; - } - leaf drop-unknown-protocol-icmpv6-bytes { - type yang:zero-based-counter64; - description "Packets with an unknown ICMPv6 protocol."; - } - leaf drop-unknown-protocol-icmpv6-packets { - type yang:zero-based-counter64; - description "Packets with an unknown ICMPv6 protocol."; - } - leaf drop-unknown-protocol-ipv6-bytes { - type yang:zero-based-counter64; - description "Packets with an unknown IPv6 protocol."; - } - leaf drop-unknown-protocol-ipv6-packets { - type yang:zero-based-counter64; - description "Packets with an unknown IPv6 protocol."; - } - leaf hairpin-ipv4-bytes { - type yang:zero-based-counter64; - description "IPv4 packets going to a known b4 (hairpinned)."; - } - leaf hairpin-ipv4-packets { - type yang:zero-based-counter64; - description "IPv4 packets going to a known b4 (hairpinned)."; - } - leaf in-ipv4-bytes { - type yang:zero-based-counter64; - description "All valid outgoing IPv4 packets."; - } - leaf in-ipv4-frag-needs-reassembly { - type yang:zero-based-counter64; - description "An IPv4 fragment was received."; - } - leaf in-ipv4-frag-reassembled { - type yang:zero-based-counter64; - description "A packet was successfully reassembled from IPv4 fragments."; - } - leaf in-ipv4-frag-reassembly-unneeded { - type yang:zero-based-counter64; - description - "An IPv4 packet which was not a fragment was received - consequently, - it did not need to be reassembled. This should be the usual case."; - } - leaf in-ipv4-packets { - type yang:zero-based-counter64; - description "All valid outgoing IPv4 packets."; - } - leaf in-ipv6-bytes { - type yang:zero-based-counter64; - description "All valid outgoing IPv4 packets."; - } - leaf in-ipv6-frag-needs-reassembly { - type yang:zero-based-counter64; - description "An IPv6 fragment was received."; - } - leaf in-ipv6-frag-reassembled { - type yang:zero-based-counter64; - description "A packet was successfully reassembled from IPv6 fragments."; - } - leaf in-ipv6-frag-reassembly-unneeded { - type yang:zero-based-counter64; - description - "An IPv6 packet which was not a fragment was received - consequently, it - did not need to be reassembled. This should be the usual case."; - } - leaf in-ipv6-packets { - type yang:zero-based-counter64; - description "All valid outgoing IPv4 packets."; - } - leaf ingress-packet-drops { - type yang:zero-based-counter64; - description "Packets dropped due to ingress filters."; - } - leaf memuse-ipv4-frag-reassembly-buffer { - type yang:zero-based-counter64; - description - "The amount of memory being used by the statically sized data structure - for reassembling IPv4 fragments. This is directly proportional to the - setting max_ipv4_reassembly_packets."; - } - leaf memuse-ipv6-frag-reassembly-buffer { - type yang:zero-based-counter64; - description - "The amount of memory being used by the statically sized data structure - for reassembling IPv6 fragments. This is directly proportional to the - setting max_ipv6_reassembly_packets."; - } - leaf out-icmpv4-bytes { - type yang:zero-based-counter64; - description "Internally generated ICMPv4 packets."; - } - leaf out-icmpv4-packets { - type yang:zero-based-counter64; - description "Internally generated ICMPv4 packets."; - } - leaf out-icmpv6-bytes { - type yang:zero-based-counter64; - description "Internally generted ICMPv6 error packets."; - } - leaf out-icmpv6-packets { - type yang:zero-based-counter64; - description "Internally generted ICMPv6 error packets."; - } - leaf out-ipv4-bytes { - type yang:zero-based-counter64; - description "Valid outgoing IPv4 packets."; - } - leaf out-ipv4-frag { - type yang:zero-based-counter64; - description - "An outgoing packet exceeded the configured IPv4 MTU, so needed to be - fragmented. This may happen, but should be unusual."; - } - leaf out-ipv4-frag-not { - type yang:zero-based-counter64; - description - "An outgoing packet was small enough to pass through unfragmented - this - should be the usual case."; - } - leaf out-ipv4-packets { - type yang:zero-based-counter64; - description "Valid outgoing IPv4 packets."; - } - leaf out-ipv6-bytes { - type yang:zero-based-counter64; - description "All valid outgoing IPv6 packets."; - } - leaf out-ipv6-frag { - type yang:zero-based-counter64; - description - "An outgoing packet exceeded the configured IPv6 MTU, so needed to be - fragmented. This may happen, but should be unusual."; - } - leaf out-ipv6-frag-not { - type yang:zero-based-counter64; - description - "An outgoing packet was small enough to pass through unfragmented - this - should be the usual case."; - } - leaf out-ipv6-packets { - type yang:zero-based-counter64; - description "All valid outgoing IPv6 packets."; - } - } - } - - container softwire-config { - description - "Configuration for Snabb lwaftr."; - - leaf name { - type string; - description - "Name of lwAFTR instance. This must be unique amongst the Snabb - processes on the system. This may be specified either here, in the - YANG configuration or via the command line when the lwAFTR is started. - - The order of presidence for this leaf is as followers: - 1. The name set on an already running lwAFTR instance via snabb set. - 2. A command line option to specify the name upon starting the lwAFTR - instance (i.e. overriding this value). - 3. The value here in the configuration when starting a lwaftr instance. - - If no name is specified the lwaftr can be referred to using the PID of - the lwAFTR process on the system."; - } - - grouping traffic-filters { - description - "Ingress and egress filters describing the set of packets - that should be allowed to pass, as pflang filters. pflang - is the language of tcpdump, libpcap and other tools. Note - that if VLAN tagging is enabled, the filters run on packets - after VLAN tags have been stripped off."; - leaf ingress-filter { - type string; - description - "Filter for incoming traffic. Packets that do not match - the filter will be silently dropped."; - } - leaf egress-filter { - type string; - description - "Filter for outgoing traffic. Packets that do not match - the filter will be silently dropped."; - } - } - - grouping icmp-policy { - description - "The lwAFTR can be configured to allow or drop incoming ICMP - messages, and to generate outgoing ICMP error messages or - not."; - - leaf allow-incoming-icmp { - type boolean; - default true; - description - "Whether to allow incoming ICMP packets."; - } - - leaf generate-icmp-errors { - type boolean; - default true; - description - "Whether to generate outgoing ICMP error messages."; - } - } - - grouping vlan-tagging { - description - "802.1Q Ethernet tagging."; - - leaf vlan-tag { - type uint16 { - range 0..4095; - } - description - "802.1Q Ethernet VLAN tag for this interface."; - } - } - - grouping error-rate-limiting { - description - "These settings limit the rate of ICMP error message - transmission."; - - container error-rate-limiting { - leaf packets { - type uint32; - description - "The number of ICMP error messages which can be sent within - the specified time period."; - } - - leaf period { - type uint32 { range 1..max; } - default 2; - description - "The time period given in seconds."; - } - } - } - - grouping reassembly { - description - "These settings limit the resources devoted to reassembling - fragmented packets."; - - container reassembly { - leaf max-fragments-per-packet { - type uint32 { range 1..max; } - default 20; - description - "The maximum number of fragments per reassembled packet. - Attempts to reassemble a packet using more fragments than - this threshold will fail and the reassembly data will be - discarded."; - } - - leaf max-packets { - type uint32; - default 20000; - description - "The maximum number of concurrent reassembly attempts. If - this limit is reached, an additional reassembly will cause - random eviction of an ongoing reassembly. Note that this - setting directly affects memory usage; the memory buffer - allocated to reassembly is this maximum number of - reassemblies times 25 kilobytes each."; - } - } - } - - - list instance { - description - "Provides configuration for specific instances of the lwAFTR. - These configuration options will only affect the specific lwaftr - with the given name specified in the name leaf. The other options - not present in this list are shared amongst all instances."; - - key "device"; - - leaf device { - type string; - description - "The PCI device the instance should use during lwAFTR operation. If - device is configured in on-a-stick mode, the 'external-interface' - device should not be configured. If the 'external-interface is - specified this option should specify the PCI device of the - 'internal-interface' (IPv6 traffic only)."; - } - - list queue { - description "List of Receive-Side Scaling (RSS) queues."; - key "id"; - - leaf id { - type uint8 { range 0..1; } - description - "RSS queue on which to attach. Traffic will be partitioned - evenly between instances servicing queues on the same - interface. The queue to which an incoming packet is assigned - is a function of the TCP or UDP source and destination ports - (if any) and the source and destination IPv4 or IPv6 - addresses. Fragmented packets will be delivered to the - lowest-numbered queue. - - Note that currently the lwAFTR is restricted to running at - most 2 RSS workers per device. This limitation may be lifted - to 4 soon. Raising it farther is possible but needs changes - to how the lwAFTR uses its PCI devices."; - } - - container external-interface { - leaf ip { - type inet:ipv4-address; - mandatory true; - description - "L3 Address of the internet-facing network interface. Used - when generating error messages and responding to ICMP echo - requests."; - } - leaf device { - description - "PCI device of the instance uses for external IPv6 traffic. If this - is left unspecified the lwAFTR configures itself in on-a-stick - mode."; - type string; - } - leaf mac { - type yang:mac-address; - mandatory true; - description - "MAC address of the internet-facing NIC."; - } - - uses vlan-tagging; - - container next-hop { - choice address { - mandatory true; - case ip { - leaf ip { - type inet:ipv4-address; - description - "IPv4 address of the next hop for the internet-facing NIC. - The lwAFTR will resolve this to a MAC address using ARP."; - } - leaf resolved-mac { - config false; - description "Resolved next-hop mac address found by ARP."; - type yang:mac-address; - } - } - case mac { - leaf mac { - type yang:mac-address; - description - "Statically configured MAC address of the next hop for the - internet-facing NIC."; - } - } - } - } - } - - container internal-interface { - leaf ip { - type inet:ipv6-address; - mandatory true; - description - "L3 Address of the internal-facing network interface. Used - when generating error messages and responding to ICMP echo - requests."; - } - leaf mac { - type yang:mac-address; - mandatory true; - description - "MAC address of the internal-facing NIC."; - } - - uses vlan-tagging; - - - container next-hop { - choice address { - mandatory true; - case ip { - leaf ip { - type inet:ipv6-address; - description - "IPv4 address of the next hop for the internet-facing NIC. - The lwAFTR will resolve this to a MAC address using ARP."; - } - leaf resolved-mac { - config false; - description "Resolved next-hop mac address found by ARP."; - type yang:mac-address; - } - } - case mac { - leaf mac { - type yang:mac-address; - description - "Statically configured MAC address of the next hop for the - internet-facing NIC."; - } - } - } - } - } - } - - uses state-counters; - } - - container external-interface { - description - "Configuration for the external, internet-facing IPv4 - interface."; - - leaf mtu { - type uint16; - default 1460; - description - "Maximum packet size to send on the IPv4 interface."; - } - - leaf mru { - type uint16; - default 1460; - description - "Maximum packet size to receive on the IPv4 interface."; - } - - uses traffic-filters; - uses icmp-policy; - uses error-rate-limiting; - uses reassembly; - - - } - - container internal-interface { - description - "Configuration for the internal IPv6 interface."; - - leaf mtu { - type uint16; - default 1500; - description - "Maximum packet size to sent on the IPv6 interface."; - } - - leaf mru { - type uint16; - default 1460; - description - "Maximum packet size to recieve on the IPv6 interface."; - } - - leaf flow-label { - type uint32; - default 0; - description - "IPv6 flow label"; - } - - uses traffic-filters; - uses icmp-policy; - uses vlan-tagging; - uses error-rate-limiting; - uses reassembly; - - leaf hairpinning { - type boolean; - default true; - description - "Indicates whether to support hairpinning of traffic between - two B4s."; - } - } - - container binding-table { - description - "A collection of softwires (tunnels), along with a description - of the IPv4 and IPv6 addresses handled by the lwAFTR."; - - list softwire { - key "ipv4 psid"; - - leaf ipv4 { - type inet:ipv4-address; - mandatory true; - description - "Public IPv4 address of the softwire."; - } - - leaf padding { - type uint16; - default 0; - } - - leaf br-address { - type inet:ipv6-address; - mandatory true; - description - "The B4-facing address of the lwAFTR for this softwire."; - } - - leaf b4-ipv6 { - type inet:ipv6-address; - mandatory true; - description - "B4 address."; - } - - leaf psid { - type uint16; - mandatory true; - description "Port set ID."; - } - - container port-set { - description - "The set of IPv4 addresses managed by the lwAFTR, along with - the way in which those IPv4 addresses share ports. A PSID map - entry associates a PSID length and reserved-ports-bit-count - with each IPv4 address served by the lwAFTR. - - The lightweight 4-over-6 architecture supports sharing of - IPv4 addresses by partitioning the space of TCP/UDP/ICMP - ports into disjoint \"port sets\". Each softwire associated - with an IPv4 address corresponds to a different set of ports - on that address. The way that the ports are partitioned is - specified in RFC 7597: each address has an associated set - of parameters that specifies how to compute a \"port set - identifier\" (PSID) from a given port. - - 0 1 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 - +-----------+-----------+-------+ - Ports in | A | PSID | j | - the CE port set | > 0 | | | - +-----------+-----------+-------+ - | a bits | k bits |m bits | - - Figure 2: Structure of a Port-Restricted Port Field - - Source: http://tools.ietf.org/html/rfc7597#section-5.1 - - We find the specification's names to be a bit obtuse, so we - refer to them using the following names: - - a bits = reserved-ports-bit-count. - k bits = psid-length. - m bits = shift. - - The shift parameter is calculated from psid-length and - reserved-ports-bit-count. The calculation performed to - get the value of shift is: - - shift = 16 - psid-length - reserved-ports-bit-count"; - - leaf psid-length { - type uint8 { range 0..16; } - mandatory true; - description - "The number of bits devoted to the PSID in the port map. - If the psid-length is N, then the IPv4 address will be - shared 2^N ways. Note that psid-length, shift, and - reserved-ports-bit-count must add up to 16."; - } - - leaf reserved-ports-bit-count { - type uint8 { range 0..16; } - default 0; - description - "Reserve the lowest 2^N ports so that they map to no - softwire. This can be useful to prevent the low 1024 - ports (for example) from being mapped to customers. Note - that psid-length and shift must add up to less than or - equal to 16."; - } - } - } - - container version { - description - "Optional versioning for binding table. The vesioning information - will change on every update or change to the binding table."; - - leaf number { - type uint64; - description "Incremental version number."; - } - leaf date { - type yang:date-and-time; - description "Timestamp of last change."; - } - } - } - } - - uses state-counters; -} diff --git a/src/program/lwaftr/README b/src/program/lwaftr/README index 6aa203703f..c5c159a46e 100644 --- a/src/program/lwaftr/README +++ b/src/program/lwaftr/README @@ -3,7 +3,6 @@ Usage: snabb lwaftr check snabb lwaftr compile-configuration snabb lwaftr generate-configuration - snabb lwaftr migrate-configuration snabb lwaftr monitor snabb lwaftr query snabb lwaftr quickcheck diff --git a/src/program/lwaftr/migrate_configuration/README b/src/program/lwaftr/migrate_configuration/README deleted file mode 100644 index 5301fb878c..0000000000 --- a/src/program/lwaftr/migrate_configuration/README +++ /dev/null @@ -1,37 +0,0 @@ -Usage: migrate-configuration LWAFTR.CONF - -Options: - -h, --help Print usage information. - -f, --from=VERSION Specify version from which to migrate. - -Migrate an old-style configuration and binding table to the new YANG -configuration. LWAFTR.CONF should be the name of an old lwAFTR -configuration. Available VERSION values are: - - legacy - Configuration from pre-v3.0.0 lwAFTR. - 3.0.1 - lwAFTR versions where "container" nodes in schemas are missing - corresponding nodes in the data unless "presence true" is - specified. - 3.0.1.1 - lwAFTR development snapshot where "br" fields of softwires were - 0-based instead of 1-based. - 3.2.0 - lwAFTR versions where "br" fields were indexes for the "br-address" - leaf-list instead of "br-address" IPv6 entries on the softwire. - 2017.07.01 - lwAFTR changes to multiprcoess configuration with the introduction of the - instance list. - - This change will put place holders "IPv4 PCI Address" and "IPv6 PCI Address" - where the external and internal PCI addresses of your NICs go respectively. - This should be changed however when running the lwAFTR with only one - instance defined a in-memory migration will occur on each run of the lwAFTR - please refer to program/lwaftr/doc/running.md documentation for further - information. - -The default version is "legacy". - -The resulting up-to-date configuration will be printed on standard -output, ready to be saved to a new file. diff --git a/src/program/lwaftr/migrate_configuration/README.inc b/src/program/lwaftr/migrate_configuration/README.inc deleted file mode 120000 index 100b93820a..0000000000 --- a/src/program/lwaftr/migrate_configuration/README.inc +++ /dev/null @@ -1 +0,0 @@ -README \ No newline at end of file diff --git a/src/program/lwaftr/migrate_configuration/conf_parser.lua b/src/program/lwaftr/migrate_configuration/conf_parser.lua deleted file mode 100644 index 39f82ad32a..0000000000 --- a/src/program/lwaftr/migrate_configuration/conf_parser.lua +++ /dev/null @@ -1,321 +0,0 @@ -module(..., package.seeall) - -local ffi = require("ffi") -local lib = require("core.lib") -local ipv4 = require("lib.protocol.ipv4") -local ipv6 = require("lib.protocol.ipv6") -local ethernet = require("lib.protocol.ethernet") - -Parser = {} - -function Parser.new(file) - local name = file.name - local err - if type(file) == 'string' then - name = file - file, err = io.open(file) - if not file then error(err) end - end - local ret = { column=0, line=1, name=name } - function ret.read_char() return file:read(1) end - function ret.cleanup() - function ret.cleanup() end - return file:close() - end - ret.peek_char = ret.read_char() - return setmetatable(ret, {__index=Parser}) -end - -function Parser:error(msg, ...) - self.cleanup() - error(('%s:%d:%d: error: '..msg):format( - self.name or '', self.line, self.column, ...)) -end - -function Parser:next() - local chr = self.peek_char - if chr == '\n' then - self.column = 0 - self.line = self.line + 1 - elseif chr then - self.column = self.column + 1 - else - self.cleanup() - end - self.peek_char = self.read_char() - return chr -end - -function Parser:peek() return self.peek_char end -function Parser:is_eof() return not self:peek() end - -function Parser:check(expected) - if self:peek() == expected then - if expected then self:next() end - return true - end - return false -end - -function Parser:consume(expected) - if not self:check(expected) then - local ch = self:peek() - if ch == nil then - self:error("while looking for '%s', got EOF", expected) - elseif expected then - self:error("expected '%s', got '%s'", expected, ch) - else - self:error("expected EOF, got '%s'", ch) - end - end -end - -function Parser:take_while(pattern) - local res = {} - while not self:is_eof() and self:peek():match(pattern) do - table.insert(res, self:next()) - end - return table.concat(res) -end - -function Parser:consume_token(pattern, expected) - local tok = self:take_while(pattern) - if tok:lower() ~= expected then - self:error("expected '%s', got '%s'", expected, tok) - end -end - -function Parser:skip_whitespace() - self:take_while('%s') - -- Skip comments, which start with # and continue to the end of line. - while self:check('#') do - self:take_while('[^\n]') - self:take_while('%s') - end -end - -function Parser:parse_uint(min, max) - local tok = self:take_while('%d') - if tok == '' then self:error('expected a number') end - if #tok > #(tostring(max)) then - self:error('numeric constant too long: %s', tok) - end - local uint = tonumber(tok) - if uint < min or uint > max then - self:error('numeric constant out of range: %d', uint) - end - return uint -end - -function Parser:parse_psid_param() return self:parse_uint(0, 16) end -function Parser:parse_ipv4_quad() return self:parse_uint(0, 255) end - -function Parser:parse_property_list(spec, bra, ket) - local res = {} - self:skip_whitespace() - if bra then - self:consume(bra) - self:skip_whitespace() - end - while not self:check(ket) do - local key = self:take_while('[%w_]') - if key == '' then - self:error("expected a key=value property or a closing '%s'", ket) - end - if res[key] then self:error('duplicate key: %s', key) end - if not spec.parse[key] then self:error('unexpected key: "%s"', key) end - self:skip_whitespace() - self:consume('=') - self:skip_whitespace() - local val = spec.parse[key](self) - res[key] = val - - -- Key-value pairs are separated by newlines or commas, and - -- terminated by the ket. A trailing comma is optional. - local line = self.line - self:skip_whitespace() - local has_comma = self:check(',') - if has_comma then self:skip_whitespace() end - if self:check(ket) then break end - if not has_comma and self.line == line then - self:error('properties should be separated by commas or newlines') - end - end - for k, default in pairs(spec.defaults) do - if res[k] == nil then res[k] = default(res) end - end - spec.validate(self, res) - return res -end - --- Returns a uint8_t[4]. -function Parser:parse_ipv4() - local addr_string = self:take_while('[%d.]') - if not addr_string or #addr_string == 0 then - self:error("IPv4 address expected") - end - local addr, err = ipv4:pton(addr_string) - if not addr then self:error('%s', err) end - return addr -end - -function Parser:parse_ipv4_as_uint32() - local addr = self:parse_ipv4() - return ffi.C.htonl(ffi.cast('uint32_t*', addr)[0]) -end - --- Returns a uint8_t[16]. -function Parser:parse_ipv6() - local addr_string = self:take_while('[%x:]') - if not addr_string or #addr_string == 0 then - self:error("IPv6 address expected") - end - local addr, err = ipv6:pton(addr_string) - if not addr then self:error('%s', err) end - return addr -end - --- Returns a uint8_t[6]. -function Parser:parse_mac() - local addr_string = self:take_while('[%x:]') - if not addr_string or #addr_string == 0 then - self:error("Ethernet MAC address expected") - end - -- FIXME: Unlike ipv6:pton, ethernet:pton raises an error if the - -- address is invalid. - local success, addr_or_err = pcall(ethernet.pton, ethernet, addr_string) - if not success then self:error('%s', addr_or_err) end - return addr_or_err -end - -function Parser:parse_ipv4_range() - local range_begin, range_end - range_begin = self:parse_ipv4_as_uint32() - self:skip_whitespace() - if self:check('-') then - self:skip_whitespace() - range_end = self:parse_ipv4_as_uint32() - else - range_end = range_begin - end - if range_end < range_begin then - self:error('invalid IPv4 address range (end before begin)') - end - return { min=range_begin, max=range_end } -end - -function Parser:parse_ipv4_range_list() - local ranges = {} - repeat - self:skip_whitespace() - table.insert(ranges, self:parse_ipv4_range()) - self:skip_whitespace() - until not self:check(',') - return ranges -end - -function Parser:parse_quoted_string(quote, escape) - local res = {} - escape = escape or '\\' - while not self:check(quote) do - local ch = self:next() - if ch == escape then ch = self:next() end - if not ch then self:error('EOF while reading quoted string') end - table.insert(res, ch) - end - return table.concat(res) -end - -function Parser:parse_string() - local str - if self:check("'") then str = self:parse_quoted_string("'") - elseif self:check('"') then str = self:parse_quoted_string('"') - else str = self:take_while('[^%s,]') end - return str -end - -function Parser:make_path(orig_path) - if orig_path == '' then self:error('file name is empty') end - if not orig_path:match('^/') and self.name then - -- Relative paths in conf files are relative to the location of the - -- conf file, not the current working directory. - return lib.dirname(self.name)..'/'..orig_path - end - return orig_path -end - -function Parser:parse_file_name() - return self:make_path(self:parse_string()) -end - -function Parser:parse_string_or_file() - local str = self:parse_string() - if not str:match('^<') then - return str - end - -- Remove the angle bracket. - local path = self:make_path(str:sub(2)) - local filter, err = lib.readfile(path, "*a") - if filter == nil then - self:error('cannot read filter conf file "%s": %s', path, err) - end - return filter -end - -function Parser:parse_boolean() - local tok = self:take_while('[%a]') - if tok:lower() == 'true' then return true end - if tok:lower() == 'false' then return false end - self:error('expected "true" or "false", instead got "%s"', tok) -end - -function Parser:parse_number() - local tok = self:take_while('[%d.eExX]') - local num = tonumber(tok) - if not num then self:error('expected a number, instead got "%s"', tok) end - return num -end - -function Parser:parse_positive_number() - local num = self:parse_number() - if num <= 0 then - self:error('expected a positive number, instead got %s', - tostring(num)) - end - return num -end - -function Parser:parse_non_negative_number() - local num = self:parse_number() - if num < 0 then - self:error('expected a non-negative number, instead got %s', - tostring(num)) - end - return num -end - -function Parser:parse_mtu() - return self:parse_uint(0,2^16-1) -end - -function Parser:parse_psid() - return self:parse_uint(0,2^16-1) -end - -function Parser.enum_parser(enums) - return function(self) - local tok = self:parse_string() - for k,v in pairs(enums) do - if k:lower() == tok:lower() then return v end - end - -- Not found; make a nice error. - local keys = {} - for k,_ in pairs(enums) do table.insert(keys, k) end - keys = table.concat(keys, ', ') - self:error('bad value: "%s". expected one of %s', tok, keys) - end -end - -function Parser:parse_vlan_tag() - return self:parse_uint(0,2^12-1) -end diff --git a/src/program/lwaftr/migrate_configuration/migrate_configuration.lua b/src/program/lwaftr/migrate_configuration/migrate_configuration.lua deleted file mode 100644 index a960c936c8..0000000000 --- a/src/program/lwaftr/migrate_configuration/migrate_configuration.lua +++ /dev/null @@ -1,664 +0,0 @@ -module(..., package.seeall) - -local lib = require('core.lib') -local ffi = require("ffi") -local ipv4 = require("lib.protocol.ipv4") -local rangemap = require("apps.lwaftr.rangemap") -local ctable = require("lib.ctable") -local cltable = require('lib.cltable') -local mem = require('lib.stream.mem') -local util = require('lib.yang.util') -local yang = require('lib.yang.yang') -local binding_table = require("apps.lwaftr.binding_table") -local Parser = require("program.lwaftr.migrate_configuration.conf_parser").Parser -local data = require('lib.yang.data') -local schema = require('lib.yang.schema') - -local br_address_t = ffi.typeof('uint8_t[16]') -local SOFTWIRE_TABLE_LOAD_FACTOR = 0.4 - -local function show_usage(code) - print(require("program.lwaftr.migrate_configuration.README_inc")) - main.exit(code) -end - -local function parse_args(args) - local handlers = {} - local version = 'legacy' - function handlers.h() show_usage(0) end - function handlers.f(v) version = string.lower(v) end - args = lib.dogetopt(args, handlers, "hf:", { help="h", from="f" }) - if #args ~= 1 then show_usage(1) end - return args[1], version -end - -local policies = { - DROP = 1, - ALLOW = 2 -} - -local function required(key) - return function(config) - error('missing required configuration key "'..key..'"') - end -end - -local function required_if(key, otherkey) - return function(config) - if config[otherkey] then - error('missing required configuration key "'..key..'"') - end - end -end - -local function required_at_least_one_of(key, otherkey) - return function(config) - if config[otherkey] == nil then - error(string.format("At least one of '%s' and '%s' must be specified", key, otherkey)) - end - end -end - -local function default(val) - return function(config) return val end -end - -local lwaftr_conf_spec = { - parse={ - aftr_ipv4_ip=Parser.parse_ipv4, - aftr_ipv6_ip=Parser.parse_ipv6, - aftr_mac_b4_side=Parser.parse_mac, - aftr_mac_inet_side=Parser.parse_mac, - next_hop6_mac=Parser.parse_mac, - binding_table=Parser.parse_file_name, - hairpinning=Parser.parse_boolean, - icmpv4_rate_limiter_n_packets=Parser.parse_non_negative_number, - icmpv4_rate_limiter_n_seconds=Parser.parse_positive_number, - icmpv6_rate_limiter_n_packets=Parser.parse_non_negative_number, - icmpv6_rate_limiter_n_seconds=Parser.parse_positive_number, - inet_mac=Parser.parse_mac, - ipv4_mtu=Parser.parse_mtu, - ipv6_mtu=Parser.parse_mtu, - max_fragments_per_reassembly_packet=Parser.parse_positive_number, - max_ipv4_reassembly_packets=Parser.parse_positive_number, - max_ipv6_reassembly_packets=Parser.parse_positive_number, - next_hop_ipv4_addr=Parser.parse_ipv4, - next_hop_ipv6_addr=Parser.parse_ipv6, - policy_icmpv4_incoming=Parser.enum_parser(policies), - policy_icmpv4_outgoing=Parser.enum_parser(policies), - policy_icmpv6_incoming=Parser.enum_parser(policies), - policy_icmpv6_outgoing=Parser.enum_parser(policies), - v4_vlan_tag=Parser.parse_vlan_tag, - v6_vlan_tag=Parser.parse_vlan_tag, - vlan_tagging=Parser.parse_boolean, - ipv4_ingress_filter=Parser.parse_string_or_file, - ipv4_egress_filter=Parser.parse_string_or_file, - ipv6_ingress_filter=Parser.parse_string_or_file, - ipv6_egress_filter=Parser.parse_string_or_file, - }, - defaults={ - aftr_ipv4_ip=required('aftr_ipv4_ip'), - aftr_ipv6_ip=required('aftr_ipv6_ip'), - aftr_mac_b4_side=required('aftr_mac_b4_side'), - aftr_mac_inet_side=required('aftr_mac_inet_side'), - next_hop6_mac=required_at_least_one_of('next_hop6_mac', 'next_hop_ipv6_addr'), - binding_table=required('binding_table'), - hairpinning=default(true), - icmpv4_rate_limiter_n_packets=default(6e5), - icmpv4_rate_limiter_n_seconds=default(2), - icmpv6_rate_limiter_n_packets=default(6e5), - icmpv6_rate_limiter_n_seconds=default(2), - inet_mac=required_at_least_one_of('inet_mac', 'next_hop_ipv4_addr'), - ipv4_mtu=default(1460), - ipv6_mtu=default(1500), - max_fragments_per_reassembly_packet=default(40), - max_ipv4_reassembly_packets=default(20000), -- Just under 500 megs memory - max_ipv6_reassembly_packets=default(20000), -- Just under 500 megs memory - next_hop_ipv4_addr = required_at_least_one_of('next_hop_ipv4_addr', 'inet_mac'), - next_hop_ipv6_addr = required_at_least_one_of('next_hop_ipv6_addr', 'next_hop6_mac'), - policy_icmpv4_incoming=default(policies.ALLOW), - policy_icmpv4_outgoing=default(policies.ALLOW), - policy_icmpv6_incoming=default(policies.ALLOW), - policy_icmpv6_outgoing=default(policies.ALLOW), - v4_vlan_tag=required_if('v4_vlan_tag', 'vlan_tagging'), - v6_vlan_tag=required_if('v6_vlan_tag', 'vlan_tagging'), - vlan_tagging=default(false) - }, - validate=function(parser, config) end -} - -local function parse_psid_map(parser) - local psid_info_spec = { - parse={ - psid_length=Parser.parse_psid_param, - shift=Parser.parse_psid_param - }, - defaults={ - psid_length=function(config) return 16 - (config.shift or 16) end, - shift=function(config) return 16 - (config.psid_length or 0) end - }, - validate=function(parser, config) - if config.psid_length + config.shift > 16 then - parser:error('psid_length %d + shift %d should not exceed 16', - config.psid_length, config.shift) - end - end - } - - local builder = rangemap.RangeMapBuilder.new(binding_table.psid_map_value_t) - local value = binding_table.psid_map_value_t() - parser:skip_whitespace() - parser:consume_token('[%a_]', 'psid_map') - parser:skip_whitespace() - parser:consume('{') - parser:skip_whitespace() - while not parser:check('}') do - local range_list = parser:parse_ipv4_range_list() - local info = parser:parse_property_list(psid_info_spec, '{', '}') - value.psid_length, value.shift = info.psid_length, info.shift - for _, range in ipairs(range_list) do - builder:add_range(range.min, range.max, value) - end - parser:skip_whitespace() - if parser:check(',') or parser:check(';') then - parser:skip_whitespace() - end - end - return builder:build(binding_table.psid_map_value_t()) -end - -local function parse_br_addresses(parser) - local addresses = {} - parser:skip_whitespace() - parser:consume_token('[%a_]', 'br_addresses') - parser:skip_whitespace() - parser:consume('{') - parser:skip_whitespace() - while not parser:check('}') do - table.insert(addresses, parser:parse_ipv6()) - parser:skip_whitespace() - if parser:check(',') then parser:skip_whitespace() end - end - local ret = util.ffi_array(ffi.new(ffi.typeof('$[?]', br_address_t), - #addresses), - br_address_t, #addresses) - for i, addr in ipairs(addresses) do ret[i] = addr end - return ret -end - -local function parse_softwires(parser, psid_map, br_address_count) - local function required(key) - return function(config) - error('missing required configuration key "'..key..'"') - end - end - local softwire_spec = { - parse={ - ipv4=Parser.parse_ipv4_as_uint32, - psid=Parser.parse_psid, - b4=Parser.parse_ipv6, - aftr=Parser.parse_non_negative_number - }, - defaults={ - ipv4=required('ipv4'), - psid=function(config) return 0 end, - b4=required('b4'), - aftr=function(config) return 0 end - }, - validate=function(parser, config) - local psid_length = psid_map:lookup(config.ipv4).value.psid_length - if config.psid >= 2^psid_length then - parser:error('psid %d out of range for IP', config.psid) - end - if config.aftr >= br_address_count then - parser:error('only %d br addresses are defined', br_address_count) - end - end - } - - local softwire_key_t = ffi.typeof[[ - struct { - uint32_t ipv4; // Public IPv4 address of this softwire (host-endian). - uint16_t padding; // Zeroes. - uint16_t psid; // Port set ID. - } __attribute__((packed)) - ]] - -- FIXME: Pull this type from the yang model, not out of thin air. - local softwire_value_t = ffi.typeof[[ - struct { - uint8_t b4_ipv6[16]; // Address of B4. - uint32_t br; // Which border router (lwAFTR IPv6 address)? - } __attribute__((packed)) - ]] - local map = ctable.new( - { key_type = softwire_key_t, value_type = softwire_value_t }) - local key, value = softwire_key_t(), softwire_value_t() - parser:skip_whitespace() - parser:consume_token('[%a_]', 'softwires') - parser:skip_whitespace() - parser:consume('{') - parser:skip_whitespace() - while not parser:check('}') do - local entry = parser:parse_property_list(softwire_spec, '{', '}') - key.ipv4, key.psid = entry.ipv4, entry.psid - value.br, value.b4_ipv6 = entry.aftr, entry.b4 - local success = pcall(map.add, map, key, value) - if not success then - parser:error('duplicate softwire for ipv4=%s, psid=%d', - lwdebug.format_ipv4(key.ipv4), key.psid) - end - parser:skip_whitespace() - if parser:check(',') then parser:skip_whitespace() end - end - map:resize(map.size / SOFTWIRE_TABLE_LOAD_FACTOR) - return map -end - -local function parse_binding_table(parser) - local psid_map = parse_psid_map(parser) - local br_addresses = parse_br_addresses(parser) - local softwires = parse_softwires(parser, psid_map, #br_addresses) - parser:skip_whitespace() - parser:consume(nil) - return { psid_map = psid_map, - br_addresses = br_addresses, - softwires = softwires } -end - -function load_binding_table(filename) - return parse_binding_table(Parser.new(filename)) -end - - -local function config_to_string(schema, conf) - if type(schema) == "string" then - schema = yang.load_schema_by_name(schema) - end - return mem.call_with_output_string( - yang.print_config_for_schema, schema, conf) -end - - -local function migrate_conf(old) - function convert_ipv4(addr) - if addr then return util.ipv4_pton(ipv4:ntop(addr)) end - end - local external = { - ip = convert_ipv4(old.aftr_ipv4_ip), - mac = old.aftr_mac_inet_side, - mtu = old.ipv4_mtu, - ingress_filter = old.ipv4_ingress_filter, - egress_filter = old.ipv4_egress_filter, - allow_incoming_icmp = old.policy_icmpv4_incoming == policies.ALLOW, - generate_icmp_errors = old.policy_icmpv4_outgoing == policies.ALLOW, - vlan_tag = old.v4_vlan_tag, - error_rate_limiting = { - packets = old.icmpv4_rate_limiter_n_packets, - period = old.icmpv4_rate_limiter_n_seconds - }, - reassembly = { - max_fragments_per_packet = old.max_fragments_per_reassembly_packet, - max_packets = old.max_ipv4_reassembly_packets - }, - next_hop = { - ip = convert_ipv4(old.next_hop_ipv4_addr), - mac = old.inet_mac - } - } - - local internal = { - ip = old.aftr_ipv6_ip, - mac = old.aftr_mac_b4_side, - mtu = old.ipv6_mtu, - ingress_filter = old.ipv6_ingress_filter, - egress_filter = old.ipv6_egress_filter, - allow_incoming_icmp = old.policy_icmpv6_incoming == policies.ALLOW, - generate_icmp_errors = old.policy_icmpv6_outgoing == policies.ALLOW, - vlan_tag = old.v6_vlan_tag, - error_rate_limiting = { - packets = old.icmpv6_rate_limiter_n_packets, - period = old.icmpv6_rate_limiter_n_seconds - }, - reassembly = { - max_fragments_per_packet = old.max_fragments_per_reassembly_packet, - max_packets = old.max_ipv6_reassembly_packets - }, - next_hop = { - ip = old.next_hop_ipv6_addr, - mac = old.next_hop6_mac - }, - hairpinning = old.hairpinning - } - - local old_bt = load_binding_table(old.binding_table) - local psid_key_t = ffi.typeof('struct { uint32_t addr; }') - local psid_map = cltable.new({ key_type = psid_key_t }) - for addr, end_addr, params in old_bt.psid_map:iterate() do - local reserved_ports_bit_count = 16 - params.psid_length - params.shift - if end_addr == addr then end_addr = nil end - if reserved_ports_bit_count ~= 16 then - psid_map[psid_key_t(addr)] = { - end_addr = end_addr, - psid_length = params.psid_length, - shift = params.shift, - reserved_ports_bit_count = reserved_ports_bit_count - } - end - end - - -- Build a version of snabb-softwire-v1 with a 0-based index so increment_br - -- does the correct thing. - local schema = yang.load_schema_by_name("snabb-softwire-v1") - local bt = schema.body["softwire-config"].body["binding-table"].body - bt.softwire.body.br.default = "0" - return config_to_string(schema, { - softwire_config = { - external_interface = external, - internal_interface = internal, - binding_table = { - psid_map = psid_map, - br_address = old_bt.br_addresses, - softwire = old_bt.softwires - } - } - }) -end - -local function increment_br(conf) - for entry in conf.softwire_config.binding_table.softwire:iterate() do - -- Sadly it's not easy to make an updater that always works for - -- the indexing change, because changing the default from 0 to 1 - -- makes it ambiguous whether a "br" value of 1 comes from the new - -- default, or was present as such in the old configuration. Sad. - if entry.value.br ~= 1 then - entry.value.br = entry.value.br + 1 - end - end - if #conf.softwire_config.binding_table.br_address > 1 then - io.stderr:write('Migrator unable to tell whether br=1 entries are '.. - 'due to new default or old setting; manual '.. - 'verification needed.\n') - io.stderr:flush() - end - return config_to_string('snabb-softwire-v1', conf) -end - -local function remove_address_list(conf) - local bt = conf.softwire_config.binding_table - for key, entry in cltable.pairs(bt.softwire) do - local br = entry.br or 1 - entry.br_address = assert(bt.br_address[br]) - entry.br = nil - end - return conf -end - -local function remove_psid_map(conf) - -- We're actually going to load the psidmap in the schema so ranges can easily be - -- looked up. With support of end-addr simply trying to lookup by addr will fail. - -- Luckily this is the last time this should bother us hopefully. - local function load_range_map(conf) - local rangemap = require("apps.lwaftr.rangemap") - local psid_map_value_t = binding_table.psid_map_value_t - - -- This has largely been taken from the binding_table.lua at 3db2896 - -- however it only builds the psidmap and not the entire binding table. - local psid_builder = rangemap.RangeMapBuilder.new(psid_map_value_t) - local psid_value = psid_map_value_t() - for k, v in cltable.pairs(conf.psid_map) do - local psid_length, shift = v.psid_length, v.shift - shift = shift or 16 - psid_length - (v.reserved_ports_bit_count or 0) - assert(psid_length + shift <= 16, - 'psid_length '..psid_length..' + shift '..shift.. - ' should not exceed 16') - psid_value.psid_length, psid_value.shift = psid_length, shift - psid_builder:add_range(k.addr, v.end_addr or k.addr, psid_value) - end - return psid_builder:build(psid_map_value_t()) - end - - local psid_map = load_range_map(conf.softwire_config.binding_table) - - -- Remove the psid-map and add it to the softwire. - local bt = conf.softwire_config.binding_table - for key, entry in cltable.pairs(bt.softwire) do - -- Find the port set for the ipv4 address - local port_set = psid_map:lookup(key.ipv4) - assert(port_set, "Unable to migrate conf: softwire without psidmapping") - - -- Add the psidmapping to the softwire - local shift, length = port_set.value.shift, port_set.value.psid_length - entry.port_set = { - psid_length=length, - reserved_ports_bit_count=(16 - shift - length) - } - end - - return conf -end - -local function v3_migration(src, conf_file) - local v2_schema = yang.load_schema_by_name("snabb-softwire-v2") - local v3_schema = yang.load_schema_by_name("snabb-softwire-v3") - local conf = yang.load_config_for_schema( - v2_schema, mem.open_input_string(src, conf_file)) - - -- Move leaf external-interface/device up as external-device. - for device, instance in pairs(conf.softwire_config.instance) do - for id, queue in pairs(instance.queue) do - if queue.external_interface.device then - if instance.external_device then - io.stderr:write('Multiple external devices detected; '.. - 'manual verification needed.\n') - io.stderr:flush() - end - instance.external_device = queue.external_interface.device - queue.external_interface.device = nil - end - end - end - - return config_to_string(v3_schema, conf) -end - -local function multiprocess_migration(src, conf_file) - local device = "IPv6 PCI Address" - local ex_device = "IPv4 PCI address" - - -- We should build up a hybrid schema from parts of v1 and v2. - local v1_schema = yang.load_schema_by_name("snabb-softwire-v1") - -- Make sure we load a fresh schema, as not to mutate a memoized copy - local hybridscm = schema.load_schema(schema.load_schema_source_by_name("snabb-softwire-v2")) - local v1_external = v1_schema.body["softwire-config"].body["external-interface"] - local v1_internal = v1_schema.body["softwire-config"].body["internal-interface"] - local external = hybridscm.body["softwire-config"].body["external-interface"] - local internal = hybridscm.body["softwire-config"].body["internal-interface"] - local queue = hybridscm.body["softwire-config"].body.instance.body.queue - - -- Remove the mandatory requirements - queue.body["external-interface"].body.ip.mandatory = false - queue.body["external-interface"].body.mac.mandatory = false - queue.body["external-interface"].body["next-hop"].mandatory = false - queue.body["internal-interface"].body.ip.mandatory = false - queue.body["internal-interface"].body.mac.mandatory = false - queue.body["internal-interface"].body["next-hop"].mandatory = false - - hybridscm.body["softwire-config"].body["external-interface"] = v1_external - hybridscm.body["softwire-config"].body["internal-interface"] = v1_internal - - -- Extract the grammar, load the config and find the key - local hybridgmr = data.config_grammar_from_schema(hybridscm) - local instgmr = hybridgmr.members["softwire-config"].members.instance - local conf = yang.load_config_for_schema( - hybridscm, mem.open_input_string(src, conf_file)) - local queue_key = ffi.typeof(instgmr.values.queue.key_ctype) - local global_external_if = conf.softwire_config.external_interface - local global_internal_if = conf.softwire_config.internal_interface - -- If there is a external device listed we should include that too. - - - -- Build up the instance list - local instance = { - [device] = {queue={}}, - } - local key = 0 - local value = { - external_interface = { - device = ex_device, - ip = conf.softwire_config.external_interface.ip, - mac = conf.softwire_config.external_interface.mac, - next_hop = {}, - vlan_tag = conf.softwire_config.external_interface.vlan_tag - }, - internal_interface = { - ip = conf.softwire_config.internal_interface.ip, - mac = conf.softwire_config.internal_interface.mac, - next_hop = {}, - vlan_tag = conf.softwire_config.internal_interface.vlan_tag - } - } - - -- Add the list to the config - if global_external_if.next_hop.mac then - value.external_interface.next_hop.mac = global_external_if.next_hop.mac - elseif global_external_if.next_hop.ip then - value.external_interface.next_hop.ip = global_external_if.next_hop.ip - else - error("One or both of next-hop values must be provided.") - end - - if global_internal_if.next_hop.mac then - value.internal_interface.next_hop.mac = global_internal_if.next_hop.mac - elseif global_internal_if.next_hop.ip then - value.internal_interface.next_hop.ip = global_internal_if.next_hop.ip - else - error("One or both of next-hop values must be provided.") - end - instance[device].queue[key] = value - conf.softwire_config.instance = instance - - -- Remove the fields which no longer should exist - conf.softwire_config.internal_interface.ip = nil - conf.softwire_config.internal_interface.mac = nil - conf.softwire_config.internal_interface.next_hop = nil - conf.softwire_config.internal_interface.vlan_tag = nil - conf.softwire_config.external_interface.ip = nil - conf.softwire_config.external_interface.mac = nil - conf.softwire_config.external_interface.next_hop = nil - conf.softwire_config.external_interface.vlan_tag = nil - - return config_to_string(hybridscm, conf) -end - -local function v2_migration(src, conf_file) - -- Lets create a custom schema programmatically as an intermediary so we can - -- switch over to v2 of snabb-softwire config. - local v1_schema = yang.load_schema_by_name("snabb-softwire-v1") - local v1_binding_table = v1_schema.body["softwire-config"].body["binding-table"] - - -- Make sure we load a fresh schema, as not to mutate a memoized copy - local hybridscm = schema.load_schema(schema.load_schema_source_by_name("snabb-softwire-v2")) - local binding_table = hybridscm.body["softwire-config"].body["binding-table"] - - -- Add the schema from v1 that we need to convert them. - binding_table.body["br-address"] = v1_binding_table.body["br-address"] - binding_table.body["psid-map"] = v1_binding_table.body["psid-map"] - binding_table.body.softwire.body.br = v1_binding_table.body.softwire.body.br - binding_table.body.softwire.body.padding = v1_binding_table.body.softwire.body.padding - - -- Add the external and internal interfaces - local hybridconfig = hybridscm.body["softwire-config"] - local v1config = v1_schema.body["softwire-config"] - hybridconfig.body["external-interface"] = v1config.body["external-interface"] - hybridconfig.body["internal-interface"] = v1config.body["internal-interface"] - - -- Remove the mandatory requirement on softwire.br-address for the migration - binding_table.body["softwire"].body["br-address"].mandatory = false - - -- Remove the mandatory requirement on softwire.port-set.psid-length for the migration - binding_table.body["softwire"].body["port-set"].body["psid-length"].mandatory = false - - local conf = yang.load_config_for_schema( - hybridscm, mem.open_input_string(src, conf_file)) - - -- Remove the br-address leaf-list and add it onto the softwire. - conf = remove_address_list(conf) - conf.softwire_config.binding_table.br_address = nil - - -- Remove the psid-map and add it to the softwire. - conf = remove_psid_map(conf) - conf.softwire_config.binding_table.psid_map = nil - - return config_to_string(hybridscm, conf) -end - -local function migrate_legacy(stream) - local conf = Parser.new(stream):parse_property_list(lwaftr_conf_spec) - conf = migrate_conf(conf) - return conf -end - - -local function migrate_3_0_1(conf_file, src) - if src:sub(0, 15) == "softwire-config" then - return src - else - return "softwire-config { "..src.." }" - end -end - -local function migrate_3_0_1bis(conf_file, src) - return increment_br( - yang.load_config_for_schema_by_name( - 'snabb-softwire-v1', mem.open_input_string(src, conf_file))) -end - -local function migrate_3_2_0(conf_file, src) - return v2_migration(src, conf_file) -end - -local function migrate_2017_07_01(conf_file, src) - return multiprocess_migration(src, conf_file) -end - -local function migrate_2022_01_19(conf_file, src) - return v3_migration(src, conf_file) -end - - -local migrations = { - {version='legacy', migrator=migrate_legacy}, - {version='3.0.1', migrator=migrate_3_0_1}, - {version='3.0.1.1', migrator=migrate_3_0_1bis}, - {version='3.2.0', migrator=migrate_3_2_0}, - {version='2017.07.01',migrator=migrate_2017_07_01}, - {version='2022.01.19',migrator=migrate_2022_01_19}, -} - - -function run(args) - local conf_file, version = parse_args(args) - - -- Iterate over migrations until we've found the - local start - for id, migration in pairs(migrations) do - if migration.version == version then - start = id - 1 - end - end - if start == nil then - io.stderr:write("error: unknown version: "..version.."\n") - show_usage(1) - end - - local conf = io.open(conf_file, "r"):read("*a") - for _, migration in next,migrations,start do - io.stderr:write(("-> %s migration\n"):format(migration.version)) - conf = migration.migrator(conf_file, conf) - -- Prompt the garbage collection to do a full collect after each migration - collectgarbage() - end - - print(conf) - main.exit(0) -end diff --git a/src/program/lwaftr/tests/config-migrations/selftest.sh b/src/program/lwaftr/tests/config-migrations/selftest.sh deleted file mode 100755 index 4ac6f1f575..0000000000 --- a/src/program/lwaftr/tests/config-migrations/selftest.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash - -# Attempt to migration from legacy to latest -LEGACY_OUT=`./snabb lwaftr migrate-configuration -f legacy \ - program/lwaftr/tests/configdata/legacy.conf` - -if [[ "$?" -ne "0" ]]; then - echo "Legacy configuration migration failed (status code != 0)" - echo "$LEGACY_OUT" - exit 1 -fi - - -# Attempt to migrate part way through the chain -V320_OUT=`./snabb lwaftr migrate-configuration -f 3.2.0 \ - program/lwaftr/tests/configdata/3.2.0.conf` - -if [[ "$?" -ne "0" ]]; then - echo "3.2.0 configuration migration failed (status code != 0)" - echo "$V320_OUT" - exit 1 -fi