diff --git a/go.mod b/go.mod index ec636097..01486245 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,9 @@ require ( github.com/networkservicemesh/sdk v0.5.1-0.20220124073803-419fa7053a1a github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.7.0 - github.com/vishvananda/netlink v1.1.0 - github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae + github.com/vishvananda/netlink v1.1.1-0.20220118170537-d6b03fdeb845 + github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 + go.uber.org/atomic v1.7.0 go.uber.org/goleak v1.1.12 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c google.golang.org/grpc v1.42.0 diff --git a/go.sum b/go.sum index 7e6df0f3..2758b4b7 100644 --- a/go.sum +++ b/go.sum @@ -218,11 +218,11 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns= +github.com/vishvananda/netlink v1.1.1-0.20220118170537-d6b03fdeb845 h1:bIVwDExax2ZzN6mYF8Az0ms0wg+v/LYA4VI8x1TSQcs= +github.com/vishvananda/netlink v1.1.1-0.20220118170537-d6b03fdeb845/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= +github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= @@ -264,6 +264,7 @@ go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKu go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.11.0 h1:cLDgIBTf4lLOlztkhzAEdQsJ4Lj+i5Wc9k6Nn0K1VyU= go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= @@ -327,7 +328,6 @@ golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -335,6 +335,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/pkg/kernel/const_linux.go b/pkg/kernel/const_linux.go index af7ec92a..c26129e8 100644 --- a/pkg/kernel/const_linux.go +++ b/pkg/kernel/const_linux.go @@ -14,6 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + package kernel import ( diff --git a/pkg/kernel/link.go b/pkg/kernel/link.go index 6890433f..b5c467bf 100644 --- a/pkg/kernel/link.go +++ b/pkg/kernel/link.go @@ -16,6 +16,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + // Package kernel contains Link representation of network interface package kernel diff --git a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/ipaddress/common.go b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/ipaddress/common.go index 4b42678e..dbcd1b8f 100644 --- a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/ipaddress/common.go +++ b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/ipaddress/common.go @@ -1,6 +1,6 @@ -// Copyright (c) 2020-2021 Cisco and/or its affiliates. +// Copyright (c) 2020-2022 Cisco and/or its affiliates. // -// Copyright (c) 2021 Nordix Foundation. +// Copyright (c) 2021-2022 Nordix Foundation. // // SPDX-License-Identifier: Apache-2.0 // @@ -56,7 +56,7 @@ func create(ctx context.Context, conn *networkservice.Connection, isClient bool) if err != nil { return errors.WithStack(err) } - defer netlinkHandle.Delete() + defer netlinkHandle.Close() ifName := mechanism.GetInterfaceName() diff --git a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/ipneighbors/common.go b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/ipneighbors/common.go index 3c968ff2..8123f0d3 100644 --- a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/ipneighbors/common.go +++ b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/ipneighbors/common.go @@ -45,7 +45,7 @@ func create(ctx context.Context, conn *networkservice.Connection, isClient bool) if err != nil { return errors.WithStack(err) } - defer netlinkHandle.Delete() + defer netlinkHandle.Close() ifName := mechanism.GetInterfaceName() diff --git a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/common.go b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/common.go new file mode 100644 index 00000000..15e00506 --- /dev/null +++ b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/common.go @@ -0,0 +1,249 @@ +// Copyright (c) 2022 Doc.ai and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build linux + +package iprule + +import ( + "context" + "time" + + "github.com/pkg/errors" + "github.com/vishvananda/netlink" + "go.uber.org/atomic" + + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/kernel" + + "github.com/networkservicemesh/sdk/pkg/tools/log" + + link "github.com/networkservicemesh/sdk-kernel/pkg/kernel" +) + +func create(ctx context.Context, conn *networkservice.Connection, tableIDs *Map, counter *atomic.Int32) error { + if mechanism := kernel.ToMechanism(conn.GetMechanism()); mechanism != nil && mechanism.GetVLAN() == 0 { + // Construct the netlink handle for the target namespace for this kernel interface + netlinkHandle, err := link.GetNetlinkHandle(mechanism.GetNetNSURL()) + if err != nil { + return errors.WithStack(err) + } + defer netlinkHandle.Close() + + l, err := netlinkHandle.LinkByName(mechanism.GetInterfaceName()) + if err != nil { + return errors.WithStack(err) + } + + if err = netlinkHandle.LinkSetUp(l); err != nil { + return errors.WithStack(err) + } + + for _, policy := range conn.Context.IpContext.Policies { + // Check if we already created required ip table + key := tableKey{ + from: policy.From, + protocol: policy.Proto, + port: policy.Port, + } + tableID, ok := tableIDs.Load(key) + if !ok { + counter.Inc() + tableID = int(counter.Load()) + } + + // If policy doesn't contain any route - add default + if len(policy.Routes) == 0 { + policy.Routes = append(policy.Routes, defaultRoute()) + } + for _, route := range policy.Routes { + if err := routeAdd(ctx, netlinkHandle, l, route, tableID); err != nil { + return err + } + } + + if !ok { + // Check and delete old rules if they don't fit + _ = delOldRules(ctx, netlinkHandle, policy, tableID) + // Add new rule + if err := ruleAdd(ctx, netlinkHandle, policy, tableID); err != nil { + return err + } + tableIDs.Store(key, tableID) + } + } + } + return nil +} + +func policyToRule(policy *networkservice.PolicyRoute) (*netlink.Rule, error) { + rule := netlink.NewRule() + if policy.From != "" { + src, err := netlink.ParseIPNet(policy.From) + if err != nil { + return nil, errors.WithStack(err) + } + rule.Src = src + } + rule.IPProto = int(policy.Proto) + rule.Dport = netlink.NewRulePortRange(uint16(policy.Port), uint16(policy.Port)) + return rule, nil +} + +func ruleAdd(ctx context.Context, handle *netlink.Handle, policy *networkservice.PolicyRoute, tableID int) error { + rule, err := policyToRule(policy) + if err != nil { + return errors.WithStack(err) + } + rule.Table = tableID + + now := time.Now() + if err := handle.RuleAdd(rule); err != nil { + log.FromContext(ctx). + WithField("From", policy.From). + WithField("IPProto", policy.Proto). + WithField("Port", policy.Port). + WithField("Table", tableID). + WithField("duration", time.Since(now)). + WithField("netlink", "RuleAdd").Errorf("error %+v", err) + return errors.WithStack(err) + } + log.FromContext(ctx). + WithField("From", policy.From). + WithField("IPProto", policy.Proto). + WithField("Port", policy.Port). + WithField("Table", tableID). + WithField("duration", time.Since(now)). + WithField("netlink", "RuleAdd").Debug("completed") + return nil +} + +func delOldRules(ctx context.Context, handle *netlink.Handle, policy *networkservice.PolicyRoute, tableID int) error { + rule, err := policyToRule(policy) + if err != nil { + return errors.WithStack(err) + } + flags := netlink.RT_FILTER_PROTOCOL + if rule.Src != nil { + flags |= netlink.RT_FILTER_SRC + } + rules, err := handle.RuleListFiltered(netlink.FAMILY_ALL, rule, flags) + if err != nil { + return errors.WithStack(err) + } + for i := range rules { + if rules[i].Dport == rule.Dport { + if rules[i].Table != tableID { + err = delRule(ctx, handle, policy) + if err != nil { + return errors.WithStack(err) + } + } + } + } + return nil +} + +func defaultRoute() *networkservice.Route { + return &networkservice.Route{ + Prefix: "0.0.0.0/0", + } +} + +func routeAdd(ctx context.Context, handle *netlink.Handle, l netlink.Link, route *networkservice.Route, tableID int) error { + if route.GetPrefixIPNet() == nil { + return errors.New("kernelRoute prefix must not be nil") + } + dst := route.GetPrefixIPNet() + dst.IP = dst.IP.Mask(dst.Mask) + kernelRoute := &netlink.Route{ + LinkIndex: l.Attrs().Index, + Scope: netlink.SCOPE_UNIVERSE, + Dst: dst, + Table: tableID, + } + + gw := route.GetNextHopIP() + if gw != nil { + kernelRoute.Gw = gw + kernelRoute.SetFlag(netlink.FLAG_ONLINK) + } + + now := time.Now() + if err := handle.RouteReplace(kernelRoute); err != nil { + log.FromContext(ctx). + WithField("link.Name", l.Attrs().Name). + WithField("Dst", kernelRoute.Dst). + WithField("Gw", kernelRoute.Gw). + WithField("Scope", kernelRoute.Scope). + WithField("Flags", kernelRoute.Flags). + WithField("Table", tableID). + WithField("duration", time.Since(now)). + WithField("netlink", "RouteReplace").Errorf("error %+v", err) + return errors.WithStack(err) + } + log.FromContext(ctx). + WithField("link.Name", l.Attrs().Name). + WithField("Dst", kernelRoute.Dst). + WithField("Gw", kernelRoute.Gw). + WithField("Scope", kernelRoute.Scope). + WithField("Flags", kernelRoute.Flags). + WithField("Table", tableID). + WithField("duration", time.Since(now)). + WithField("netlink", "RouteReplace").Debug("completed") + return nil +} + +func del(ctx context.Context, conn *networkservice.Connection) error { + if mechanism := kernel.ToMechanism(conn.GetMechanism()); mechanism != nil && mechanism.GetVLAN() == 0 { + netlinkHandle, err := link.GetNetlinkHandle(mechanism.GetNetNSURL()) + if err != nil { + return errors.WithStack(err) + } + defer netlinkHandle.Close() + for _, policy := range conn.Context.IpContext.Policies { + if err := delRule(ctx, netlinkHandle, policy); err != nil { + return errors.WithStack(err) + } + } + } + return nil +} + +func delRule(ctx context.Context, handle *netlink.Handle, policy *networkservice.PolicyRoute) error { + rule, err := policyToRule(policy) + if err != nil { + return errors.WithStack(err) + } + + now := time.Now() + if err := handle.RuleDel(rule); err != nil { + log.FromContext(ctx). + WithField("From", policy.From). + WithField("IPProto", policy.Proto). + WithField("Port", policy.Port). + WithField("duration", time.Since(now)). + WithField("netlink", "RuleDel").Errorf("error %+v", err) + return errors.WithStack(err) + } + log.FromContext(ctx). + WithField("From", policy.From). + WithField("IPProto", policy.Proto). + WithField("Port", policy.Port). + WithField("duration", time.Since(now)). + WithField("netlink", "RuleDel").Debug("completed") + return nil +} diff --git a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/doc.go b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/doc.go new file mode 100644 index 00000000..3d1aa11c --- /dev/null +++ b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/doc.go @@ -0,0 +1,18 @@ +// Copyright (c) 2022 Doc.ai and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package iprule provides networkservice chain elements that support setting ip rules +package iprule diff --git a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/gen.go b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/gen.go new file mode 100644 index 00000000..e2d3452a --- /dev/null +++ b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/gen.go @@ -0,0 +1,30 @@ +// Copyright (c) 2022 Doc.ai and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package iprule + +import "sync" + +//go:generate go-syncmap -output table_map.gen.go -type Map + +type tableKey struct { + from string + protocol uint32 + port uint32 +} + +// Map - sync.Map with key == tableKey and value == uint32 +type Map sync.Map diff --git a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/server.go b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/server.go new file mode 100644 index 00000000..eee22181 --- /dev/null +++ b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/server.go @@ -0,0 +1,67 @@ +// Copyright (c) 2022 Doc.ai and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build linux + +package iprule + +import ( + "context" + + "github.com/golang/protobuf/ptypes/empty" + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" + "github.com/networkservicemesh/sdk/pkg/tools/postpone" + "github.com/pkg/errors" + "go.uber.org/atomic" +) + +type ipruleServer struct { + counter atomic.Int32 + tables Map +} + +// NewServer creates a new server chain element setting ip rules +func NewServer() networkservice.NetworkServiceServer { + return &ipruleServer{} +} + +func (i *ipruleServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) { + postponeCtxFunc := postpone.ContextWithValues(ctx) + + conn, err := next.Server(ctx).Request(ctx, request) + if err != nil { + return nil, err + } + + if err := create(ctx, conn, &i.tables, &i.counter); err != nil { + closeCtx, cancelClose := postponeCtxFunc() + defer cancelClose() + + if _, closeErr := i.Close(closeCtx, conn); closeErr != nil { + err = errors.Wrapf(err, "connection closed with error: %s", closeErr.Error()) + } + + return nil, err + } + + return conn, nil +} + +func (i *ipruleServer) Close(ctx context.Context, conn *networkservice.Connection) (*empty.Empty, error) { + _ = del(ctx, conn) + return next.Server(ctx).Close(ctx, conn) +} diff --git a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/table_map.gen.go b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/table_map.gen.go new file mode 100644 index 00000000..713cc8a3 --- /dev/null +++ b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/iprule/table_map.gen.go @@ -0,0 +1,73 @@ +// Code generated by "-output table_map.gen.go -type Map -output table_map.gen.go -type Map"; DO NOT EDIT. +package iprule + +import ( + "sync" // Used by sync.Map. +) + +// Generate code that will fail if the constants change value. +func _() { + // An "cannot convert Map literal (type Map) to type sync.Map" compiler error signifies that the base type have changed. + // Re-run the go-syncmap command to generate them again. + _ = (sync.Map)(Map{}) +} + +var _nil_Map_int_value = func() (val int) { return }() + +// Load returns the value stored in the map for a key, or nil if no +// value is present. +// The ok result indicates whether value was found in the map. +func (m *Map) Load(key tableKey) (int, bool) { + value, ok := (*sync.Map)(m).Load(key) + if value == nil { + return _nil_Map_int_value, ok + } + return value.(int), ok +} + +// Store sets the value for a key. +func (m *Map) Store(key tableKey, value int) { + (*sync.Map)(m).Store(key, value) +} + +// LoadOrStore returns the existing value for the key if present. +// Otherwise, it stores and returns the given value. +// The loaded result is true if the value was loaded, false if stored. +func (m *Map) LoadOrStore(key tableKey, value int) (int, bool) { + actual, loaded := (*sync.Map)(m).LoadOrStore(key, value) + if actual == nil { + return _nil_Map_int_value, loaded + } + return actual.(int), loaded +} + +// LoadAndDelete deletes the value for a key, returning the previous value if any. +// The loaded result reports whether the key was present. +func (m *Map) LoadAndDelete(key tableKey) (value int, loaded bool) { + actual, loaded := (*sync.Map)(m).LoadAndDelete(key) + if actual == nil { + return _nil_Map_int_value, loaded + } + return actual.(int), loaded +} + +// Delete deletes the value for a key. +func (m *Map) Delete(key tableKey) { + (*sync.Map)(m).Delete(key) +} + +// Range calls f sequentially for each key and value present in the map. +// If f returns false, range stops the iteration. +// +// Range does not necessarily correspond to any consistent snapshot of the Map's +// contents: no key will be visited more than once, but if the value for any key +// is stored or deleted concurrently, Range may reflect any mapping for that key +// from any point during the Range call. +// +// Range may be O(N) with the number of elements in the map even if f returns +// false after a constant number of calls. +func (m *Map) Range(f func(key tableKey, value int) bool) { + (*sync.Map)(m).Range(func(key, value interface{}) bool { + return f(key.(tableKey), value.(int)) + }) +} diff --git a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/routes/common.go b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/routes/common.go index 19c9f828..3862d0df 100644 --- a/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/routes/common.go +++ b/pkg/kernel/networkservice/connectioncontextkernel/ipcontext/routes/common.go @@ -1,6 +1,6 @@ -// Copyright (c) 2020-2021 Cisco and/or its affiliates. +// Copyright (c) 2020-2022 Cisco and/or its affiliates. // -// Copyright (c) 2021 Nordix Foundation. +// Copyright (c) 2021-2022 Nordix Foundation. // // SPDX-License-Identifier: Apache-2.0 // @@ -40,7 +40,7 @@ func create(ctx context.Context, conn *networkservice.Connection, isClient bool) if err != nil { return errors.WithStack(err) } - defer netlinkHandle.Delete() + defer netlinkHandle.Close() ifName := mechanism.GetInterfaceName() diff --git a/pkg/kernel/networkservice/connectioncontextkernel/mtu/common.go b/pkg/kernel/networkservice/connectioncontextkernel/mtu/common.go index 3b06eea6..c3b86bc6 100644 --- a/pkg/kernel/networkservice/connectioncontextkernel/mtu/common.go +++ b/pkg/kernel/networkservice/connectioncontextkernel/mtu/common.go @@ -1,6 +1,6 @@ -// Copyright (c) 2021 Cisco and/or its affiliates. +// Copyright (c) 2021-2022 Cisco and/or its affiliates. // -// Copyright (c) 2021 Nordix Foundation. +// Copyright (c) 2021-2022 Nordix Foundation. // // SPDX-License-Identifier: Apache-2.0 // @@ -46,7 +46,7 @@ func setMTU(ctx context.Context, conn *networkservice.Connection) error { if err != nil { return errors.WithStack(err) } - defer netlinkHandle.Delete() + defer netlinkHandle.Close() ifName := mechanism.GetInterfaceName() diff --git a/pkg/kernel/networkservice/ethernetcontext/vf_client.go b/pkg/kernel/networkservice/ethernetcontext/vf_client.go index 26b144fb..384054ee 100644 --- a/pkg/kernel/networkservice/ethernetcontext/vf_client.go +++ b/pkg/kernel/networkservice/ethernetcontext/vf_client.go @@ -16,6 +16,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + package ethernetcontext import ( diff --git a/pkg/kernel/networkservice/ethernetcontext/vf_common.go b/pkg/kernel/networkservice/ethernetcontext/vf_common.go index b5748336..c476e306 100644 --- a/pkg/kernel/networkservice/ethernetcontext/vf_common.go +++ b/pkg/kernel/networkservice/ethernetcontext/vf_common.go @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Nordix Foundation. +// Copyright (c) 2021-2022 Nordix Foundation. // // SPDX-License-Identifier: Apache-2.0 // @@ -14,6 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + package ethernetcontext import ( @@ -37,7 +39,7 @@ func setKernelHwAddress(ctx context.Context, conn *networkservice.Connection, is if err != nil { return errors.WithStack(err) } - defer netlinkHandle.Delete() + defer netlinkHandle.Close() ifName := mechanism.GetInterfaceName() diff --git a/pkg/kernel/networkservice/ethernetcontext/vf_server.go b/pkg/kernel/networkservice/ethernetcontext/vf_server.go index a4efc5e3..1cfd67c2 100644 --- a/pkg/kernel/networkservice/ethernetcontext/vf_server.go +++ b/pkg/kernel/networkservice/ethernetcontext/vf_server.go @@ -16,6 +16,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + // Package ethernetcontext provides chain element for setup link ethernet properties package ethernetcontext diff --git a/pkg/kernel/networkservice/inject/client.go b/pkg/kernel/networkservice/inject/client.go index 17562ad7..3316385e 100644 --- a/pkg/kernel/networkservice/inject/client.go +++ b/pkg/kernel/networkservice/inject/client.go @@ -14,6 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + package inject import ( diff --git a/pkg/kernel/networkservice/inject/common.go b/pkg/kernel/networkservice/inject/common.go index 8d16c583..1d0719d7 100644 --- a/pkg/kernel/networkservice/inject/common.go +++ b/pkg/kernel/networkservice/inject/common.go @@ -14,6 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + package inject import ( diff --git a/pkg/kernel/networkservice/inject/server.go b/pkg/kernel/networkservice/inject/server.go index 43c6226c..80b8bf89 100644 --- a/pkg/kernel/networkservice/inject/server.go +++ b/pkg/kernel/networkservice/inject/server.go @@ -14,6 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + // Package inject contains chain element that moves network interface to and from a Client's pod network namespace package inject diff --git a/pkg/kernel/tools/peer/metadata.go b/pkg/kernel/tools/peer/metadata.go index c23aa2aa..117c98dd 100644 --- a/pkg/kernel/tools/peer/metadata.go +++ b/pkg/kernel/tools/peer/metadata.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +// +build linux // Package peer allows storing peer netlink.Link in per Connection.Id metadata package peer