Skip to content

Commit

Permalink
Add initial IPv6 compliance test and fluent library support.
Browse files Browse the repository at this point in the history
 * (M) client/gribiclient(_test)?.go
  - Add support within the client library for IPv6 and MPLS where
    required, and test coverage for the client.
 * (M) fluent/fluent.go
  - Add support for IPv6 within fluent library.
 * (M) compliance/compliance.go
  - Add test cases for basic IPv6 functionality.
  • Loading branch information
robshakir committed Nov 11, 2023
1 parent 396260a commit 133fc8c
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 0 deletions.
6 changes: 6 additions & 0 deletions client/gribiclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,8 @@ type OpDetailsResults struct {
NextHopGroupID uint64
// IPv4Prefix is the IPv4 prefix modified by the operation.
IPv4Prefix string
// IPv6Prefix is the IPv6 prefix modified by the operation.
IPv6Prefix string
// MPLSLabel is the MPLS label that was modified by the operation.
MPLSLabel uint64
}
Expand All @@ -720,6 +722,8 @@ func (o *OpDetailsResults) String() string {
buf.WriteString(fmt.Sprintf("NHG ID: %d", o.NextHopGroupID))
case o.IPv4Prefix != "":
buf.WriteString(fmt.Sprintf("IPv4: %s", o.IPv4Prefix))
case o.IPv6Prefix != "":
buf.WriteString(fmt.Sprintf("IPv6: %s", o.IPv6Prefix))
case o.MPLSLabel != 0:
buf.WriteString(fmt.Sprintf("MPLS: %d", o.MPLSLabel))
}
Expand Down Expand Up @@ -949,6 +953,8 @@ func (c *Client) clearPendingOp(op *spb.AFTResult) (*OpResult, error) {
switch opEntry := v.Op.Entry.(type) {
case *spb.AFTOperation_Ipv4:
det.IPv4Prefix = opEntry.Ipv4.GetPrefix()
case *spb.AFTOperation_Ipv6:
det.IPv6Prefix = opEntry.Ipv6.GetPrefix()
case *spb.AFTOperation_Mpls:
det.MPLSLabel = opEntry.Mpls.GetLabelUint64()
case *spb.AFTOperation_NextHopGroup:
Expand Down
60 changes: 60 additions & 0 deletions client/gribiclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,66 @@ func TestGet(t *testing.T) {
},
}},
},
}, {
desc: "single IPv6 entry in Server - specific NI",
inOperations: []*spb.AFTOperation{{
NetworkInstance: server.DefaultNetworkInstanceName,
Entry: &spb.AFTOperation_Ipv6{
Ipv6: &aftpb.Afts_Ipv6EntryKey{
Prefix: "2001:db8::/32",
Ipv6Entry: &aftpb.Afts_Ipv6Entry{},
},
},
}},
inGetRequest: &spb.GetRequest{
NetworkInstance: &spb.GetRequest_Name{
Name: server.DefaultNetworkInstanceName,
},
Aft: spb.AFTType_ALL,
},
wantResponse: &spb.GetResponse{
Entry: []*spb.AFTEntry{{
NetworkInstance: server.DefaultNetworkInstanceName,
Entry: &spb.AFTEntry_Ipv6{
Ipv6: &aftpb.Afts_Ipv6EntryKey{
Prefix: "2001:db8::/32",
Ipv6Entry: &aftpb.Afts_Ipv6Entry{},
},
},
}},
},
}, {
desc: "single MPLS entry in Server - specific NI",
inOperations: []*spb.AFTOperation{{
NetworkInstance: server.DefaultNetworkInstanceName,
Entry: &spb.AFTOperation_Mpls{
Mpls: &aftpb.Afts_LabelEntryKey{
Label: &aftpb.Afts_LabelEntryKey_LabelUint64{
LabelUint64: 42,
},
LabelEntry: &aftpb.Afts_LabelEntry{},
},
},
}},
inGetRequest: &spb.GetRequest{
NetworkInstance: &spb.GetRequest_Name{
Name: server.DefaultNetworkInstanceName,
},
Aft: spb.AFTType_ALL,
},
wantResponse: &spb.GetResponse{
Entry: []*spb.AFTEntry{{
NetworkInstance: server.DefaultNetworkInstanceName,
Entry: &spb.AFTEntry_Mpls{
Mpls: &aftpb.Afts_LabelEntryKey{
Label: &aftpb.Afts_LabelEntryKey_LabelUint64{
LabelUint64: 42,
},
LabelEntry: &aftpb.Afts_LabelEntry{},
},
},
}},
},
}, {
desc: "multiple entries - single NI",
inOperations: []*spb.AFTOperation{{
Expand Down
107 changes: 107 additions & 0 deletions compliance/compliance.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ type Test struct {
RequiresNonDefaultNINHG bool
// RequiresMPLS marks a test that requires MPLS support in the gRIBI server.
RequiresMPLS bool
// RequiresIPv6 marks a test that requires IPv6 support in the gRIBI server.
RequiresIPv6 bool
}

// TestSpec is a description of a test.
Expand Down Expand Up @@ -503,6 +505,25 @@ var (
ShortName: "MPLS add entry with NH label stack",
RequiresMPLS: true,
},
}, {
In: Test{
Fn: makeTestWithACK(AddIPv6Entry, fluent.InstalledInRIB),
ShortName: "Add IPv6 entry that can be programmed on the server - with RIB ACK",
RequiresIPv6: true,
},
}, {
In: Test{
Fn: makeTestWithACK(AddIPv6Entry, fluent.InstalledInFIB),
ShortName: "Add IPv6 entry that can be programmed on the server - with FIB ACK",
RequiresFIBACK: true,
RequiresIPv6: true,
},
}, {
In: Test{
Fn: AddIPv6Metadata,
ShortName: "Add IPv6 entry with metadata",
RequiresIPv6: true,
},
}}
)

Expand Down Expand Up @@ -1784,3 +1805,89 @@ func AddDeleteAdd(c *fluent.GRIBIClient, wantACK fluent.ProgrammingResult, t tes
AsResult(),
chk.IgnoreOperationID())
}

// AddIPv6Entry adds a fully referenced IPv4Entry and checks whether the specified ACK
// type (wantACK) is returned.
func AddIPv6Entry(c *fluent.GRIBIClient, wantACK fluent.ProgrammingResult, t testing.TB, _ ...TestOpt) {
defer flushServer(c, t)

ops := []func(){
func() {
c.Modify().AddEntry(t, fluent.NextHopEntry().WithNetworkInstance(defaultNetworkInstanceName).WithIndex(1).WithIPAddress("192.0.2.1"))
},
func() {
c.Modify().AddEntry(t, fluent.NextHopGroupEntry().WithNetworkInstance(defaultNetworkInstanceName).WithID(42).AddNextHop(1, 1))
},
func() {
c.Modify().AddEntry(t, fluent.IPv6Entry().WithPrefix("2001:db8::/32").WithNetworkInstance(defaultNetworkInstanceName).WithNextHopGroup(42))
},
}

res := DoModifyOps(c, t, ops, wantACK, false)

// Check the three entries in order.
chk.HasResult(t, res,
fluent.OperationResult().
WithOperationID(1).
WithProgrammingResult(wantACK).
AsResult(),
)

chk.HasResult(t, res,
fluent.OperationResult().
WithOperationID(2).
WithProgrammingResult(wantACK).
AsResult(),
)

chk.HasResult(t, res,
fluent.OperationResult().
WithOperationID(3).
WithProgrammingResult(wantACK).
AsResult(),
)
}

// AddIPv6Metadata adds an IPv6 Entry (and its dependencies) with metadata alongside the
// entry.
func AddIPv6Metadata(c *fluent.GRIBIClient, t testing.TB, _ ...TestOpt) {
defer flushServer(c, t)
ops := []func(){
func() {
c.Modify().AddEntry(t, fluent.NextHopEntry().WithIndex(1).WithNetworkInstance(defaultNetworkInstanceName).WithIPAddress("192.0.2.3"))
c.Modify().AddEntry(t, fluent.NextHopGroupEntry().WithID(1).WithNetworkInstance(defaultNetworkInstanceName).AddNextHop(1, 1))
c.Modify().AddEntry(t, fluent.IPv6Entry().
WithPrefix("2001:db8::1/128").
WithNetworkInstance(defaultNetworkInstanceName).
WithNextHopGroup(1).
WithMetadata([]byte{1, 2, 3, 4, 5, 6, 7, 8}),
)
},
}

res := DoModifyOps(c, t, ops, fluent.InstalledInRIB, false)

chk.HasResult(t, res,
fluent.OperationResult().
WithIPv6Operation("2001:db8::1/128").
WithOperationType(constants.Add).
WithProgrammingResult(fluent.InstalledInRIB).
AsResult(),
chk.IgnoreOperationID())

chk.HasResult(t, res,
fluent.OperationResult().
WithNextHopGroupOperation(1).
WithOperationType(constants.Add).
WithProgrammingResult(fluent.InstalledInRIB).
AsResult(),
chk.IgnoreOperationID())

chk.HasResult(t, res,
fluent.OperationResult().
WithNextHopOperation(1).
WithOperationType(constants.Add).
WithProgrammingResult(fluent.InstalledInRIB).
AsResult(),
chk.IgnoreOperationID())
}
11 changes: 11 additions & 0 deletions fluent/fluent.go
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,17 @@ func (o *opResult) WithIPv4Operation(p string) *opResult {
return o
}

// WithIPv6Operation indicates that the result corresponds to
// an operation impacting the IPv6 prefix p which is of the form
// prefix/mask.
func (o *opResult) WithIPv6Operation(p string) *opResult {
if o.r.Details == nil {
o.r.Details = &client.OpDetailsResults{}
}
o.r.Details.IPv6Prefix = p
return o
}

// WithNextHopGroupOperation indicates that the result correspodns to
// an operation impacting the next-hop-group with index i.
func (o *opResult) WithNextHopGroupOperation(i uint64) *opResult {
Expand Down

0 comments on commit 133fc8c

Please sign in to comment.