Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
c9606fd
Add initial RIB management.
robshakir Jun 8, 2021
74a88d6
Add support for different network instances in the RIB.
robshakir Jun 9, 2021
fb91477
Add support for adding NHG and NH values.
robshakir Jun 9, 2021
b1b0104
validate entries against schema before allowing them.#
robshakir Jun 9, 2021
2bd0bc1
Update comments.
robshakir Jun 9, 2021
e73db09
Address review comments.
robshakir Jun 10, 2021
7514349
Merge branch 'rib1' into rib2
robshakir Jun 10, 2021
7a7caaa
Merge branch 'main' into rib2
robshakir Jun 10, 2021
c4d17e1
Merge branch 'main' into rib2
robshakir Jun 10, 2021
5803e14
Add support for a callback after each RIB operation.
robshakir Jun 11, 2021
1aef65f
Add an initial implementation of a resolved-RIB. (#22)
robshakir Jun 11, 2021
8208a66
Add gNMI cache for target to use.
robshakir Jun 11, 2021
d6a2a06
Improve commenting and avoid hostname repetition.
robshakir Jun 11, 2021
3d957e1
Merge branch 'main' into rib4
robshakir Jun 12, 2021
2eee535
Fix bad merge.
robshakir Jun 12, 2021
6996899
Fix commenting.
robshakir Jun 12, 2021
b5bc01b
start to integrate services for device.
robshakir Jun 12, 2021
fd1a4b8
Add test file.
robshakir Jun 12, 2021
12cc0a0
Move to latest version of ygot, server goroutines.
robshakir Jun 14, 2021
85ce82d
Deflake test by validating correct semantics.
robshakir Jun 14, 2021
f49693f
Merge branch 'rib4' into rib4.5
robshakir Jun 15, 2021
4b20ff9
Add support for entries in fluent, improve coverage.
robshakir Jun 15, 2021
b61e8b9
Add support for adding IPv4 Entries.
robshakir Jun 15, 2021
0540a61
Merge branch 'rib4.6' into rib5
robshakir Jun 15, 2021
ae26c50
Refactor RIB implementation.
robshakir Jun 15, 2021
a9afd5f
Add initial 'device' function which acts as a combined server.
robshakir Jun 15, 2021
bb0b789
Add main package.
robshakir Jun 15, 2021
245e4c0
Split into separate tests rather than using subtests.
robshakir Jun 15, 2021
aa061b0
Merge branch 'rib4' into rib4.5
robshakir Jun 15, 2021
85795df
Merge branch 'main' into rib4.5
robshakir Jun 15, 2021
8041fe3
Merge branch 'rib4.5' into rib4.6
robshakir Jun 15, 2021
ed26938
Remove stale comment.
robshakir Jun 15, 2021
b82d9a6
Merge branch 'rib4.5' into rib4.6
robshakir Jun 15, 2021
69ed249
Add test coverage, robustness, cleaner election handling.
robshakir Jun 16, 2021
3a3e934
Resolve race.
robshakir Jun 16, 2021
84f1e2e
🧹
robshakir Jun 16, 2021
b5d9589
Add lock to check whether the RIB is valid.
robshakir Jun 16, 2021
0e80281
Merge branch 'rib4.6' into rib5
robshakir Jun 16, 2021
4aa7fd1
Remove const package.
robshakir Jun 16, 2021
7e1a0ad
Plumb TLS through the client.
robshakir Jun 16, 2021
43d36b1
# TODO: Summary
robshakir Jun 16, 2021
e274145
Update CI to exclude files from race testing.
robshakir Jun 16, 2021
4b12cc7
Switch to race testing everything.
robshakir Jun 16, 2021
a4f0ea9
Add checking whether candidates can be resolved in gRIBI.
robshakir Jun 16, 2021
73c4c01
Make race tests run for all code.
robshakir Jun 16, 2021
bdcf19e
Merge branch 'main' into rib5
robshakir Jun 17, 2021
bd6d4fe
Merge branch 'rib5' into rib6
robshakir Jun 17, 2021
d2e6e88
Merge branch 'main' into rib5
robshakir Jun 17, 2021
b80637b
Merge branch 'rib5' into rib6
robshakir Jun 17, 2021
4f222c8
Remove duplicate default network instance name const.
robshakir Jun 17, 2021
c600905
Merge branch 'rib5' into rib6
robshakir Jun 17, 2021
9e78142
Resolve test failures following merge.
robshakir Jun 17, 2021
f554887
Fix stale references.
robshakir Jun 17, 2021
d8adc99
Merge branch 'rib5' into rib6
robshakir Jun 17, 2021
98ae8be
Address review comments.
robshakir Jun 18, 2021
0e70e5d
Clean up use of context.
robshakir Jun 18, 2021
b788c46
Fix tests.
robshakir Jun 18, 2021
cafce1f
Merge branch 'rib5' into rib6
robshakir Jun 18, 2021
6dbf870
gofmt.
robshakir Jun 18, 2021
820d242
Merge branch 'rib5' into rib6
robshakir Jun 18, 2021
2c5fc15
Merge branch 'main' into rib6
robshakir Jun 18, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go: ['1.13', '1.14', '1.15', '1.16']
go: ['1.13', '1.14', '1.15', '1.16', '1.x']
steps:

- name: Set up Go ${{ matrix.go }}
Expand All @@ -36,10 +36,10 @@ jobs:

- name: Race Test
run: |
go test -race ./...
go test -race ./...

- name: Coveralls
if: ${{ matrix.go == '1.14' }}
if: ${{ matrix.go == '1.x' }}
uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: profile.cov
Expand Down
227 changes: 105 additions & 122 deletions aft/oc.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions aft/update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ generator -path=gribi -output_file=oc.go \
-typedef_enum_with_defmod \
-enum_suffix_for_simple_union_enums \
-exclude_modules=openconfig-interfaces,ietf-interfaces \
-generate_simple_unions \
-generate_getters \
-generate_leaf_getters \
-generate_delete \
Expand Down
3 changes: 3 additions & 0 deletions device/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ func (d *Device) GNMIAddr() string {
}

// gnmiNoti creates a gNMI Notification from a RIB operation.
// TODO(robjs): It would be nice to see whether we can generate
// this function automatically from somewhere - or at least make it
// cleaner. It also needs unit test coverage adding.
func gnmiNoti(t constants.OpType, ts int64, ni string, e ygot.GoStruct) (*gpb.Notification, error) {
var ns []*gpb.Notification
var err error
Expand Down
17,672 changes: 8,775 additions & 8,897 deletions ocrt/oc.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions ocrt/update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ generator -path=public -output_file=oc.go \
-typedef_enum_with_defmod \
-enum_suffix_for_simple_union_enums \
-exclude_modules=ietf-interfaces,openconfig-acl,openconfig-routing-policy \
-generate_simple_unions \
-generate_getters \
-generate_leaf_getters \
-generate_delete \
Expand Down
128 changes: 128 additions & 0 deletions rib/rib.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,109 @@ func (r *RIB) NetworkInstanceRIB(s string) (*RIBHolder, bool) {
return rh, ok
}

// canResolve takes an input candidate RIB, which contains only the new entry
// being added and determines whether it can be resolved against the existing set
// of RIBs that are stored in r. The specified netInst string is used to
// determine the current network instance within which this entry is being
// considered, such that where the assumption is that a reference is resolved within
// the same network-instance this NI can be used.
//
// canResolve returns a boolean indicating whether the entry
// can be resolved or not.
//
// An entry is defined to be resolved if all its external references within the gRIBI
// RIB can be resolved - particularly (starting from the most specific):
//
// * for a next-hop
// - always consider this valid, since all elements can be resolved outside of
// gRIBI.
// * for a next-hop-group
// - all the next-hops within the NHG can be resolved
// * for an ipv4-entry
// - the next-hop-group can be resolved
//
// An error is returned if the candidate RIB contains more than one new type.
func (r *RIB) canResolve(netInst string, candidate *aft.RIB) (bool, error) {
caft := candidate.GetAfts()
if caft == nil {
return false, errors.New("invalid nil candidate AFT")
}
switch {
case len(caft.Ipv6Entry) != 0:
return false, fmt.Errorf("IPv6 entries are unsupported, got: %v", caft.Ipv6Entry)
case len(caft.LabelEntry) != 0:
return false, fmt.Errorf("MPLS label entries are unsupported, got: %v", caft.LabelEntry)
case len(caft.MacEntry) != 0:
return false, fmt.Errorf("ethernet MAC entries are unsupported, got: %v", caft.MacEntry)
case len(caft.PolicyForwardingEntry) != 0:
return false, fmt.Errorf("PBR entries are unsupported, got: %v", caft.PolicyForwardingEntry)
case (len(caft.Ipv4Entry) + len(caft.NextHopGroup) + len(caft.NextHop)) == 0:
return false, errors.New("no entries in specified candidate")
case (len(caft.Ipv4Entry) + len(caft.NextHopGroup) + len(caft.NextHop)) > 1:
return false, fmt.Errorf("multiple entries are unsupported, got ipv4: %v, next-hop-group: %v, next-hop: %v", caft.Ipv4Entry, caft.NextHopGroup, caft.NextHop)
}

for _, n := range caft.NextHop {
if n.GetIndex() == 0 {
return false, fmt.Errorf("invalid index zero for next-hop in NI %s", netInst)
}
// we always resolve next-hop entries because they can be resolved outside of gRIBI.
return true, nil
}

// resolve in the default NI if we didn't get asked for a specific NI.
if netInst == "" {
netInst = r.defaultName
}
niRIB, ok := r.NetworkInstanceRIB(netInst)
if !ok {
return false, fmt.Errorf("invalid network-instance %s", netInst)
}

for _, g := range caft.NextHopGroup {
if g.GetId() == 0 {
return false, fmt.Errorf("invalid zero-index NHG")
}
for _, n := range g.NextHop {
// Zero is an invalid value for a next-hop index. GetIndex() will also return 0
// if the NH index is nil, which is also invalid - so handle them together.
if n.GetIndex() == 0 {
return false, fmt.Errorf("invalid zero index NH in NHG %d, NI %s", g.GetId(), netInst)
}
// nexthops are resolved in the same NI as the next-hop-group
if _, ok := niRIB.GetNextHop(n.GetIndex()); !ok {
// this is not an error - it's just that we can't resolve this seemingly
// valid looking NHG at this point.
return false, nil
}
}
return true, nil
}

for _, i := range caft.Ipv4Entry {
if i.GetNextHopGroup() == 0 {
// handle zero index again.
return false, fmt.Errorf("invalid zero-index NHG in IPv4Entry %s, NI %s", i.GetPrefix(), netInst)
}
resolveRIB := niRIB
if otherNI := i.GetNextHopGroupNetworkInstance(); otherNI != "" {
resolveRIB, ok = r.NetworkInstanceRIB(otherNI)
if !ok {
return false, fmt.Errorf("invalid unknown network-instance for IPv4Entry, %s", otherNI)
}
}
if _, ok := resolveRIB.GetNextHopGroup(i.GetNextHopGroup()); !ok {
// again, not an error - we just can't resolve this IPv4 entry due to missing NHG right now.
return false, nil
}
return true, nil
}

// We should never reach here since we checked that at least one of the things that we are looping over has
// length >1, but return here too.
return false, errors.New("no entries in specified candidate")
}

// NewRIBHolder returns a new RIB holder for a single network instance.
func NewRIBHolder(name string) *RIBHolder {
return &RIBHolder{
Expand All @@ -121,6 +224,31 @@ func (r *RIBHolder) IsValid() bool {
return true
}

// GetNextHop gets the next-hop with the specified index from the RIB
// and returns it. It returns a bool indicating whether the value was
// found.
func (r *RIBHolder) GetNextHop(index uint64) (*aft.Afts_NextHop, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
n := r.r.GetAfts().GetNextHop(index)
if n == nil {
return nil, false
}
return n, true
}

// GetNextHopGroup gets the next-hop-group with the specified ID from the RIB
// and returns it. It returns a bool indicating whether the value was found.
func (r *RIBHolder) GetNextHopGroup(id uint64) (*aft.Afts_NextHopGroup, bool) {
r.mu.RLock()
defer r.mu.RUnlock()
n := r.r.GetAfts().GetNextHopGroup(id)
if n == nil {
return nil, false
}
return n, true
}

// rootSchema returns the schema of the root of the AFT YANG tree.
func rootSchema() (*yang.Entry, error) {
s, err := aft.Schema()
Expand Down
Loading