Repository navigation
Commit 7006928
Route multi-host RoCE rails over direct cables (#232)
* Route multi-host RoCE over direct cables and add --roce-switch-only
Multi-host RoCE serving leaves direct cables between ranks idle when
the ranks also share a switch. Helios paired rails by device index:
rail h used device h on every rank whenever each such pair shared a
subnet, and otherwise preferred the lowest-numbered subnet. On DGX
Sparks whose first ConnectX-7 port joins a switch and whose second
port is cabled to one partner, both rules send the partner's traffic
over the switch. Rails also landed on the two PCIe functions behind
one x4 link, which share that link's bandwidth. A subnet that only two
ranks hold identifies their cable, and the PCIe address identifies the
link behind each function, so the planner can choose both from the
endpoints every rank already exchanges at rendezvous.
Helios's route planner (helios/src/execution/roce_fabric.rs) computes
each subnet's breadth, the number of ranks holding an address on it:
two for a direct cable, the whole world for a switch. Index pairing
applies only when every subnet joining two or more ranks joins all of
them and no rank's rail devices share a PCIe link; otherwise per-peer
pairing places one rail behind each PCIe link and then prefers the
narrowest subnets. IPv4 link-local subnets count as world-wide,
because sharing 169.254.0.0/16 does not imply a cable. Each endpoint
record gains its PCIe link, the function's PCI address without the
function number, read from sysfs.
Fabric TCP transfers (serving core distribution, Orbit prestaging and
Ignition checkpoint transfers) plan each edge with
roce_fabric::plan_link over every rank's endpoints, in place of a plan
from the edge's two ranks, which cannot tell a cable from a switch.
Every pair of ranks then connects over the devices its RDMA rails use.
--roce-switch-only, a serving option of flare run, flare orbit run and
flare orbit push that is forwarded to every rank, restricts RDMA rails
and fabric transfers to subnets every rank holds
(roce_fabric::Links::Shared): a switch-only baseline, or a way to keep
traffic off a faulty cable. With two ranks every subnet joins both, so
the option cannot separate a cable from a switch. Ranks exchange
"mesh switch-only" instead of "mesh" in the transport shape record and
stop at transport connection when they disagree; peers adopt rank
zero's choice from the serving distribution plan. The Connect RoCE
transport startup phase lists each peer's local devices in rail order
and marks a peer whose rails all ride direct cables, for example
"rank 2 direct roceP2p1s0f1,rocep1s0f1".
The expected result is that each rank reaches a cabled partner over
the cable's two functions, one behind each PCIe link, and every other
peer over the switch. Cores are unchanged, because routes are planned
at serve time. Without --roce-switch-only, the transport shape record
and the serving distribution plan encode as before. The rendezvous
endpoint line gains an optional third field carrying the PCIe link;
builds without this change reject such lines as malformed, and on
fabrics with direct cables or shared PCIe links the two planners choose
different rails, so every rank must run a build containing this
change.
Evidence: on bbad44f with this change, on Gracie (ARM64),
`cargo test --lib --features roce,runtime-package,server roce` in
helios passed 32 tests. The route tests cover partner cables in either
device order, a cable absent at one end, link-local addresses on
uncabled ports, switch-only routing, single-edge planning equal to full
planning, a cabled pair's PCIe links, endpoint encoding with links and
per-peer route summaries. `cargo test --features roce --no-fail-fast`
in flare-cli passed 177 unit and 24 integration tests; they include
transfer edges over partner cables and with --roce-switch-only,
forwarding of the option to agent-started ranks, and shape-record
agreement. Two Orbit agent tests,
groups_run_together_on_disjoint_gpus_and_status_lists_them and
running_groups_are_stopped_and_outlive_their_controller_session, fail
with the same core-size assertion on bbad44f without this change. A
build that combined this planner with other transport and model changes
served GLM-5.3-Flash at TP4 on four DGX Sparks, each with one
ConnectX-7 port on a switch and the other cabled to one partner. Every
rank's Connect RoCE transport phase reached its partner over
`direct roceP2p1s0f1,rocep1s0f1` and the other two ranks over the
switch functions, and the out-of-sequence, packet-sequence-error and
local-ACK-timeout counters of all 16 RoCE devices were unchanged across
answer checks and prefill and decode benchmarks at 1 to 16 concurrent
requests. A build of this commit alone has not served traffic.
Design-Signed-Off-By: flare-02; design-review=cfcf
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
* Route a two-rank RoCE group over its cable by LLDP adjacency
A two-rank RoCE group on a cabled pair of hosts that also share a
switch, such as GLM-5.3 TP2 on two cabled DGX Sparks, routes both rails
over the switch functions and leaves the cable idle. Helios's route
planner (helios/src/execution/roce_fabric.rs) identifies a direct cable
as a subnet held by fewer ranks than the world, but the two ranks of
such a group hold every subnet in common. Breadth then ties, and the
lowest network, here the switch's, carries both rails. LLDP gives the
missing evidence: LLDP frames do not cross a bridge, so devices of two
ranks that list each other as neighbors share a cable.
Discovery records each RoCE device's network device MAC address, read
from sysfs under the device's PCI function. It also records the MAC
addresses its LLDP neighbors advertise as port IDs, from
`lldpctl -f keyvalue` with a two-second limit; the list is empty when
lldpctl is missing or fails. Index pairing is invalid when any devices
of two ranks are LLDP neighbors. Per-peer matching prefers links
between LLDP neighbors after PCIe link separation and before subnet
breadth. Links::Shared (`--roce-switch-only`) excludes such links. The
`direct` marker in the `Connect RoCE transport` phase also covers
LLDP-adjacent rails. The endpoint record line gains the MAC address
and the comma-separated neighbor list after the PCIe link, `-` when
unknown, with trailing unknown fields omitted.
The expected result is that a two-rank group on a cabled pair running
lldpd uses both cable functions, one behind each PCIe link, and uses
the switch with `--roce-switch-only`. On fabrics with three or more
ranks, the LLDP neighbors of DGX Sparks coincide with subnets two ranks
hold, so their routes and markers are unchanged. Hosts without lldpd
record no neighbors and keep breadth routing. Core distribution and
Orbit fabric transfers plan links with the same planner, so they follow
the RDMA rails. Cores are unaffected; the fabric is discovered at
serving time. Ranks, Orbit controllers and agents must run builds that
read the five-field record, since a reader of the three-field record
rejects these lines as malformed, and every rank of a group must run
this planner, because ranks with and without it choose different rails
for a two-rank cabled pair.
Evidence: on bbad44f with the direct-cable planner and this change, on
Gracie (ARM64), `cargo test --lib --features roce,runtime-package,server
roce` in helios passed 35 tests. The tests added here cover lldpctl
parsing, MAC and neighbor discovery and the five-field record, and a
cabled pair routed over its cable with the `direct` marker,
`--roce-switch-only` on the switch and fabric-transfer links on the
cable. Routes and direct markers of a four-rank fabric with partner
cables, and of four ranks in two cabled pairs, are the same with and
without LLDP data. `cargo test --features roce --no-fail-fast` in
flare-cli passed 177 unit and 24 integration tests; the two Orbit agent
tests that fail on bbad44f without this change fail the same way. A
build that combined this planner with other transport and model changes
served GLM-5.3-Flash at TP2 on two DGX Sparks that are cabled to each
other and share a switch, both running lldpd. Its Connect RoCE
transport phase reported `rank 0 direct roceP2p1s0f1,rocep1s0f1`, and
the out-of-sequence, packet-sequence-error and local-ACK-timeout
counters of all 8 RoCE devices were unchanged across answer checks and
prefill and decode benchmarks at 1 to 16 concurrent requests. A build
of this commit alone has not served traffic.
Design-Signed-Off-By: flare-02; design-review=cfcf
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
* Plan ring and chain RoCE rails over every rank's endpoints
In ring and chain mode, each rank planned its RoCE routes over the
endpoints of itself and its linked neighbors only. Subnet breadth and
index-pairing validity then came from a different subset at each end of
an edge, so the two ranks of one edge could choose different devices.
The native proxy connects the device indexes each rank supplies without
exchanging them, so a disagreement surfaces as an RDMA failure or a
collective timeout rather than a route error. With one rail and four
ranks, where rank 0 holds a 10.0.0.1/24 and b 10.0.1.1/24, rank 1
a 10.0.0.2/24 and b 10.0.1.2/24, rank 2 a 10.0.0.3/24 and c 10.0.2.3/24,
and rank 3 b 10.0.1.4/24 and c 10.0.2.4/24, rank 0 chose devices (0, 0)
toward rank 1 while rank 1 chose (1, 1) toward rank 0. Mesh routing and
the fabric TCP transfer planner already plan over every rank's
endpoints.
plan_shape_routes builds one route planner over every rank's endpoints
and asks it only for the peers the shape links, in place of planning
over the neighborhood subset. Peers the shape does not link still get
no route, so their queue pairs stay unconnected.
The expected result is that both ends of every ring or chain link
compute the same breadths and index-pairing validity and choose
mirrored devices. Mesh routes are unchanged.
Evidence: ring_and_chain_ends_agree_when_subnets_differ_between_neighborhoods
plans the four-rank example above in ring and chain mode and checks
that every linked pair's routes mirror each other over a shared subnet
and that unlinked pairs have none. On the parent commit it fails with
rank 0 choosing (0, 0) and rank 1 choosing (1, 1). On Gracie (ARM64),
`cargo test --lib --features roce,runtime-package,server roce` in
helios passed 36 tests, including the ring, line and variable-size
ring tests. No ring or chain fabric has served traffic with this
change.
Design-Signed-Off-By: flare-02; design-review=cfcf
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
* Require evidence before link-local or unaddressed RoCE links carry rails
Per-peer RoCE route matching accepted two kinds of link without evidence
that the devices are connected. Any two IPv4 link-local addresses
(169.254.0.0/16) counted as a link, although hosts using link-local
addressing share that subnet whether or not their ports are connected.
Link-local subnets have world-wide breadth, and 169.254 sorts below
192.168, so a link-local pair on unrelated ports could displace a switch
rail. With four ranks on 192.168.0.0/24 and 192.168.1.0/24, a private
cable subnet between ranks 0 and 2 (which rules out index pairing), and
link-local addresses on unrelated ports of ranks 1 and 3, rank 1 routed
rank 3 over devices [(2, 2), (0, 0)], where device 2 is the link-local
port. Separately, --roce-switch-only (Links::Shared) promises rails only
over subnets every rank holds, yet a device whose interface prefix
discovery could not resolve still received same-index pairing on the
index-pairing and per-peer paths, even when LLDP showed that the two
devices share a cable.
Per-peer matching admits a link-local pair only when its two devices are
LLDP neighbors, and then ranks it as a direct cable. Under Links::Shared,
index pairing requires every rail device to have a known address outside
link-local space, and per-peer matching admits no same-index pair whose
subnet is unknown. With Links::All, same-index pairs without an address
are still trusted in device order, and index pairing still accepts
same-index link-local pairs.
The expected result is that a peer with verified switch or cable rails
uses them instead of a link-local port, and --roce-switch-only fails
with "0 of N RoCE rails have a link" when no verified shared subnet
exists instead of falling back to device order. A fabric whose RoCE
devices carry only link-local addresses and no LLDP data has no
per-peer candidates; it is still routed when index pairing applies,
which requires no subnet narrower than the world, no PCIe link shared
by one rank's rail devices, and same-index devices on one subnet.
Evidence: link_local_pairs_carry_rails_only_between_lldp_neighbors
plans the four-rank example above. Rank 1 reaches rank 3 over both
switch rails, ranks 0 and 2 use their cable and one switch rail, an
LLDP-adjacent link-local pair carries a rail, and switch-only routing
uses neither the cable nor a link-local pair. On the parent commit it
fails with rank 1 routing rank 3 over [(2, 2), (0, 0)].
switch_only_routing_rejects_links_whose_subnet_is_unknown covers
unaddressed devices with and without LLDP adjacency, and a known switch
subnet beside an unaddressed device; on the parent commit switch-only
routing returns [(0, 0)] for the LLDP-adjacent pair. On Gracie (ARM64),
`cargo test --lib --features roce,runtime-package,server roce` in
helios passed 38 tests. No fabric with link-local RoCE addresses has
served traffic with this change.
Design-Signed-Off-By: flare-02; design-review=cfcf
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
* Bound lldpctl by one deadline for its output and exit
RoCE endpoint discovery runs `lldpctl -f keyvalue` under a documented
two-second limit, but the limit covered only reading its standard
output. After the output closed, discovery waited for the process
without bound, so an lldpctl that closed its output and stayed alive
would block transport startup indefinitely.
bounded_output runs a command under one deadline for both its output
and its exit: a thread collects standard output, the caller polls for
exit until the deadline, and a command still running at the deadline
is killed and reaped. lldp_neighbors uses it with a two-second limit. A
command that cannot start, fails, or misses the deadline yields no
neighbors, as a failing lldpctl did before.
The expected result is that endpoint discovery spends at most about two
seconds on lldpctl, whichever way lldpctl stalls, and keeps breadth
routing when lldpctl does not answer in time.
Evidence: a_command_is_bounded_by_one_deadline_for_its_output_and_exit
runs sh commands under a 300 ms limit. A successful command returns its
output, a failing one and a missing executable return none, and a
command that closes its output and sleeps for ten seconds, or sleeps
with its output open, returns none in under five seconds. On Gracie
(ARM64), `cargo test --lib --features roce,runtime-package,server roce`
in helios passed 39 tests. lldpctl itself was not run with this change.
Design-Signed-Off-By: flare-02; design-review=cfcf
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
* Reject RoCE endpoint records and Orbit agents from builds without the route planner
Ranks, Orbit controllers and agents with and without Helios's RoCE
route planner choose different rails and transfer links on cabled
fabrics, so every participant must run a build with this planner. A
build without it reads endpoint lines of exactly two fields (device name
and address) and rejects longer lines as malformed, but this planner
accepted its two-field lines, and Orbit controllers and agents with and
without the planner both spoke agent protocol 6. A controller with the
planner therefore accepted agents without it, and a rank with the
planner decoded endpoints from a rank without it. Only the older side
reported an error, and "malformed RoCE endpoint" does not name the
build mismatch.
roce_fabric::encode writes the PCIe link field on every line, `-` when
unknown, so every line has at least three fields. roce_fabric::decode
rejects a two-field line with "RoCE endpoint record has no PCIe link
field: its rank runs a build that plans rails from addresses alone, and
every rank needs a build that records PCIe links and LLDP neighbors".
The Orbit agent protocol becomes 7, so a session handshake or HELLO
exchange between protocol 6 and protocol 7 peers fails with "peer
speaks agent protocol 6; this agent speaks 7". docs/orbit.md states
what protocol 7 carries in FABRIC replies, and docs/multi-host.md lists
the endpoint record error. Test fixtures that encoded endpoint records
by hand carry the link field.
The expected result is that a group mixing builds with and without the
route planner stops at rank rendezvous or at the Orbit handshake on
every side, with an error naming the incompatibility, instead of
planning different rails. Orbit controllers and agents must be updated
together, as for earlier agent protocol changes. Cores are unaffected.
Evidence: endpoints_survive_the_rendezvous_encoding in helios checks
that an endpoint with only a name and an address encodes with the link
field and decodes back, and that a two-field line fails with the record
error. tampered_records_and_wrong_versions_are_refused in flare-cli
checks that an agent refuses handshakes from protocol 6 and protocol 8
peers. On Gracie (ARM64), `cargo test --lib --features
roce,runtime-package,server roce` in helios passed 39 tests, and
`cargo test --features roce --no-fail-fast` in flare-cli passed 177
unit and 24 integration tests. The same two Orbit agent tests that fail
on bbad44f, groups_run_together_on_disjoint_gpus_and_status_lists_them
and running_groups_are_stopped_and_outlive_their_controller_session,
fail with the same core-size assertion. A mixed-build group has not
been run on hardware.
Design-Signed-Off-By: flare-02; design-review=cfcf
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
* Document the evidence and limits of RoCE route inference
The multi-host guide stated that a two-rank group on a cabled pair uses
the switch whenever lldpd does not run on both hosts. The planner
treats two devices as LLDP neighbors when either lists the other, so
lldpd on one host identifies the cable. Without LLDP data such a group
has no evidence of its cable, and its rails take one device behind each
PCIe link and then the lowest-numbered network, which is the switch's
only when the switch's subnets sort first. The guide and CLI design
also described the `direct` startup marker as a peer reached over a
cable and `--roce-switch-only` as leaving every cable unused, while the
marker reports the topology inferred from endpoint records and the
option can exclude only cables that subnet breadth or LLDP identifies.
docs/multi-host.md states that lldpd on one host suffices, the
fallback without LLDP data, that two link-local addresses form a link
only between LLDP neighbors, and that the `direct` marker reports
inferred topology rather than verified reachability. docs/cli-design.md
states which cables `--roce-switch-only` excludes and that devices
without a known subnet carry no rails under it. The roce_fabric module
documentation and Topology::direct carry the same limits.
These changes correct documentation only; behavior is unchanged.
Evidence: the statements follow the planner in
helios/src/execution/roce_fabric.rs. lldp_adjacent accepts a listing in
either direction; a_cabled_pair_keeps_its_two_rails_on_separate_pcie_links
shows a two-rank cabled pair without LLDP data placing one rail behind
each PCIe link on the lowest network;
link_local_pairs_carry_rails_only_between_lldp_neighbors and
switch_only_routing_rejects_links_whose_subnet_is_unknown cover the
link-local and switch-only statements. Documentation changes need no
GPU tests.
Design-Signed-Off-By: flare-02; design-review=cfcf
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
* Keep link-local RoCE addresses out of index pairing
Per-peer route matching admits a link-local pair (169.254.0.0/16) only
between LLDP neighbors, but index pairing still accepted same-index
devices whose link-local addresses match, although hosts using
link-local addressing share that subnet whether or not their ports are
connected. With four ranks and no LLDP data, where device 0 holds
169.254.1.r/16 on an unconnected private port and devices 1 and 2 hold
192.168.0.r/24 and 192.168.1.r/24 on a switch, every subnet joins every
rank, so index pairing applied, and every rank routed every peer over
devices [(0, 0), (1, 1)]. The rail on device 0 has no path. Index
pairing cannot use LLDP evidence, because any LLDP adjacency already
rules it out, so a link-local rail device must rule it out as well.
index_pairing_valid rejects index pairing when any rank's rail device
has a link-local address, under every link selection; under
--roce-switch-only it also rejects a rail device without a known
address, as before. Per-peer matching then applies the LLDP rule. When
per-peer matching finds too few rails and skipped a link-local pair
without LLDP adjacency, its error adds "link-local addresses link only
devices that are LLDP neighbors". docs/multi-host.md states that a
device whose only RoCE address is link-local carries rails only over a
cable LLDP identifies, so switch ports need configured subnets, and its
troubleshooting table repeats this for rail errors.
The expected result is that an unconnected link-local port never
carries a rail: in the example above every rank reaches every peer over
devices [(1, 1), (2, 2)], and a fabric with link-local devices after its
rail devices keeps index pairing. A fabric whose RoCE devices carry only
link-local addresses now plans rails only between LLDP neighbors. Such
a fabric on a switch, which `main` routes by index pairing, fails
planning with the error above until its switch ports have configured
subnets.
Evidence: index_pairing_admits_no_link_local_rail_device plans the
example above for every pair of ranks, checks that index pairing still
applies with the link-local device after the rail devices, and checks
that two ranks addressed only by link-local addresses fail with the
link-local error without LLDP data and route over the pair with it. On
the parent commit it fails with [(0, 0), (1, 1)]. On Gracie (ARM64),
`cargo test --lib --features roce,runtime-package,server roce` in
helios passed 40 tests, and `cargo test --lib --features
runtime-core,server roce_fabric` passed 24. No fabric with link-local
RoCE addresses has served traffic with this change.
Design-Signed-Off-By: flare-02; design-review=cfcf
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
---------
Signed-off-by: Jason Cook <jasonc@maxlyn.com>
Co-authored-by: Luke Alonso <lalonso@gmail.com>1 parent 91b2e85 commit 7006928
16 files changed
Lines changed: 1597 additions & 206 deletions
File tree
- docs
- flare-cli/src
- distribution
- orbit
- helios/src/execution
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
94 | 94 | | |
95 | 95 | | |
96 | 96 | | |
97 | | - | |
98 | | - | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
99 | 138 | | |
100 | 139 | | |
101 | 140 | | |
| |||
505 | 544 | | |
506 | 545 | | |
507 | 546 | | |
508 | | - | |
| 547 | + | |
| 548 | + | |
509 | 549 | | |
510 | 550 | | |
511 | 551 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
806 | 806 | | |
807 | 807 | | |
808 | 808 | | |
809 | | - | |
810 | | - | |
811 | | - | |
| 809 | + | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
812 | 815 | | |
813 | 816 | | |
814 | 817 | | |
| |||
818 | 821 | | |
819 | 822 | | |
820 | 823 | | |
821 | | - | |
| 824 | + | |
822 | 825 | | |
823 | 826 | | |
824 | 827 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
24 | 27 | | |
25 | 28 | | |
26 | 29 | | |
| |||
854 | 857 | | |
855 | 858 | | |
856 | 859 | | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
857 | 865 | | |
858 | 866 | | |
859 | 867 | | |
| |||
1063 | 1071 | | |
1064 | 1072 | | |
1065 | 1073 | | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
1066 | 1077 | | |
1067 | 1078 | | |
1068 | 1079 | | |
| |||
1758 | 1769 | | |
1759 | 1770 | | |
1760 | 1771 | | |
| 1772 | + | |
| 1773 | + | |
| 1774 | + | |
| 1775 | + | |
| 1776 | + | |
| 1777 | + | |
| 1778 | + | |
| 1779 | + | |
| 1780 | + | |
| 1781 | + | |
| 1782 | + | |
| 1783 | + | |
| 1784 | + | |
| 1785 | + | |
| 1786 | + | |
1761 | 1787 | | |
1762 | 1788 | | |
1763 | 1789 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
12 | 19 | | |
13 | 20 | | |
14 | 21 | | |
| |||
66 | 73 | | |
67 | 74 | | |
68 | 75 | | |
69 | | - | |
| 76 | + | |
70 | 77 | | |
71 | 78 | | |
72 | 79 | | |
| |||
77 | 84 | | |
78 | 85 | | |
79 | 86 | | |
80 | | - | |
| 87 | + | |
81 | 88 | | |
82 | 89 | | |
83 | 90 | | |
84 | 91 | | |
85 | 92 | | |
86 | 93 | | |
87 | 94 | | |
| 95 | + | |
88 | 96 | | |
89 | | - | |
90 | | - | |
91 | | - | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
92 | 100 | | |
93 | 101 | | |
94 | 102 | | |
95 | 103 | | |
96 | | - | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
97 | 109 | | |
98 | 110 | | |
99 | 111 | | |
100 | | - | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
101 | 115 | | |
102 | | - | |
103 | | - | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
104 | 122 | | |
105 | 123 | | |
106 | | - | |
107 | | - | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
108 | 127 | | |
109 | | - | |
110 | | - | |
| 128 | + | |
| 129 | + | |
111 | 130 | | |
112 | 131 | | |
113 | 132 | | |
| |||
165 | 184 | | |
166 | 185 | | |
167 | 186 | | |
168 | | - | |
| 187 | + | |
169 | 188 | | |
170 | 189 | | |
171 | 190 | | |
| |||
175 | 194 | | |
176 | 195 | | |
177 | 196 | | |
178 | | - | |
179 | | - | |
| 197 | + | |
| 198 | + | |
180 | 199 | | |
181 | 200 | | |
182 | | - | |
| 201 | + | |
183 | 202 | | |
184 | 203 | | |
185 | 204 | | |
| |||
197 | 216 | | |
198 | 217 | | |
199 | 218 | | |
200 | | - | |
| 219 | + | |
201 | 220 | | |
202 | 221 | | |
203 | 222 | | |
| |||
208 | 227 | | |
209 | 228 | | |
210 | 229 | | |
211 | | - | |
| 230 | + | |
212 | 231 | | |
213 | 232 | | |
214 | 233 | | |
| |||
217 | 236 | | |
218 | 237 | | |
219 | 238 | | |
220 | | - | |
221 | | - | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
222 | 242 | | |
223 | 243 | | |
224 | 244 | | |
225 | 245 | | |
226 | 246 | | |
227 | | - | |
| 247 | + | |
228 | 248 | | |
229 | 249 | | |
230 | 250 | | |
| |||
249 | 269 | | |
250 | 270 | | |
251 | 271 | | |
252 | | - | |
| 272 | + | |
253 | 273 | | |
254 | 274 | | |
255 | 275 | | |
| |||
289 | 309 | | |
290 | 310 | | |
291 | 311 | | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
292 | 343 | | |
293 | 344 | | |
294 | 345 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
226 | 226 | | |
227 | 227 | | |
228 | 228 | | |
| 229 | + | |
229 | 230 | | |
230 | 231 | | |
231 | 232 | | |
| |||
383 | 384 | | |
384 | 385 | | |
385 | 386 | | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
386 | 390 | | |
387 | 391 | | |
388 | 392 | | |
389 | 393 | | |
390 | 394 | | |
| 395 | + | |
391 | 396 | | |
392 | 397 | | |
393 | 398 | | |
| |||
1427 | 1432 | | |
1428 | 1433 | | |
1429 | 1434 | | |
1430 | | - | |
| 1435 | + | |
1431 | 1436 | | |
1432 | 1437 | | |
1433 | 1438 | | |
| |||
0 commit comments