Skip to content

Fresh python support, GBP support, fail-static mode - #5

Open
gmelikov wants to merge 4 commits into
masterfrom
sdn-min
Open

Fresh python support, GBP support, fail-static mode#5
gmelikov wants to merge 4 commits into
masterfrom
sdn-min

Conversation

@gmelikov

Copy link
Copy Markdown
Member

See separate commit descriptions.

@gmelikov gmelikov changed the title Fresh python support, BGP support, fail-static mode Fresh python support, GBP support, fail-static mode Aug 16, 2026
@gmelikov
gmelikov force-pushed the sdn-min branch 4 times, most recently from 48c38aa to 0650571 Compare August 17, 2026 11:46
When the route reflector dies, gobgp withdraws reflected routes (it
flushes on the shutdown NOTIFICATION even with graceful-restart), and
replace-flows tears down the matching OVS flows — so an RR outage breaks
existing connectivity.

New [gobgp] fail_static option (default: true): while too few peers have
converged, sync the union of the freshly computed flows and the
last-known-good snapshot; deletions resume once the sessions are back.
[gobgp] fail_static_min_peers (default: 0 — all of them) says how many
have to converge: 1 fits redundant route reflectors, where a single
session still carries the whole RIB.

Converged is stricter than ESTABLISHED, which only says the session is
up while the peer is still streaming its table — a RIB read in that
window is not the fabric, and trusting it would snapshot a half-read set
and delete the rest. Measured on a pair of gobgp 3.37 with 20k EVPN
routes over a veth: 0.90s between ESTABLISHED and End-of-RIB, against a
default 3s step. A peer counts once End-of-RIB (RFC 4724) has arrived
for every family that negotiated graceful-restart, and once the session
has been up for [gobgp] fail_static_settle_sec (default: 0 — two steps),
which is all there is to wait for when nothing reports the end. Health
is sampled before the RIB is read and again before syncing, both having
to hold, so a session that converges or dies mid-step does not pass
either.

An empty peer list counts as degraded too, being what a restarted gobgp
looks like before it has read its config; a node that genuinely has no
peers is unaffected, its snapshot never fills, so the union is a no-op.
A peer list that cannot be read is a local gobgp fault, not degradation,
and is raised: the step stops before syncing, so flows are retained
either way, but it is reported as an error instead of a silently held
state. State is logged when it changes rather than on every step.
Metrics: fail_static_active, fail_static_retained_cnt.

A union only adds. Local additions and changes still land, a flow being
equal to another by its match alone and the fresh side winning; local
deletions wait for the sessions to come back.

Validated on a 3-node stand: a 2-minute RR outage with flows and
connectivity retained, clean release on recovery.
A rule that names a group of workloads rather than a prefix needs the
sender's identity to travel with the packet, or every host enforcing it
has to be told who the members are and told again on every change.

VXLAN-GBP has 16 bits for it, but a tunnel field is cleared crossing a
patch port in both directions, so nothing set where policy lives reaches
the wire. The skb mark survives that hop, so the fabric copies between
the two at the tunnel and interprets neither.

Both directions are complete on purpose: every path onto the wire carries
it (switched, routed, flooded), and off the wire it is recovered on every
flow a tunnel ingress can hit — the Type 2 one, VirtNet's stand-in for a
missing Type 2 announce, and the VRF's. Never on local traffic, which had
no header and whose mark reading one would erase.

[ovs] gbp (default: false) is read once and handed to both the tunnel and
the flows, so they cannot disagree, and turning it off unmakes an existing
GBP tunnel, so the flag is not one-way.

Proven on two real hosts (gcl_sdk sdn_fabric tier).
oslo.config 3.22 reads collections.Mapping, removed in python 3.10, so the
service died on import; protobuf 3.14 and grpcio 1.26 have no wheels for a
current interpreter. Split by python version, so the old band keeps the
pins it had, and bound each new one from above as the rest of this file
does. setuptools is pinned for all of them: pbr reads the package version
through pkg_resources, which setuptools 81 dropped and a fresh venv no
longer provides. pbr itself cannot move past it, loopster caps it at
5.8.1.
The unit job ran `tox -e 3.8`, which is not an environment this tox.ini
defines: its commands are bound to the py27/py38 factors, so an env named
`3.8` matched none of them and the job passed in 0.02s having run nothing.
The matrix now names real environments, py313/py314 are added to the factor
list they were missing from, and 3.14 is covered. Lint stays on 3.8.

That surfaced two failures the job had never been in a position to see:
pytest 8 no longer calls nose-style setup/teardown (renamed to
setup_method/teardown_method, which every pytest since 2.x accepts), and
pbr needs pkg_resources, which a fresh venv does not ship. Both also fail
on master with the same invocation.
@gmelikov

Copy link
Copy Markdown
Member Author

Reworked fail-static to actually check for end_of_rib_received if mp_graceful_restart supported, otherwise settle time can be used.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant