Merge pull request #45892 from corhere/libn/overlay-cut-vni-list
libnetwork/drivers/overlay: parse VNI list option in O(1) memory
This commit is contained in:
commit
c9397ec8d4
4 changed files with 114 additions and 17 deletions
|
@ -16,6 +16,7 @@ import (
|
|||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/docker/docker/libnetwork/driverapi"
|
||||
"github.com/docker/docker/libnetwork/drivers/overlay/overlayutils"
|
||||
"github.com/docker/docker/libnetwork/netlabel"
|
||||
"github.com/docker/docker/libnetwork/ns"
|
||||
"github.com/docker/docker/libnetwork/osl"
|
||||
|
@ -111,14 +112,10 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d
|
|||
return errors.New("no VNI provided")
|
||||
}
|
||||
log.G(context.TODO()).Debugf("overlay: Received vxlan IDs: %s", vnisOpt)
|
||||
vniStrings := strings.Split(vnisOpt, ",")
|
||||
for _, vniStr := range vniStrings {
|
||||
vni, err := strconv.Atoi(vniStr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid vxlan id value %q passed", vniStr)
|
||||
}
|
||||
|
||||
vnis = append(vnis, uint32(vni))
|
||||
var err error
|
||||
vnis, err = overlayutils.AppendVNIList(vnis, vnisOpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, ok := optMap[secureOption]; ok {
|
||||
|
|
|
@ -3,6 +3,8 @@ package overlayutils
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
@ -40,3 +42,23 @@ func VXLANUDPPort() uint32 {
|
|||
defer mutex.RUnlock()
|
||||
return vxlanUDPPort
|
||||
}
|
||||
|
||||
// AppendVNIList appends the VNI values encoded as a CSV string to slice.
|
||||
func AppendVNIList(vnis []uint32, csv string) ([]uint32, error) {
|
||||
for {
|
||||
var (
|
||||
vniStr string
|
||||
found bool
|
||||
)
|
||||
vniStr, csv, found = strings.Cut(csv, ",")
|
||||
vni, err := strconv.Atoi(vniStr)
|
||||
if err != nil {
|
||||
return vnis, fmt.Errorf("invalid vxlan id value %q passed", vniStr)
|
||||
}
|
||||
|
||||
vnis = append(vnis, uint32(vni))
|
||||
if !found {
|
||||
return vnis, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
82
libnetwork/drivers/overlay/overlayutils/utils_test.go
Normal file
82
libnetwork/drivers/overlay/overlayutils/utils_test.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package overlayutils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestAppendVNIList(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
slice []uint32
|
||||
csv string
|
||||
want []uint32
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "NilSlice",
|
||||
csv: "1,2,3",
|
||||
want: []uint32{1, 2, 3},
|
||||
},
|
||||
{
|
||||
name: "TrailingComma",
|
||||
csv: "1,2,3,",
|
||||
want: []uint32{1, 2, 3},
|
||||
wantErr: `invalid vxlan id value "" passed`,
|
||||
},
|
||||
{
|
||||
name: "EmptySlice",
|
||||
slice: make([]uint32, 0, 10),
|
||||
csv: "1,2,3",
|
||||
want: []uint32{1, 2, 3},
|
||||
},
|
||||
{
|
||||
name: "ExistingSlice",
|
||||
slice: []uint32{4, 5, 6},
|
||||
csv: "1,2,3",
|
||||
want: []uint32{4, 5, 6, 1, 2, 3},
|
||||
},
|
||||
{
|
||||
name: "InvalidVNI",
|
||||
slice: []uint32{4, 5, 6},
|
||||
csv: "1,2,3,abc",
|
||||
want: []uint32{4, 5, 6, 1, 2, 3},
|
||||
wantErr: "invalid vxlan id value \"abc\" passed",
|
||||
},
|
||||
{
|
||||
name: "InvalidVNI2",
|
||||
slice: []uint32{4, 5, 6},
|
||||
csv: "abc,1,2,3",
|
||||
want: []uint32{4, 5, 6},
|
||||
wantErr: "invalid vxlan id value \"abc\" passed",
|
||||
},
|
||||
}
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := AppendVNIList(tt.slice, tt.csv)
|
||||
assert.Check(t, is.DeepEqual(tt.want, got))
|
||||
if tt.wantErr == "" {
|
||||
assert.Check(t, err)
|
||||
} else {
|
||||
assert.Check(t, is.ErrorContains(err, tt.wantErr))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("DoesNotAllocate", func(t *testing.T) {
|
||||
slice := make([]uint32, 0, 10)
|
||||
csv := "1,2,3,4,5,6,7,8,9,10"
|
||||
want := []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||
allocs := testing.AllocsPerRun(10, func() {
|
||||
var err error
|
||||
slice, err = AppendVNIList(slice[:0], csv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
assert.Check(t, is.DeepEqual(slice, want))
|
||||
assert.Check(t, is.Equal(int(allocs), 0))
|
||||
})
|
||||
}
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
|
@ -13,6 +12,7 @@ import (
|
|||
"github.com/docker/docker/libnetwork/datastore"
|
||||
"github.com/docker/docker/libnetwork/discoverapi"
|
||||
"github.com/docker/docker/libnetwork/driverapi"
|
||||
"github.com/docker/docker/libnetwork/drivers/overlay/overlayutils"
|
||||
"github.com/docker/docker/libnetwork/netlabel"
|
||||
"github.com/docker/docker/libnetwork/types"
|
||||
)
|
||||
|
@ -88,14 +88,10 @@ func (d *driver) NetworkAllocate(id string, option map[string]string, ipV4Data,
|
|||
for key, val := range option {
|
||||
if key == netlabel.OverlayVxlanIDList {
|
||||
log.G(context.TODO()).Debugf("overlay network option: %s", val)
|
||||
valStrList := strings.Split(val, ",")
|
||||
for _, idStr := range valStrList {
|
||||
vni, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid vxlan id value %q passed", idStr)
|
||||
}
|
||||
|
||||
vxlanIDList = append(vxlanIDList, uint32(vni))
|
||||
var err error
|
||||
vxlanIDList, err = overlayutils.AppendVNIList(vxlanIDList, val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
opts[key] = val
|
||||
|
|
Loading…
Add table
Reference in a new issue